004.大模型 RAG 嵌入向量数据库实战

一:向量数据库概念介绍

RAG 的入库流程,也称为索引构建或数据摄取(Ingestion),这个流程的核心目标是:将非结构化的文本数据,转化为结构化的、富含语义信息的“知识碎片”,并建立高效的索引,转化为大型语言模型(LLM)可以检索和利用的结构化知识库的过程。入库的质量直接决定了 RAG 系统检索的上限,一个高质量、易于检索的知识库,直接决定了您的大模型在回答特定领域问题时的准确性和可靠性。

Pasted image 20260716161017.png


二:Embedding 模型介绍

在检索增强生成(Retrieval-Augmented Generation, RAG)系统中,嵌入(Embedding)模型承担着将文本转换为向量表示的核心职责,直接决定检索质量的上限与整体系统的可扩展性。本节课围绕 LlamaIndex 框架,系统梳理与评估主流 Embedding 模型的集成路径、性能特征与成本结构,面向企业级落地给出可操作的选型策略与实施路线。

Pasted image 20260716161206.png

2.1. 主流 Embedding 模型对比(云 API vs 本地开源)

集成类型 典型依赖 配置要点 优势 注意事项
云端 API (OpenAI、Cohere) 对应 Python 客户端、API 密钥 通过 LlamaIndex 的 Embedding 类配置模型 ID 与参数;可设置 base_url 兼容自建兼容层 快速上线、免运维、弹性扩容 成本随调用量线性增长;需关注速率限制与数据出境合规
本地开源(HuggingFace / SentenceTransformers、BGE) sentence-transformers 或特定模型库;可选 ONNX / Optimum 通过 HuggingFaceEmbedding 等类加载;可配置最大序列长度、维度与指令模板;可导出 ONNX 加速 数据可控、长期 TCO 友好、可离线使用 初期工程投入较高;需自建服务与监控;硬件与吞吐需评估

2.2. 主流 Embedding 模型特性对比与中文推荐

模型系列 代表模型 维度 最大序列长度 (Tokens) 核心优势 主要适用场景
OpenAI text-embedding-3-large 3072 / 1536 / 512 8192 顶级通用语义理解、多语言能力强 高质量检索、复杂和多语言业务
OpenAI text-embedding-3-small 1536 / 512 8192 极高性价比、性能均衡 大规模索引、成本敏感型应用
Cohere embed-multilingual-v3.0 1024 512 强大的多语言能力,与 Rerank 模型生态协同好 全球化业务、需要高质量精排的场景
BGE (BAAI) BGE-M3 1024 8192 多功能(稠密、稀疏、多向量)、长文本、中英文强 混合检索、长文档问答、中英混合场景
M3E(Moka AI) m3e-base / m3e-large 768 8192 多语混合(中英优),长文本支持、检索表现强 企业多语种检索、中文主导场景、长文档问答
Jina AI jina-embeddings-v2-base-en 768 8192 性价比高,长文本支持好 预算有限但需要处理长文本的场景
智谱 AI Embedding-3 256 / 512 / 1024 / 2048 8 K 维度上进行多种选择 支持中文 / 英文混合、大段文本、甚至跨模态的语义检索
from llama_index.core.settings import Settings
import os
from llama_index.embeddings.openai import OpenAIEmbedding
from dotenv import load_dotenv

load_dotenv()

# 设置为全局默认 Embedding 模型
Settings.embed_model = OpenAIEmbedding(
    model="text-embedding-3-small",   # 模型的维度是 1536
    api_key=os.getenv("OPENAI_API_KEY"),
    api_base=os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
    dimensions=1536,        # 可控制返回向量的维度
    embed_batch_size=100,   # 控制批量处理文本时每个批次包含的文本数量,提高吞吐量,减少 API 的调用量
    timeout=60,             # 配合 batch size 设置合理超时
    max_retries=3           # 批量失败时的重试机制
)
# 将文本进行向量化
embeddings = Settings.embed_model.get_query_embedding("hello world")
print(len(embeddings))

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

Pasted image 20260716161934.png

2.4. 本地部署实践(HuggingFaceEmbedding)

集成类 依赖 关键特性 适用场景
HuggingFaceEmbedding sentence-transformers 通用包装,易用;可选 BGE、Instructor、E5 等模型 快速试用与通用本地检索
InstructorEmbedding Instructor + SentenceTransformers 指令模板区分 query 与 passage;增强语义区分 检索粒度要求高、指令可控场景
OptimumEmbedding transformers + Optimum[exporters] ONNX 导出与加速;跨平台兼容 吞吐优化、CPU / 边缘部署
from llama_index.core.settings import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

