使用 LangChain 快速搭建 RAG 知识库
本文介绍基于 LangChain 构建检索增强生成(RAG)知识库的实战方案。首先解析 RAG 技术原理,包括检索模块与生成模块的协作机制。随后展示从文档加载、切片、向量化到构建 FastAPI 服务端的完整流程,提供核心代码示例及依赖配置。最后总结知识库动态更新、混合检索策略等优化方向,旨在帮助开发者快速搭建企业级智能问答系统。

本文介绍基于 LangChain 构建检索增强生成(RAG)知识库的实战方案。首先解析 RAG 技术原理,包括检索模块与生成模块的协作机制。随后展示从文档加载、切片、向量化到构建 FastAPI 服务端的完整流程,提供核心代码示例及依赖配置。最后总结知识库动态更新、混合检索策略等优化方向,旨在帮助开发者快速搭建企业级智能问答系统。

在日常工作中,对接第三方合作方时常面临文档繁多、沟通不及时、问题排查繁琐以及工作重复性高等挑战。传统的工单流程(门户网站→产品部门接口人→开发人员排查/修复→产品部门接口人→合作方回复)导致联调与验收周期过长。
为解决这一问题,需要有效利用前期积累的问题日志、对接规范、指导手册及接口文档。大模型虽具备强大的自然语言理解和文档整理能力,但缺乏特定领域的垂类知识。检索增强生成(RAG, Retrieval-Augmented Generation)技术恰好能在通用大模型与私有知识库之间建立桥梁,实现精准问答。
RAG (Retrieval-Augmented Generation) 是一种结合了检索和生成的混合式深度学习模型,常用于处理复杂的自然语言处理任务。RAG 模型通过将外部知识库中的信息与生成模型结合在一起,可以提供更准确和上下文相关的答案。具体来说,RAG 由两个核心部分组成:
这种技术的优势在于它能够利用海量的外部数据进行知识补充,从而提升回答的质量和准确性。这在动态性强、知识库更新频繁的场景中尤为重要。
在实际应用中,搭建一个基于 RAG 的知识库通常包括以下几个步骤:
下面用较少的代码快速搭建一个 RAG 系统,包括服务端和基础逻辑。仅用于 Demo 展示,生产级的 RAG 系统架构要复杂得多。
建议采用模块化设计,将配置、数据处理、服务接口分离。
如果纯自己编码实现 RAG,可能需要上千行代码。这里借助成熟的大模型开发框架来简化开发过程,把重心放到流程控制上。本例使用了 LangChain,关键代码给出注释,开发者可结合大模型进行理解和改进。
LangChain:一套在大模型能力上封装的工具框架(SDK),它为开发者提供了一系列工具和组件,以简化语言模型在复杂任务中的集成和应用,尤其是涉及到多步骤的流程和需要结合外部数据源的场景。
import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from dotenv import load_dotenv, find_dotenv
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.prompts import ChatPromptTemplate
from starlette.middleware.cors import CORSMiddleware
# 加载环境变量,读取本地 .env 文件,里面定义了 OPENAI_API_KEY
_ = load_dotenv(find_dotenv())
# 初始化 LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 加载文档,可换成 PDF、txt、doc 等其他格式文档
loader = TextLoader('../docs/解答手册.md', encoding='utf-8')
documents = loader.load()
# 文本切片策略
# chunk_size: 每个分块的大小,chunk_overlap: 重叠部分大小
text_splitter = RecursiveCharacterTextSplitter.from_language(
language="markdown",
chunk_size=200,
chunk_overlap=0
)
texts = text_splitter.create_documents([documents[0].page_content])
# 选择向量模型,并灌库
# FAISS 是 Facebook AI Similarity Search 的 Python 接口,适合本地向量检索
db = FAISS.from_documents(texts, OpenAIEmbeddings(model="text-embedding-ada-002"))
# 获取检索器,选择 top-k 相关的检索结果
retriever = db.as_retriever(search_kwargs={"k": 2})
# 创建带有 system 消息的模板
prompt_template = ChatPromptTemplate.from_messages([
("system", """你是一个对接问题排查机器人。
你的任务是根据下述给定的已知信息回答用户问题。
确保你的回复完全依据下述已知信息。不要编造答案。
请用中文回答用户问题。
已知信息:
{context} """),
("user", "{question}")
])
# 自定义的提示词参数
chain_type_kwargs = {
"prompt": prompt_template,
}
# 定义 RetrievalQA 链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # 使用 stuff 模式将上下文拼接到提示词中
chain_type_kwargs=chain_type_kwargs,
retriever=retriever
)
# 构建 FastAPI 应用,提供服务
app = FastAPI()
# 可选,前端报 CORS 跨域错误时开启
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
# 定义请求模型
class QuestionRequest(BaseModel):
question: str
# 定义响应模型
class AnswerResponse(BaseModel):
answer: str
# 提供查询接口 http://127.0.0.1:8000/ask
@app.post("/ask", response_model=AnswerResponse)
async def ask_question(request: QuestionRequest):
try:
# 获取用户问题
user_question = request.question
print(user_question)
# 通过 RAG 链生成回答
answer = qa_chain.run(user_question)
# 返回答案
answer_response = AnswerResponse(answer=answer)
print(answer_response)
return answer_response
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
代码采用 python3.11 版本运行,并安装了如下依赖:
# pip install -r requirements.txt
fastapi==0.112.1
langchain==0.2.14
langchain_community==0.2.12
langchain_openai==0.1.22
langchain_text_splitters==0.2.2
pydantic==2.8.2
python-dotenv==1.0.1
Requests==2.32.3
starlette==0.38.2
uvicorn==0.30.6
按照自己熟悉的文档组织方式组织 QA,并按照业务需求选择是将 Q 向量化,还是将 QA 一起向量化。本例采用如下格式组织 QA,并且 QA 一起向量化。
### xx 接口不通怎么办
请首先确认接口地址以及鉴权参数,可找 coderjia 进行排查
简陋的客户端界面测试正常,系统能根据知识库内容返回准确答案。当咨询知识库存在的知识时,返回具体指引;当咨询知识库不存在的知识时,模型会依据指令拒绝编造或表示未知。
以上只是搭建基于 RAG 的知识库最基本的步骤,实际应用时,有几点优化建议:
stuff 模式可能超出 Token 限制。可尝试 map_reduce 或 refine 链类型,或使用父文档检索策略(Parent Document Retriever)。
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online