基于LangChain的AI智能体开发实战:从ReAct模式到工程化部署
最近在尝试将大模型能力集成到实际业务系统时你是否也遇到过这样的困境模型调用接口复杂上下文管理混乱多轮对话状态难以维护更别提让AI自主调用工具完成任务了。从简单的API调用到构建一个能理解意图、规划步骤、执行工具、反思结果的智能体Agent中间的鸿沟远比想象中要大。本文将围绕Harness Engineering理念与Hermes Agent框架为你提供一套从零到一的完整实战指南。无论你是刚接触AI应用开发的初学者还是希望将大模型能力系统化落地的工程师都能通过本文掌握智能体AI Agent的核心技术并亲手搭建一个可运行的智能体项目。我们将从基础概念讲起逐步深入到环境搭建、核心组件开发、项目实战并涵盖部署优化与常见问题排查确保你能吃透并应用这套技术。1. 背景与核心概念为什么需要AI智能体与工程化框架在深入代码之前我们有必要厘清几个关键概念理解它们为何成为当前AI应用开发的热点。1.1 什么是AI智能体AI Agent简单来说一个AI智能体是一个能够感知环境、自主决策并执行行动以实现目标的软件实体。它不同于传统的“一问一答”式聊天机器人。核心区别在于自主性和工具使用能力。传统大模型调用用户输入问题 - 模型生成回答。模型只是一个被动的“文本生成器”。AI智能体用户下达目标如“帮我查一下北京明天的天气并推荐出门穿搭”- 智能体理解目标 -规划步骤先查天气再根据天气推荐穿搭-执行步骤调用天气API获取数据-反思结果检查数据是否完整是否需要补充查询- 最终生成符合用户目标的回答。智能体框架如 Hermes Agent的核心价值就是为大模型封装了这套“思考-行动-观察”的循环机制使其能够串联多个工具处理复杂任务。1.2 什么是Harness Engineering这是一个较新的工程理念其核心思想是像驾驭Harness马车一样去驾驭AI能力通过精心设计的“缰绳”框架、规范、流程来引导和控制AI的输出使其稳定、可靠、安全地服务于具体业务。它强调的不再是单纯调优模型本身而是构建一套围绕模型的工程体系。Harness Engineering 通常关注以下几个方面提示工程Prompt Engineering设计稳定、高效的提示词模板。工作流编排Workflow Orchestration将复杂的AI任务分解为可重复、可监控的步骤。工具集成Tool Integration让AI能够安全、可控地调用外部API、数据库或代码。评估与监控Evaluation Monitoring建立评估体系监控AI输出的质量、成本、延迟。安全与合规Safety Compliance防止幻觉Hallucination、注入攻击确保输出符合伦理与法规。将 Hermes Agent 这样的框架置于 Harness Engineering 的视角下我们就能更系统地思考如何构建企业级AI应用而不仅仅是做一个演示原型。1.3 Hermes Agent 框架简介Hermes Agent 是一个开源的AI智能体开发框架。它旨在降低构建复杂AI智能体的门槛提供了一套清晰的抽象和丰富的内置工具。其核心设计通常包括以下组件具体名称可能随版本变化但思想相通Agent Core智能体的核心逻辑负责管理记忆、决策循环。Tool/Ability定义智能体可以执行的动作如搜索、计算、读写文件等。Memory管理对话历史、上下文可能包括短期记忆和长期记忆。Planner将用户目标分解为具体的任务步骤。Executor负责执行规划好的任务步骤调用相应的工具。接下来我们将从零开始搭建开发环境并实现一个功能完整的智能体。2. 环境准备与版本说明为了确保示例的稳定性和可复现性我们选择在相对隔离的 Python 虚拟环境中进行。以下环境经过验证但不同版本可能存在细微差异请根据实际情况调整。基础环境操作系统Ubuntu 22.04 LTS / Windows 10/11 with WSL2 / macOS Monterey 及以上。本文以 Ubuntu/WSL2 环境为例。Python版本 3.9 或 3.10。推荐使用 3.10因其在AI生态中兼容性最好。避免使用 3.11 的早期版本可能遇到依赖冲突。包管理工具pip(21.0)代码编辑器VS Code、PyCharm 等均可。核心依赖版本关键由于 AI 领域库更新频繁锁定版本能避免大部分环境问题。我们将主要使用hermes-agent框架这里以其一个流行的开源实现为概念基础实际安装请以官方仓库为准和 OpenAI 的 API 作为大模型后端。创建一个requirements.txt文件来管理依赖# 核心AI与智能体框架 openai1.6.0 # 假设的 hermes-agent 包实际请替换为正确的包名例如agi-chain 或 langchain # 这里我们使用 langchain 和 langchain-community 来演示类似 Hermes Agent 的智能体构建因为它们是当前最流行的基础框架。 langchain0.1.0 langchain-community0.0.10 langchain-openai0.0.2 langchain-core0.1.0 # 工具类依赖 requests2.28.0 # 用于调用外部API python-dotenv1.0.0 # 管理环境变量 # 可选用于Web应用演示 fastapi0.104.0 uvicorn0.24.0 # 开发与工具 jupyter1.0.0 # 用于交互式实验重要提示hermes-agent作为一个示例框架名在公开的PyPI仓库中可能不存在。在实际项目中你可能需要使用langchain、autogen、crewai或其它具体的智能体框架。本文后续将基于langchain这一业界公认的标准框架来讲解智能体的核心概念和实现其思想与 Hermes Agent 倡导的“工程化驾驭AI”完全一致。请根据你的具体需求选择框架。3. 核心概念与框架原理拆解在动手编码前深入理解框架的运作原理至关重要。我们以langchain的智能体Agent模块为例它完美体现了 Harness Engineering 的思想。3.1 智能体的核心循环ReAct 模式最经典的智能体推理模式是ReAct (Reason Act)。其工作流程如下思考Think智能体分析当前目标、历史记录和可用工具决定下一步该做什么。行动Act智能体选择一个工具并执行传入必要的参数。观察Observe智能体接收工具执行的结果可能是成功的数据也可能是错误信息。循环基于观察结果智能体再次进入“思考”步骤直到任务完成或达到终止条件。在langchain中大模型LLM是“思考”的核心而Tool对象就是“行动”的载体。3.2 关键组件详解3.2.1 工具Tool工具是智能体与外界交互的桥梁。一个工具通常包含name工具的唯一标识。description对工具功能的清晰描述。这个描述至关重要因为LLM会根据描述来决定是否以及如何使用该工具。args_schema输入参数的JSON Schema定义帮助LLM生成正确的参数。_run或_arun方法工具的实际执行逻辑。# 示例一个简单的计算器工具 from langchain.tools import BaseTool from pydantic import BaseModel, Field from typing import Type class CalculatorInput(BaseModel): 计算器输入参数 a: float Field(description第一个数字) b: float Field(description第二个数字) operator: str Field(description运算符支持 , -, *, /) class CalculatorTool(BaseTool): name calculator description 用于执行两个数字之间的基本算术运算。输入必须包含两个数字和一个运算符。 args_schema: Type[BaseModel] CalculatorInput def _run(self, a: float, b: float, operator: str) - str: 同步执行 try: if operator : result a b elif operator -: result a - b elif operator *: result a * b elif operator /: if b 0: return 错误除数不能为零 result a / b else: return f错误不支持的运算符 {operator} return f计算结果{a} {operator} {b} {result} except Exception as e: return f计算过程中发生错误{str(e)} async def _arun(self, a: float, b: float, operator: str): 异步执行这里简单调用同步方法 return self._run(a, b, operator)3.2.2 智能体执行器AgentExecutorAgentExecutor是langchain中驱动 ReAct 循环的“发动机”。它负责初始化智能体包含LLM和工具列表。管理对话历史Memory。在每一步调用LLM进行思考。解析LLM的输出决定调用哪个工具或直接给出最终答案。处理工具执行结果并将其作为新的上下文传递给下一步的LLM。处理错误和终止条件如最大迭代次数。3.2.3 记忆Memory记忆使智能体拥有“上下文”感知能力。常见的记忆类型对话缓冲记忆ConversationBufferMemory保存完整的对话历史。简单但上下文长时成本高。对话摘要记忆ConversationSummaryMemoryLLM自动对历史对话进行摘要只保留关键信息节省token。向量存储记忆VectorStoreRetrieverMemory将历史对话存入向量数据库根据当前问题检索相关记忆适合超长上下文。4. 完整实战案例构建一个多功能个人助理智能体现在我们将综合运用以上知识构建一个能查询天气、搜索网络信息、进行简单计算的个人助理智能体。4.1 项目初始化与环境配置首先创建项目目录并安装依赖。# 1. 创建项目目录 mkdir my_ai_agent cd my_ai_agent # 2. 创建虚拟环境推荐 python -m venv venv # 3. 激活虚拟环境 # Linux/macOS source venv/bin/activate # Windows # venv\Scripts\activate # 4. 安装依赖 # 将前面提到的 requirements.txt 内容保存到当前目录 pip install -r requirements.txt # 5. 设置环境变量用于OpenAI API # 创建一个 .env 文件并填入你的 OpenAI API Key # OPENAI_API_KEYsk-your-actual-api-key-here.env文件内容OPENAI_API_KEY你的OpenAI_API密钥4.2 编写核心工具我们创建三个工具天气查询、网络搜索、计算器。计算器工具上面已经定义这里我们实现天气和搜索工具。注意以下工具需要接入真实API请先申请相关服务的API Key如 OpenWeatherMap, SerpAPI 或 Tavily Search。# file: tools/weather_tool.py import os import requests from langchain.tools import BaseTool from pydantic import BaseModel, Field from typing import Type class WeatherInput(BaseModel): city: str Field(description城市名称例如北京 Shanghai New York) class WeatherTool(BaseTool): name get_weather description 获取指定城市的当前天气情况。需要提供城市名称。 args_schema: Type[BaseModel] WeatherInput def _run(self, city: str) - str: # 示例使用 OpenWeatherMap API你需要注册并获取 API_KEY api_key os.getenv(OPENWEATHER_API_KEY) # 请在.env中添加 if not api_key: return 错误未配置 OpenWeatherMap API Key。 url fhttp://api.openweathermap.org/data/2.5/weather?q{city}appid{api_key}unitsmetriclangzh_cn try: response requests.get(url) data response.json() if response.status_code 200: weather_desc data[weather][0][description] temp data[main][temp] humidity data[main][humidity] return f{city}的天气{weather_desc}温度 {temp}°C湿度 {humidity}% else: return f获取天气失败{data.get(message, 未知错误)} except Exception as e: return f请求天气API时出错{str(e)} async def _arun(self, city: str): return self._run(city)# file: tools/search_tool.py import os from langchain.tools import BaseTool from langchain_community.utilities import SerpAPIWrapper from pydantic import BaseModel, Field from typing import Type class SearchInput(BaseModel): query: str Field(description需要搜索的关键词或问题) class SearchTool(BaseTool): name web_search description 在互联网上搜索最新信息。当需要获取实时、未知或最新数据时使用此工具。 args_schema: Type[BaseModel] SearchInput def _run(self, query: str) - str: # 使用 SerpAPI (Google Search) 或 Tavily Search # 这里以 SerpAPI 为例你需要注册并获取 API_KEY api_key os.getenv(SERPAPI_API_KEY) # 请在.env中添加 if not api_key: return 错误未配置 SerpAPI API Key。 search SerpAPIWrapper(serpapi_api_keyapi_key) try: result search.run(query) # 对结果进行精简避免返回过长文本 return result[:500] ... if len(result) 500 else result except Exception as e: return f搜索过程中出错{str(e)} async def _arun(self, query: str): return self._run(query)4.3 组装智能体现在我们将工具、LLM和记忆组装成一个完整的智能体。# file: agent_builder.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_react_agent from langchain.memory import ConversationBufferMemory from langchain.prompts import PromptTemplate from tools.weather_tool import WeatherTool from tools.search_tool import SearchTool from tools.calculator_tool import CalculatorTool # 假设calculator_tool.py已创建 # 加载环境变量 load_dotenv() def build_agent(): # 1. 初始化LLM # 使用 gpt-3.5-turbo 或 gpt-4注意控制成本 llm ChatOpenAI( modelgpt-3.5-turbo, temperature0, # 降低随机性使智能体行为更稳定 openai_api_keyos.getenv(OPENAI_API_KEY) ) # 2. 准备工具列表 tools [WeatherTool(), SearchTool(), CalculatorTool()] # 3. 创建提示词模板 # ReAct 框架的标准提示词告诉LLM如何思考和使用工具 prompt_template 你是一个强大的AI助手可以调用工具来帮助用户解决问题。 你可以使用的工具如下 {tools} 使用以下格式 问题用户输入的问题 思考你需要思考当前应该做什么解释为什么 行动需要调用的工具名称必须是以下之一[{tool_names}] 行动输入调用该工具所需的输入必须是严格的JSON格式 观察工具返回的结果 ... (这个 思考/行动/行动输入/观察 循环可以重复多次) 思考我现在知道了最终答案 最终答案对用户问题的最终、完整的回答 开始 之前的对话历史 {history} 问题{input} 思考{agent_scratchpad} prompt PromptTemplate.from_template(prompt_template) # 4. 创建记忆 memory ConversationBufferMemory(memory_keyhistory, return_messagesTrue) # 5. 创建智能体 # create_react_agent 是 LangChain 新版中创建智能体的方式 agent create_react_agent(llm, tools, prompt) # 6. 创建执行器 agent_executor AgentExecutor( agentagent, toolstools, memorymemory, verboseTrue, # 设置为True可以看到详细的思考过程调试时非常有用 handle_parsing_errorsTrue, # 处理LLM输出解析错误 max_iterations5, # 防止智能体陷入无限循环 early_stopping_methodgenerate # 当LLM直接生成最终答案时停止 ) return agent_executor if __name__ __main__: agent build_agent() # 测试对话 while True: try: user_input input(\n用户: ) if user_input.lower() in [quit, exit, q]: break response agent.invoke({input: user_input}) print(f\n助手: {response[output]}) except KeyboardInterrupt: break except Exception as e: print(f发生错误{e})4.4 运行与验证运行agent_builder.py脚本开始与你的智能体对话。python agent_builder.py预期交互示例用户: 北京今天天气怎么样 思考用户想知道北京的天气我需要使用天气查询工具。 行动get_weather 行动输入{city: 北京} 观察北京的天气晴温度 22°C湿度 35% 思考我已经获得了天气信息可以直接回答用户。 最终答案北京今天天气晴朗温度大约22摄氏度湿度35%是个好天气。 用户: 这个温度下穿什么衣服合适再帮我搜索一下最近的时尚穿搭建议。 思考用户问了两个问题。第一个关于穿衣建议我可以基于天气信息给出一般性建议。第二个问题需要最新的时尚信息我必须使用网络搜索工具。 行动web_search 行动输入{query: 2024春季 22度 日常穿搭建议} 观察根据时尚杂志和博主推荐22度左右的天气适合...搜索结果摘要 思考我有了天气数据和穿搭建议可以综合回答。 最终答案根据当前22°C的晴朗天气建议您穿长袖T恤或薄衬衫搭配一件轻薄外套或针织开衫下身可以穿休闲裤或牛仔裤。根据网络上的最新时尚建议今年春季流行...结合搜索结果的回答。通过verboseTrue你可以在控制台看到完整的 ReAct 循环日志这对于调试智能体的决策过程至关重要。4.5 进阶为智能体添加记忆和复杂规划上面的示例使用了简单的ConversationBufferMemory。对于更复杂的场景我们可以升级记忆系统并引入规划器Planner。# file: agent_advanced.py from langchain.agents import AgentExecutor, create_react_agent from langchain.memory import ConversationSummaryBufferMemory from langchain_openai import ChatOpenAI from langchain.prompts import MessagesPlaceholder from langchain.tools import Tool from langchain.chains import LLMMathChain import os from dotenv import load_dotenv load_dotenv() def build_advanced_agent(): llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 使用 LangChain 内置的数学工具链 llm_math LLMMathChain.from_llm(llmllm) math_tool Tool( nameCalculator, funcllm_math.run, description用于回答数学问题。输入应该是一个需要计算的数学表达式。 ) tools [math_tool, WeatherTool(), SearchTool()] # 使用摘要记忆节省token并保留长期上下文 memory ConversationSummaryBufferMemory( llmllm, memory_keychat_history, return_messagesTrue, max_token_limit1000 # 控制记忆的token数量 ) # 提示词中预留位置给聊天历史 prompt PromptTemplate.from_template( 你是一个专业的助理。你有以下工具 {tools} 对话历史摘要 {chat_history} 当前问题{input} 请按照以下格式思考 思考分析问题决定是否需要使用工具以及使用哪个。 行动工具名 行动输入工具输入 观察工具结果 ...重复直到问题解决 最终答案最终回复 开始 {agent_scratchpad} ) agent create_react_agent(llm, tools, prompt) agent_executor AgentExecutor( agentagent, toolstools, memorymemory, verboseTrue, max_iterations7, handle_parsing_errorsTrue ) return agent_executor5. 常见问题与排查思路在开发AI智能体过程中你一定会遇到各种问题。下表汇总了常见问题及其解决方法。问题现象可能原因排查与解决思路智能体不调用工具直接回答1. 工具描述不清晰。2. LLM的temperature参数过高随机性太强。3. 提示词Prompt未明确要求使用工具。1.优化工具描述确保description字段准确、具体说明工具的用途和输入格式。2.降低温度设置temperature0或0.1使输出更确定。3.强化提示词在提示词中明确写出“你必须使用工具来回答问题”或使用标准的ReAct格式提示。智能体陷入无限循环或达到最大迭代次数1. 工具返回的结果无法让LLM推导出答案。2. 任务过于复杂超出智能体规划能力。3. 工具执行出错但错误信息未被LLM理解。1.检查工具输出确保工具返回的是清晰、结构化的文本而不是错误堆栈或无关信息。2.简化任务或分步引导将复杂任务拆解或先让智能体完成子任务。3.增强错误处理在工具中返回更友好的错误提示如“未找到相关信息请尝试其他关键词”。4.调整max_iterations适当增加但需警惕成本。解析错误ValueError: Could not parse LLM outputLLM生成的输出不符合AgentExecutor预期的格式如Action: ...。1.开启verboseTrue查看LLM的原始输出确认格式是否正确。2.使用handle_parsing_errorsTrue让执行器尝试从解析错误中恢复。3.优化提示词格式确保格式指令清晰无误可以使用更严格的示例。API调用超时或网络错误1. 网络连接问题。2. 外部API服务不稳定或达到速率限制。3. 未正确设置API Key。1.添加重试机制在工具函数中使用retry装饰器或tenacity库。2.检查环境变量确认.env文件已加载且变量名正确。3.查看API文档确认端点、参数和速率限制。Token消耗过快成本高1. 对话历史Memory过长。2. 智能体循环次数过多。3. 工具返回的内容过于冗长。1.使用摘要记忆用ConversationSummaryBufferMemory替代ConversationBufferMemory。2.限制历史长度设置max_token_limit。3.精简工具输出让工具只返回核心信息过滤无关内容。4.使用更便宜的模型在非关键步骤使用gpt-3.5-turbo。工具执行成功但智能体给出的最终答案与结果不符LLM在生成最终答案时“遗忘”或“曲解”了工具返回的观察结果。1.检查提示词确保提示词中强调要基于“观察”来生成“最终答案”。2.简化观察文本过于复杂的观察可能干扰LLM。尝试用更简洁的语言总结工具结果。3.在最终答案前让LLM复述观察在提示词中增加一步“请总结你从工具中获得的信息”。6. 最佳实践与工程化建议Harness Engineering in Action遵循 Harness Engineering 理念将智能体开发从“玩具”升级为“工程”你需要关注以下方面6.1 提示词工程标准化模板化管理不要将提示词硬编码在代码中。使用PromptTemplate或将其存储在配置文件如YAML、JSON中便于版本控制和A/B测试。提供清晰示例在提示词中加入少量示例Few-Shot Learning能显著提升智能体使用工具的准确性。角色设定为智能体设定明确的角色如“严谨的数据分析师”、“幽默的旅行助手”使其行为更符合预期。6.2 工具设计的健壮性输入验证在工具的_run方法内部进行严格的参数验证和类型检查防止无效输入导致崩溃。优雅降级工具调用失败时应返回有意义的错误信息而不是抛出异常。例如“天气服务暂时不可用请稍后再试”。超时与重试为所有网络调用设置合理的超时并实现重试逻辑提高系统鲁棒性。权限与安全工具可能执行敏感操作如文件读写、数据库查询。务必实施最小权限原则并对用户输入进行消毒Sanitization防止注入攻击。6.3 系统监控与可观测性日志记录详细记录智能体的每一步决策思考、行动、观察这是调试和优化的重要依据。verboseTrue是开始生产环境需要接入结构化日志系统如JSON Logger。性能指标监控每次调用的Token消耗、响应时间、工具调用成功率、任务完成率。成本控制设置预算警报监控API调用费用。对于内部应用可以考虑使用开源的本地大模型如Qwen、Llama来降低成本。6.4 测试与评估单元测试工具为每个工具编写独立的单元测试模拟各种正常和异常输入。集成测试智能体构建一个测试用例集包含各种典型和边缘的用户问题定期运行确保智能体行为稳定。评估框架定义清晰的评估标准如答案准确性、工具调用正确率、用户满意度并定期进行人工或自动化评估。6.5 部署与扩展API服务化使用 FastAPI 或 Flask 将智能体封装成 RESTful API方便前端或其他服务集成。异步处理对于耗时较长的任务考虑使用异步智能体_arun方法和消息队列避免阻塞。多智能体协作对于极其复杂的任务可以设计多个 specialized 的智能体并通过一个“主控”智能体或工作流引擎来协调它们这就是CrewAI等框架所擅长的领域。从理解AI智能体的核心概念ReAct模式、工具、记忆到使用langchain框架一步步构建出一个能查天气、搜信息、做计算的多功能个人助理我们完成了一次完整的Harness Engineering实践。这不仅仅是调用一个API而是设计一个能够自主理解、规划并执行任务的智能系统。真正的挑战始于项目上线。如何保证智能体在成千上万次调用中依然稳定可靠如何评估并持续提升它的表现如何控制成本这些问题都需要你用工程化的思维去解决——设计健壮的工具、编写可维护的提示词、建立监控评估体系。这正是 Harness Engineering 的精髓所在不是对抗AI的“黑盒”特性而是通过精心的工程设计为它套上可靠的“缰绳”使其朝着我们设定的业务目标稳步前进。