# 设置为全局默认 Embedding 模型
Settings.embed_model = HuggingFaceEmbedding(
    model_name='BAAI/bge-large-zh-v1.5',  # 模型名称,可以在魔搭社区或者 huggingface 上查询
    device="cpu",                         # 有显卡的使用 cuda:0
    embed_batch_size=64,                  # 控制批量处理文本时每个批次包含的文本数量,提高吞吐量,减少 API 的调用量
)

# 将文本进行向量化
embeddings = Settings.embed_model.get_query_embedding("hello world")
print(len(embeddings))

2.5. 评估指标定义与计算逻辑

指标 定义 计算逻辑 解释与适用场景
Hit Rate@k 前 k 条检索结果包含正确答案的是否命中 Hit Rate = 命中查询数 / 总查询数 衡量“能否找到”,适合召回充分性的对比
MRR@k 正确答案的首次出现位置的倒数,在前 k 条内的平均值 MRR = (1 / rank_i) 之和 / 总查询数,其中 rank_i 为第 i 个查询的正确答案首次排名 强调“找得准”,适合首条答案质量敏感的业务
from llama_index.core.evaluation import RetrieverEvaluator, generate_question_context_pairs
from llama_index.core.schema import TextNode

# 自定义测试数据
nodes = [
        TextNode(text="""在检索增强生成(RAG)系统中,文档切分与 Node 转换作为连接原始数据与语言模型的关键预处理环节,直接决定了系统的检索精度、生成质量及整体性能。行业实践数据表明,90% 的 RAG 效果问题源于元数据与分块策略不当,而通过优化分块策略可使检索准确率提升 30 - 50%,语义分块较固定分块的准确率优势可达 27%。这一技术环节的重要性体现在:分块过大易引入冗余噪音,增加语言模型理解负担;分块过小或切分不当则可能破坏语义连贯性,导致完整知识点被拆分;未能适配文档结构的机械分块方式还会忽视标题、列表等结构化信息,影响信息提取完整性。"""),
        TextNode(text="""LlamaIndex 作为连接自定义数据与大语言模型(LLMs)的核心框架,通过将文档(如 PDF、文本文件)分解为包含文本内容、向量嵌入和元数据的 Node 组件,构建了结构化文档管理的技术范式。其核心抽象在于将原始文档转换为语义连贯的 Node 集合,向量存储仅保留 Node 内容的嵌入向量与文本信息,这一机制简化了索引构建流程并提升了检索相关性。文档切分与 Node 转换的质量不仅影响向量检索的效率,更决定了上下文增强(Context Augmentation)这一 RAG 核心能力的实现效果。"""),
        TextNode(text="""本文聚焦文档切分与 Node 转换的技术实践,结合 LlamaIndex 框架的实现机制,系统调研分块策略设计、元数据管理及 Node 组件化等关键技术点。通过分析行业最佳实践与典型案例,旨在为 RAG 系统开发者提供可落地的优化方案,解决分块噪音、语义断裂、结构信息丢失等核心痛点,为构建高性能检索增强生成应用奠定技术基础。"""),
    ]

def load_corpus_and_queries():
    # 示例: 从文件加载语料与查询(实际实现需按企业数据格式适配)
    index = VectorStoreIndex(nodes, embed_model=Settings.embed_model)
    
    # 模拟用户提出的问题
    queries = ["在 RAG 系统中,文档切分与节点转换不当可能导致哪些具体问题?",
               "在 LlamaIndex 框架中,一个 Node 组件通常包含哪些核心元素?",
               "通过研究文档切分与 Node 转换,帮助 RAG 系统开发者解决哪些核心痛点?"]
    
    # 模拟正确答案的 node_id
    qrels = ['7c4ee258-36fa-4907-afe3-a7e3e894562a',
             '67b2fe9b-1a76-4ab2-9fb9-6b6581b1d440',
             '26fff0e9-2ecf-40ad-af7c-779e43c75762']
    return index, queries, qrels

index, queries, qrels = load_corpus_and_queries()
# 构建 Retriever(设置 top_k=5 返回前 5 个最相关节点)
retriever = index.as_retriever(similarity_top_k=5)

# 对查询进行检索
results = retriever.retrieve("在 RAG 系统中,文档切分与节点转换不当可能导致哪些具体问题?")
for i, r in enumerate(results):
    print(r.score, r.node.node_id, r.node.get_text()[:150])
    print("=" * 60)
retriever = index.as_retriever(similarity_top_k=5)

