news 2026/5/26 12:38:42

手把手构建一个完整的 RAG(检索增强生成)系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手构建一个完整的 RAG(检索增强生成)系统

RAG(Retrieval-Augmented Generation,检索增强生成)是当前大模型应用中最主流的架构之一。它通过结合外部知识库与大语言模型(LLM),有效缓解了模型幻觉、知识滞后和领域专业性不足等问题。本文将带你从零开始,完整实现一个生产级 RAG 系统。


一、RAG 系统整体架构

一个典型的 RAG 系统包含以下核心模块:

用户提问 → 查询理解 → 向量检索 → 文档重排 → 提示工程 → LLM 生成 → 输出 ↑ ↑ (可选) (可选) 查询改写 重排序模型

我们将逐步实现每个环节。


二、环境准备

pipinstalllangchain==0.2.0\langchain-community\langchain-core\langchain-text-splitters\sentence-transformers\chromadb\rank_bm25\transformers\torch\openai\python-dotenv

建议使用 Python 3.9+,并设置虚拟环境。


三、数据准备:加载与切分文档

1. 加载文档

支持 PDF、Word、TXT、HTML 等格式:

fromlangchain_community.document_loadersimportPyPDFLoader,DirectoryLoader loader=DirectoryLoader("./docs",glob="*.pdf",loader_cls=PyPDFLoader)documents=loader.load()

2. 文本切分(Chunking)

合理切分对检索质量至关重要。推荐使用语义感知切分

fromlangchain_text_splittersimportRecursiveCharacterTextSplitter text_splitter=RecursiveCharacterTextSplitter(chunk_size=512,chunk_overlap=50,separators=["\n\n","\n","。","!","?",";"," ",""])chunks=text_splitter.split_documents(documents)

技巧:chunk_overlap可避免语义割裂;separators按优先级断句。


四、向量化:构建嵌入(Embedding)

1. 选择 Embedding 模型

  • 开源本地模型:BAAI/bge-large-zh-v1.5(中文强)、text-embedding-ada-002(OpenAI)
  • 本地部署推荐sentence-transformers
fromlangchain_community.embeddingsimportHuggingFaceBgeEmbeddings embeddings=HuggingFaceBgeEmbeddings(model_name="BAAI/bge-large-zh-v1.5",model_kwargs={"device":"cuda"},encode_kwargs={"normalize_embeddings":True})

2. 构建向量数据库

使用 Chroma(轻量级)或 Milvus(生产级):

importchromadbfromlangchain_chromaimportChroma vectorstore=Chroma.from_documents(documents=chunks,embedding=embeddings,persist_directory="./chroma_db")retriever=vectorstore.as_retriever(search_kwargs={"k":5})

k=5表示检索 Top-5 相关片段。


五、检索优化(关键!)

原始向量检索可能召回不相关结果,需优化:

1. 查询改写(Query Rewriting)

使用 LLM 对用户问题进行澄清或扩展:

fromlangchain_core.promptsimportPromptTemplatefromlangchain_openaiimportChatOpenAI rewrite_prompt=PromptTemplate.from_template("你是一个查询优化器。请将以下用户问题改写为更清晰、更适合检索的形式:{question}")llm=ChatOpenAI(model="gpt-4o")rewriter=rewrite_prompt|llm rewritten_query=rewriter.invoke({"question":"怎么重启服务?"}).content

2. 混合检索(Hybrid Search)

结合关键词(BM25) + 向量检索:

fromrank_bm25importBM25Okapiimportjieba# 构建 BM25 索引(中文需分词)corpus=[doc.page_contentfordocinchunks]tokenized_corpus=[list(jieba.cut(text))fortextincorpus]bm25=BM25Okapi(tokenized_corpus)defhybrid_search(query,k=5):# 向量检索vec_results=retriever.invoke(query)vec_ids={doc.metadata["id"]fordocinvec_results}# BM25 检索tokenized_query=list(jieba.cut(query))bm25_scores=bm25.get_scores(tokenized_query)top_bm25=sorted(range(len(bm25_scores)),key=lambdai:bm25_scores[i],reverse=True)[:k]# 融合(取并集去重)all_docs=vec_results+[chunks[i]foriintop_bm25ifinotinvec_ids]returnall_docs[:k]

3. 重排序(Re-ranking)

使用 Cross-Encoder 模型对 Top-K 结果重新打分:

