0. 文档定位与主线目标

这份 Notebook 的核心是在讲 RAG 的入库(Ingestion/索引构建)与检索(Retrieval) 里最关键的一环:

Embedding 模型如何选、向量数据库如何选、以及如何用 LlamaIndex 把“文档→切分→向量→入库→过滤→检索→工具封装/Agent 调用”串起来。

它反复强调一个观点:

  • 知识库/索引质量决定 RAG 检索上限(切分、embedding、索引、过滤、更新策略都直接影响召回质量与最终回答)。

第一阶段:向量数据库概念介绍(RAG 入库流程)

这一阶段用“入库流程”把概念讲清楚,核心是把非结构化文本变为可检索的结构化“向量索引”。

1) 入库(Ingestion / Indexing)在做什么

  • 文档加载(PDF/Word/HTML/Markdown 等)

  • 文本切分(chunking)成多个片段/节点(nodes)

  • 用 Embedding 模型把每个 chunk 变成向量

  • 把向量 + 原文片段 + 元数据 一起存入向量库,并建立索引(ANN 或精确索引)

2) 向量数据库的意义

  • 支撑高效相似度检索(top-k)

  • 支持规模化(百万/千万/亿级向量)

  • 通常还需要:元数据过滤、更新/删除、持久化、命名空间/多租户、混合检索 等能力


第二阶段:Embedding 模型介绍(选型、成本、部署、评估)

这部分很“工程化”:不仅讲模型好坏,还讲成本、中文能力、部署方式、评估指标。

2.1 云 API vs 本地开源:集成方式对比

文档用表格总结了两大路线:

云端 API(OpenAI、Cohere 等)

  • 依赖:对应 SDK + API Key

  • 优点:上线快、免运维、弹性扩容

  • 风险/注意:成本随调用量线性增长;速率限制;数据出境/合规

本地开源(HuggingFace/SentenceTransformers、BGE 等)

  • 依赖:本地模型权重、推理框架、服务化

  • 优点:数据可控、长期 TCO 更友好、可离线

  • 风险/注意:初期工程投入高;需要监控、硬件评估、吞吐优化(batch、ONNX 等)

2.2 模型特性与中文推荐

它给了面向中文的推荐路径(按“入门→进阶→生产”):

  • 中文入门:BAAI/bge-small-zhmoka-ai/m3e-base

  • 进阶:BGE-M3(强调支持稠密/稀疏/多向量、长文本检索)

  • 生产:参考 MTEB leaderboard + 结合业务做 A/B Test

并强调两个关键工程点:

  • 向量维度越高通常更稳,但存储/计算更贵

  • 最大序列长度影响切分策略与上下文覆盖

2.3 价格对比与预算估算(每 1m tokens)

这一节的目的不是给死数,而是教你按“token 量→调用次数→预算”去估算,并把成本纳入选型。

2.4 本地部署实践(HuggingFaceEmbedding)

给出 LlamaIndex 的标准写法:

  • Settings.embed_model = HuggingFaceEmbedding(model_name='BAAI/bge-large-zh-v1.5', device=..., embed_batch_size=64)

  • 演示 get_query_embedding() 得到向量并打印维度

2.5 评估指标:hit_rate 与 MRR

通过 RetrieverEvaluator 演示检索评估:

  • 构造 TextNode 作为语料

  • VectorStoreIndex(nodes, embed_model=...)

  • retriever = index.as_retriever(similarity_top_k=5)

  • 指标:

    • hit_rate:top_k 里是否命中正确节点

    • MRR:正确结果出现得越靠前分越高(越早命中越好)

它还特地演示了:
同一个 query,expected_id 不同 → 评估结果可能完全不同,用于定位召回问题。

2.6 使用思考(工程经验导向)

这一节整体倾向于:

  • 不要只看榜单,要用真实数据测

  • 维度、top_k、reranker、切分策略是“联动调参”的系统问题


第三阶段:向量数据库多维度对比(能力矩阵 + 索引原理 + 元数据)

3.1 存储能力矩阵与选择要点

文档给了一个很实用的矩阵(重点字段):

  • 是否存文本

  • 是否支持元数据过滤

  • 是否支持混合检索(稠密+稀疏)

  • 是否支持删除/更新

  • 持久化形态(本地文件/云/集群)

  • 部署复杂度

  • 典型场景

它覆盖了:

  • SimpleVectorStore

  • Chroma

  • Pinecone

  • Weaviate

  • Qdrant

  • Milvus

  • Faiss

并给出非常直接的场景化结论(大意):

  • 小规模/实验:SimpleVectorStore、Chroma

  • 本地高性能相似度:Faiss(但不管文本/元数据)

  • 云端高并发低延迟:Pinecone

  • 亿级向量/企业扩展:Milvus(但运维更重)

3.2 工作原理与索引类型(概念层)

这部分主要在讲:向量检索一般走 ANN(近似最近邻),不同库会实现不同索引结构;选型要结合“规模、延迟、召回率、更新频率”。

3.3 元数据建模与过滤

