ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

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

近几年被问得最多的问题就是:我想入门 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 & State)Agent 的多次推理-行动-观察过程以为一次请求就能完成复杂任务

你只要把这个表格里的概念都亲手验证过一遍,后面看任何框架都会轻松很多。接下来我就按这个顺序展开说,并给出一套从零手写最小 Agent 的完整过程。

2. 别急着装框架,先把三块地基打牢

2.1 第一块地基:会调大模型 API,看得懂 Token

这一节看上去基础得过分,但我带过的人里,有 30% 卡在“API 调用都跑不通”这个阶段。不是不会写代码,而是不懂怎么跟大模型 API 打交道。

以目前最常见的 OpenAI 兼容接口为例,一个最基本的调用是这样的:

from openai import OpenAI client = OpenAI() resp = client.chat.completions.create( model="gpt-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( model="gpt-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( model="gpt-4o", messages=[{"role": "user", "content": "北京今天适合出门吗?先查天气"}], tools=tools ) 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( model="gpt-4o", messages=messages, tools=tools ) 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( model="gpt-4o", messages=messages, tools=TOOLS, temperature=0 ) 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 Schema@tool 装饰器自动生成
参数解析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: "tool"+tool_call_id拼接。

问题二:JSON 解析时不时报错

  • 排查过程:把模型原始输出完整打印出来,发现模型在 JSON 前后加了注释或解释文字。单纯json.loads时稍微有点杂质就挂了。
  • 解决方案:改用模型的结构化输出模式,或者用健壮一点的解析库做extract_json。

问题三:Agent 在工具调用里死循环,预算烧得飞快

  • 排查过程:检查循环停止条件,发现工具结果里缺少能告诉模型“任务已完成”的信号,于是模型每次都以为“还要再查一次”。
  • 解决方案:给 Agent 循环加最大轮数硬限制,同时设计工具结果时,加上类似status: success的字段,帮助模型判断完成状态。

问题四:上下文越来越长,响应变慢且贵

  • 排查过程:打印每次请求的 token 用量,发现每次循环都带着全部历史记录。一个 8 轮循环,调用 8 次模型,token 总消耗是首轮请求的 4 倍以上。
  • 解决方案:加简单的历史摘要压缩,把早期对话浓缩成摘要再放入 messages,或者设置最大历史条数。这一步能省 30% 到 50% 的费用。

这些问题的共性是什么?它们没有一个和框架的选择有直接关系,全部是 Agent 基础机制层面的东西。你换成哪个框架,问题都会以类似形态出现。

5.2 给新手和转行者的学习路径建议与避坑清单

最后给一条可执行的路径,我在内部带新人时基本就是按这个顺序:

  1. 第一个月,只学基础调用。做 API 调用,理解 messages、Token、参数。目标:能把一个带工具调用的最小 Agent 手写出来。
  2. 第二个月,做三个真实小项目。比如桌面端天气助手、一个自动整理周报的小工具、一个基于本地文件的问答机器人。别贪多,关键是每个都要包含至少一次工具调用。
  3. 第三个月,再接触框架。把一个手写项目用框架重写一遍,比较差异。这时候你对框架的理解,会比直接从框架开始的人深入得多。

避坑清单,几乎是拿真金白银换来的:

  • 不要用生产环境去练手。很多人一上手就接公司生产数据库,结果工具参数解析有问题,把客户数据查坏了。先用假数据跑通全流程。
  • 不要迷信超长上下文。上下文越长,单次请求越慢越贵,且模型注意力会分散。该精简就精简。
  • 不要忽视成本估算。Agent 项目上线后最大的坑是费用。写代码时就要在日志里记录每次调用的 token 数,做到心里有数。
  • 不要忽略日志。Agent 的调试比一般程序难,因为每次输出有随机性。所有关键步骤——模型返回、工具选择、工具参数、工具结果——都要打日志,否则等于盲人摸象。

说实话,Agent 本身是个逻辑并不复杂的系统,它难在“看得见全局”和“能容忍不确定输出”。这两个能力只能靠亲手写代码、亲手调试来磨炼,框架帮不了你。我在实际项目里,最怕的不是候选人不熟悉某个框架,而是他只会照着官方示例跑通 Demo,却没有独立排查问题的能力。这篇文章的核心就是帮你建立这种能力——从手写开始,后面的一切都会顺畅很多。

返回列表