首页 / 资讯中心 / 文章详情

AI Agent学习路径:先手写最小Agent,再学LangChain框架

AI Agent学习路径:先手写最小Agent,再学LangChain框架 ★ FEATURED ARTICLE
近几年被问得最多的问题就是我想入门 AI Agent是不是应该先学 LangChain每次听到这句话我都想拦人——你连 Agent 的“核”还没摸到就去啃框架只会越学越晕。这篇就写给两类人完全没接触过 Agent 的新手以及想从其他岗位转来做 AI 应用的人。我会直接告诉你什么值得先学、什么真的可以晚点再碰并给出一条我自己验证过的学习路径。我不反对框架甚至现在做项目我也会用框架。但“先学框架”和“先懂原理再学框架”学习效率完全是两回事。这篇文章不是那种“30分钟搭一个Agent”的速通指南而是一篇会劝阻你“慢下来”的路径梳理。看完你大致能回答三个问题Agent 的本质是什么、手写一个最小 Agent 需要哪几步、以及框架到底该在什么时候进入你的学习列表。1. 先搞清楚Agent 到底是什么别把框架当成 Agent 本身1.1 一句话说清 Agent 的本质Agent 在 AI 圈被用得太滥了。我的定义很简单Agent 是一个能自己理解目标、拆解任务、调用工具、检查结果、并在失败后纠正自己的程序。它不是一个产品名字也不等于“ChatGPT 套壳”更不是某个框架的代名词。拆开来说核心能力就四件事理解目标把一段模糊的用户需求转换成可执行的任务描述。这依赖大模型的理解能力也依赖你写 Prompt 的水平。拆解任务把一个大目标拆成多个小步骤。比如“帮我准备一份周末北京出行计划”可能要拆成查天气、查高铁票、查景点、列行程表。调用工具Agent 不能只靠模型自身知识它需要外部能力。查天气要调天气 API发邮件要调邮件 API查数据库要写 SQL。这部分就是 Function Calling 或 Tool Calling。检查与纠正执行结果可能不对比如天气接口返回 500或者查询结果不完整。Agent 要能识别异常换一种方式重试。你发现没有这四件事里没有一件是“某个框架特有的”。框架只是把以上过程封装成组件让你少写样板代码。但封装的代价是你很可能看不透它内部发生了什么。等出了问题你连日志都看不懂。1.2 为什么新手总把 Agent 和框架混为一谈因为市面上 90% 的 Agent 教程标题都是“用 LangChain 做一个 PDF 问答机器人”或者“基于 Dify 搭建一个联网搜索助手”。这些教程的共同点是用少量代码跑通一个 Demo然后大家对 Agent 的认知就变成了“LangChain 就是 Agent”。这个印象太牢固了。以至于我做技术分享时只要说到 Agent总有人问“那用哪个框架好”。我跟他们说“先别问框架”他们一脸茫然——不学框架那 Agent 怎么做出来的这其实是“工具思维”和“原理思维”的差别。普通人用电脑不需要懂操作系统只要会点鼠标就行。但 Agent 开发不一样因为你遇到的大多数问题都藏在原理层模型返回 JSON 格式不稳定是因为你需要强制结构化输出而不是换个框架。Agent 老是重复执行同一个工具是因为你的循环逻辑缺少终止条件和框架无关。上下文越来越长导致费用飙升是因为你没有做上下文压缩这同样是设计问题。还有一个现实原因框架迭代太快。你今天学的 LangChain 0.3 用法下个月可能就被 0.4 或者被新的 Agent 库取代。但大模型 API 的调用逻辑、Token 计算方式、Prompt 设计原则两三年都不会大变。把时间花在稳定的事物上才是新手回报率最高的策略。1.3 学 Agent 前必须弄懂的五个底层概念我把这些概念称为“Agent 的地基”顺序也是我建议的学习顺序概念一句话解释常见误区模型Model大模型本身如 GPT、Claude、国产开源模型以为 Agent 是模型之外的魔法上下文Context模型一次能看到的全部内容含系统提示、历史、工具结果以为上下文越大越好Token模型计量文本的单位约等于 0.7 个汉字以为只有输入才消耗 Token工具调用Function Calling模型输出“要调哪个函数、传什么参数”的结构化指令以为工具调用是框架自动生成的循环与状态Loop StateAgent 的多次推理-行动-观察过程以为一次请求就能完成复杂任务你只要把这个表格里的概念都亲手验证过一遍后面看任何框架都会轻松很多。接下来我就按这个顺序展开说并给出一套从零手写最小 Agent 的完整过程。2. 别急着装框架先把三块地基打牢2.1 第一块地基会调大模型 API看得懂 Token这一节看上去基础得过分但我带过的人里有 30% 卡在“API 调用都跑不通”这个阶段。不是不会写代码而是不懂怎么跟大模型 API 打交道。以目前最常见的 OpenAI 兼容接口为例一个最基本的调用是这样的from openai import OpenAI client OpenAI() resp client.chat.completions.create( modelgpt-4o, messages[ {role: system, content: 你是一个旅游助手回答要简洁。}, {role: user, content: 推荐一下北京玩三天怎么安排} ] ) print(resp.choices[0].message.content)这套代码值得吃透的细节比看上去多得多messages 结构system、user、assistant、tool 四种角色顺序不能乱。Agent 的每一次自我对话本质上就是往 messages 里追加消息。温度参数默认 1 或 0.7影响随机性。做 Agent 时我通常调到 0因为不希望模型在调用工具时自由发挥。Token 消耗输入和输出都计费。每次带着全部历史记录调用Token 会随对话轮数线性增长。有个 100 条历史记录的工具调用场景费用可能比单次问答贵 10 倍。实操心得我让每个新手先做一个“Token 计算器”练习。用 tiktoken 库把一段文本拆成 Token 并统计数量体会一下“一个汉字大概占 1.5 个 Token”“一段 API 返回结果到底吃了多少钱”。做过这个练习的人后面设计 Agent 时都会条件反射地控制上下文长度。2.2 第二块地基Prompt 工程与结构化输出很多新手以为 Prompt 就是“把问题说清楚”。Agent 开发里的 Prompt 要复杂得多因为你是在给一个“会自动执行工具的程序”下达指令任何模糊都会造成执行偏差。Agent 的 System Prompt 至少要包含以下要素角色与目标你是谁、要完成什么任务。工作流程先做什么、再做什么、什么情况下调用哪个工具。输出格式要求 Markdown、JSON还是表格。边界规则什么不能做、什么情况下停止。兜底策略工具出错时怎么反馈而不是胡编。结构化输出在 Agent 里尤其关键。因为你要让模型输出可解析的 JSON而不是“好的现在我来调用查天气函数”。两种方式都试过之后你就知道自由文本的可用性有多差。推荐的做法是使用模型的 JSON Mode 或结构化输出能力resp client.chat.completions.create( modelgpt-4o, messages[ {role: system, content: 你只输出 JSON字段为 city 和 date。}, {role: user, content: 查一下北京明天的天气} ], response_format{type: json_object} )加了这一层之后模型的输出就从“废话加结果”变成了干净的 JSON。这一步是后续所有工具调用解析的前提。很多框架内部帮你做了这件事但如果你自己不知道出了问题就只会瞎按。2.3 第三块地基工具调用与数据流转工具调用Function Calling是整个 Agent 的技术核心。很多人以为 Agent 里的“查天气”是模型自己查的其实大模型根本不会查任何东西它只会输出一段“我想调用 get_weather 函数参数是 {city: 北京}”的结构化指令真正去请求天气 API 的是你的程序代码。我用一个最简单的例子说明工具调用的完整流程import json from openai import OpenAI client OpenAI() tools [{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: { city: {type: string, description: 城市名例如北京} }, required: [city] } } }] # 1. 告诉模型有哪些工具可用 resp client.chat.completions.create( modelgpt-4o, messages[{role: user, content: 北京今天适合出门吗先查天气}], toolstools ) msg resp.choices[0].message print(msg.tool_calls)模型会返回类似这样的结果[{id: call_xxx, type: function, function: {name: get_weather, arguments: {\city\:\北京\}}}]注意此刻模型并没有真的查到天气它只是表示了查询意图。接下来要由你的代码去执行 get_weather再把结果作为 tool 消息传回给模型# 2. 执行工具函数 city json.loads(msg.tool_calls[0].function.arguments)[city] weather get_weather(city) # 真正的API调用发生在这一步 # 3. 把工具结果传回给模型 messages [{role: user, content: 北京今天适合出门吗先查天气}] messages.append(msg) messages.append({ role: tool, tool_call_id: msg.tool_calls[0].id, content: weather }) # 4. 模型读取工具结果生成最终回答 resp2 client.chat.completions.create( modelgpt-4o, messagesmessages, toolstools ) print(resp2.choices[0].message.content)这段代码就是 Agent 的真身。所谓“Agent 循环”不过是把上面的 1 到 4 包在一个 while 循环里反复执行“生成意图 → 调用工具 → 传回结果 → 再生成意图”直到模型认为任务完成。看起来不复杂吧这就是为什么我一直强调先手写一遍。你亲手写完这 20 行代码再看 LangChain 里的AgentExecutor会发现它本质上就是个循环管理器只是帮你处理了消息拼接、异常重试、停止条件这些后勤工作。你已经被剧透了后面就不可能再被框架的抽象概念吓住。3. 从零手写一个最小 Agent比跑通任何 Demo 都有价值3.1 最小 Agent 的设计思路所谓最小是指“能完成一次工具调用并返回最终答案”的完整 Agent功能再少都没关系。我开始带团队时给每个新人的第一个任务就是这个不做任何框架封装纯用 OpenAI SDK 写。设计思路是只有一个工具get_weather(city)返回固定字符串模拟真实天气接口。循环上限设 5 次防止 Agent 陷入死循环烧钱。每次循环都打印当前步骤的意图这样你能直观看到 Agent 在“想什么”。再加上一个真实项目里必须有但对新手不太友好的点异常兜底。如果工具函数抛异常比如城市名是空的Agent 要把异常信息传给模型由模型决定是重新调用还是询问用户。这一步能帮你建立“容错设计”的直觉。3.2 完整实现代码import json from openai import OpenAI client OpenAI() TOOLS [{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气。, parameters: { type: object, properties: { city: {type: string, description: 城市名例如北京} }, required: [city] } } }] def get_weather(city: str) - str: 真实项目里这里会去请求天气API这里用固定值模拟 if not city: raise ValueError(城市名为空) return f{city}当前 25℃多云东南风3级 def run_agent(user_input: str) - str: messages [{role: user, content: user_input}] for step in range(5): print(f[Step {step 1}] 调用模型...) resp client.chat.completions.create( modelgpt-4o, messagesmessages, toolsTOOLS, temperature0 ) msg resp.choices[0].message messages.append(msg) # 模型没有调用工具说明任务已完成 if not msg.tool_calls: return msg.content for tool_call in msg.tool_calls: fn tool_call.function print(f[Step {step 1}] 调用工具 {fn.name}, 参数: {fn.arguments}) try: args json.loads(fn.arguments) result get_weather(args.get(city, )) except Exception as e: result f工具执行失败错误信息: {type(e).__name__}: {e} messages.append({ role: tool, tool_call_id: tool_call.id, content: result }) return 已达最大运行轮数Agent 已停止。 if __name__ __main__: print(run_agent(北京今天适合出门吗先帮我查一下天气))运行之后你会看到类似下面这样的输出这是 Agent 工作过程的“X光片”[Step 1] 调用模型... [Step 1] 调用工具 get_weather, 参数: {city: 北京} [Step 2] 调用模型... 北京当前 25℃多云东南风3级。今天天气较好适合出门。这个 60 行不到的代码里已经包含了 Agent 的所有关键部分模型推理、工具选择、参数解析、工具执行、结果回传、循环控制、异常处理。把它跑通一次你就拥有了对 Agent 最原始的体感。3.3 手写版与框架版的差异对照等你手写完再打开框架的文档会发现所有概念都似曾相识。我列一个对照表方便你理解框架到底做了什么环节手写版所做框架版的封装方式消息循环自己写 for/whileAgentExecutor 自动管理工具注册手写 JSON Schematool 装饰器自动生成参数解析json.loads 手动处理框架自动注入参数历史管理自己拼接 messages自动累加并可选剪裁停止条件检测 tool_calls 为空max_iterations 参数记忆需要自己实现各种 Memory 类这个对照表不是让你觉得框架没用而是让你看清框架是替你写模板代码不是替你写业务逻辑。业务逻辑在你自己脑子里。我见过不少转行者简历上写着“熟悉 LangChain、Dify”但问到“如果 Agent 在调用第三个工具后疯了怎么办”答不上来。因为框架的报错信息和文档里根本没有这个答案你需要懂得底层原理才能推断。而手写过最小 Agent 的人至少会想到“检查 messages 拼接是否重复、检查循环终止条件、检查有没有把多余的历史传给它”。这些思路只有亲手踩过坑的人才会有。4. 框架到底该什么时候学、怎么选4.1 主流 Agent 框架到底解决什么问题等你手写过一遍就可以去学框架了。但学之前得搞懂它存在的意义。框架解决的痛点本质上就四个模板代码复用不用每次手写循环、消息拼接、工具注册。生态组件丰富内置各种解析器、记忆组件、向量存储对接。多模型对接换底座模型时改配置而不是改代码。可视化编排像 Dify 这种平台可以拖拽节点完成流程设计。但框架也带来新的问题学习成本高、版本碎片化、抽象层把细节藏得太深。这就是我要反复强调“先手写一遍”的原因——当你已经理解 Agent 的全流程后框架文档里的术语就不再是障碍而是你已经认识的东西的“别名”。4.2 按场景选型LangChain / Dify / CrewAI 怎么挑市面上常见的 Agent 相关框架和平台我挑三个大家公认的典型做横向对比列完后你大概能知道哪种适合你的目标维度LangChainDifyCrewAI定位开发框架/工具链低代码平台 API多角色协作框架上手门槛高需要写代码低拖拽即可中需要写少量代码灵活性很高适合深度定制中等适合快速搭建中等侧重于编排典型场景构建复杂 RAG 应用、深度定制 Agent快速验证产品原型、企业内部助手模拟多 Agent 协作团队具体建议如下如果你在做产品验证阶段只想快速看效果选 Dify。它能把知识库、工作流、Agent 调试串起来界面友好。如果目标是进公司做 AI 应用开发LangChain 还是主流选择因为它在企业项目里的存量很大相关岗位的 JD 也经常点名。如果你对多智能体协作感兴趣比如想做一个“产品经理 程序员 测试”的虚拟小组可以看看 CrewAI。不过我必须提醒一句框架选型不是非此即彼的关系。我现在的常规项目经常是 Dify 搭快速原型、LangChain 做复杂链路、二者通过 API 对接到生产系统。这是典型的“组合应用”但前提是你要理解接缝在哪里——真到了这个地步其实你已经不需要纠结选型了。4.3 框架选型的四个判断标准我帮大家把选型标准提炼成四句口诀每条都对应踩过的坑看项目阶段而非流行程度。0 到 1 验证用低代码平台1 到 100 规模化再用定制框架。一上来就是最重的架构大概率是给自己找不痛快。看团队水平而非框架热度。团队里全是新手选 Dify 这类可视化平台能快速产出选 LangChain 的复杂抽象会变成维护噩梦。看生态成熟度而非Star数量。有些框架 Star 多但文档烂。实际用起来多翻官方文档和 GitHub Issues 的活跃度比看 Star 数靠谱得多。看是否容易脱离。这是最容易被忽略的一条。用框架时核心业务逻辑一定要写在独立模块里别让框架的 API 渗透到每个角落。否则框架一旦升级或者要迁移你的项目就跟着“陪葬”。选型本质上是“在约束条件下做取舍”。约束条件没有标准答案但你必须有清晰的选择依据。5. 新手和转行者最容易踩的坑一条条排给你看5.1 四个典型问题和排查实录我接触过的实战问题不少挑了四个新手们几乎必遇到的并附上排查过程。问题一Agent 明明调了工具最后还是答非所问排查过程先打印出每次循环的 messages看看 tool 消息有没有正确拼进历史。最常见的问题是把 tool 结果塞进了 user 角色模型没识别为工具执行结果于是乱答。解决方案严格按role: tooltool_call_id拼接。问题二JSON 解析时不时报错排查过程把模型原始输出完整打印出来发现模型在 JSON 前后加了注释或解释文字。单纯json.loads时稍微有点杂质就挂了。解决方案改用模型的结构化输出模式或者用健壮一点的解析库做extract_json。问题三Agent 在工具调用里死循环预算烧得飞快排查过程检查循环停止条件发现工具结果里缺少能告诉模型“任务已完成”的信号于是模型每次都以为“还要再查一次”。解决方案给 Agent 循环加最大轮数硬限制同时设计工具结果时加上类似status: success的字段帮助模型判断完成状态。问题四上下文越来越长响应变慢且贵排查过程打印每次请求的 token 用量发现每次循环都带着全部历史记录。一个 8 轮循环调用 8 次模型token 总消耗是首轮请求的 4 倍以上。解决方案加简单的历史摘要压缩把早期对话浓缩成摘要再放入 messages或者设置最大历史条数。这一步能省 30% 到 50% 的费用。这些问题的共性是什么它们没有一个和框架的选择有直接关系全部是 Agent 基础机制层面的东西。你换成哪个框架问题都会以类似形态出现。5.2 给新手和转行者的学习路径建议与避坑清单最后给一条可执行的路径我在内部带新人时基本就是按这个顺序第一个月只学基础调用。做 API 调用理解 messages、Token、参数。目标能把一个带工具调用的最小 Agent 手写出来。第二个月做三个真实小项目。比如桌面端天气助手、一个自动整理周报的小工具、一个基于本地文件的问答机器人。别贪多关键是每个都要包含至少一次工具调用。第三个月再接触框架。把一个手写项目用框架重写一遍比较差异。这时候你对框架的理解会比直接从框架开始的人深入得多。避坑清单几乎是拿真金白银换来的不要用生产环境去练手。很多人一上手就接公司生产数据库结果工具参数解析有问题把客户数据查坏了。先用假数据跑通全流程。不要迷信超长上下文。上下文越长单次请求越慢越贵且模型注意力会分散。该精简就精简。不要忽视成本估算。Agent 项目上线后最大的坑是费用。写代码时就要在日志里记录每次调用的 token 数做到心里有数。不要忽略日志。Agent 的调试比一般程序难因为每次输出有随机性。所有关键步骤——模型返回、工具选择、工具参数、工具结果——都要打日志否则等于盲人摸象。说实话Agent 本身是个逻辑并不复杂的系统它难在“看得见全局”和“能容忍不确定输出”。这两个能力只能靠亲手写代码、亲手调试来磨炼框架帮不了你。我在实际项目里最怕的不是候选人不熟悉某个框架而是他只会照着官方示例跑通 Demo却没有独立排查问题的能力。这篇文章的核心就是帮你建立这种能力——从手写开始后面的一切都会顺畅很多。
阅读完成 · 觉得有帮助?
咨询建站