从零搭建LangChain+RAG知识库:企业级实战指南

从零搭建LangChain+RAG知识库:企业级实战指南
从零搭建LangChain+RAG知识库:企业级实战指南

为什么需要RAG知识库?

大语言模型(LLM)虽然强大,但存在知识截止、幻觉以及无法访问私有数据的问题。检索增强生成(RAG)通过将外部知识库中的相关文档片段实时注入LLM上下文,显著提升回答的准确性和时效性。LangChain作为目前最流行的AI应用框架,提供了模块化的RAG组件,让开发者能在几小时内搭建出一个企业级知识库原型。

环境准备与核心依赖

首先安装必要的Python包(建议Python≥3.10):

pip install langchain langchain-community langchain-openai chromadb pypdf python-docx tiktoken

本指南使用OpenAI的Embedding模型和ChatGPT作为LLM,你也可以替换为本地模型(如Ollama+llama3)。设置环境变量:OPENAI_API_KEY=你的key

第一步:文档加载与分割

企业知识库通常包含PDF、Word、Markdown、网页等格式。LangChain提供统一的DocumentLoader接口。以PDF和Word为例:

from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载
loaders = [PyPDFLoader("report.pdf"), Docx2txtLoader("guide.docx")]
docs = []
for loader in loaders:
    docs.extend(loader.load())
# 分割(按chunk size=500, overlap=50)
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
splits = splitter.split_documents(docs)
print(f"共分割为 {len(splits)} 个片段")

注意:chunk_size和overlap需要根据文档类型和LLM上下文长度调整。对于中英文混合内容,建议使用RecursiveCharacterTextSplitter,它会智能保留段落结构。

第二步:向量嵌入与向量库

将分割后的文本片段转换为向量并存入向量数据库。Chroma可以本地运行且免费:

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
vectorstore = Chroma.from_documents(documents=splits, embedding=embeddings, persist_directory="./chroma_db")
vectorstore.persist()  # 持久化存储

生产环境中可考虑Pinecone、Weaviate或Milvus,支持分布式与更复杂的过滤。

第三步:构建检索链

LangChain的RetrievalQA链将检索与生成无缝衔接:

from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 4})
qa_chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever)
# 测试
query = "我们的产品退货政策是什么?"
response = qa_chain.invoke({"query": query})
print(response["result"])

chain_type参数:
- stuff:将检索到的文档全部塞入上下文,适合片段少(≤4个)。
- map_reduce/refine:处理大量文档时性能更好,但会增加推理成本。

第四步:进阶优化——混合检索与重排序

纯向量相似度搜索可能漏掉精确匹配(如人名、编号)。推荐引入BM25稀疏检索

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
bm25_retriever = BM25Retriever.from_documents(splits)
bm25_retriever.k = 4
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, retriever],
    weights=[0.3, 0.7]
)
qa_chain_with_ensemble = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=ensemble_retriever)

此外,可在检索后增加重排序器(如Cohere rerank),提升最相关片段的优先级。

第五步:企业级部署与监控

生产环境需关注以下几个要点:

  • 缓存:对高频重复查询使用CacheBackedEmbeddings或Redis减少API调用成本。
  • 异步支持:使用langchain_community.chat_models.ChatOpenAI(async_mode=True)配合FastAPI实现高并发。
  • 安全审计:所有用户查询先通过内容过滤模型;对向量库实施访问控制。
  • 日志与评估:记录用户Query、检索到的文档ID、LLM响应,定期用RAGAS等框架评测准确率。

完整示例:结合记忆的对话式RAG

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
conv_chain = ConversationalRetrievalChain.from_llm(
    llm=ChatOpenAI(model="gpt-4o-mini"),
    retriever=ensemble_retriever,
    memory=memory
)
while True:
    user = input("问题:")
    if user.lower() in ("exit","quit"): break
    print(conv_chain.invoke({"question": user})["answer"])

该链自动维护对话历史,让用户能追问(如“上一条提到的退款流程再详细解释”)。

常见陷阱与应对

  1. 分割不合理:过长/过短的chunk都会降低检准率。建议动态chunk(依据标题层级切分)。
  2. 向量维度灾难:OpenAI ada-002是1536维,Chroma本地使用无压力;若用更大模型,考虑降维。
  3. LLM幻觉依旧:在系统提示词中强制要求“根据提供的上下文回答,不知道就说不知道”。

通过以上步骤,你已成功搭建一个具备企业级能力的RAG知识库。LangChain的模块化设计让你可以随时替换组件(如换成本地模型、换向量库),实现真正的灵活落地。下一步可尝试引入多模态RAG(处理表格、图片)或构建Agent来自动更新知识文档。

阅读剩余
THE END