大模型技术-RAG 向量存储和检索 概述

19 阅读4分钟

在 LangChain 构建的 RAG(检索增强生成)应用中,**向量存储(Vector Stores)检索(Retrieval)**是紧密相连的两个阶段。

简单来说:向量存储是“把书放进图书馆并编好索引”,而检索是“根据问题从图书馆里快速找到相关的几页书”。


一、 向量存储 (Vector Stores)

大模型无法处理非结构化的长文本。向量存储的作用是将文本转化为数学向量(一组数字),并存储在专门的数据库中,以便进行“语义搜索”。

1. 工作原理

  1. 嵌入 (Embedding):利用 Embedding 模型(如 OpenAI、HuggingFace 或 Ollama 提供的模型)将文本块转化为高维向量。
  2. 存储:将这些向量连同原始文本内容和元数据(如来源、页码)存入向量数据库。
  3. 索引:数据库为这些向量建立索引,以便在数百万条数据中实现毫秒级的相似度查找。

2. 常用的向量数据库

  • Chroma / FAISS:轻量级,支持本地运行,非常适合开发调试和中小型应用。
  • Pinecone / Weaviate / Milvus:云端或企业级,支持海量数据和高并发,具备更强的生产环境特性。

二、 检索 (Retrieval)

检索是从向量库中提取相关信息的过程。LangChain 提供了多种“检索器”(Retrievers),它们比简单的相似度搜索更智能。

1. 基础检索:相似度搜索 (Similarity Search)

这是最基本的检索方式,寻找在数学空间中距离问题向量最近的文本块。

2. 高级检索策略(解决“搜不准”的问题)

  • MMR (Maximum Marginal Relevance):不仅考虑相关性,还考虑多样性。防止检索到的内容全是重复的内容。
  • 多查询检索 (Multi Query Retriever):让 LLM 将用户的一个模糊问题改写成三个不同的版本,分别去搜,然后取并集。
  • 父文档检索 (Parent Document Retriever):检索时搜索小的文本块(粒度细,匹配准),但返回给模型时提供更大的上下文(整段或整页),避免信息碎片化。

三、 代码示例:存储并检索

我们将展示如何使用 FAISS(本地库)存储一些关于“秘密配方”的信息,并进行检索。

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document

# 1. 准备数据
docs = [
    Document(page_content="秘制炸鸡的配方包括:面粉、红椒粉、大蒜粉和一种秘密香料。", metadata={"source": "厨房笔记"}),
    Document(page_content="炸鸡需要先在酸奶中浸泡2小时以增加嫩度。", metadata={"source": "厨师访谈"}),
    Document(page_content="波士顿的气温今天预计是25摄氏度。", metadata={"source": "天气预报"}),
]

# 2. 向量化并存储 (需要配置 OPENAI_API_KEY)
embeddings = OpenAIEmbeddings()
# 创建本地向量库
vectorstore = FAISS.from_documents(docs, embeddings)

# 3. 转化为检索器 (Retriever)
# search_kwargs={"k": 1} 表示只返回最相关的 1 条结果
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})

# 4. 执行检索
query = "炸鸡怎么做才嫩?"
relevant_docs = retriever.invoke(query)

# 5. 查看结果
for doc in relevant_docs:
    print(f"内容: {doc.page_content}")
    print(f"来源: {doc.metadata['source']}")

四、 检索与传统搜索的区别

特性传统搜索 (如 SQL/关键词)向量检索 (Vector Search)
匹配方式字面匹配(必须包含某个词)语义匹配(理解意思)
输入精确的关键词模糊的自然语言提问
例子搜“猫”,搜不到“小猫咪”问“宠物”,能搜到“猫”、“狗”
优势准确、适合搜 ID、日期智能、适合处理长文本和问答

五、 开发者建议

  1. 分块大小 (Chunk Size) 很关键:如果块太小,会丢失上下文;如果块太大,检索匹配度会下降。通常建议在 500-1000 字符之间。
  2. 关注 Embedding 质量:不同的 Embedding 模型效果差异巨大。如果你处理的是中文,建议使用 shibing624/text2vec-base-chinese 或 OpenAI 的最新模型。
  3. 持久化存储
    # 将向量库保存到本地磁盘
    vectorstore.save_local("faiss_index")
    # 下次使用时直接加载
    new_db = FAISS.load_local("faiss_index", embeddings)
    

总结:向量存储解决了“存”的问题,检索解决了“找”的问题。在 LangChain 中,通过灵活配置 Retriever,你可以显著提升 RAG 应用回答问题的准确度和深度。