尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LangGraph与Agentic RAG:从静态提示词到动态工作流的范式转变

LangGraph与Agentic RAG:从静态提示词到动态工作流的范式转变 你有没有过这样的经历花了一下午调试一个提示词模型输出的结果却总是差那么一点意思要么格式不对要么逻辑混乱要么干脆答非所问你可能会想是不是我的提示词写得不够好于是你开始在网上搜索“最佳提示词模板”试图找到一个“银弹”。但真相可能更让人沮丧问题或许不完全出在你的提示词上。在2024年单纯依赖一个完美的静态提示词Prompt来驱动大模型已经越来越像一场赌博。模型的状态、上下文的长短、工具的调用、多步骤的推理这些动态因素共同决定了最终输出的质量。一个孤立的、写死的提示词在复杂的真实任务面前往往力不从心。这正是为什么当吴恩达教授在最近的分享中将构建于LangGraph之上的Agent智能体与RAG检索增强生成工作流称为“2026年公认最好的提示词工程”时其背后揭示了一个深刻的范式转变。这个判断的核心不在于否定提示词的重要性而在于指出最高效的“提示词工程”已经从一个静态的“文本撰写”问题演变成了一个动态的“流程编排”问题。LangGraph 不是一个新模型也不是一个魔法框架。它是一个用于构建有状态、多步骤工作流的库其核心思想是用图Graph来定义和控制 Agent 的行为逻辑。当它与 RAG 结合时我们得到的不是一个更聪明的搜索引擎而是一个能自主规划、调用工具、检索信息、并基于复杂上下文进行推理的“思考机器”。本文将带你深入这个被寄予厚望的技术组合。我们不会停留在概念层面而是会拆解其核心机制并通过一个从零开始的代码示例展示如何构建一个能解决实际问题的智能体。你会发现真正的“提示词工程”高手可能更像一个系统架构师而非一个文案写手。1. 为什么静态提示词不够用从“指令”到“工作流”的必然演进在深入 LangGraph 和 Agentic RAG 之前我们必须先理解为什么传统的提示词方法会遭遇瓶颈。这并非提示词本身失效了而是我们面对的任务复杂度已经超出了它的能力边界。1.1 静态提示词的三大局限想象一下你给模型这样一个任务“分析公司上季度的财报PDF总结出三个关键风险点并针对每个风险点从我们的内部知识库中找出相关的应对案例最后生成一份给管理层的报告。”如果你试图用一个超长的、包含所有步骤的提示词来完成这个任务你很可能会失败。原因在于上下文长度与信息过载财报PDF、知识库文档、中间分析结果这些内容会迅速撑爆模型的上下文窗口。即使是最新的128K上下文模型在如此多的原始信息中保持焦点和一致性也极其困难。工具调用的不可预测性任务中涉及“读取PDF”、“检索知识库”、“生成报告”等多个步骤。这些步骤需要调用不同的外部工具或函数。一个静态提示词无法根据上一步的结果动态决定下一步调用哪个工具、传入什么参数。状态管理与复杂逻辑的缺失任务包含条件判断如果找到案例则引用否则说明无案例、循环对每个风险点执行检索、以及状态传递将分析出的风险点传递给检索步骤。静态文本难以清晰地表达和维护这种复杂的、有状态的逻辑。此时你写的提示词更像一份希望模型能“心领神会”的愿望清单而不是一份可执行的蓝图。1.2 Agent 与 RAG 的互补能力与知识的结合为了解决上述问题业界逐渐形成了两条清晰的路径而 LangGraph 正是将它们融合的粘合剂RAG检索增强生成解决“知识”问题。它让模型能够访问并引用外部的、非参数化的知识如你的公司文档、最新新闻、专有数据库从而生成更准确、更可信、信息更新的回答。它扩展了模型的“记忆体”。Agent智能体解决“能力”问题。它赋予模型“动手”的能力通过调用工具Tools来执行模型自身无法完成的操作如计算、搜索、读写文件、调用API等。它扩展了模型的“手脚”。然而早期的 RAG 和 Agent 实现往往是割裂的。一个典型的 RAG 系统可能只是“检索 - 拼接上下文 - 生成”的简单管道。而一个简单的 Agent 可能只能执行单一指令。当任务需要基于检索到的知识进行多步决策和行动时简单的管道就无能为力了。1.3 LangGraph 的核心价值将工作流“可视化”为可编程的图这就是 LangGraph 登场的时候。它不是一个替代 LangChain 的框架而是 LangChain 生态系统中的一个专门用于构建有状态、多参与者工作流的库。你可以把它想象成绘制程序流程图的可视化工具但这个“图”本身就是可执行的代码。它的核心抽象非常简单节点Node代表一个步骤可以是一个 LLM 调用一个工具调用或一段条件判断逻辑。边Edge定义了节点之间的流转条件。可以是无条件跳转到下一个节点也可以是基于上一步结果的“如果-那么”条件分支。通过将 Agent 的逻辑使用哪些工具、按什么顺序、在什么条件下定义成一张图我们获得了几个关键优势透明可控整个 Agent 的决策流程一目了然不再是黑盒。易于调试你可以跟踪执行路径精确看到是在哪个节点、因为什么输入导致了问题。支持复杂逻辑循环、条件分支、并行、子流程等复杂模式可以自然地表达。状态持久化整个工作流的中间状态对话历史、工具调用结果、变量被统一管理可以在步骤间传递。因此“基于 LangGraph 的 Agentic RAG”的本质是构建一个智能体其核心决策逻辑由一张图来驱动而这张图中关键的节点之一就是执行 RAG 检索。这实现了从“一次性问答”到“多步知识型任务求解”的跃迁。2. 深入 LangGraph理解 State、Node 与 Edge 三要素要驾驭 LangGraph必须理解它的三个核心概念State状态、Node节点和Edge边。这构成了所有工作流的基础。2.1 State工作流的共享记忆簿State 是一个类似字典Dict的对象它贯穿整个图的执行过程是所有节点读写信息的唯一场所。你可以把它理解为整个智能体的“短期记忆”或“工作白板”。定义一个 State 通常使用TypedDict这能让代码更清晰、类型更安全。from typing import TypedDict, List, Annotated import operator class AgentState(TypedDict): # 用户输入的问题 input: str # 对话历史 chat_history: List[str] # LLM 生成的思考或指令 llm_output: str # 工具调用的结果列表 tool_outputs: List[str] # RAG 检索到的相关文档片段 retrieved_docs: List[str] # 最终给用户的答案 final_answer: strAnnotated可以用来定义更复杂的操作比如让某个字段自动进行追加操作而不是覆盖。class AgentState(TypedDict): chat_history: Annotated[List[str], operator.add] # 自动追加而非覆盖 retrieved_docs: List[str] # ... 其他字段关键理解State 的设计决定了工作流的“数据流”。在规划工作流时首先要问我的不同步骤之间需要共享和传递哪些信息把这些信息设计为 State 的字段。2.2 Node执行具体任务的单元Node 是一个普通的 Python 函数或可调用对象它接收当前的State作为参数执行一些操作然后返回一个更新后的State或包含部分更新的字典。一个 Node 可以干任何事情调用 LLM。调用一个工具如搜索引擎、计算器、数据库。执行 RAG 检索。进行条件判断。格式化字符串。from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate llm ChatOpenAI(modelgpt-4o) def retrieve_node(state: AgentState) - dict: RAG 检索节点根据问题从向量库查找相关文档 question state[input] # 假设我们有一个已初始化的检索器 retriever docs retriever.invoke(question) # 更新 State将检索结果存入 return {retrieved_docs: docs} def llm_node(state: AgentState) - dict: LLM 处理节点根据检索结果和问题生成思考或答案 question state[input] docs state[retrieved_docs] context \n\n.join([doc.page_content for doc in docs]) prompt ChatPromptTemplate.from_messages([ (system, 你是一个有帮助的助手。请根据以下上下文回答问题。如果上下文不包含答案请如实说明。), (human, 上下文{context}\n\n问题{question}) ]) chain prompt | llm response chain.invoke({context: context, question: question}) # 更新 State return {llm_output: response.content}2.3 Edge决定流程走向的路由器Edge 定义了在某个 Node 执行完毕后接下来应该执行哪个或哪些Node。这是实现条件逻辑和循环的关键。有两种主要的 Edge普通边add_edge无条件地从节点 A 指向节点 B。条件边add_conditional_edges根据State中的某个值动态决定下一个节点。from langgraph.graph import StateGraph, END # 创建图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(retrieve, retrieve_node) workflow.add_node(generate, llm_node) workflow.add_node(rewrite, rewrite_node) # 假设一个重写节点 # 添加普通边检索完后总是去生成 workflow.add_edge(retrieve, generate) # 添加条件边生成后根据内容质量决定是结束还是重写 def decide_next_step(state: AgentState) - str: llm_output state[llm_output] # 一个简单的判断逻辑如果回答中包含“不确定”则重写 if 不确定 in llm_output or 不知道 in llm_output: return rewrite else: return END # END 是一个特殊的节点表示结束 workflow.add_conditional_edges( generate, decide_next_step, # 这个函数返回下一个节点的名字 {rewrite: rewrite, END: END} ) # 从“retrieve”节点开始 workflow.set_entry_point(retrieve) # 编译图 app workflow.compile()通过组合 State、Node 和 Edge你可以构建出任意复杂的工作流。接下来我们将用一个完整的例子把 Agent、RAG 和 LangGraph 结合起来。3. 实战构建一个能“思考”的 Agentic RAG 问答系统让我们构建一个相对复杂的智能体它不仅能用 RAG 回答问题还能在答案不确定时自主决定是否进行多轮检索或联网搜索。场景用户问一个专业问题。智能体首先从本地知识库RAG中寻找答案。如果找到高置信度的答案直接返回。如果答案模糊或知识库中没有则自动切换到联网搜索整合搜索结果后生成最终答案。3.1 环境准备与知识库搭建首先安装必要的库并准备一个简单的本地知识库。pip install langchain langchain-openai langgraph chromadb tiktoken假设我们有一些 Markdown 格式的技术文档。我们将其加载、切分并存入向量数据库。from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_chroma import Chroma # 1. 加载文档 loader DirectoryLoader(./my_docs/, glob**/*.md, loader_clsTextLoader) documents loader.load() # 2. 分割文档 text_splitter RecursiveCharacterTextSplitter(chunk_size500, chunk_overlap50) docs text_splitter.split_documents(documents) # 3. 创建向量存储 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma.from_documents(documentsdocs, embeddingembeddings, persist_directory./chroma_db) retriever vectorstore.as_retriever(search_kwargs{k: 3}) # 检索最相关的3个片段3.2 定义智能体的 State 与工具定义工作流的状态并创建智能体可以使用的工具。from typing import TypedDict, List, Annotated, Optional import operator from langchain.tools import Tool from langchain_community.utilities import SerpAPIWrapper # 假设使用 SerpAPI 进行搜索 class AgentState(TypedDict): 智能体的状态定义 question: str # 原始问题 chat_history: Annotated[List[str], operator.add] # 对话历史自动追加 retrieved_docs: List[str] # RAG 检索到的文档 llm_thought: str # LLM 的思考过程 action: str # 下一步要执行的动作如 “answer”, “search_web” final_answer: Optional[str] # 最终答案 # 工具1RAG 检索工具 def retrieve_from_knowledge_base(query: str) - str: 从本地知识库检索相关文档 docs retriever.invoke(query) return \n---\n.join([doc.page_content for doc in docs]) # 工具2联网搜索工具需要 SERPAPI_API_KEY 环境变量 search SerpAPIWrapper() def search_web(query: str) - str: 在互联网上搜索最新信息 return search.run(query) # 将函数封装成 LangChain Tool tools [ Tool( nameKnowledgeBaseRetriever, funcretrieve_from_knowledge_base, description当需要从公司内部知识库或特定文档中查找信息时使用此工具。输入是一个搜索查询。 ), Tool( nameWebSearch, funcsearch_web, description当问题涉及最新事件、实时信息或内部知识库中没有的信息时使用此工具。输入是一个搜索查询。 ) ]3.3 构建 LangGraph 工作流现在我们来绘制智能体的“思考”流程图。它将包含以下节点route_question: 分析问题决定第一步是检索知识库还是直接搜索。retrieve: 执行知识库检索。generate_initial_answer: 基于检索结果生成初步答案和思考。decide_next_action: 评估初步答案决定是直接回答还是需要联网搜索。search_web: 执行联网搜索。generate_final_answer: 整合所有信息生成最终答案。from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents import create_react_agent, AgentExecutor from langchain_core.messages import HumanMessage, AIMessage llm ChatOpenAI(modelgpt-4o, temperature0) # 创建 ReAct 智能体用于决策和工具调用 agent_prompt ChatPromptTemplate.from_messages([ (system, 你是一个智能助手。请逐步思考。 你可以使用以下工具 {tools} 使用工具时请严格按照以下格式 思考解释你为什么需要这个工具以及你的计划 行动要使用的工具名称 行动输入工具的输入 当你有了最终答案时请使用格式 最终答案你的答案 ), MessagesPlaceholder(variable_namechat_history), (human, {input}), ]) react_agent create_react_agent(llm, tools, agent_prompt) agent_executor AgentExecutor(agentreact_agent, toolstools, verboseTrue, handle_parsing_errorsTrue) # 节点1路由问题这是一个简化示例实际可能更复杂 def route_question(state: AgentState): 根据问题类型决定第一步。这里简单假设所有问题先走知识库。 return {action: retrieve} # 节点2检索知识库 def retrieve(state: AgentState): question state[question] docs retrieve_from_knowledge_base(question) return {retrieved_docs: [docs]} # 存入状态 # 节点3生成初步答案和思考 def generate_initial_answer(state: AgentState): question state[question] context state[retrieved_docs][0] if state[retrieved_docs] else 无相关内容。 prompt ChatPromptTemplate.from_messages([ (system, 你是一个严谨的助手。请基于提供的上下文生成一个初步答案。同时评估这个答案的置信度。如果上下文不充分或答案不确定请明确指出。), (human, f上下文{context}\n\n问题{question}\n\n请生成初步答案并在最后一行用‘置信度[高/中/低]’来评估。) ]) chain prompt | llm response chain.invoke({}) return {llm_thought: response.content} # 节点4决策下一步行动 def decide_next_action(state: AgentState): thought state[llm_thought] # 简单的规则如果思考中包含“置信度低”或“不确定”则去搜索 if 置信度低 in thought or 不确定 in thought: return {action: search_web} else: return {action: finalize} # 节点5执行联网搜索通过Agent Executor def search_web_node(state: AgentState): question state[question] # 使用Agent Executor来调用搜索工具 result agent_executor.invoke({ input: f请搜索关于{question}的最新、最相关信息。, chat_history: state[chat_history] }) # 将搜索结果也存入状态供最终生成使用 search_result result.get(output, 搜索未返回结果。) # 更新聊天历史记录这次工具调用 new_history state[chat_history] [HumanMessage(contentf搜索{question}), AIMessage(contentsearch_result)] return {chat_history: new_history, retrieved_docs: state[retrieved_docs] [f[网络搜索结果]\n{search_result}]} # 节点6生成最终答案 def generate_final_answer(state: AgentState): question state[question] all_contexts \n\n---\n\n.join(state[retrieved_docs]) prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的助手。请综合以下所有信息为用户的问题生成一个准确、完整、清晰的最终答案。), (human, f所有相关信息{all_contexts}\n\n问题{question}) ]) chain prompt | llm response chain.invoke({}) return {final_answer: response.content, action: END} # 构建图 workflow StateGraph(AgentState) # 添加所有节点 workflow.add_node(router, route_question) workflow.add_node(retriever, retrieve) workflow.add_node(initial_answer, generate_initial_answer) workflow.add_node(decider, decide_next_action) workflow.add_node(web_searcher, search_web_node) workflow.add_node(finalizer, generate_final_answer) # 设置边 workflow.set_entry_point(router) workflow.add_edge(router, retriever) # 路由后总是先检索 workflow.add_edge(retriever, initial_answer) # 检索后生成初步答案 workflow.add_edge(initial_answer, decider) # 根据初步答案做决策 # 条件边决策后是搜索还是结束 workflow.add_conditional_edges( decider, lambda state: state[action], # 根据 state[‘action’] 的值路由 { search_web: web_searcher, finalize: finalizer } ) workflow.add_edge(web_searcher, finalizer) # 搜索完后去生成最终答案 workflow.add_edge(finalizer, END) # 编译图 app workflow.compile()3.4 运行与调试智能体现在你可以运行这个智能体了。# 定义输入 inputs {question: LangGraph 和 LangChain 在架构上最主要的区别是什么, chat_history: []} # 运行图 final_state app.invoke(inputs) print(最终答案, final_state.get(final_answer)) print(\n--- 执行轨迹 ---) # LangGraph 提供了很好的可视化工具这里打印关键步骤 for step in final_state.get(chat_history, []): if isinstance(step, AIMessage) and 行动 in step.content: print(step.content)这个智能体会自动执行以下流程路由到知识库检索。基于检索结果生成初步答案并评估置信度。如果置信度低则自动触发联网搜索。综合本地知识和网络信息生成最终答案。你可以通过 LangGraph 自带的可视化功能查看执行图这比调试一堆散落的if-else语句清晰得多。4. 从项目到生产Agentic RAG 的工程化考量构建一个能跑的 Demo 只是第一步。要将基于 LangGraph 的 Agentic RAG 投入生产必须考虑以下几个关键方面这也是区分玩具与工具的核心。4.1 状态管理与持久化在 Demo 中State 存在于内存中会话结束就消失。在生产环境中你需要持久化 State。为什么重要支持长对话、故障恢复、用户会话管理。如何做LangGraph 支持与外部存储集成。你可以将 State 序列化如 JSON后存入数据库如 PostgreSQL、Redis。每次调用app.invoke()时先从数据库加载 State执行后再保存回去。关键是要确保 State 中每个字段都是可序列化的。4.2 工具生态的构建与安全智能体的能力取决于其工具集。构建一个安全、可靠、丰富的工具层至关重要。工具设计原则单一职责每个工具只做一件事并做好。良好描述工具的description必须清晰准确这是 LLM 能否正确调用它的关键。输入验证在工具函数内部对输入参数进行严格的类型和范围检查。错误处理工具调用可能失败网络超时、API限流必须有优雅的降级和重试机制。工具安全权限控制不是所有工具都对所有用户开放。需要建立工具-用户权限映射。沙箱环境对于执行代码、访问文件系统等高风险工具应在沙箱中运行。输入净化防止通过工具输入进行注入攻击。4.3 图的复杂度控制与性能优化图可以变得非常复杂但复杂的图也意味着更难调试和更慢的响应。模块化与子图LangGraph 支持子图Subgraph。将复杂的逻辑如一个完整的多轮问答子流程封装成一个子图使主图结构清晰。子图可以被编译和独立测试。异步执行对于可以并行执行的节点如同时检索多个不同的知识库应使用异步调用以提高性能。LangGraph 支持异步节点。超时与断路为每个节点或工具调用设置超时防止某个步骤卡死整个工作流。实现断路机制当连续失败次数过多时暂时禁用某个工具或路径。4.4 评估、监控与可观测性智能体的行为难以预测必须建立强大的监控体系。链路追踪Tracing记录每个节点的输入、输出、耗时和错误。LangSmithLangChain 的商业产品与此无缝集成是绝佳选择。开源方案可以考虑 OpenTelemetry。评估指标功能性最终答案是否正确需要人工或黄金数据集评估效率性耗时多少调用了多少次工具Token 消耗如何经济性每次调用的成本是多少稳定性失败率是多少日志与告警将关键事件如工具调用失败、高延迟、高成本记录到日志系统并设置告警。4.5 RAG 组件的深度优化智能体的“知识”部分RAG本身就是一个需要持续优化的子系统。检索质量分块策略根据文档类型调整分块大小和重叠度。向量模型评估不同嵌入模型在您领域数据上的效果。混合检索结合向量检索和关键词检索如 BM25提高召回率。重排序Re-ranking使用更精细的模型对检索出的 Top K 个片段进行重排序提升精度。上下文管理对于超长对话或多轮检索需要智能地管理上下文窗口选择性保留历史避免信息丢失或冗余。将 LangGraph 视为你编排智能体“思维过程”的蓝图而将 RAG、工具、LLM 等视为可供调用的“技能”和“记忆”。这种架构分离使得系统各部分的升级、替换和调试都变得可行。这才是面向未来的、可维护的提示词工程实践。它不再是与模型“斗智斗勇”的文字游戏而是构建可靠智能系统的扎实工程。
返回列表