# 创建评估 Retriever
evaluator = RetrieverEvaluator.from_metric_names(
metric_names=["hit_rate", "mrr"],
retriever=retriever)

# 针对查询问题评估 Retriever
res1 = evaluator.evaluate(
    "在 RAG 系统中,文档切分与节点转换不当可能导致哪些具体问题?",
    expected_ids = ["7c4ee258-36fa-4907-afe3-a7e3e894562a"]
)
print(res1)

res2 = evaluator.evaluate(
    "在 RAG 系统中,文档切分与节点转换不当可能导致哪些具体问题?",
    expected_ids = ["67b2fe9b-1a76-4ab2-9fb9-6b6581b1d440"]
)
print(res2)

res3 = evaluator.evaluate(
    "在 RAG 系统中,文档切分与节点转换不当可能导致哪些具体问题?",
    expected_ids = ["26fff0e9-2ecf-40ad-af7c-779e43c75762"]
)
print(res3)

在实际 RAG 评估中的应用建议

2.6. 模型使用思考


三:向量数据库多维度对比

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

向量存储 存储文本 元数据过滤 混合检索 删除/更新 持久化形态 部署复杂度 典型场景
SimpleVectorStore 是(默认内存,可持久化) 支持(框架层过滤) 依赖后端能力 支持删除与持久化 本地文件 快速实验、本地小规模
Chroma 支持(集合中管理文本与元数据) 支持 部分能力(依实现与查询) 支持 add / update / upsert / delete 本地 / 持久化 / 容器 开发者友好、本地到中小规模
Pinecone 否(侧重向量;文档内容依赖外部存储) 支持 支持(稠密 / 稀疏 / 混合) 支持删除与命名空间清理 云托管(Serverless) 低 - 中 云端高并发、低延迟
Weaviate 支持(集合中管理对象与文本) 支持 支持(与 BM25 等稀疏结合) 支持(动态批处理) 自托管 / 云 现有集群集成、混合检索
Qdrant 支持(集合中管理 payloads) 支持 支持(稠密 + BM25) 支持(集合级操作) 自托管 / 云 混合检索、性能取向
Milvus 依集成与模式(向量为主) 支持(字段过滤) 依索引与实现 支持(集合 / 分区级) 自托管 / 云 中 - 高 亿级向量、毫秒级检索
Faiss 否(仅存储向量) 删除未实现 本地文件 本地高效相似度搜索

3.2. 工作原理与索引类型

3.3. 元数据建模与过滤

from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters
from llama_index.core import VectorStoreIndex

nodes = [
        TextNode(
            text=(
                "HR 年假政策:员工入职未满一年按入职月数按比例计算年假。"
            ),
            metadata={
                "department": "HR",
                "lang": "zh",
                "source": "policy_hr_2024.md",
                "section": "leave_policy",
                "page": 1,
                "updated_at": "2024-08-01",
            },
        ),
        TextNode(
            text=(
                "年假计算口径:以自然年为周期,离职结算时按实际在岗月份折算。"
            ),
            metadata={
                "department": "HR",
                "lang": "zh",
                "source": "policy_hr_2024.md",
                "section": "leave_policy",
                "page": 2,
                "updated_at": "2024-08-01",
            },
        ),
        TextNode(
            text=(
                "请假流程:OA 系统提交 → 直属主管审批 → HR 备案。"
            ),
            metadata={
                "department": "HR",
                "lang": "zh",
                "source": "process_hr_oa.md",
                "section": "leave_process",
                "page": 1,
                "updated_at": "2024-07-15",
            },
        ),
        TextNode(
            text=(
                "IT 资产借用流程:工单申请 → IT 审批 → 资产出库。"
            ),
            metadata={
                "department": "IT",
                "lang": "zh",
                "source": "process_it_asset.md",
                "section": "asset_borrow",
                "page": 1,
                "updated_at": "2024-06-10",
            },
        ),
    ]

# 构建索引
index = VectorStoreIndex(nodes)
# 定义过滤器
filters = MetadataFilters(filters=[
    ExactMatchFilter(key="department", value="HR"),
    ExactMatchFilter(key="lang", value="zh"),
])
# 应用过滤器
qe = index.as_query_engine(similarity_top_k=3, filters=filters)
print(qe.query("年假政策的计算口径?"))

四:LlamaIndex 向量数据库核心组件

4.1. 核心组件 StorageContext 存储

核心作用:统一管理向量索引涉及的多种存储组件(向量、文档、索引元数据、图结构)。

from llama_index.core import StorageContext

