资讯动态

LangChain Agent实现与优化:从手动到框架化开发

发布时间:2026/9/13 6:38:41 来源:尧图企业网站定制
1. 理解LangChain Agent的核心价值大语言模型LLM的函数调用能力正在改变AI应用的开发范式。当模型能够主动调用外部工具如数据库查询、API接口、计算引擎时AI系统就从简单的对话机器人进化成了能够自主完成复杂任务的智能体Agent。这种能力让AI真正融入了业务流程而不仅仅是提供文字回复。手动实现一个支持工具调用的Agent并不复杂但开发者需要处理大量重复性工作管理对话历史、处理多轮交互、执行工具调用、处理错误恢复等。这些通用逻辑在每个Agent项目中都会重复出现极大地降低了开发效率。LangChain框架通过两个核心组件解决了这个问题create_tool_calling_agent负责Agent的配置阶段AgentExecutor负责Agent的执行阶段这种分工让开发者可以专注于业务逻辑工具实现而将通用流程交给框架处理。下面我们通过一个完整的案例从手动实现开始逐步揭示LangChain Agent的工作原理。2. 手动实现Agent的核心流程让我们先看一个手动实现的火车票查询Agent示例。这个Agent需要完成两个核心功能查询当前日期根据日期和城市查询火车票余量2.1 基础工具定义首先定义两个工具函数import json from datetime import datetime def check_ticket(date: str, start: str, end: str) - str: 查询指定日期和区间的火车票余量 # 这里应该是调用12306或其他票务API的实际代码 # 为示例简化返回模拟数据 return f{date} {start}到{end}的余票G101(08:00) 二等座20张 def get_current_date() - str: 返回当前日期字符串 return str(datetime.now().date())2.2 工具描述准备为了让LLM知道可以调用哪些工具我们需要按照OpenAI的函数调用规范准备工具描述tools_description [ { type: function, function: { name: check_ticket, description: 查询指定日期和城市间的火车票余量, parameters: { type: object, properties: { date: {type: string, description: 查询日期格式YYYY-MM-DD}, start: {type: string, description: 出发站代码}, end: {type: string, description: 到达站代码} }, required: [date, start, end] } } }, { type: function, function: { name: get_current_date, description: 获取当前日期, parameters: {type: object, properties: {}} } } ]2.3 多轮对话处理核心的Agent逻辑是一个循环处理过程import openai def run_agent(query: str): messages [ {role: system, content: 你是一个火车票查询助手。城市编码北京-BJP上海-SHH}, {role: user, content: query} ] while True: response openai.ChatCompletion.create( modelgpt-4, messagesmessages, toolstools_description ) message response.choices[0].message messages.append(message) if not message.tool_calls: return message.content for tool_call in message.tool_calls: func_name tool_call.function.name args json.loads(tool_call.function.arguments) if func_name check_ticket: result check_ticket(**args) elif func_name get_current_date: result get_current_date() else: result 未知工具 messages.append({ role: tool, content: result, tool_call_id: tool_call.id })这个手动实现展示了Agent的核心工作流程模型决定何时调用工具开发者负责执行具体工具将工具结果反馈给模型循环直到得到最终答案3. LangChain的优雅实现现在让我们看看如何使用LangChain简化上述流程。主要使用两个关键组件3.1 使用tool装饰器定义工具LangChain提供了更简洁的工具定义方式from langchain_core.tools import tool tool def check_ticket(date: str, start: str, end: str) - str: 查询指定日期和城市间的火车票余量 return f{date} {start}到{end}的余票G101(08:00) 二等座20张 tool def get_current_date() - str: 获取当前日期 return str(datetime.now().date())tool装饰器会自动从函数签名和文档字符串生成完整的工具描述省去了手动编写JSON Schema的工作。3.2 创建提示模板定义Agent的对话模板预留agent_scratchpad用于记录中间步骤from langchain_core.prompts import ChatPromptTemplate prompt ChatPromptTemplate.from_messages([ (system, 你是一个火车票查询助手。城市编码北京-BJP上海-SHH), (human, {input}), (placeholder, {agent_scratchpad}), ])3.3 创建Agent和执行器将各个组件组合起来from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-4) tools [check_ticket, get_current_date] agent create_tool_calling_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue)3.4 执行查询result agent_executor.invoke({input: 查询今天北京到上海的火车票}) print(result[output])4. create_tool_calling_agent原理剖析create_tool_calling_agent完成了三个核心工作工具描述生成将Python函数转换为模型可理解的工具描述自动从函数签名提取参数类型使用文档字符串作为工具描述生成符合OpenAI规范的JSON Schema提示工程将工具信息整合到系统提示中将工具描述以自然语言形式加入系统消息预留agent_scratchpad占位符用于记录中间步骤优化提示结构提高工具调用准确性创建可执行对象返回一个配置好的Runnable包含LLM实例、工具映射、增强后的提示模板定义了标准的输入输出接口支持链式调用和组合5. AgentExecutor的运行机制AgentExecutor是一个状态机管理着Agent的完整生命周期初始化阶段验证工具列表设置最大迭代次数等参数准备运行时状态执行循环def _run(self, inputs): intermediate_steps [] for _ in range(self.max_iterations): # 构造完整输入 agent_input self._prepare_inputs(inputs, intermediate_steps) # 调用Agent获取下一步动作 output self.agent.invoke(agent_input) # 解析输出 next_step self._parse_output(output) # 检查是否结束 if next_step.return_values: return next_step.return_values # 执行工具调用 observation self._execute_tool(next_step.tool, next_step.input) # 记录步骤 intermediate_steps.append((next_step, observation)) # 达到最大迭代次数 return {output: 达到最大迭代次数}工具执行根据工具名找到对应的Python函数验证参数类型和格式执行函数并捕获异常格式化执行结果状态跟踪维护中间步骤列表管理对话历史处理错误和重试6. 高级应用与最佳实践6.1 自定义工具的高级用法结构化工具输出tool def search_flights(date: str, origin: str, destination: str) - dict: 查询航班信息 return { flights: [ {number: CA123, departure: 08:00, price: 1200}, {number: MU456, departure: 10:30, price: 980} ] }异步工具支持tool async def async_check_weather(city: str) - str: 查询城市天气 async with aiohttp.ClientSession() as session: async with session.get(fhttps://api.weather.com/{city}) as resp: return await resp.text()6.2 性能优化技巧批量处理工具调用agent_executor AgentExecutor( agentagent, toolstools, max_iterations10, early_stopping_methodgenerate, return_intermediate_stepsTrue )缓存工具结果from langchain.cache import InMemoryCache llm ChatOpenAI(modelgpt-4, cacheInMemoryCache())并发执行工具agent_executor AgentExecutor( agentagent, toolstools, parallelize_toolsTrue )6.3 调试与监控详细日志记录agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue )中间步骤检查result agent_executor.invoke( {input: 查询明天北京到上海的机票}, return_intermediate_stepsTrue ) for step in result[intermediate_steps]: print(step)性能分析from langchain.callbacks import tracing_v2_enabled with tracing_v2_enabled(): result agent_executor.invoke({input: ...})7. 常见问题与解决方案7.1 工具调用失败问题现象模型反复尝试调用不存在的工具解决方案检查工具描述是否准确增强系统提示中的工具说明添加工具不存在时的处理逻辑def safe_tool_execution(tool_name, args): try: return tool_map[tool_name](**args) except KeyError: return f工具{tool_name}不存在7.2 无限循环问题现象Agent无法自行终止解决方案设置合理的max_iterations添加循环检测逻辑优化提示工程agent_executor AgentExecutor( agentagent, toolstools, max_iterations15, early_stopping_methodgenerate )7.3 参数解析错误问题现象工具调用时参数类型不匹配解决方案在工具描述中明确参数类型添加参数验证逻辑提供更清晰的错误反馈tool def check_ticket(date: str, start: str, end: str) - str: 查询火车票 try: datetime.strptime(date, %Y-%m-%d) except ValueError: return 日期格式错误请使用YYYY-MM-DD格式 # 其余逻辑...8. 架构设计与实现考量8.1 LangChain Agent的组件设计核心接口class Agent: def plan( self, intermediate_steps: List[Tuple[AgentAction, str]], **kwargs ) - Union[AgentAction, AgentFinish]: pass工具抽象class BaseTool: name: str description: str args_schema: Type[BaseModel] def _run(self, *args, **kwargs) - Any: pass执行流程用户输入 → Agent.plan()生成动作 → 执行工具 → 记录结果 → 循环直到AgentFinish8.2 与原生函数调用的对比特性原生实现LangChain工具定义手动JSONtool装饰器提示工程完全手动自动增强多轮对话手动管理自动处理错误处理自行实现内置机制可观测性需要开发开箱即用扩展性高中等开发效率低高8.3 性能考量延迟优化工具并行执行模型响应缓存精简提示内容资源管理工具超时设置内存使用监控并发请求限制成本控制限制最大迭代次数监控token使用选择性记录日志在实际项目中我发现最影响Agent性能的因素往往是工具的执行时间。一个耗时的API调用会阻塞整个Agent流程。因此对于IO密集型工具强烈建议实现异步版本或者添加超时机制。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价