全文链接https://tecdat.cn/?p45181原文出处拓端数据部落公众号关于分析师在此对YouMing Zhang对本文所作的贡献表示诚挚感谢他在东北大学完成了信息与计算科学专业的学士学位专注机器学习与深度学习算法领域。擅长Python、MATLAB、神经网络架构设计、数据挖掘与智能系统开发。引言在企业级AI应用中如何让大语言模型LLM既能利用内部知识库又能实时获取最新信息一直是技术落地的核心挑战。传统检索增强生成RAG通过外挂知识库让模型“边查边答”但当检索到的文档质量不佳时答案便会出现偏差。这好比一位学者只凭几本旧书回答问题遇到新问题要么答非所问要么承认无知。在近期为一家跨国保险集团设计智能理赔助手的咨询项目中我们直面了这一痛点。客户要求系统不仅要准确回答基于保单条款的问题还要能实时应对理赔政策变更、法院判例更新等动态信息。传统RAG在静态文档上表现尚可但面对需要联网核实或跨文档推理的场景便力不从心。于是我们引入了智能体Agent的概念——让大模型自己决定何时检索、何时上网、何时直接回答并通过LangGraph构建了一个可编排、可回溯的状态化流程。本文将这一项目中的技术沉淀提炼成文从零开始逐步构建一个具备纠正性检索Corrective RAG能力的多智能体系统。本文内容改编自过往客户咨询项目的技术沉淀并且已通过实际业务校验该项目3实例完整代码与数据已分享至交流社群。阅读原文进群获取完整代码数据及更多最新AI见解、行业洞察可与900行业人士交流成长还提供人工答疑拆解核心原理、代码逻辑与业务适配思路帮大家既懂“怎么做”也懂“为什么这么做”遇代码运行问题更能享24小时调试支持。文章脉络可用以下流程图概括用户输入 | v ---------- | 检索节点 | --- 向量数据库 ---------- | v ---------- | 文档评分节点 | (LLM判断相关性) ---------- | v ----------- | 条件分支 | ----------- | -----v----- ----------- | 全部相关 | | 部分/不相关 | ----------- ---------- | | v v ---------- ---------- | 生成答案 | | 查询重写 | ----------- ---------- | | | v | ---------- | | Web搜索 | (Tavily API) | ---------- | | | v | ---------- | | 生成答案 | | ---------- | | --------------------- | v 最终输出基础大模型调用与工具绑定一切始于最基础的LLM调用。# 结构化对话 from langchain_core.messages import HumanMessage, SystemMessage dialogue [ SystemMessage(content你是一位能用简单语言解释复杂概念的助手。), HumanMessage(content请用两句话解释机器学习。) ] reply my_llm.invoke(dialogue) print(reply.content)为了让模型具备工具使用能力我们需要定义工具并绑定。下面我们创建了两个工具一个简单的计算器和一个网络搜索工具此处为示意实际使用时需配置Tavily或DuckDuckGo。阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。状态化聊天机器人LangGraph初探LangGraph的核心是构建一个状态图StateGraph其中节点处理消息并更新状态。我们先定义一个包含消息列表的状态类。测试发现这个简单图不保存跨轮记忆。为此我们引入MemorySaver检查点。from langgraph.checkpoint.memory import MemorySaver memory MemorySaver() chat_with_mem builder.compile(checkpointermemory) def talk(message: str, thread_id: str): config {configurable: {thread_id: thread_id}} initial {msgs: [HumanMessage(contentmessage)]} result chat_with_mem.invoke(initial, config) print(助手, result[msgs][-1].content) talk(你好我叫小明, thread-1) talk(我叫什么名字, thread-1) # 现在能记住了阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。相关文章DeepSeek、LangGraph和Python融合LSTM、RF、XGBoost、LR多模型预测NFLX股票涨跌|附完整代码数据原文链接https://tecdat.cn/?p44060让智能体自主调用工具为了构建真正的智能体我们需要两个节点一个负责决定是否调用工具agent另一个负责执行工具tools。同时需要一个条件边来路由。from langgraph.prebuilt import ToolNode # 绑定工具后的模型 model_with_tools my_llm.bind_tools([simple_calculator]) # 实际可绑定多个工具 def agent_node(state: DialogState) - DialogState: sys_msg 你是一个智能助手需要时可使用工具。 messages [SystemMessage(contentsys_msg)] state[msgs] response model_with_tools.invoke(messages) return {msgs: [response]} tools_node ToolNode([simple_calculator]) # 自动执行工具调用 def route_condition(state: DialogState): last_msg state[msgs][-1] return tools if hasattr(last_msg, tool_calls) else end阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。集成RAG让智能体拥有私有知识现在我们为智能体添加文档检索能力。首先需要构建一个向量数据库这里以Markdown简历或Wikipedia数据为例。from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma # 加载文档此处省略具体加载代码 # docs ... text_splitter RecursiveCharacterTextSplitter(chunk_size1000, chunk_overlap200) chunks text_splitter.split_documents(docs) embed_model OpenAIEmbeddings(modeltext-embedding-3-small) vector_store Chroma.from_documents(chunks, embed_model, persist_directory./kb_store) retriever vector_store.as_retriever(search_kwargs{k: 3})然后将检索器封装为工具供智能体使用。tool def knowledge_retriever(query: str) - str: 在内部知识库中检索相关信息。 docs retriever.invoke(query) return \n\n.join([d.page_content for d in docs]) tools [simple_calculator, knowledge_retriever] # 可继续添加web搜索工具 model_with_rag my_llm.bind_tools(tools)为了演示纠正性RAG我们需要引入评估节点检查检索到的文档是否真的与问题相关。如果不相关则触发查询重写和Web搜索。阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。传统RAG的局限与纠正性RAG的提出传统RAG系统虽然通过外挂知识库增强了LLM的事实性但仍存在几个固有缺陷无法访问实时数据知识库一旦建立便静止不动无法反映最新信息。检索质量依赖索引如果向量检索召回的是不相关文档生成阶段就会产生错误答案。缺乏自我评估系统无法判断检索到的文档是否真的能回答问题。这些问题在实际应用中屡见不鲜。例如当用户询问“2024年欧冠冠军是谁”时如果知识库只有2023年以前的数据传统RAG只能回答“不知道”。又或者当检索到的文档部分相关但不足以完整回答时模型可能会拼凑出错误结论。针对这些痛点Yan等人在2024年提出了纠正性检索增强生成Corrective RAG, CRAG。其核心思想是在检索后增加一个轻量级评估器对检索文档的相关性打分并根据分数决定后续行动如果文档足够相关直接生成答案如果不够相关则通过Web搜索补充信息或提供更全面的上下文。数据准备与基础RAG链我们以一份Markdown格式的个人简历作为知识源构建一个能够回答简历相关问题的智能体。首先我们演示传统RAG链的表现。# 读取Markdown文件 with open(source.md, r) as f: full_text f.read() # 按标题分割 from langchain.text_splitter import MarkdownHeaderTextSplitter headers_to_split [(#, H1), (##, H2), (###, H3)] splitter MarkdownHeaderTextSplitter(headers_to_split_onheaders_to_split, strip_headersFalse) chunks splitter.split_text(full_text) # 构建向量存储 embeddings OpenAIEmbeddings() vector_db Chroma.from_documents(chunks, embeddings) retriever vector_db.as_retriever()定义标准RAG提示模板并构建链。from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_core.output_parsers import StrOutputParser rag_prompt PromptTemplate.from_template( 你是一个AI助手根据提供的上下文回答问题。如果不知道答案就说不知道。 问题{question} 上下文{context} 答案) rag_chain ( {context: retriever, question: RunnablePassthrough()} | rag_prompt | ChatOpenAI(modelgpt-4.1-mini, temperature0) | StrOutputParser() )测试几个问题发现当答案直接存在于某个块中时回答正确但当问题需要跨块汇总信息时传统RAG表现不佳。提问“S在哪些国家工作过” 传统RAG输出“提供的文档未明确说明S工作过的国家数量……”实际上简历中隐含着工作地点信息新加坡、菲律宾、印度但分散在不同部分传统RAG无法整合。阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。从传统RAG到智能体RAG以LangGraph实现CRAG我们采用LangGraph构建一个包含检索、评估、重写、Web搜索和生成节点的图。评估节点使用LLM判断文档相关性如果发现文档不足则触发查询重写和Web搜索。定义状态检索节点文档评分节点使用带结构化输出的LLM进行打分。查询重写节点当需要Web搜索时先用LLM优化查询。rewriter_llm ChatOpenAI(modelgpt-4.1-mini, temperature0.3) def rewrite(state: CRAGState) - CRAGState: print(---重写查询---) new_q rewriter_llm.invoke(f将以下问题改写成更适合搜索引擎的表述{state[query]}) return { query: new_q.content, docs: state[docs], web_needed: state[web_needed] }Web搜索节点使用Tavily API搜索结果转为Document对象。生成答案节点条件路由函数构建LangGraph测试同样的问题提问“S在哪些国家工作过” CRAG输出“S至少在新加坡、菲律宾和印度工作过。他在新加坡的OneZero和Splo工作为菲律宾一家大银行开发了概念验证”系统成功从多个文档块中提取信息并整合出完整答案。阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。智能体纠正性RAG更精细的决策与多源融合在CRAG基础上我们可以进一步引入智能体Agent概念让LLM不仅评估文档还能自主决定使用哪个工具知识库检索、Web搜索、直接回答并管理多轮对话状态。这构成了“智能体纠正性RAG”Agentic CRAG。其架构包含以下节点路由器节点根据用户问题决定走“直接回答”、“知识库检索”还是“结束”。RAG节点执行知识库检索并让一个“裁判”LLM判断检索块是否足够若不足则标记需Web搜索。Web搜索节点调用Tavily API获取实时信息。回答节点综合所有上下文生成最终答案。LangGraph使得这些节点的编排变得直观。实战基于Wikipedia数据的智能问答我们使用Wikipedia的子集约500篇文档构建知识库然后测试系统在实时事件如2024年欧冠上的表现。# 创建文档评分器使用结构化输出 class GradeDocs(BaseModel): score: str Field(descriptionyes 或 no) grader ChatOpenAI(modelgpt-4.1-mini, temperature0).with_structured_output(GradeDocs)定义智能体状态和节点后编译图并测试。提问“2024年欧冠冠军是谁” 输出“2024年欧冠冠军是皇家马德里他们在决赛中2-0击败多特蒙德卡瓦哈尔和维尼修斯建功。”由于本地知识库无此信息系统自动触发Web搜索获得了正确答案。阅读原文进群获取完整内容及更多AI见解、行业洞察与900行业人士交流成长。总结与展望本文从最基础的LLM调用开始逐步构建了具有记忆、工具使用能力的LangGraph智能体进而集成了RAG并最终实现了纠正性RAGCRAG和智能体纠正性RAGAgentic CRAG。通过实际代码和案例我们展示了如何让LLM自主评估检索质量、动态决定是否补充实时信息从而大幅提升问答系统的准确性和时效性。这套方法已在多家企业的智能客服、文档分析项目中落地证明了其在处理动态知识、多源融合方面的有效性。未来我们还可以引入自我反思、多智能体协作等机制让系统更加智能。希望本文能为读者在构建企业级RAG系统时提供有价值的参考。参考文献Yan, S.-Q., Gu, J.-C., Zhu, Y., Ling, Z.-H. (2024). Corrective Retrieval Augmented Generation.arXiv. https://doi.org/10.48550/arXiv.2401.15884LangGraph Documentation. https://langchain-ai.github.io/langgraph/