# 创建 StorageContext 的典型方式
storage_context = StorageContext.from_defaults(
    vector_store=vector_store,      # 向量存储
    docstore=docstore,              # 文档存储
    index_store=index_store,        # 索引元数据存储
    graph_store=graph_store         # 图结构存储(用于知识图谱)
)

主要功能:多存储组件协调

# 管理四种核心存储类型
storage_context = StorageContext.from_defaults(
    vector_store=ChromaVectorStore(chroma_collection),  # 向量嵌入存储
    docstore=SimpleDocumentStore(),                     # 原始文档内容存储
    index_store=SimpleIndexStore(),                     # 索引元数据存储
    graph_store=SimpleGraphStore()                      # 节点关系存储
)

数据持久化与恢复

# 应用重启后恢复索引状态
if os.path.exists("./storage"):
    storage_context = StorageContext.from_defaults(persist_dir="./storage")
    index = load_index_from_storage(storage_context)
else:
    # 重新构建索引
    storage_context = StorageContext.from_defaults(vector_store=vector_store)
    index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

4.2. VectorStoreIndex(向量存储索引)

核心作用:基于向量相似性搜索的索引实现,服务语义搜索与相似度查询。

from llama_index.core import VectorStoreIndex

# 创建向量索引
index = VectorStoreIndex.from_documents(
    documents,
    storage_context=storage_context,
    embed_model=embed_model,
    show_progress=True
)

文档分割与节点创建

# 自动处理文档分割和节点创建
index = VectorStoreIndex.from_documents(
    documents,
    chunk_size=512,           # 文本分块大小
    chunk_overlap=50,         # 块之间重叠
    embed_model=embed_model   # 嵌入模型
)

相似性搜索接口

# 创建查询引擎
query_engine = index.as_query_engine(
    similarity_top_k=5,        # 返回最相似的 5 个结果
    response_mode="compact"    # 响应模式
)

response = query_engine.query("你的查询问题")

内部工作机制(示意)

# VectorStoreIndex 的核心处理流程
class VectorStoreIndex:
    def from_documents(self, documents):
        # 1. 文档分割成节点
        nodes = self._split_documents(documents)
        # 2. 为节点生成嵌入向量
        embeddings = self._generate_embeddings(nodes)
        # 3. 存储到向量数据库
        self._store_embeddings(nodes, embeddings)
        # 4. 构建索引结构
        self._build_index_structure()
        return self

适用场景

# 文档问答系统
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("人工智能的发展历史?")

大规模文档检索

# 处理大量文档
index = VectorStoreIndex.from_documents(
    large_document_collection,
    storage_context=storage_context,  # 使用外部向量数据库
    show_progress=True
)

基于内容的推荐

retriever = index.as_retriever(similarity_top_k=10)
similar_items = retriever.retrieve("用户偏好内容")

4.3. 两者协同工作关系

组件 职责 数据流向
StorageContext 存储管理、持久化、多存储协调 向下管理具体存储后端
VectorStoreIndex 索引构建、查询处理、相似性计算 向上提供查询接口

典型工作流程

# 1. 初始化存储组件
vector_store = ChromaVectorStore(chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# 2. 创建向量索引(自动使用 storage_context)
index = VectorStoreIndex.from_documents(
    documents,
    storage_context=storage_context,
    embed_model=OpenAIEmbedding()
)

# 3. 查询时自动利用存储上下文
query_engine = index.as_query_engine()
response = query_engine.query("查询问题")

五:数据入库实现方式

数据读取

from llama_index.core.text_splitter import SentenceSplitter

# 初始化 TokenTextSplitter
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=64, separator=" ")
nodes = splitter.get_nodes_from_documents(documents)   # 将 docs -> nodes(每个 node 可嵌入)
from llama_index.llms.openai import OpenAI

# 设置为全局默认 LLM
Settings.llm = OpenAI(
    # model="gpt-3.5-turbo",
    model="gpt-4-turbo",
    api_key=os.getenv("OPENAI_API_KEY"),
    api_base=os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
)

5.1. 基于内存的向量数据库实现

from llama_index.core import VectorStoreIndex, StorageContext

# 1. 构建 VectorStoreIndex(内存)基于 documents
index = VectorStoreIndex.from_documents(documents, text_splitter=splitter)

# 直接基于 nodes 构建索引
# index = VectorStoreIndex(nodes)

# 2. 索引持久化
index.storage_context.vector_store.persist("vector_store.json")

# 3. 加载缓存过的向量索引
# ctx = StorageContext.from_defaults(persist_dir="vector_store.json")
# index = VectorStoreIndex.from_documents(documents, storage_context=ctx)