fromsentence_transformersimportCrossEncoder reranker=CrossEncoder("BAAI/bge-reranker-large")pairs=[(query,doc.page_content)fordocinretrieved_docs]scores=reranker.predict(pairs)reranked=[docfor_,docinsorted(zip(scores,retrieved_docs),reverse=True)]

六、提示工程与生成

构建高质量 Prompt

template=""" 你是一个专业客服助手,请根据以下上下文回答用户问题。 - 如果答案不在上下文中,请回答“根据现有资料无法回答”。 - 保持回答简洁、准确。 上下文: {context} 问题:{question} 回答: """prompt=ChatPromptTemplate.from_template(template)

构建 RAG 链

fromlangchain_core.runnablesimportRunnablePassthroughfromlangchain_core.output_parsersimportStrOutputParser rag_chain=({"context":retriever,"question":RunnablePassthrough()}|prompt|llm|StrOutputParser())answer=rag_chain.invoke("如何配置 API 密钥?")

七、评估与迭代

RAG 系统需持续评估:

  • 检索质量:MRR
  • 生成质量:ROUGE、BLEU、人工评分
  • 端到端效果:使用 TruLens 或 RAGAS 框架
# 示例:用 RAGAS 评估fromragasimportevaluatefromragas.metricsimportfaithfulness,answer_relevancy result=evaluate(dataset=your_test_set,metrics=[faithfulness,answer_relevancy],llm=llm,embeddings=embeddings)

八、部署建议

  • 本地测试:FastAPI + Uvicorn
  • 生产部署:Docker 容器化,搭配 Redis 缓存、Nginx 负载均衡
  • 监控:记录查询日志、延迟、失败率

总结

一个健壮的 RAG 系统 ≠ 简单拼接“检索 + LLM”。关键在于:

  1. 高质量数据切分
  2. 混合检索 + 重排序
  3. 精准的提示工程
  4. 持续评估与迭代
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 21:02:58

LangFlow Kibana仪表盘展示AI流程运行情况

LangFlow Kibana:构建可观察的AI流程开发闭环 在AI应用快速落地的今天,一个常见的困境摆在团队面前:如何让复杂的语言模型工作流既易于构建,又能被清晰地监控和维护?尤其是当业务方、产品经理与工程师共同参与智能系…

作者头像 李华
网站建设 2026/5/25 9:12:00

基于Python+大数据+SSM基于机器学习的电商评论情感分析(源码+LW+调试文档+讲解等)/电商评论分析/电商情感分析/评论情感分析/电商文本情感分析/电商评论情绪分析

博主介绍 💗博主介绍:✌全栈领域优质创作者,专注于Java、小程序、Python技术领域和计算机毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 2025-2026年最新1000个热门Java毕业设计选题…

作者头像 李华
网站建设 2026/5/25 7:38:34

零基础玩转树莓派5:完整学习路径

从零开始玩转树莓派5:新手也能轻松上手的完整学习路径 你有没有想过,一块巴掌大的小板子,居然能运行完整的操作系统、连接传感器、控制灯光、甚至搭建自己的云服务器?这听起来像科幻电影的情节,但在今天,它…

作者头像 李华
网站建设 2026/5/26 5:42:47

LangFlow OpenTelemetry支持开启可观测新时代

LangFlow OpenTelemetry支持开启可观测新时代 在AI应用快速落地的今天,大语言模型(LLM)已经不再是实验室里的“黑科技”,而是企业实现智能客服、知识管理、自动化决策的核心引擎。越来越多团队基于LangChain构建复杂的工作流——从…

作者头像 李华
网站建设 2026/5/25 11:32:37

ESP32-CAM WiFi信号强度对UDP流影响深度研究

ESP32-CAM实战:WiFi信号弱了,视频为啥卡成PPT?你有没有过这样的经历?手里的ESP32-CAM明明代码烧好了、摄像头也亮了,可一放到客厅角落,画面就开始一顿一顿,动不动还黑屏几秒。换到离路由器近的地…

作者头像 李华
网站建设 2026/5/26 5:42:45

深入理解上拉电阻:系统学习其偏置电流路径

上拉电阻的“小身材大智慧”:从悬空引脚到系统稳定的底层逻辑你有没有遇到过这样的情况——明明代码写得没问题,MCU却莫名其妙重启?或者按键按一下触发好几次?又或者IC通信时不时丢数据,示波器一看,上升沿“…

作者头像 李华