强调“检索不仅要找得近,还要找得对”:

  • 例子:source/section/page/lang/department/updated_at

  • 建议:

    • 元数据键名统一

    • 时间用 ISO 格式

    • 必要时做“路由层”:先按元数据决定命名空间/库,再做向量检索


第四阶段:LlamaIndex 向量数据库核心组件(StorageContext & VectorStoreIndex)

这部分是 LlamaIndex 内核理解:Index 不是单一东西,它背后有多种存储组件协作

4.1 StorageContext(统一管理四类存储)

核心作用:统一管理

  • vector_store(向量)

  • docstore(文本/节点)

  • index_store(索引元数据、结构)

  • graph_store(图结构/知识图谱用途)

并讲了典型用法:

  • StorageContext.from_defaults(vector_store=..., docstore=..., index_store=..., graph_store=...)

  • 应用重启后:

    • 若已持久化:从 storage 恢复 index

    • 否则:重新构建索引

4.2 VectorStoreIndex(向量检索索引)

强调它面向“语义检索/相似度查询”,并给出内部流程(文档用伪代码风格写了 4 步):

  1. 文档切成 nodes

  2. nodes 生成 embedding

  3. 写入向量数据库

  4. 构建索引结构

同时给出“文档问答”的典型链路:

  • index = VectorStoreIndex.from_documents(documents)

  • query_engine = index.as_query_engine()

  • response = query_engine.query(...)

4.3 两者协同关系

核心结论:

StorageContext 是底座(存储),VectorStoreIndex 是检索索引(逻辑),创建 index 时会自动使用 storage_context,查询时也会自动读取该上下文。


第五阶段:数据入库实现方式(多种向量库实战)

这是整份文档最“实战”的部分:把同一套 ingestion 流程落到不同后端。

5.0 数据读取与切分(通用入口)

  • 提供 smart_load(file_path):根据文件类型选择解析策略

    • 优先用 UnstructuredReader(LlamaIndex reader)

    • 失败/回退时用 unstructured.partition.auto.partition

  • 示例:加载一个证券研报 PDF:
    documents = smart_load("甬兴证券-AI行业点评报告....pdf")

切分:

  • SentenceSplitter(chunk_size=512, chunk_overlap=64, separator=" ")

  • nodes = splitter.get_nodes_from_documents(documents)

这一步非常关键:后续所有向量库写入、过滤、检索,都是围绕 nodes 展开的。


5.1 基于内存的向量数据库

对应 “快速实验/小规模”,通常就是 LlamaIndex 默认或简单存储方式(强调轻量、易上手)。

5.2 LlamaIndex + Chroma(持久化、可扩展)

核心步骤(代码展示得很完整):

  1. chroma_client = chromadb.PersistentClient(path="./chroma_db")

  2. collection = get_or_create_collection("my_collection")

  3. vector_store = ChromaVectorStore(chroma_collection=collection)

  4. storage_context = StorageContext.from_defaults(vector_store=vector_store)

  5. index = VectorStoreIndex(nodes, storage_context=storage_context)

  6. vector_store.persist(persist_path=db_path)

  7. query_engine = index.as_query_engine(); query_engine.query(...)

并演示了 元数据过滤检索

  • 构造 MetadataFilters

  • FilterOperator.EQ 过滤 element_type == "Text"

  • index.as_query_engine(filters=filters).query(...)

5.3 Pinecone(云服务)

主要强调 Pinecone Serverless 的适用场景:

  • 流量波动大(波峰波谷明显)

  • 初创/快速迭代,减少前期基础设施投入

  • dev/test 环境省成本

代码展示了:

  • pc = Pinecone(api_key=...)

  • 创建 index(dimension=1536,metric=cosine,serverless spec)

  • upsert(vectors=[(id, vector, metadata)], namespace="...")

  • 用 metadata 存 category/text

这里隐含了一个重要点:Pinecone 更偏“向量服务”,文本内容常依赖 metadata 或外部 docstore。

5.4 Milvus(本地部署/自托管)

文档给了 docker-compose 获取方式,并强调:

  • MilvusVectorStore 默认可以同时保存 text + vector + metadata(取决于模式/集成)

  • 支持元数据过滤示例(比如 year > 2000 的思路)

代码链路:

  • MilvusVectorStore(dim=1536, collection_name=..., uri="http://localhost:19530", overwrite=True)

  • storage_context = StorageContext.from_defaults(vector_store=vector_store)

  • index = VectorStoreIndex(nodes, storage_context=storage_context)

  • index.as_query_engine().query(...)

并演示过滤检索:

  • retriever = index.as_retriever(filters=..., similarity_top_k=5)

  • results = retriever.retrieve("...")

  • 打印 node 的 metadata 与 text

5.5 Faiss(本地高效相似度检索,但不存文本)

关键结论写得很明确:

  • Faiss 只管向量,不负责文本/元数据/删除

  • 文本要交给 LlamaIndex 的 docstore 管理

代码链路:

  • faiss.IndexFlatL2(d=1536)

  • FaissVectorStore(faiss_index=...)

  • VectorStoreIndex.from_documents(documents, storage_context=...)

  • vector_store.persist("./faiss_index.bin")