# 4. 查询(QueryEngine 由 index.build_query_engine() 提供)
query_engine = index.as_query_engine()
resp = query_engine.query("请用中文总结这些文档的主要内容")
print(resp)

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

import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import VectorStoreIndex, StorageContext
import os

# 1. 创建数据库目录并初始化 Chroma 客户端
db_path = "./chroma_db"  # 指定数据库路径
os.makedirs(db_path, exist_ok=True)  # 确保目录存在

try:
    # 数据库层级持久化,构建索引后 - 数据会自动持久化
    chroma_client = chromadb.PersistentClient(path=db_path)  # 指定路径的持久化客户端
except Exception as e:
    # 如果持久化客户端失败,尝试使用内存客户端
    chroma_client = chromadb.Client()

# 2. 创建或获取集合(处理集合已存在的情况)
collection_name = "my_collection"
try:
    chroma_collection = chroma_client.get_or_create_collection(collection_name)
except Exception as e:
    # 尝试删除并重新创建
    try:
        chroma_client.delete_collection(collection_name)
        chroma_collection = chroma_client.create_collection(collection_name)
    except Exception as e2:
        raise e2

# 3. 创建 ChromaVectorStore 实例
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)

# 4. 配置存储上下文
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# 5. 构建索引并查询,基于向量相似度进行召回
# index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
index = VectorStoreIndex(nodes, storage_context=storage_context)

# 6. 持久化(Chroma 会在内部 persist)需要手动调用 persist 来保存数据
vector_store.persist(persist_path=db_path)
# 保存 index metadata(可选)
# index.storage_context.persist(persist_dir="./index_storage")

query_engine = index.as_query_engine()
response = query_engine.query("请用中文总结这些文档的主要内容")
print(f"模型回答:{response}")

chroma 数据持久化展示

Pasted image 20260716173239.png

index 存储展示

Pasted image 20260716173256.png

MetadataFilters 元数据过滤器

from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core.vector_stores import MetadataFilter, MetadataFilters, FilterCondition, FilterOperator

import chromadb

# 1. 加载 Chroma 向量数据库
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_collection("my_collection")
vector_store = ChromaVectorStore(chroma_collection=collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# 2. 加载文档并构建索引
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
# 3. 单个过滤:只看 element_type = Text
filters = MetadataFilters(
    filters=[
        MetadataFilter(key="element_type", value="Text", operator=FilterOperator.EQ),
    ],
    condition=FilterCondition.AND
)
# 4. 应用过滤后的查询引擎
query_engine = index.as_query_engine(filters=filters)
resp = query_engine.query("AI海外企业有哪些巨头巨头企业?")
print(resp)

5.3. Pinecone 云服务数据库

Pinecone Serverless 非常适合流量波动大的应用场景,例如:

Pasted image 20260716173529.png

import os
from dotenv import load_dotenv
from pinecone import Pinecone
load_dotenv()

# 1 初始化 Pinecone,需要申请官网的 PINECONE_API_KEY
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
import time
# 设置索引名称和向量维度
index_name = "my-first-index"
# 维度必须与你后续使用的嵌入向量模型匹配
dimension = 1536

# 1. 创建索引
# 检查索引是否已存在,不存在则创建
if index_name not in pc.list_indexes().names():
    pc.create_index(
        name=index_name,
        dimension=dimension,  # 维度必须与你后续使用的嵌入向量模型匹配
        metric="cosine",       # 相似度计算方式,常用 cosine, euclidean, dotproduct
        spec={                 # 选择免费套餐适用的 serverless 规格
          "serverless": {
            "cloud": "aws",
            "region": "us-east-1"
          }
        }
    )
    # 等待索引准备就绪
    time.sleep(10)
else:
    # 如果索引已存在,先删除它
    pc.delete_index(index_name)
    # 然后创建新索引
    pc.create_index(
        name=index_name,
        dimension=dimension,  # 维度必须与你后续使用的嵌入向量模型匹配
        metric="cosine",       # 相似度计算方式,常用 cosine, euclidean, dotproduct
        spec={                 # 选择免费套餐适用的 serverless 规格
          "serverless": {
            "cloud": "aws",
            "region": "us-east-1"
          }
        }
    )
    # 等待索引准备就绪
    time.sleep(10)

# 2. 连接到索引
index = pc.Index(index_name)

# 3. 准备并插入数据(向量)
# 这里插入 3 个简单的示例向量,每个向量是 1536 维
sample_vectors = [
    ("vec1", Settings.embed_model.get_query_embedding(documents[0].text), {"category": "Title", "text": documents[0].text}),
    ("vec2", Settings.embed_model.get_query_embedding(documents[1].text), {"category": "Text", "text": documents[1].text}),
    ("vec3", Settings.embed_model.get_query_embedding(documents[2].text), {"category": "Text", "text": documents[2].text})
]

# 4. 使用 upsert 方法插入数据
index.upsert(vectors=sample_vectors, namespace="example-namespace")

# 短暂等待数据被处理
time.sleep(5)

建立索引效果展示

Pasted image 20260716173745.png

Pinecone 的 upsert 操作是 "insert or update" 的组合:

多租户隔离

import os
from pinecone import Pinecone, ServerlessSpec
from llama_index.vector_stores.pinecone import PineconeVectorStore
from llama_index.core import VectorStoreIndex, StorageContext

# 1 初始化 Pinecone
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])

