RAG 实操教程:使用 LangChain + Milvus 构建本地知识库
本文是 Milvus 向量数据库学习的总结篇,旨在通过实战打造自己的本地知识库系统。我们将深入探讨检索增强生成(RAG)技术,并演示如何使用 LangChain 框架结合 Milvus 向量数据库实现基于私有文档的智能问答。
一、RAG 是什么
RAG(Retrieval-Augmented Generation)即检索增强生成。其核心思想是将大语言模型(LLM)与外部知识库相结合。当用户提问时,系统先从外部知识库中检索相关信息,然后将这些信息作为上下文提供给 LLM,由 LLM 基于这些准确的信息生成回答。
这种方法解决了传统 LLM 仅依赖训练数据的问题,使其能够访问最新、最准确的数据。
二、LLM 的痛点与挑战
现有的开源或商业 LLM 通常基于网络公开数据进行训练,这带来了以下主要痛点:
- 知识滞后性:模型的训练数据截止于特定时间点,无法知晓最新的新闻、政策或技术更新。
- 私有数据缺失:企业内部的规章制度、业务文档、代码库等私有数据具有极高价值且涉及安全,无法直接用于公共模型训练,导致 LLM 无法回答企业内部问题。
- 幻觉问题:当面对未知问题时,LLM 可能会产生'幻觉',编造看似合理但实际错误的答案,严重影响可信度。
三、为什么选择 RAG
针对上述问题,提升 LLM 能力主要有三种路径:
- Prompt Engineering(提示工程):通过优化输入提示词来引导模型输出。例如 In-context Learning,在提示中提供示例或上下文。优点是成本低,但受限于模型本身的参数容量和上下文窗口限制。
- Fine-tuning(微调):在特定数据集上重新训练模型参数。适用于让模型学习特定的风格或领域知识。缺点是成本高、周期长,且难以快速迭代新数据,容易遗忘旧知识(灾难性遗忘)。
- RAG(检索增强生成):不修改模型参数,而是外挂知识库。检索系统从数据库提取信息,LLM 基于此生成答案。
RAG 的核心优势:
- 准确性:通过引用外部事实来源,显著减少虚假信息。
- 及时性:知识库可以随时更新,LLM 能获取最新信息。
- 可解释性:可以追溯信息来源,增强用户信任。
- 成本效益:无需频繁微调模型,只需更新向量数据库。
- 安全性:敏感数据存储在私有数据库中,不泄露给公共模型。
四、环境准备与安装
本教程将使用 Python 生态进行开发。首先安装必要的依赖库。
1. 安装 LangChain 及相关组件
pip install langchain
pip install langchain-community
pip install langchain-core
pip install langchain-cli
pip install --upgrade --quiet pypdf
2. 安装 Milvus 客户端
Milvus 是一个高性能的向量数据库。我们需要安装 Python SDK。
pip install pymilvus
确保你的本地或服务器已部署好 Milvus 服务(默认端口 19530)。
五、文档加载与处理
构建知识库的第一步是将非结构化数据(如 PDF)转化为模型可理解的文本。
1. 文档加载器
LangChain 提供了丰富的文档加载器,支持 txt、pdf、html、url 等多种格式。我们这里以 PDF 为例。
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader
file_path = 'CodeGeeX 模型 API.pdf'
loader = PyPDFLoader(file_path=file_path)
documents = loader.load()
2. 文本分块(Chunking)
由于 LLM 的上下文窗口有限,需要将长文档拆分为较小的片段(Chunks)。
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
docs = text_splitter.split_documents(documents)
参数调优建议:
chunk_size:过小会导致信息碎片化,过大则增加 Token 消耗且可能超出上下文窗口。通常根据模型支持的上下文长度调整。
chunk_overlap:设置为 100-200 左右较为常见,防止关键信息在切分时被切断,避免语义歧义。
六、向量化与存储
将文本转换为向量(Embedding),并存入向量数据库。
1. Embedding Model
Embedding 模型负责将文本映射为高维向量。可以使用云服务商提供的 API(如 Azure OpenAI)或本地部署的开源模型(如 BGE、M3E)。
from langchain_openai import AzureOpenAIEmbeddings
import os
embeddings = AzureOpenAIEmbeddings(
azure_deployment="text-embedding-ada-002",
openai_api_version="2024-03-01-preview"
)
2. 存入 Milvus
LangChain 封装了 Milvus 的接口,方便直接保存。
from langchain_community.vectorstores import Milvus
vector = Milvus.from_documents(
documents=docs,
embedding=embeddings,
collection_name="local_knowledge_base",
drop_old=True,
connection_args={"host": "127.0.0.1", "port": "19530"},
)
在此过程中,Milvus 会自动创建索引(Index),以便加速相似性搜索。常用的指标类型包括 COSINE(余弦相似度)、L2(欧氏距离)等。
七、构建 RAG 聊天链路
准备工作就绪后,我们可以构建完整的问答链。
1. 角色设定与 Prompt
通过 Prompt 模板定义 AI 助手的角色和行为准则。
from langchain_core.prompts import ChatPromptTemplate
template = """You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say that you don't know.
Question: {question}
Context: {context}
Answer:"""
prompt = ChatPromptTemplate.from_template(template)
2. 链式调用(Chain)
利用 LangChain 的 Runnable 机制串联检索器和模型。
from langchain_openai import AzureChatOpenAI
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
llm = AzureChatOpenAI(
azure_deployment=os.environ.get('AZURE_DEPLOYMENT_NAME_GPT35')
)
retriever = vector.as_retriever(search_kwargs={"k": 3})
chain = (
RunnableParallel({"context": retriever, "question": RunnablePassthrough()})
| prompt
| llm
| StrOutputParser()
)
这里的逻辑是:
- 接收用户输入
question。
- 并行执行:将
question 传给检索器获取 context,同时保留 question。
- 将两者填入 Prompt 模板。
- 发送给 LLM 生成回答。
- 解析输出字符串。
八、测试与验证
1. 基础问答测试
question = "CodeGeeX 模型 API 参数有哪些?"
answer = chain.invoke(question)
print(answer)
预期输出应包含具体的 API 参数说明,如 prompt, max_tokens, temperature 等。
2. 复杂场景测试
question = "请给一个 chat 模型非流式请求示例"
answer = chain.invoke(question)
print(answer)
3. 结果评估
在实际生产中,建议引入评估指标(如 RAGAS 框架)来衡量回答的忠实度(Faithfulness)和答案相关性(Answer Relevance)。
九、最佳实践与注意事项
- 数据安全:API Key 应存储在环境变量中,切勿硬编码在代码里。生产环境建议使用密钥管理服务(如 Vault)。
- 索引优化:对于大规模数据,Milvus 的索引类型(如 HNSW, IVF_FLAT)会影响查询速度和精度,需根据数据量级调整。
- 混合检索:单纯向量检索可能丢失关键词匹配能力,建议结合 BM25 等稀疏检索算法进行混合排序。
- 缓存机制:对于高频重复问题,可在应用层增加 Redis 缓存,降低 LLM 调用成本和延迟。
- 错误处理:在代码中增加 try-except 块,处理网络超时或数据库连接失败的情况,保证服务稳定性。
十、总结
本文详细讲解了如何利用 LangChain 和 Milvus 构建本地知识库系统。通过 RAG 架构,我们成功解决了 LLM 知识滞后和私有数据不可用的问题。
核心流程包括:
- 文档加载与清洗
- 文本分块策略
- 向量化嵌入
- 向量数据库存储
- 检索增强生成链路
掌握这一技术栈,开发者可以快速为企业搭建智能客服、内部知识库助手等应用场景,显著提升工作效率。后续可进一步探索多模态检索、动态路由等高级特性。