从零构建AI Agent:核心架构、开发实践与工程化指南

发布时间:2026/7/6 22:55:59
从零构建AI Agent:核心架构、开发实践与工程化指南 1. 项目概述为什么“从零构建 AI Agent”是当下开发者的必修课最近和不少同行交流发现一个挺有意思的现象大家聊起大模型已经从最初的“哪个模型效果最好”的惊叹逐渐转向了“怎么用它来真正解决我的业务问题”的务实思考。这背后反映的正是从“玩模型”到“做应用”的认知跃迁。而“AI Agent”或者说智能体正是这个跃迁过程中最核心的载体。它不再是一个简单的问答接口而是一个能感知、规划、决策、执行并持续学习的自主系统。简单来说它让大模型从一个“聪明的百科全书”变成了一个能帮你“动手干活”的虚拟员工。我之所以想深入聊聊“从零构建”这个话题是因为我发现很多开发者包括我自己在早期都容易陷入两个误区。要么是觉得过于神秘被各种框架和论文吓退要么是过于轻视以为简单套个API就能做出有用的东西。结果往往是要么迟迟不敢动手要么做出来的东西脆弱不堪一碰就碎。这个项目就是想和你一起用最接地气的方式亲手把一个AI Agent从概念草图变成能稳定运行的代码。我们会聚焦于LLM大语言模型的应用开发实践这意味着我们关心的是如何利用现有的强大模型能力结合工程化的思维去构建可靠、可用的智能应用而不是去从头训练一个模型。这个过程适合所有对AI应用开发感兴趣的开发者无论你是前端、后端还是全栈。你不需要是机器学习专家但需要对编程有基本了解并且怀有强烈的好奇心和动手欲望。我们将一起拆解Agent的核心组件理解其工作流并最终实现一个具备基础能力的原型。相信我当你亲手完成第一个能连贯执行多步任务的Agent时那种“原来如此”的成就感会远超单纯调用一个API。2. 核心架构设计拆解AI Agent的“五脏六腑”构建一个AI Agent有点像组装一台精密的机器人。你不能只给它一个聪明的大脑LLM就指望它什么都会。它还需要感知环境的“感官”、规划行动的“思维链”、调用工具的“手脚”以及记忆历史的“经验库”。一个健壮的Agent架构必须将这些模块清晰地解耦。2.1 大脑核心LLM的选型与角色设定LLM是Agent的决策核心但“选哪个模型”和“怎么用这个模型”是两回事。对于大多数应用开发场景我建议的选型思路是在效果、成本、延迟和可控性之间寻找平衡点。云端通用大模型如GPT-4、Claude 3效果顶尖功能全面支持多模态、长上下文等开发速度快。这是快速原型验证和效果上限的标杆。但成本较高API调用有延迟且对于数据隐私要求极高的场景需要谨慎。云端专用或优化模型如特定领域的微调模型在特定任务上可能表现更精准、成本更低。需要关注云服务商提供的行业模型。本地部署的开源模型如Llama 3、Qwen、DeepSeek数据完全私有无网络延迟长期成本可能更低。但对硬件有要求需要一定的部署和运维能力且同等参数规模下效果可能略逊于顶级闭源模型。我的实操心得是从云端顶级模型开始验证核心逻辑再根据需求向成本或隐私端迁移。先用GPT-4或Claude快速跑通你Agent的整个工作流确保你的架构设计是可行的。当逻辑稳定后再尝试用GPT-3.5-Turbo或开源的70亿参数模型如Qwen2-7B进行替代和优化以降低成本。选定模型后更关键的一步是角色设定System Prompt。这是告诉LLM“你是谁”以及“你该如何行事”的宪法。一个模糊的指令会导致行为不可控。例如一个数据分析Agent的System Prompt应该是你是一个专业的数据分析助手。你的核心职责是帮助用户理解数据、回答问题并生成可视化建议。 你必须遵循以下原则 1. 当用户提供数据或数据相关问题时首先尝试理解其结构和含义。 2. 在给出任何分析前必须确认你的理解是否正确可以简要复述用户的问题。 3. 你可以建议进行哪些类型的分析如趋势分析、对比分析、分布分析。 4. 当建议可视化时必须明确说明图表类型如折线图、柱状图、散点图和理由。 5. 如果用户的问题无法仅通过现有数据回答请清晰指出需要补充哪些信息。 6. 所有输出必须专业、简洁、以事实为依据避免主观臆测。这个Prompt明确了角色、边界、工作流程和输出规范比简单的“你是一个数据分析AI”要有效得多。2.2 感知与执行工具Tools的抽象与集成LLM本身是“思想上的巨人行动上的矮子”。它知道“应该去查天气”但自己不会调用API。这就需要工具Tools机制。将外部能力搜索、计算、数据库查询、API调用封装成统一的工具接口供LLM调用。工具设计的关键在于抽象和描述。每个工具应该有一个清晰的函数签名和自然语言描述。例如一个查询天气的工具可以这样定义# 工具函数 def get_weather(city: str, date: str None) - str: 获取指定城市的天气信息。 参数: city: 城市名称例如“北京”、“上海”。 date: 查询日期格式为‘YYYY-MM-DD’。默认为None表示查询当前天气。 返回: 一个描述天气状况的字符串。 # 实际调用天气API的逻辑... pass # 给LLM的工具描述通常由框架自动生成或手动编写 weather_tool_description { name: get_weather, description: 根据城市名称和可选日期查询天气信息。, parameters: { type: object, properties: { city: {type: string, description: 要查询天气的城市名}, date: {type: string, description: 查询日期格式为YYYY-MM-DD默认为今天} }, required: [city] } }LLM根据用户请求“北京明天天气怎么样”和工具描述会生成一个结构化的调用请求如{name: get_weather, arguments: {city: 北京, date: 2023-10-27}}然后由Agent的执行器去调用真实的函数并返回结果。注意工具的描述至关重要。描述不清会导致LLM错误调用或不敢调用。务必用LLM能理解的自然语言清晰说明工具的用途、参数含义和返回值。2.3 记忆与思考对话历史与思维链Chain-of-Thought一个没有记忆的Agent每次对话都是全新的开始这显然不符合“智能”的期待。记忆Memory模块负责维护对话历史、上下文信息以及Agent自身的状态。短期记忆通常指当前会话的对话历史。实现方式简单就是将之前的问答对作为上下文喂给LLM。但要注意上下文长度限制需要做摘要或滑动窗口管理。长期记忆可以理解为知识库或向量数据库。当Agent需要处理超出模型训练数据或本次对话的信息时如公司内部文档、用户个人偏好就需要从这里检索。例如使用ChromaDB或Pinecone存储文档块用户提问时先检索相关片段再连同问题和片段一起交给LLM生成答案。而思维链CoT则是让LLM“把思考过程说出来”的技术。对于复杂任务直接要求LLM给出最终答案容易出错。我们可以通过Prompt引导它先分解任务、逐步推理。在Agent框架中这常常体现为规划Planning步骤。例如面对“帮我分析一下上季度销售数据并写一份总结报告”这样的复杂请求一个具备规划能力的Agent会先输出一个计划从数据库获取上季度销售数据。计算关键指标总销售额、环比增长率、Top 10产品等。分析增长或下降的主要原因。根据分析结果起草报告大纲。填充大纲内容生成完整报告。然后它再逐步执行这个计划每一步都可能调用相应的工具。这样不仅提高了任务完成的可靠性也让整个过程更透明、可调试。3. 开发实践手把手构建一个任务执行型Agent理论说了这么多是时候动手了。我们以构建一个“智能日程管理与信息查询助手”为例贯穿整个开发流程。这个Agent能理解用户关于时间、日程、天气、百科等综合请求并协调不同工具来完成。3.1 环境搭建与框架选型工欲善其事必先利其器。目前AI Agent开发框架生态丰富各有侧重。LangChain/LangGraph生态最丰富模块化设计灵活性极高但学习曲线较陡需要自己组装和调试的部件较多。LlamaIndex专注于数据检索和增强RAG场景在此领域非常强大。Semantic Kernel微软出品与.NET生态结合紧密概念清晰。AutoGen由微软推出专注于多Agent协作场景适合构建复杂的多角色对话系统。简易自研对于功能明确的简单Agent直接使用OpenAI的Function Calling或Anthropic的Tools API配合自己的逻辑循环可能是最轻量、最可控的方式。对于初学者我建议两条路径想快速理解核心概念从OpenAI Function Calling自研开始想构建复杂、可扩展的系统从LangChain入手。这里我们选择后者进行演示因为它最能体现Agent的各个组件。首先准备环境# 创建虚拟环境推荐 python -m venv agent_env source agent_env/bin/activate # Linux/Mac # agent_env\Scripts\activate # Windows # 安装核心依赖 pip install langchain langchain-openai langchain-community pip install python-dotenv # 用于管理API密钥在项目根目录创建.env文件存放你的API密钥OPENAI_API_KEYsk-your-openai-key-here3.2 核心组件实现工具、记忆与逻辑循环我们首先实现几个核心工具查天气、查时间、搜索百科。# tools.py import requests from datetime import datetime from langchain.tools import tool import wikipedia tool def get_current_time(timezone: str Asia/Shanghai) - str: 获取指定时区的当前时间。timezone是时区名称例如‘Asia/Shanghai’或‘America/New_York’。 # 这里简化处理实际应用中应使用pytz等库 now datetime.now() return f当前时间{timezone}是{now.strftime(%Y-%m-%d %H:%M:%S)} tool def search_wikipedia(query: str) - str: 使用维基百科搜索一个主题的摘要。query是搜索关键词。 try: # 设置语言为中文 wikipedia.set_lang(zh) summary wikipedia.summary(query, sentences2) return summary except wikipedia.exceptions.DisambiguationError as e: return f“您查询的‘{query}’可能指代多个条目请更具体一些。例如{e.options[:3]}” except wikipedia.exceptions.PageError: return f“未找到关于‘{query}’的维基百科页面。” except Exception as e: return f“搜索时出现错误{str(e)}” # 天气工具需要依赖一个天气API这里用模拟函数代替 tool def get_weather_forecast(city: str) - str: 获取城市的天气预报。city是城市名称如‘北京’、‘上海’。””” # 模拟API返回 weather_data { 北京: 北京今天晴转多云气温15-25°C南风2-3级。, 上海: 上海今天阴有小雨气温18-22°C东风3-4级。, 广州: 广州今天雷阵雨气温24-30°C南风1-2级。 } return weather_data.get(city, f“暂未找到{city}的天气信息。”)接下来我们设置记忆和LLM。这里使用简单的对话缓冲记忆。# agent_core.py from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from tools import get_current_time, search_wikipedia, get_weather_forecast import os from dotenv import load_dotenv load_dotenv() # 1. 初始化LLM llm ChatOpenAI(modelgpt-3.5-turbo-0125, temperature0, openai_api_keyos.getenv(OPENAI_API_KEY)) # 2. 定义工具列表 tools [get_current_time, search_wikipedia, get_weather_forecast] # 3. 创建Prompt模板包含系统指令、聊天历史、用户输入和工具占位符 prompt ChatPromptTemplate.from_messages([ (system, 你是一个乐于助人的智能助理可以帮用户查询时间、天气和百科知识。 请根据用户的问题谨慎地选择使用提供的工具。 如果你使用了工具请将工具返回的结果清晰地整合到你的回答中。 如果用户的问题不需要工具或没有合适工具请直接基于你的知识进行友好、简洁的回答。 不要编造你不知道的信息。), MessagesPlaceholder(variable_namechat_history), (user, {input}), MessagesPlaceholder(variable_nameagent_scratchpad), # 这是给Agent记录其思考过程的地方 ]) # 4. 初始化记忆 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 5. 创建Agent agent create_openai_tools_agent(llm, tools, prompt) # 6. 创建执行器 agent_executor AgentExecutor(agentagent, toolstools, memorymemory, verboseTrue, handle_parsing_errorsTrue)3.3 运行测试与迭代优化现在让我们运行这个Agent进行测试。# test_agent.py from agent_core import agent_executor if __name__ __main__: queries [ 现在上海是几点钟, 北京今天的天气怎么样, 告诉我爱因斯坦的主要贡献。, 我明天要去广州需要带伞吗, # 这是一个需要推理的问题 我们刚才聊了什么 # 测试记忆 ] for query in queries: print(f\n用户: {query}) try: response agent_executor.invoke({input: query}) print(f助手: {response[output]}) except Exception as e: print(f执行出错: {e})运行后你应该能在控制台看到类似以下的详细输出verboseTrue时这让我们能清晰地看到Agent的思考过程 进入新的AgentExecutor链... 用户我明天要去广州需要带伞吗 思考用户问明天去广州是否需要带伞。这取决于广州明天的天气。我需要查询广州的天气预报。 行动调用工具 get_weather_forecast。 行动输入{city: 广州} 观察广州今天雷阵雨气温24-30°C南风1-2级。 思考工具返回的是“今天”的天气但用户问的是“明天”。工具描述里没有指定日期的参数可能只支持查询当前天气。我需要向用户说明这个限制并根据今天的天气给出一个谨慎的建议。 最终回答我目前只能查询到广州今天的天气情况雷阵雨。对于明天的准确预报建议您稍后通过专门的天气应用或网站查询。不过鉴于今天有雷阵雨明天出行时带上一把伞以备不时之需总是一个稳妥的选择。 链结束。第一次迭代优化从上面的测试我们发现天气工具功能有缺陷不支持未来日期。我们需要改进它或者调整Prompt让Agent更早地管理用户预期。我们可以修改系统Prompt增加一句“请注意天气工具目前仅能查询当前天气状况无法提供未来几天的预报。”第二次迭代优化测试记忆功能。当问“我们刚才聊了什么”时Agent应该能回忆起之前的对话。这依赖于ConversationBufferMemory。如果上下文很长可能会超出模型的令牌限制。这时就需要引入记忆摘要或向量存储记忆等更高级的记忆管理方式。这个简单的实践涵盖了Agent的核心循环解析用户输入 - 规划/思考 - 选择并调用工具 - 整合结果 - 输出。通过不断测试和优化每个环节你的Agent会变得越来越可靠。4. 进阶挑战与工程化考量当一个基础Agent能跑起来后要让它真正可用、可靠我们还会面临一系列工程挑战。4.1 可靠性提升错误处理与稳定性设计LLM的输出具有不确定性工具调用可能失败网络可能不稳定。一个生产级的Agent必须有完善的错误处理机制。工具调用异常处理每个工具函数都应该有健壮的try...except返回结构化的错误信息而不是直接抛出异常让整个Agent崩溃。tool def get_weather_forecast_v2(city: str) - dict: # 返回结构化的字典 获取城市天气。返回一个包含状态和数据的字典。 try: # 模拟可能失败的API调用 if city 未知城市: raise ConnectionError(天气服务不可用) # ... 调用逻辑 return {status: success, data: 北京晴15-25°C} except Exception as e: return {status: error, message: f获取天气失败{str(e)}}Agent的决策逻辑在收到{status: error}时应该能决定是重试、使用备用方案还是向用户坦诚错误。LLM输出解析与重试LLM可能返回无法解析为工具调用的文本。好的框架如LangChain内置了重试逻辑和输出解析器。我们也可以自己实现一个fallback机制比如当解析失败时用一个更明确的Prompt让LLM再试一次。超时与限流为Agent的整体执行和每个工具调用设置超时。对于付费API要做好限流rate limiting和重试策略如指数退避。4.2 效率优化上下文管理与成本控制LLM按Token收费上下文越长越贵而且模型本身有上下文窗口限制。上下文窗口管理摘要记忆当对话历史很长时可以定期用LLM对之前的对话进行摘要然后用摘要代替原始长历史放入上下文。例如每10轮对话摘要一次。滑动窗口只保留最近N轮对话丢弃更早的。向量检索记忆将历史对话分块存入向量数据库。当需要回忆时根据当前问题检索最相关的片段而不是塞入全部历史。这非常适合处理超长对话和知识库。成本控制模型分级调用对于简单的意图识别或分类任务使用便宜的小模型如gpt-3.5-turbo对于复杂的推理和生成再用大模型如gpt-4。这就是所谓的“路由”或“分层”策略。缓存对相同的用户查询和工具调用结果进行缓存避免重复计算和API调用。Token计数与预算在代码中集成Token计数器为每个用户会话或每次任务设置Token预算超出后采取相应措施如拒绝、切换到摘要模式。4.3 可观测性与评估如何知道你的Agent在好好工作“黑盒”是AI应用的一大痛点。我们需要知道Agent内部发生了什么哪里出了问题。日志记录详细记录每个环节的输入输出。包括原始用户输入、LLM接收的完整Prompt、LLM的原始回复包括思考过程、工具调用的请求和响应、最终输出。使用结构化的日志格式如JSON方便后续分析。链路追踪Tracing使用像LangSmith、Weights Biases或自定义的追踪系统可视化Agent的完整执行链路。这能让你一眼看清一次查询经历了哪些步骤每一步耗时多少Token消耗多少哪里出错了。评估Evaluation端到端评估准备一批测试用例人工或通过规则判断最终输出是否正确。这是最直接的评估但成本高。组件评估分别评估工具调用的准确性、检索的相关性、LLM回答的质量等。基于LLM的评估用另一个LLM如GPT-4作为裁判根据一些标准相关性、正确性、有帮助性给Agent的回答打分。这可以自动化但需要设计好的评估Prompt和注意裁判模型的偏差。5. 典型问题排查与实战技巧在实际开发中你一定会遇到各种稀奇古怪的问题。这里分享一些我踩过的坑和总结的技巧。5.1 Agent“发呆”或循环调用症状Agent不停地调用同一个工具或者陷入“思考-调用-再思考”的死循环就是不输出最终答案。根因工具描述不清LLM不理解工具的功能或输出导致它觉得信息不足需要反复调用。Prompt指令不明确没有在System Prompt里强制要求“在获得足够信息后必须给出最终回答”。LLM的“恐惧”LLM可能对做出最终结论信心不足倾向于不断寻求更多信息。解决方案优化工具描述确保描述精准举例说明输入输出。强化Prompt在系统指令中加入明确的终止条件。例如“如果你已经通过工具获得了足够的信息来回答问题请直接给出整合后的最终答案不要再次调用工具。”设置调用次数上限在Agent执行器中强制设定最大迭代次数如max_iterations10超过则强制终止并返回当前结果。5.2 工具调用错误或参数不对症状Agent选择了错误的工具或者调用工具时参数格式错误、缺少必要参数。根因工具函数签名与描述不匹配Python函数的参数名、类型和给LLM的描述不一致。LLM理解偏差用户的问题有歧义LLM做出了错误的理解。解决方案保持一致性使用框架如LangChain的tool装饰器自动生成描述确保与函数签名一致。提供示例在Prompt中提供几个“用户问题 - 正确工具调用”的示例进行少样本学习Few-shot Learning。参数验证与后处理在工具函数内部对参数进行二次验证和清洗。例如城市名去除空格日期字符串尝试解析等。5.3 回答冗长、啰嗦或偏离主题症状Agent的回答包含大量无关信息或者反复复述已知信息不简洁。根因Temperature参数过高导致生成随机性大容易跑偏。Prompt缺乏风格约束没有明确要求回答的格式和风格。上下文中有冗余信息过长的、无关的对话历史干扰了LLM。解决方案降低Temperature对于任务型Agent通常设置temperature0或0.1以获得更确定、更聚焦的输出。在Prompt中规定格式例如“请用不超过三句话回答”、“首先给出是或否然后简要解释”。优化记忆管理使用前面提到的摘要或检索记忆保持上下文的简洁和相关性。5.4 处理复杂、多步骤任务能力弱症状面对“帮我规划一个三天的北京旅游行程包括天气和景点介绍”这类复杂请求Agent要么拒绝要么给出非常笼统、不具操作性的计划。根因基础的单循环Agent思考-行动-观察不适合需要深度规划和状态管理的长序列任务。解决方案升级到有状态的、支持规划的Agent框架。使用LangGraph它可以让你用图Graph的方式定义Agent的工作流。你可以明确地定义“规划节点”、“执行节点”、“评估节点”以及它们之间的流转条件。实现子任务分解在规划阶段引导LLM将大任务分解成一系列清晰的、可顺序或并行执行的子任务清单。然后让Agent逐个攻克子任务并维护一个总的任务状态。引入“反思”步骤在执行完一个子任务后让LLM评估结果是否满意是否需要调整后续计划。这模仿了人类的试错和调整过程。构建一个成熟可用的AI Agent是一个持续迭代和打磨的过程。它一半是艺术设计Prompt和工作流一半是工程处理错误、管理状态、优化性能。从这个小型的日程助手开始你可以逐步为它添加更多能力比如连接你的日历API、邮件系统、项目管理系统最终让它成为你数字世界中的一个真正得力的智能副驾。最关键的是迈出第一步并在实践中不断学习和调整。