# 2 创建索引
index_name = "my-first-index"
pinecone_index = pc.Index(index_name)

# 3 向量存储与索引
vector_store = PineconeVectorStore(
    pinecone_index=pinecone_index,
    namespace="default",  # 多租户隔离
    batch_size=100,       # 批量 upsert
    add_sparse_vector=False,
)

# 4 加载存储上下文
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# 5 构建索引
# index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
index = VectorStoreIndex(nodes, storage_context=storage_context)

# 6 查询
query_engine = index.as_query_engine()

response = query_engine.query("请用中文总结这些文档的主要内容")
print(f"模型回答:{response}")

多租户效果展示

Pasted image 20260716173953.png

数据查询展示

Pasted image 20260716174007.png

5.4. Milvus 数据库本地部署存储

下载安装 milvus 的 docker-compose 文件

docker-compose.yml 文件展示

Pasted image 20260716174135.png

from llama_index.vector_stores.milvus import MilvusVectorStore
from llama_index.core import  VectorStoreIndex, StorageContext

# 1. 加载文档并构建索引
vector_store = MilvusVectorStore(
    dim=1536,
    collection_name="milvus_collection",
    uri="http://localhost:19530",
    overwrite=True
)
# 2. 从向量数据库构建索引
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# 3. 构建索引
# index = VectorStoreIndex.from_documents(documents,  storage_context=storage_context)
index = VectorStoreIndex(nodes,  storage_context=storage_context)

# 4. 查询
milvus_response = index.as_query_engine().query("请用中文总结这些文档的主要内容")
milvus_response.response

使用 MetadataFilter 进行过滤查询

from llama_index.core.vector_stores import MetadataFilter, MetadataFilters, FilterOperator

# 定义 MetadataFilter 进行过滤查询
filters = MetadataFilters(filters=[
    MetadataFilter(key="element_type", value="Text", operator=FilterOperator.EQ)
])
# 执行过滤查询
retriever = index.as_retriever(filters=filters, similarity_top_k=5)

# 输入检索文本
results = retriever.retrieve("龙头公司中报业绩")

# 打印查询结果
for node in results:
    print(node.metadata)
    print(node.text)
    print("=" * 60)

5.5. Faiss 本地高效检索,不存储文本

import faiss
from llama_index.vector_stores.faiss import FaissVectorStore
from llama_index.core import VectorStoreIndex, StorageContext

# 1 创建 Faiss 索引(此处为 L2 距离的 Flat Index)
d = 1536
faiss_index = faiss.IndexFlatL2(d)
vector_store = FaissVectorStore(faiss_index=faiss_index)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

# 2 构建索引(注意: Faiss 不存储文本, 文本需由 Docstore 管理)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

# 3 持久化向量索引到本地文件
vector_store.persist("./faiss_index.bin")

# 4 查询
query_engine = index.as_query_engine()
response = query_engine.query("请用中文总结这些文档的主要内容")
print(response)

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

结论:你已把文档 / 索引元数据放在 Mongo,本地 Chroma 负责向量。这是一种常见组合(Mongo 负责结构化数据 & metadata,专用向量 DB 负责 ANN 检索)。

import os
from llama_index.core import StorageContext, SummaryIndex, VectorStoreIndex, TreeIndex
from llama_index.storage.docstore.mongodb import MongoDocumentStore
from llama_index.storage.index_store.mongodb import MongoIndexStore

# 1 连接 MongoDB (通过 MONGO_URI)
# MONGO_URI = os.environ.get("MONGO_URI", "mongodb://localhost:27017")

