切好的 Node 若每次进程启动都重新 embedding,本地 Ollama 会把 CPU 打满,云端则重复计费。VectorStoreIndex 把 Node 的向量放进向量库、原文放进 docstore;一次 from_documents 之后用 persist 落盘,下次 load_index_from_storage 直接问。
段末注释:VectorStoreIndex = 默认的语义索引:对每个 Node 算 embedding,按 query 向量取 top-k。它不等于整条 RAG 产品,只覆盖「向量召回」这一段。

1. 一句话定位
| 维度 | 内容 |
|---|---|
| 角色 | 知识层的向量索引:Node ↔ embedding ↔ 相似度召回 |
| 输入 → 输出 | list[Document] 或 list[Node] → VectorStoreIndex → NodeWithScore / Response |
| 典型调用入口 | from_documents()、storage_context.persist()、as_retriever()、as_query_engine().query() |
| 与 LangChain / LangGraph | 近邻是 LangChain VectorStore;LangGraph 节点里调用 retriever.retrieve / qe.query,不要在图里重建索引 |
出现背景:from_documents 把切分 + 嵌入 + 入库收成一条捷径,默认用内存 SimpleVectorStore。生产把 vector_store 换成 Qdrant / pgvector 等,索引 API 不变。
2. 前置依赖与环境
1 | pip install -U llama-index-core llama-index-llms-ollama llama-index-embeddings-ollama |
- Python 3.10+;版本锚点
llama-index-core0.14.x - 必须同时设
Settings.embed_model与Settings.llm,否则会打 OpenAI - 示例用同步
query();FastAPI 用await qe.aquery(...)
3. 实现逻辑
1 | 1. Settings.embed_model / Settings.llm 设成本地 Ollama |
字段级变形:
1 | Document(text="……GAPDH……小鼠……", metadata={species:"小鼠"}) |
4. 原理说明
主轴是:from_documents 一次走完切分与嵌入;persist 只是把已经算好的向量和 Node 快照写出去。
1 | 1. from_documents 读取 transformations 或 Settings.text_splitter,得到 TextNode[] |
VectorStoreIndex.from_documents(documents, ...)(类方法)出现在步骤 1。功能:切分 + 嵌入 + 建索引。可选 show_progress=True、storage_context=、embed_model= 局部覆盖。
StorageContext 出现在步骤 3~5。功能:凑齐 vector_store / docstore / index_store。默认全是 Simple* 内存实现。
as_retriever(similarity_top_k=...) 出现在步骤 6。retrieve(str) → list[NodeWithScore]。score 含义随后端(余弦 / 内积 / 距离),不要跨后端比较绝对分数。
as_query_engine(similarity_top_k=..., response_mode=...) 出现在步骤 7。query / aquery 返回 Response。
换 Qdrant 只换 vector_store=,不要换一套 from_documents 调用习惯。对接具体库是向量库集成包的事,本篇用默认 Simple 店讲清契约。
5. 最小可运行示例
1 | pip install -U llama-index-core llama-index-llms-ollama llama-index-embeddings-ollama |
1 | from llama_index.core import ( |
6. 重要配置参数
| 参数(API 名) | 类型 / 默认值 | 功能说明 | 作用与影响 | 参考起点 / 常用范围 | 配置指导 |
|---|---|---|---|---|---|
Settings.embed_model |
Embedding 实例 / 默认 OpenAI | 入库与 query 共用的编码器 | 未设打云端;换模型维数变了必须重建 | OllamaEmbedding(model_name="nomic-embed-text") |
与生成模型分开 pull |
Settings.llm |
LLM 实例 / 默认 OpenAI | as_query_engine 合成答案 |
未设则 query 打云端;retriever 不需要它 | Ollama(model="qwen3.5:9b") |
只检索时可后设 |
transformations |
list,可选 | from_documents 用的切分等变换 |
不传则用 Settings 默认 splitter | 显式 SentenceSplitter |
与线上 query 无关,只影响入库 |
similarity_top_k |
int,retriever/qe 默认常为 2 | 召回 Node 条数 | 过小漏证据;过大噪声与费用升 | 5~10 入门 | 有 rerank 可先放大 |
response_mode |
str,qe 默认 "compact" |
多 Node 如何喂给 LLM | refine 更稳更贵;tree_summarize 适合汇总 |
compact / refine / tree_summarize | 单事实用 compact |
persist_dir |
str,默认 ./storage |
Simple 店序列化目录 | 指错目录等于空索引 | 项目内固定路径 | 与 embed 模型 ID 一起写进 README |
storage_context.vector_store |
向量库适配器,可选 | 换成 Qdrant 等远端 | 远端库 persist 语义变了,向量不在本地 JSON | 生产必换 | API 仍 from_documents / from_vector_store |
show_progress |
bool,默认 False |
嵌入进度条 | 只影响可观测性 | 本地调试 True |
生产日志用 callback |
7. 适用 / 不适用
| 维度 | 适用 | 不适用 |
|---|---|---|
| 任务形态 | 语义问答、同义改写查询 | 必须精确命中基因号 / 货号——要加 sparse/hybrid,不是本索引单独能解决 |
| 集成约束 | 可接受一次全库 embedding | 小时级增量且文件频繁改——配 IngestionPipeline + 外部向量库 |
| 工程阶段 | 原型到单机落盘 | 多实例并发写同一 Simple 目录——换带锁的外部库 |
工具环、审批、会话恢复:索引仍用本对象,编排走 LangGraph。
8. 易踩坑
- 未设
Settings.embed_model:本地 LLM 已通,嵌入仍打 OpenAI。 - 每次启动
from_documents:persist 形同虚设。 - persist 后换了嵌入模型还
load:维数/空间不一致,分数乱、召回崩,需要重建。 - 只
print(resp):丢掉source_nodes,无法证明答的是 methods 那条 Node。
小结
from_documents= 切分 + 嵌入 + 写入 store;persist/load_index_from_storage避免重复嵌入。- 检索用
as_retriever;问答用as_query_engine,引用看source_nodes。 - 换 Qdrant 只换
vector_store,不要换调用习惯。 - 混合检索、Router、重排是后续专篇;本篇只保证向量索引契约正确。