使用 LangChain 搭建自己的本地知识库系统
随着大语言模型(LLM)的快速发展,如何将其与私有数据或最新知识结合成为热门话题。本文介绍如何利用 LangChain 框架构建基于检索增强生成(RAG)技术的本地知识库系统。
什么是 RAG
RAG(Retrieval-Augmented Generation,检索增强生成)是一种通过检索外部知识库来辅助 LLM 生成的技术。它允许模型在回答问题时参考最新的、私有的或非训练数据集中的信息,从而减少幻觉并提高准确性。
LLM 现存的痛点
现有的 LLM 主要基于公开网络数据进行训练,存在以下局限性:
- 知识时效性:训练数据截止于过去,无法获取最新信息。
- 数据隐私:企业私有数据无法直接用于公共模型训练,导致模型不了解内部知识。
- 幻觉问题:面对未知问题时,模型可能编造答案。
RAG 通过引入外部知识源,有效解决了上述问题,确保回答基于事实且可追溯。
LangChain 简介
LangChain 是一个用于开发由语言模型驱动的应用程序的开源框架。它提供了丰富的组件,使开发者能够轻松实现:
- 上下文感知:将语言模型与提示词、示例及动态内容关联。
- 推理能力:利用模型进行逻辑推理和任务规划。
环境依赖安装
首先,需要安装 LangChain 及其相关生态包。建议使用 Python 虚拟环境管理依赖。
pip install langchain
pip install langchain-community
pip install langchain-core
pip install langchain-experimental
pip install "langserve[all]"
pip install langchain-cli
pip install langsmith
核心配置
1. LLM 模型配置
本文以 Azure OpenAI 为例。若使用其他服务(如 OpenAI 官方、百度千帆等),需参照对应文档实例化模型。
import os
os.environ["AZURE_OPENAI_ENDPOINT"] = "your_endpoint_here"
os.environ["AZURE_OPENAI_API_KEY"] = "your_api_key_here"
2. Embedding 模型配置
Embedding 模型负责将文本转换为向量。这里演示百度千帆接入方式。
import os
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
def embedQianfan():
os.environ["QIANFAN_AK"] = "your_ak_here"
os.environ["QIANFAN_SK"] = "your_sk_here"
return QianfanEmbeddingsEndpoint()
RAG 工作流程详解
一个标准的 RAG 系统包含以下步骤:
- 文档加载:从网页、PDF 或数据库中读取原始数据。
- 文本拆分:将长文档切分为适合 Embedding 处理的片段(Chunk)。
- 向量化:使用 Embedding 模型将文本片段转换为向量。
- 存储:将向量存入向量数据库(如 Chroma)。
- 检索:根据用户问题检索最相关的向量片段。
- 生成:将检索到的上下文与问题组合,输入 LLM 生成最终回答。
代码实现
以下是完整的实现流程,整合了上述步骤。
from langchain_community.vectorstores import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import AzureChatOpenAI
import os
embed_model = embedQianfan()
raw_documents = WebBaseLoader("https://docs.dify.ai/v/zh-hans/getting-started/readme").load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
all_splits = text_splitter.split_documents(raw_documents)
vectorstore = Chroma.from_documents(
documents=all_splits,
collection_name="rag-chroma",
embedding=embed_model,
)
retriever = vectorstore.as_retriever()
template = """Answer the question in Chinese and based only on the following context:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = AzureChatOpenAI(
azure_deployment="gpt-4",
openai_api_version="2023-05-15"
)
chain = (
RunnableParallel({"context": retriever, "question": RunnablePassthrough()})
| prompt
| model
| StrOutputParser()
)
():
__root__:
chain = chain.with_types(input_type=Question)
(chain.invoke())
(chain.invoke())
(chain.invoke())
(chain.invoke())
启动服务
使用 LangServe 可以快速将 Chain 部署为 API 服务。
langchain serve
启动成功后,终端会显示服务地址,例如 http://127.0.0.1:8000。访问 /playground 路径即可进入调试界面。
常见问题与优化建议
-
文本拆分策略:
- 如果 Embedding 模型有 Token 限制(如 512 或 8192),务必设置合适的
chunk_size。
- 适当增加
chunk_overlap 有助于保留上下文连贯性。
-
检索精度:
- 调整
top_k 参数控制检索返回的文档数量。
- 尝试不同的相似度阈值过滤低相关性结果。
-
Prompt 优化:
- 明确指示模型'仅基于提供的上下文回答',以减少幻觉。
- 对于多轮对话,需维护会话历史状态。
-
性能优化:
- 对于大规模数据,考虑使用更高效的向量数据库(如 Milvus, Pinecone)。
- 启用缓存机制减少重复计算。
总结
本文详细介绍了如何使用 LangChain 构建本地知识库系统。通过 RAG 架构,我们成功将外部知识与 LLM 结合,解决了知识时效性和隐私性问题。核心步骤包括文档加载、切片、向量化存储以及检索生成链路的搭建。开发者可根据实际需求替换 LLM 和 Embedding 模型,灵活扩展应用场景。