# 设置 MongoDB 连接参数
MONGO_HOST = os.environ.get("MONGO_HOST", "localhost")
MONGO_PORT = os.environ.get("MONGO_PORT", "27017")
MONGO_USERNAME = os.environ.get("MONGO_USERNAME", "root")
MONGO_PASSWORD = os.environ.get("MONGO_PASSWORD", "example123")
MONGO_DATABASE = os.environ.get("MONGO_DATABASE", "my_database")

# 构建带认证的连接字符串
MONGO_URI = f"mongodb://{MONGO_USERNAME}:{MONGO_PASSWORD}@{MONGO_HOST}:{MONGO_PORT}/{MONGO_DATABASE}?authSource=admin"

# 连接 MongoDB
docstore = MongoDocumentStore.from_uri(uri=MONGO_URI)
index_store = MongoIndexStore.from_uri(uri=MONGO_URI)

# 向量存储使用 Chroma
chroma_client = chromadb.PersistentClient(path="./chroma_db")
vector_store = ChromaVectorStore(chroma_collection=chroma_client.get_or_create_collection("docs"))
storage_context = StorageContext.from_defaults(
    docstore=docstore,         # 文档存储
    index_store=index_store,   # 索引元数据存储
    vector_store=vector_store  # 向量存储
)

# 2 构建多索引(共享同一组节点)
# summary_index = SummaryIndex(nodes, storage_context=storage_context)
# vector_index = VectorStoreIndex(nodes, storage_context=storage_context)

# 摘要索引
summary_index = SummaryIndex.from_documents(documents, storage_context=storage_context)
# 向量索引
vector_index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
# 树索引
tree_index = TreeIndex.from_documents(documents, storage_context=storage_context)

# 3 查询
summary_engine = summary_index.as_query_engine()
vector_engine = vector_index.as_query_engine()
tree_engine = tree_index.as_query_engine()

s = summary_engine.query("请用中文总结这些文档的主要内容")
v = vector_engine.query("请用中文总结这些文档的主要内容")
t = tree_engine.query("请用中文总结这些文档的主要内容")

print(s.response)
print("=" * 60)
print(v.response)
print("=" * 60)
print(t.response)

六:两种持久化方法对比

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

import chromadb
# 数据库层级的持久化
chroma_client = chromadb.PersistentClient(path="./chroma_db")

特点:自动实时持久化,数据一致性更高;频繁 I/O,资源消耗较高,适合生产。

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

from llama_index.vector_stores.chroma import ChromaVectorStore

# 框架层级的持久化
chroma_client = chromadb.PersistentClient(path="./chroma_db")
vector_store = ChromaVectorStore(chroma_collection=chroma_client.get_or_create_collection("docs"))
# 或者显式调用
vector_store.persist(persist_path="./chroma_db")

七:向量检索工具封装

VectorDB 是 LlamaIndex 提供的一个 向量数据库工具封装类,它继承自 BaseToolSpec

它不是直接用来检索的,而是把一个“向量检索能力”包装成一个可调用工具(ToolSpec);之后,你可以在 AgentQueryEngineTool、或者多工具组合系统(Multi-Tool Agent)中直接使用; 它能让大语言模型通过自然语言调用底层向量检索逻辑(例如 Milvus、Pinecone、FAISS 等);同时保留了 LlamaIndex 原有的过滤、权重和组合能力。

使用场景 说明
Agent 工具集成 让一个 LLM(如 GPT)能通过自然语言调用“知识库检索”功能。
多模态或多知识源融合 当系统有多个 VectorIndex(例如“报告知识库”“产品知识库”),可以给每个建一个 VectorDB,并交给 Agent 动态选择调用。
自定义 Query Engine 集成 将 VectorDB 与 RetrieverQueryEngine 或 RouterQueryEngine 组合,实现多源路由检索。
企业内部知识问答系统 通常配合 Milvus / Pinecone / MongoDB Vector Store 使用,将不同业务库做成不同 Tool。
from llama_index.core import VectorStoreIndex
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import QueryEngineTool
from llama_index.core.workflow import Context
from llama_index.vector_stores.milvus import MilvusVectorStore

# 1. 加载已有 Milvus / Mongo 向量数据库
milvus_vector_store = MilvusVectorStore(
    dim=1536,
    collection_name="milvus_collection",
    uri="http://localhost:19530",
    overwrite=True
)
# 2. 从向量数据库构建索引
storage_context = StorageContext.from_defaults(vector_store=milvus_vector_store)
vector_index = VectorStoreIndex(nodes,  storage_context=storage_context)

# 3. 构建查询引擎
query_engine = vector_index.as_query_engine(similarity_top_k=4)

