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

资讯详情

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

从LangChain到LangGraph:手把手构建AI智能体系统

从LangChain到LangGraph:手把手构建AI智能体系统 在上一篇文章中我们探讨了大语言模型LLM工程的基础概念、核心组件以及RAG检索增强生成架构的搭建。如果你已经成功搭建了一个能够回答问题的知识库那么恭喜你你已经迈出了坚实的第一步。然而一个真正智能、能在复杂环境中自主行动的AI系统远不止于“问答”。它需要能够感知环境、规划任务、调用工具并执行决策——这就是智能体Agent的世界。本文将作为“大语言模型工程”系列的第二部分我们将深入智能体开发的核心。从LangChain的AgentExecutor到新兴的LangGraph工作流从简单的工具调用到复杂的多智能体协作我们将手把手带你构建一个能够自主处理现实任务的智能体系统。无论你是希望将AI能力集成到现有业务中还是想探索下一代AI应用的可能性本文都将提供从理论到实践的完整路径。1. 从问答到行动理解智能体Agent在传统的LLM应用中模型更像一个“知识渊博的顾问”你提问它回答。但智能体赋予了LLM“手和脚”使其成为一个能够主动执行任务的“智能员工”。1.1 智能体的核心概念一个智能体通常由以下几个核心部分组成大脑LLM Core负责理解指令、进行推理和做出决策。这是智能体的“思考”部分。工具Tools智能体可以调用的外部函数或API。例如搜索网络、查询数据库、执行计算、调用其他服务等。这是智能体的“手”。记忆Memory存储与当前会话或任务相关的历史信息包括对话历史、工具调用结果、中间状态等。这是智能体的“经验”。规划器Planner对于复杂任务智能体需要将其分解为一系列子步骤。规划器负责制定这个执行计划。执行器Executor按照规划器的步骤依次调用工具、处理结果并决定下一步行动。1.2 智能体 vs. 传统程序 vs. RAG为了更清晰地理解智能体的定位我们可以做一个简单的对比特性传统程序RAG 系统智能体系统决策方式确定性逻辑if-else规则基于检索内容的生成一次调用基于LLM推理的循环决策灵活性低规则固定中回答基于检索内容高能根据环境动态调整策略可执行动作程序内定义的固定操作仅文本生成可调用任意外部工具适用场景流程固定、逻辑明确的任务知识密集型问答、文档总结复杂、多步骤、需交互的任务示例计算器、数据ETL脚本公司知识库客服、论文解读助手自动数据分析报告生成、旅行规划助手、自动化运维机器人智能体的本质是将LLM的推理能力与外部工具的执行能力相结合通过循环的“思考-行动-观察”过程最终完成一个用户目标。2. 环境准备与核心框架选择在开始构建智能体之前我们需要搭建开发环境并选择合适的框架。目前LangChain和LangGraph是构建智能体最流行和强大的生态系统。2.1 环境与依赖安装我们使用Python进行开发。建议使用Python 3.10或更高版本并创建一个虚拟环境。# 创建并激活虚拟环境 (可选) python -m venv llm-agent-env source llm-agent-env/bin/activate # Linux/Mac # llm-agent-env\Scripts\activate # Windows # 安装核心依赖 pip install langchain langchain-community langgraph # 安装一个LLM提供商这里以OpenAI为例需自行准备API Key pip install openai # 安装一些可能用到的工具库 pip install requests duckduckgo-search wikipedia2.2 框架简介LangChain 与 LangGraphLangChain提供了构建LLM应用的基础模块如模型I/O、提示模板、链、记忆、索引以及智能体Agent。其AgentExecutor是早期构建智能体的标准方式。LangGraph建立在LangChain之上用于构建有状态、多智能体Multi-Agent工作流。它用图Graph的概念来定义智能体之间的交互和状态流转非常适合复杂、循环的任务。如何选择对于单一智能体、任务相对线性的场景如先搜索再总结使用LangChain的AgentExecutor足够简单高效。对于需要复杂编排、多角色协作、循环审批或具有严格状态管理的场景如一个智能体写代码另一个智能体评审LangGraph是更现代、更强大的选择。本文后续将重点介绍LangGraph。2.3 配置LLM模型你需要一个LLM的API Key。本文以OpenAI GPT-4为例但你也可以轻松替换为Anthropic Claude、Google Gemini或本地部署的Ollama模型。# 文件config.py 或直接在代码开头设置 import os from langchain_openai import ChatOpenAI # 设置你的OpenAI API Key os.environ[OPENAI_API_KEY] your-api-key-here # 初始化LLM。对于智能体任务建议使用能力更强的模型如gpt-4-turbo llm ChatOpenAI(modelgpt-4-turbo-preview, temperature0) # temperature0 使输出更确定适合执行任务。可以调高以获得更多创造性。3. 构建你的第一个智能体LangChain AgentExecutor让我们从经典的LangChain智能体开始直观感受“思考-行动”循环。3.1 定义工具Tools工具是智能体能力的延伸。我们定义两个简单的工具一个计算器和一个网络搜索器。# 文件simple_agent.py from langchain.agents import tool from langchain_community.tools import DuckDuckGoSearchRun import math # 1. 自定义工具计算器 tool def calculator(expression: str) - str: 执行数学计算。输入是一个数学表达式字符串例如 ‘(3 5) * 2‘。 try: # 警告使用eval存在安全风险仅用于演示。生产环境应使用安全库如ast.literal_eval或专门数学库。 result eval(expression, {__builtins__: None}, {math: math}) return f计算结果: {result} except Exception as e: return f计算错误: {e} # 2. 使用社区工具网络搜索 search DuckDuckGoSearchRun() # 将工具放入列表 tools [calculator, search]3.2 创建智能体Agent我们使用LangChain提供的create_react_agent函数。ReActReasoning Acting是一种经典的智能体范式让模型在思考中显式地规划行动。# 续 simple_agent.py from langchain import hub from langchain.agents import create_react_agent, AgentExecutor # 从LangChain Hub拉取一个适合ReAct的提示模板 prompt hub.pull(hwchase17/react) # 创建智能体 agent create_react_agent(llm, tools, prompt) # 创建执行器它负责运行智能体的循环 agent_executor AgentExecutor(agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue) # verboseTrue 会打印出详细的思考过程便于调试。3.3 运行与观察现在让我们向智能体提问一个需要组合使用工具的问题。# 续 simple_agent.py if __name__ __main__: question 请先搜索‘Python之父的最新演讲主题’然后用计算器计算这个主题标题的字符数乘以2。 try: result agent_executor.invoke({input: question}) print(\n 最终回答 ) print(result[output]) except Exception as e: print(f执行出错: {e})运行结果与过程分析verbose输出节选 Entering new AgentExecutor chain... 我需要回答一个包含两个步骤的问题先搜索再计算。 我应该使用搜索工具来获取信息。 Action: DuckDuckGoSearchRun Action Input: Python之父的最新演讲主题 Observation: 根据搜索结果Python之父Guido van Rossum最近的一次公开演讲主题可能是“Python in 2024: The State of the Union”... Thought: 我得到了演讲主题。现在需要计算这个主题的字符数然后乘以2。主题是“Python in 2024: The State of the Union”。让我先计算字符数包括空格和标点。 Action: calculator Action Input: len(Python in 2024: The State of the Union) * 2 Observation: 计算结果: 78 Thought: 我已经完成了所有步骤。现在可以给出最终答案。 Final Answer: Python之父Guido van Rossum近期的一个演讲主题是“Python in 2024: The State of the Union”。该主题标题的字符数包括空格和标点为39乘以2后结果是78。 最终回答 Python之父Guido van Rossum近期的一个演讲主题是“Python in 2024: The State of the Union”。该主题标题的字符数包括空格和标点为39乘以2后结果是78。你可以清晰地看到智能体的“思考Thought”、“行动Action”、“观察Observation”循环。这就是智能体工作的核心机制。4. 进阶使用LangGraph构建可控工作流智能体AgentExecutor虽然简单但对于复杂流程的控制力较弱。LangGraph通过“图”和“状态”的概念让你能像设计流程图一样设计智能体的行为。4.1 LangGraph核心概念StateGraph 与 Nodes在LangGraph中你定义一个State状态它是一个字典包含任务执行过程中的所有信息如用户输入、中间结果、对话历史。然后你创建多个Node节点每个节点是一个函数负责处理状态的一部分。最后你用StateGraph将这些节点连接起来并定义流转条件Edges。4.2 实战构建一个带“人工审核”的写作智能体假设我们需要一个智能体来撰写技术博客大纲但在发布前需要经过“人工审核”节点模拟人类干预。第1步定义状态State# 文件writing_agent.py from typing import TypedDict, Annotated, List import operator from langgraph.graph import StateGraph, END # 定义状态结构 class AgentState(TypedDict): # 用户原始需求 user_request: str # 由规划器生成的任务列表 task_list: List[str] # 当前执行的任务索引 current_task_index: int # 收集每个任务的执行结果 task_results: Annotated[List[str], operator.add] # 最终生成的大纲 outline: str # 审核意见 review_feedback: str # 最终输出 final_output: str第2步创建节点Nodes我们将创建四个节点规划器Planner、执行器Executor、审核员Reviewer、修订器Revisor。# 续 writing_agent.py from langchain_core.messages import HumanMessage, SystemMessage # 节点1规划器 - 将用户需求分解为具体任务 def planner_node(state: AgentState): 分析用户需求拆解成可执行的步骤。 print(f\n[规划器] 正在分析需求: {state[user_request]}) prompt f 用户希望撰写一篇技术博客。需求是{state[user_request]} 请将整个写作过程分解为3-4个清晰的、顺序执行的任务步骤。 以列表形式返回例如 1. 确定博客核心主题与目标读者。 2. 设计博客的章节结构大纲。 3. 为每个章节搜集关键要点。 4. 撰写开场白和结尾总结。 messages [SystemMessage(content你是一个专业的写作规划助手。), HumanMessage(contentprompt)] response llm.invoke(messages) task_list [line.strip() for line in response.content.split(\n) if line.strip() and line[0].isdigit()] print(f[规划器] 生成任务列表: {task_list}) return {task_list: task_list, current_task_index: 0, task_results: []} # 节点2执行器 - 执行当前任务 def executor_node(state: AgentState): 执行当前索引指向的任务。 idx state[current_task_index] task state[task_list][idx] print(f\n[执行器] 正在执行任务 {idx1}: {task}) # 这里简单模拟执行实际可以调用更复杂的工具或LLM prompt f基于写作需求‘{state[user_request]}’请完成以下子任务{task}。请提供详细、可操作的结果。 response llm.invoke([HumanMessage(contentprompt)]) result response.content print(f[执行器] 任务结果: {result[:100]}...) # 打印前100字符 return {task_results: [result], current_task_index: idx 1} # 节点3审核员 - 模拟人工审核 def reviewer_node(state: AgentState): 审核生成的大纲提出修改意见。 outline state[outline] print(f\n[审核员] 正在审核大纲...) prompt f 你是一名资深技术编辑。请审核以下博客大纲 {outline} 请提供具体的修改意见例如结构是否合理重点是否突出有无遗漏关键点 如果大纲质量很好可以直接说‘通过审核’。 response llm.invoke([HumanMessage(contentprompt)]) feedback response.content print(f[审核员] 审核意见: {feedback[:150]}...) return {review_feedback: feedback} # 节点4修订器 - 根据审核意见修改大纲 def revisor_node(state: AgentState): 根据审核意见修订大纲。 outline state[outline] feedback state[review_feedback] print(f\n[修订器] 正在根据意见修订大纲...) prompt f 原始大纲 {outline} 审核意见 {feedback} 请根据审核意见输出修订后的完整大纲。 response llm.invoke([HumanMessage(contentprompt)]) revised_outline response.content print(f[修订器] 修订完成。) return {outline: revised_outline, final_output: revised_outline}第3步构建图Graph并定义流转逻辑# 续 writing_agent.py # 初始化图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(planner, planner_node) workflow.add_node(executor, executor_node) workflow.add_node(reviewer, reviewer_node) workflow.add_node(revisor, revisor_node) # 设置入口点 workflow.set_entry_point(planner) # 定义边条件流转 # 规划后进入执行阶段 workflow.add_edge(planner, executor) # 执行器节点后判断是否所有任务都执行完了 def decide_after_execute(state: AgentState): if state[current_task_index] len(state[task_list]): # 所有任务完成汇总结果生成大纲然后进入审核 print(\n[决策] 所有任务执行完毕开始生成大纲并进入审核。) # 简单地将所有任务结果拼接作为大纲初稿 draft_outline \n.join([f任务{i1}结果{res[:200]} for i, res in enumerate(state[task_results])]) # 可以在这里让LLM基于结果提炼一个正式大纲此处为演示简化处理 state[outline] draft_outline return reviewer else: # 还有任务继续执行 return executor workflow.add_conditional_edges( executor, decide_after_execute, { reviewer: reviewer, executor: executor, } ) # 审核后根据意见决定是结束还是修订 def decide_after_review(state: AgentState): feedback state[review_feedback] if 通过审核 in feedback or 很好 in feedback: print(\n[决策] 审核通过流程结束。) return END else: print(\n[决策] 审核未通过进入修订环节。) return revisor workflow.add_conditional_edges( reviewer, decide_after_review, { END: END, revisor: revisor, } ) # 修订后再次进入审核形成循环 workflow.add_edge(revisor, reviewer) # 编译图 app workflow.compile()第4步运行工作流# 续 writing_agent.py if __name__ __main__: # 初始化状态 initial_state AgentState( user_request写一篇关于如何使用LangGraph构建AI智能体的教程博客, task_list[], current_task_index0, task_results[], outline, review_feedback, final_output ) print( 启动写作智能体工作流 ) # 运行图 final_state app.invoke(initial_state, config{recursion_limit: 10}) print(\n 工作流执行完毕 ) print(\n--- 最终生成的大纲 ---) print(final_state.get(final_output, 无输出))这个例子展示了LangGraph如何清晰地管理复杂状态和循环逻辑审核-修订-再审核。你可以通过修改decide_after_review函数中的条件或增加更多节点如“发布器”、“数据分析器”来构建极其复杂和强大的多智能体工作流。5. 工程化与最佳实践构建玩具智能体很有趣但要将其用于生产环境必须考虑工程化问题。5.1 智能体的稳定性与可靠性错误处理与重试工具调用可能失败网络超时、API限流。必须在工具函数和智能体循环中加入健壮的错误处理与指数退避重试机制。from tenacity import retry, stop_after_attempt, wait_exponential retry(stopstop_after_attempt(3), waitwait_exponential(multiplier1, min4, max10)) tool def call_unstable_api(query: str) - str: response requests.post(api_url, json{query: query}, timeout10) response.raise_for_status() return response.text超时控制为整个智能体调用或单个工具调用设置超时避免无限循环或长时间等待。验证与过滤对智能体生成的行动指令如要调用的函数名、参数进行严格验证防止注入攻击或非法操作。5.2 提示工程Prompt Engineering智能体的表现极度依赖提示词。系统提示System Prompt明确智能体的角色、职责、约束和输出格式。例如“你是一个谨慎的助手在调用工具前必须充分思考。你不能执行任何破坏性操作。”工具描述为每个工具编写清晰、准确的描述说明其功能、输入格式和输出示例。少样本示例Few-Shot在提示词中提供几个“思考-行动-观察”的完整示例能显著提升智能体使用工具的准确性。5.3 记忆Memory管理智能体需要记住上下文。LangChain提供了多种记忆方案对话记忆存储用户和AI的对话历史。ConversationBufferMemory,ConversationSummaryMemory。向量记忆将历史信息存入向量数据库需要时检索。适用于长上下文。自定义记忆在LangGraph的State中你可以设计任何结构来存储需要记忆的信息。5.4 监控、评估与成本控制日志记录详细记录每个智能体的输入、输出、中间思考步骤、工具调用及结果。这对于调试和审计至关重要。评估指标定义如何评估智能体的表现。是任务完成率用户满意度还是结果准确性需要设计自动化或人工评估流程。成本估算智能体可能进行多次LLM调用和工具调用。必须估算单次任务的平均Token消耗和API成本并设置预算上限。6. 常见问题与排查思路在开发智能体时你可能会遇到以下典型问题问题现象可能原因排查与解决思路智能体陷入循环不断重复同一个工具调用。1. 提示词未明确停止条件。2. 工具返回的结果无法让LLM做出新决策。3. 图LangGraph的边逻辑有误形成死循环。1. 在系统提示中强调“在获得最终答案后必须输出Final Answer:”。2. 检查工具输出是否清晰、格式正确。3. 调试LangGraph的conditional_edges函数确保有指向END的路径。智能体拒绝调用工具直接给出猜测性答案。1. 工具描述不清LLM不理解何时使用。2. 模型温度temperature过高导致行为不稳定。3. 示例Few-Shot不足。1. 重写工具描述明确使用场景和输入格式。2. 将temperature调低如0.1。3. 在提示词中加入正确调用工具的示例。LangGraph报错RecursionLimit reached。工作流图中存在无限循环超过了默认的递归限制通常为25。1. 检查图中是否存在未正确终止的循环如审核-修订循环没有通过条件。2. 在app.invoke()的config中增加{recursion_limit: 50}但这只是临时解决需找到循环根源。工具调用失败如网络错误。工具依赖的外部服务不稳定或参数错误。1. 在工具函数内部实现重试和异常捕获。2. 让智能体具备错误处理能力在提示词中教导它“如果工具X失败可以尝试工具Y或向用户报告”。智能体输出的行动指令格式错误无法解析。LLM没有严格按照要求的格式如JSON特定关键词输出。1. 使用LangChain的OutputParser来强制格式化输出。2. 在提示词中更严格地规定输出格式并使用少样本示例。7. 总结与展望智能体开发的未来通过本文我们完成了从理解智能体概念到使用LangChain构建简单智能体再到利用LangGraph设计复杂工作流的完整旅程。智能体开发的核心在于将LLM的通用推理能力与专用工具的执行能力通过一个可编程的“循环控制器”有机结合。下一步学习路线建议深入框架研究LangGraph的更多特性如持久化检查点Checkpoint、并行节点、分支与合并。探索多智能体构建多个具有不同角色的智能体如“研究员”、“写手”、“评审员”让它们通过消息传递进行协作。集成真实工具将智能体与你公司的内部API、数据库、云服务连接起来解决实际业务问题。评估与优化建立一套评估体系用数据驱动的方式迭代提示词、工具集和工作流设计。关注新兴架构了解如Microsoft的AutoGen、CrewAI等其他多智能体框架以及模型上下文推理MCP等新协议。智能体技术正在快速发展从自动编码助手、数据分析机器人到完全自主的虚拟员工其应用场景无限广阔。成功的智能体工程不再是简单的API调用而是涉及提示工程、软件架构、可靠性设计和人机交互的综合学科。现在你已经掌握了核心的构建方法接下来就是发挥创意用代码将智能体的潜力转化为现实价值的时候了。
返回列表