5.6 MongoDB Docstore + IndexStore(多索引共享节点)

这是一个偏“企业工程组合”的实践:

  • MongoDocumentStore:存 node text、metadata(docstore)

  • MongoIndexStore:存索引结构/元数据(index_store)

  • 向量仍可交给 Chroma(或其他 vector_store)

并强调:

这种组合常见:Mongo 管结构化与元数据,专用向量库管 ANN 检索;多个索引(SummaryIndex/VectorStoreIndex/TreeIndex)可以共享同一套 StorageContext。


第六阶段:两种持久化方法对比(Chroma 为例)

6.1 chromadb.PersistentClient(path=...)(数据库层级持久化)

特点总结:

  • 自动实时持久化、一致性更高

  • 频繁 I/O,资源消耗较高

  • 更偏生产可用

6.2 vector_store.persist(persist_path=...)(框架层级持久化)

特点总结:

  • 由 LlamaIndex/封装层触发 persist

  • 更可控(什么时候落盘由你决定)

  • 适合实验/批量写入场景


第七阶段:向量检索工具封装(面向 Agent)

这里的重点是:把“检索能力”包装成 Tool,让 Agent(ReAct)可调用。

文档给了一个工具对比表:

  • VectorDB:封装向量检索能力为工具(面向 Agent,底层是 VectorStoreIndex)

  • QueryEngineTool:封装 QueryEngine(面向 Agent,更偏“直接返回答案”)

  • ToolSpec:工具基础类(可自定义)

  • RetrieverQueryEngine:执行检索查询(不一定面向 Agent,更底层)

并给出选型建议(非常实用):

  • Agent 需要拿“原始片段”做后续决策/交给外部系统加工:用 VectorDB/VectorDBToolSpec

  • 希望 Agent 直接输出“答案”(检索+LLM汇总):用 QueryEngineTool

  • 做评估/调参/想拿 raw_scores、ids:直接用 RetrieverQueryEngine / retriever

代码展示了两条路线:

  1. RetrieverTool.from_defaults(retriever=..., name=..., description=...) + ReActAgent(tools=[...])

  2. VectorDB(...) + tool_spec.to_tool_list() + ReActAgent(...)


第八阶段:向量数据库进阶思考(安全/成本/运维)

8.1 安全与多租户(形态选择)

给出典型演进路径:

  • 单机(Chroma/Faiss)

  • 自托管集群(Qdrant/Milvus/Weaviate)

  • 云托管(Pinecone/Weaviate Cloud)

并强调运维现实:

  • 自托管(尤其 Milvus)往往需要 k8s 能力

  • 云托管省心,供应商负责升级/可用性

8.2 性能与成本优化(全链路思路)

核心理念总结得很“方法论”:

前置减负(模型/量化/降维)→ 中间加速(batch/cache)→ 后续精准(top_k + reranker)

具体建议包括:

  • 降维/模型选择:维度越高越贵,能用 512 就别硬上 1536(视精度而定)

  • 批处理与缓存:batch embedding、batch upsert;热点问题缓存

  • top_k 与重排:top_k 不要盲目大,用 reranker 提升前几条质量

  • 删除与更新:不支持删除(Faiss)就“软删除+重建”或旁路过滤;增量更新要去重、版本标记

8.3 部署与运维

强调:

  • 持久化与备份:快照、异地备份、版本化索引目录

  • 监控指标:QPS、p95/p99、召回质量漂移、存储占用、失败率

  • 定期 compaction / rebuild

(这一节在文档里与 8.1 有部分重复,但核心点就是这些。)


第九阶段:常见问题(FAQ 方向清单)

列的是工程落地中最容易踩坑的点(按主题):

  • Embedding 维度变更:存储膨胀、索引重建、兼容性迁移

  • 中英混合:语种路由、多语模型、切分是否保留标点

  • Chroma collection/目录组织:按业务域/部门/dev-prod 做命名空间

  • Faiss 无删除:重建或失效标记旁路过滤

  • Milvus 索引参数(IVF/HNSW/DiskANN):按规模、延迟、召回权衡

  • 云 API 限速:退避重试、并发控制、网络抖动处理


第十阶段:官网参考

最后给了一组主流向量库官网链接(Faiss/Milvus/Chroma/Pinecone/Qdrant/Weaviate),方便进一步查文档。


总体评价:这份 Notebook 的“可复用骨架”

如果把它抽象成一个可复用模板,主干就是:

  1. Load:smart_load(UnstructuredReader + partition 回退)

  2. Split:SentenceSplitter(chunk_size/overlap)

  3. Embed:Settings.embed_model(OpenAI 或 HuggingFace)

  4. Store:StorageContext + VectorStoreIndex(Chroma/Pinecone/Milvus/Faiss/Mongo 组合)

  5. Filter:MetadataFilters(EQ 等)

  6. Persist:DB层持久化 vs 框架层 persist

  7. Tool/Agent:RetrieverTool / VectorDB / QueryEngineTool

  8. Eval & Ops:hit_rate、MRR、top_k+reranker、监控与重建


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