# 4. 封装为向量数据库检索 tool 工具
vector_tool = QueryEngineTool.from_defaults(
    query_engine=query_engine,  # 简化示例: 将其封装为查询引擎工具
    name="vector_auto_retrieve",
    description="对向量数据库进行自动检索并应用元数据过滤"
)

# 5. 创建 Agent(ReActAgent 演示),异步执行,可以使用 asyncio.run() 来执行
agent = ReActAgent(tools=[vector_tool], llm=Settings.llm)
ctx = Context(agent)

# 6. 调用示例
handler = agent.run("请检索向量数据库中关于海外AI龙头企业有哪几家?", ctx=ctx)

可自定义向量元数据

from llama_index.tools.vector_db import VectorDB
from llama_index.core.agent import ReActAgent
from llama_index.core.vector_stores import VectorStoreInfo, MetadataInfo
from llama_index.core.tools import ToolMetadata

# 1. 加载已有 Milvus / Mongo 向量数据库
milvus_vector_store = MilvusVectorStore(
    dim=1536,
    collection_name="milvus_collection",
    uri="http://localhost:19530",
    overwrite=True
)

# 2. 从向量数据库构建索引
storage_context = StorageContext.from_defaults(vector_store=milvus_vector_store)
vector_index = VectorStoreIndex(nodes,  storage_context=storage_context)

# 3. 初始化 VectorDB 封装为工具
tool_spec = VectorDB(index=vector_index)

# 4. 可以定义向量数据库的相关元数据信息
# vector_store_info = VectorStoreInfo(
#     content_info="公司公告与研报摘要、标题与正文片段",
#     metadata_info=[
#         MetadataInfo(
#             name="element_type",
#             type="str",
#             description="文档元素类型,例如 Title、Paragraph 等",
#         ),
#         MetadataInfo(
#             name="year",
#             type="int",
#             description="文档年份",
#         ),
#     ],
# )

# 5. 将 VectorDB 转换为工具列表
# tools = tool_spec.to_tool_list(
#     func_to_metadata_mapping={
#         "auto_retrieve_fn": ToolMetadata(
#             name="kb_retrieve",
#             description=f"""用于从向量库检索公司公告与研报相关内容。
#             向量库 Schema:
#             {vector_store_info.json()}
#             {tool_spec.auto_retrieve_fn.__doc__}
#             """,
#         )
#     }
# )

# 6. 创建 Agent
agent = ReActAgent(
    tools=tool_spec.to_tool_list(),   # 工具列表
    llm=Settings.llm, # LLM
    verbose=True,  # 输出详细信息
)

# 7. 异步运行(ReActAgent 的 run 为 async)
result = agent.run("请检索有关 AI 行业动向的两条信息")

RetrieverTool 检索器工具

from llama_index.core.tools import RetrieverTool
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI

# 1. 构建检索器
retriever = vector_index.as_retriever(similarity_top_k=5)

# 2. 封装为检索工具
retr_tool = RetrieverTool.from_defaults(
    retriever=retriever,
    name="文档片段检索",
    description="直接检索相关文档片段"
)

# 3. 创建 Agent
agent = ReActAgent(tools=[retr_tool], llm=Settings.llm, verbose=True)

# 4. 异步运行(ReActAgent 的 run 为 async)
response = agent.run("筛选包含 Title 的片段并返回内容")

与其他工具类对比

工具类 作用 是否面向 Agent 使用底层
VectorDB 封装向量检索能力为工具 VectorStoreIndex
QueryEngineTool 封装 QueryEngine,为多源检索设计 QueryEngine
ToolSpec 所有工具的基础类 任意能力(可自定义)
RetrieverQueryEngine 执行检索查询 Retriever

八:向量数据库进阶思考

8.1. 安全与多租户

在构建基于 RAG(检索增强生成)等 AI 应用时,向量数据库的安全性与多租户能力是确保系统稳定、可靠、合规的基石。多租户架构的核心目标是让多个租户(可以是不同部门、不同业务线或不同客户)共享同一套系统,但保证每个租户的数据、配置和性能表现是相互隔离的。

8.2. 性能与成本优化

向量数据库的优化是一个系统工程,贯穿了从数据准备、入库到查询的全链路。核心思路在于:“前置减轻负担,中间加速处理,后续精准打击”。 前置:通过合适的模型和量化技术,从源头减少数据体积。 中间:利用批处理和缓存,提升系统整体的吞吐量和响应速度。 后续:在检索时,通过 top_k 与 Reranker 的配合,以最小成本获取最佳答案。

8.3. 部署与运维


九: 常见问题


十:官网参考

各主流向量数据库官网地址