news 2026/8/8 12:35:19

LangGraph做Agent完整工程实战:从0到1避开大半坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangGraph做Agent完整工程实战:从0到1避开大半坑

文章目录

      • 前言
      • 1 环境基座:先把项目搭得像个正经工程
        • 1.1 别再死磕pip了,uv才是提速神器
        • 1.2 Python版本钉死3.11,少走半年弯路
        • 1.3 密钥别写代码里,安全组找你喝茶别喊冤
      • 2 模型接入:换供应商就改一行字的快乐
        • 2.1 一行代码通吃各家模型
        • 2.2 Groq用来做开发,效率直接翻倍
      • 3 结构化输出:别再用正则抠JSON了
        • 3.1 Pydantic:边界数据的守门员
        • 3.2 TypedDict:内部传参的轻量选择
        • 3.3 dataclass:带默认值的中间派
        • 3.4 include_raw:调试和计费必备
      • 4 消息模型:别再把所有内容塞一个字符串里
        • 4.1 四种消息,各司其职
        • 4.2 消息列表才是多轮对话的正确姿势
      • 5 工具调用:让模型学会自己动手查资料
        • 5.1 一个装饰器,把Python函数变成模型工具
        • 5.2 工具粒度别太大,一个工具干一件事
        • 5.3 配对机制:多工具并发也不会串台
      • 6 LangGraph三要素:状态、节点、边
        • 6.1 State:全图共享的上下文
        • 6.2 Node:干活的处理单元
        • 6.3 Edge:决定下一步去哪
      • 7 上手第一个图:货币转换器
        • 7.1 三步搭起最小图
        • 7.2 可视化:一眼看明白图长啥样
      • 8 条件边:让图自己做决策
        • 8.1 一个路由函数搞定动态分支
        • 8.2 分支独立,好维护好测试
      • 9 ReAct代理:思考-行动循环,开箱即用
        • 9.1 不用手写循环,预置组件直接用
        • 9.2 一个例子看懂整个流程
      • 10 记忆与多会话:每个用户都有独立上下文
        • 10.1 一行代码开启记忆
        • 10.2 thread_id:多用户隔离的关键
        • 10.3 内存不够用?换数据库就行
      • 11 从demo到生产:工程落地清单
        • 11.1 工具层加固:超时、重试、鉴权
        • 11.2 可观测性:别瞎调参,先看数据
        • 11.3 兜底机制:别让用户看到“我不会”


P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。

前言

不知道大家有没有这种经历:刚接触大模型开发的时候,一行model.invoke就能跑通,觉得Agent也不过如此。结果需求一加,要记忆、要工具调用、要分支判断,代码写着写着就缠成了一团耳机线,改一个地方崩三个地方。

别慌,今天咱们就从地基到封顶,把用LangGraph做Agent的完整工程逻辑掰碎了讲,看完至少能帮你少踩半个月的坑。

1 环境基座:先把项目搭得像个正经工程

很多人一上来就急着写业务代码,环境全靠手动凑,最后同事拉你代码跑不起来,你俩对着报错面面相觑。地基不稳,后面全是雷。

1.1 别再死磕pip了,uv才是提速神器

说真的,我以前用pip装依赖,点完安装就能起身去接杯水,回来还在解析依赖冲突,运气不好直接给你报一屏红。

uv这东西就不一样了,Rust写的,速度快到你以为自己没点安装。初始化项目、锁版本、装依赖一条龙,一个uv.lock文件就能保证所有人环境一模一样,再也不会出现“我这能跑啊”的世界名场面。

1.2 Python版本钉死3.11,少走半年弯路

别总追新用3.12、3.13,爽是爽了,装依赖的时候就知道苦了。很多AI库的预编译包还没跟上新版本,装的时候本地编译半天,最后还不一定能成。

3.11就不一样,兼容性拉满,主流库全支持,部署也省心。把版本号钉死在pyproject.toml里,连Python解释器都给你统一了,环境一致性直接拉满。

1.3 密钥别写代码里,安全组找你喝茶别喊冤

我真见过不少新人,图省事把API key直接写在代码开头,转头就提交到公开仓库,第二天公司安全组的消息就弹过来了。

正经做法就是.env文件加python-dotenv,密钥全扔环境变量里,.env直接加到.gitignore,代码里只管读环境变量,干净又安全。以后换key、换环境,改配置文件就行,业务代码一行都不用动。

2 模型接入:换供应商就改一行字的快乐

以前接不同厂商的模型,得分别import不同的类,参数还不一样,换个模型跟重构一遍似的。现在有了init_chat_model,这事就简单得离谱。

2.1 一行代码通吃各家模型

就写个provider:model的字符串,比如groq:qwen-3-family,剩下的LangChain全给你搞定。底层SDK、鉴权方式全给你封装好了,业务代码根本不用关心背后是哪家的模型。

以后想做A/B测试、想换便宜的模型跑测试,改个字符串就行,上层逻辑纹丝不动。这才叫抽象的意义,不然每次换模型都改半天,早累死了。

2.2 Groq用来做开发,效率直接翻倍

开发阶段别死磕贵的模型,等半天出个结果,调试效率低到离谱。Groq这种低延迟的推理服务就很合适,首token快得离谱,跑demo、调流程特别顺手。

等流程全跑通了,再切到主力模型优化效果,成本和效率两头都占了。做工程的,得学会把钱花在刀刃上。

3 结构化输出:别再用正则抠JSON了

说个扎心的:很多人做Agent,一半时间在写prompt让模型输出JSON,另一半时间在写正则修复模型输出的畸形JSON。头发就这么掉没的。

结构化输出就是干这个的:给模型定好契约,它按格式填,程序直接拿对象用,省心得多。

3.1 Pydantic:边界数据的守门员

最常用的就是Pydantic,定义个BaseModel,每个字段加个description,不仅能校验类型,还能把字段说明一起塞给模型,相当于给模型画好了填空格。

别觉得description是写给人看的注释,你写得越清楚,模型填错的概率越低。比如日期字段你写清楚“ISO8601格式”,它就不会给你整出“昨天”“上周”这种幺蛾子。

外面进来的数据、模型吐出来的数据,用Pydantic卡一道,脏数据根本流不到下游,省了无数排查时间。

3.2 TypedDict:内部传参的轻量选择

要是数据只在内部节点之间传,已经确认过是干净的,就没必要每次都跑一遍Pydantic校验。TypedDict就够了,零运行时开销,还能有类型提示。

配合Annotated把字段说明挂上,一样能给模型当schema用,轻量又好用。毕竟内部系统之间,没必要每次都过安检,浪费性能。

3.3 dataclass:带默认值的中间派

想要点面向对象的感觉,又不想引入Pydantic的重量,dataclass就很合适。标准库自带,能加默认值、能写方法,LangChain也能直接识别成schema。

写demo、做原型的时候用它最快,等后续要做强校验了,再迁到Pydantic也不麻烦。

3.4 include_raw:调试和计费必备

默认只返回解析好的对象,干净是干净,但你想知道花了多少token、模型原始返回是什么,就没辙了。开了include_raw就不一样,原始消息、用量统计全给你带回来。

调试的时候看原始返回找问题,线上的时候统计token算成本,一举两得。当然生产环境不用全开,抽样打点就行,不然日志量能给你撑爆。

4 消息模型:别再把所有内容塞一个字符串里

新手最容易犯的错:把系统提示、用户问题、历史对话全拼成一个大字符串传给模型。短的时候还好,一长就乱,模型也分不清哪句是指令哪句是对话。

4.1 四种消息,各司其职

SystemMessage:定调子的,告诉模型你是谁、该怎么说话、要遵守什么规则,优先级最高。别把对话历史塞这里面,纯纯浪费高优先级位。

HumanMessage:用户说的话,输入内容、图片文件都塞这里。多用户场景还能加个name字段,模型就不会分不清谁在说话。

AIMessage:模型的回复,文本内容、工具调用指令都在这上面。token用量统计也从这里拿。

ToolMessage:工具执行完的结果,必须带tool_call_id跟前面的调用配对。不然模型都不知道这结果是对应哪次调用的,推理直接跑偏。

4.2 消息列表才是多轮对话的正确姿势

单轮任务你用字符串无所谓,只要涉及多轮、工具调用,老老实实用消息列表。结构清晰,角色分明,模型理解起来也准。

而且这是LangChain的统一标准,不管换哪家模型,消息列表的格式都不用改。这就是抽象层的好处,把差异全挡在底下。

5 工具调用:让模型学会自己动手查资料

大模型不是万能的,实时数据、内部系统数据它都不知道。硬问就只能瞎编,俗称幻觉。工具调用就是给模型开了个外挂,需要啥自己查去。

5.1 一个装饰器,把Python函数变成模型工具

写个普通Python函数,加个@tool装饰器,完事。模型就能识别到这个工具,知道它是干啥的、要传什么参数。

重点提醒:函数的docstring不是写给你自己看的,是写给模型看的。你写得越含糊,模型越容易瞎调用。就一句话说清楚:这个工具是干啥的、入参是什么、返回什么,比啥都强。

5.2 工具粒度别太大,一个工具干一件事

别图省事写个万能工具,啥功能都塞里面。模型根本分不清什么时候该调它,参数也容易传错。

就拆成单一职责的小工具,查股价的就查股价,算汇率的就算汇率。工具多几个没关系,模型选得准,比啥都强。

5.3 配对机制:多工具并发也不会串台

模型一次可以调用好几个工具,并行执行效率高。但要是返回顺序乱了怎么办?放心,每个tool_call都有唯一id,ToolMessage必须带上对应id,模型自己会配对。

就跟快递面单似的,不管哪个先到,扫码就知道是谁的。这协议设计得还是挺讲究的,省了我们自己写分发逻辑。

6 LangGraph三要素:状态、节点、边

前面都是LangChain的积木,接下来LangGraph就是骨架,把这些积木串成有状态、能分支的工作流。核心就三个东西:State、Node、Edge。

6.1 State:全图共享的上下文

State就是整张图的共享内存,所有节点都能读能写。一般用TypedDict定义,字段清清楚楚,谁都能一眼看明白这张图在传什么数据。

重点说下reducer,也就是合并规则。比如messages字段,我们要的是追加新消息,不是覆盖旧历史。这时候就得用add_messages这个reducer,不然每轮对话都清空历史,Agent跟金鱼似的,记不住任何东西。

6.2 Node:干活的处理单元

节点本质就是个函数,输入是当前State,输出是要更新的字段。你可以放纯计算逻辑,可以放LLM调用,也可以放工具执行,灵活得很。

每个节点只干一件事,职责单一,好测试也好维护。别把所有逻辑塞一个节点里,那不叫图,叫巨型函数。

6.3 Edge:决定下一步去哪

普通边就是固定顺序,A做完就做B。条件边就有意思了,根据当前State的值动态决定下一个节点是谁。这才是Agent的灵魂:下一步做什么,由运行时的状态决定,不是写死的。

就像人做决策一样,遇到问题先判断要不要查资料,要就去查,不要就直接回答。以前你得自己写while循环加if判断,现在用条件边,声明一下就行。

7 上手第一个图:货币转换器

说再多不如动手写一个。咱们就整个最简单的货币转换:输入美元金额,先加8%手续费,再按汇率转成印度卢比。三步就能跑通。

7.1 三步搭起最小图

第一步,定义State:三个字段,原始金额、加价后金额、最终卢比金额。

第二步,写两个节点函数:一个算加价,一个算汇率转换,每个函数只读需要的字段,返回要更新的结果。

第三步,建图、注册节点、连边:START → 加价节点 → 转换节点 → END。

最后compile一下,invoke传初始值,直接出结果。就这么简单,一张有状态的工作流就跑起来了。

7.2 可视化:一眼看明白图长啥样

写完别着急跑,先调用draw_mermaid_png把图画出来。节点有没有漏、边有没有接错,一眼就能看见。

别觉得这步多余,等你图里十几个节点、好几个分支的时候,不靠可视化,光靠脑子想,很容易接错线。调试半天发现是边连错了,哭都来不及。

8 条件边:让图自己做决策

固定流水线只能做简单任务,要想做智能Agent,必须得有动态路由。比如用户想换欧元还是换卢比,得让图自己判断走哪个分支。

8.1 一个路由函数搞定动态分支

写个路由函数,读取State里的目标币种,返回对应的节点名字。然后用add_conditional_edges把源节点和路由函数绑上就行。

运行的时候,源节点执行完,自动调用路由函数,拿到目标节点名,接着往下走。整个流程完全由数据驱动,不用写一堆if-else嵌套。

8.2 分支独立,好维护好测试

每个分支节点都是独立的,改欧元的汇率逻辑不会影响卢比的分支。测试的时候也可以单独测每个分支,不用绕完整条链路。

以后要加新币种?加个节点、加个分支条件就行,不用动老代码。这就是图结构的扩展性,比线性脚本强太多。

9 ReAct代理:思考-行动循环,开箱即用

有了工具调用和条件边,我们就能拼出最经典的ReAct模式:模型先思考要不要调用工具,要就去执行工具,结果返回来再继续思考,直到给出最终答案。

9.1 不用手写循环,预置组件直接用

LangGraph已经把常用的都做好了:ToolNode负责执行工具,tools_condition负责判断要不要调工具。你只要把聊天节点和工具节点连上,循环自动就跑起来了。

模型想调用几次工具就调用几次,循环次数完全由模型自己决定。不用你写while True,也不用你手动维护对话历史,框架全给你处理了。

9.2 一个例子看懂整个流程

比如用户问“买20股苹果股票要多少钱”。模型一看不知道实时股价,就发起工具调用,触发tools_condition,走到ToolNode执行查询。

工具把股价结果塞回消息列表,再回到聊天节点。模型拿到数据,算一下总价,这次不带工具调用了,条件边就路由到END,任务结束。

整个过程行云流水,你要做的就是定义好工具、写好prompt,剩下的循环交给框架。

10 记忆与多会话:每个用户都有独立上下文

没有记忆的Agent就是个一次性工具,用户问下一句就忘了上一句。加上checkpointer,瞬间就有了长时记忆。

10.1 一行代码开启记忆

实例化一个MemorySaver,compile的时候传进去,完事。每次invoke结束,整张图的State都会自动存下来。

下次调用的时候带上同一个thread_id,框架自动把上次的状态加载回来,接着上次的聊。就这么简单,跨轮记忆直接拉满。

10.2 thread_id:多用户隔离的关键

不同用户、不同会话,给不同的thread_id就行。每个线程的状态完全独立,张三的对话不会跑到李四那里去。

做生产服务的话,每个用户会话生成一个唯一的thread_id,跟业务ID绑定上。多租户隔离直接就搞定了,不用你自己写一堆状态管理的代码。

10.3 内存不够用?换数据库就行

MemorySaver是存在进程内存里的,重启就没了,适合开发测试。生产环境直接换成SqliteSaver或者PostgresSaver,接口完全一样,换个导入就行。

这就是抽象的好处:底层存储随便换,上层业务代码一行不用改。想扩容、想持久化,都是分分钟的事。

11 从demo到生产:工程落地清单

跑通demo只是第一步,要放到线上扛流量,还有几个必须做的升级。

11.1 工具层加固:超时、重试、鉴权

线上环境什么幺蛾子都有,网络超时、第三方接口挂了、参数传错了,都有可能。别让工具异常直接把整趟图干崩。

给工具加上超时控制、指数退避重试、异常捕获。失败了把错误信息返回给模型,让它自己决定重试还是换方案,比直接抛错强一万倍。

11.2 可观测性:别瞎调参,先看数据

没有监控的Agent就是黑盒,出了问题你都不知道卡在哪。至少要盯三个指标:token用量、端到端延迟、错误率。

哪个节点耗时最长、哪个工具调用失败最多、哪类问题token消耗大,有了数据才能针对性优化。不然全靠感觉调prompt,效率低得离谱。

11.3 兜底机制:别让用户看到“我不会”

条件边别只写正常分支,失败了、参数不对了,得有兜底路径。比如工具调用失败,让模型先尝试换个参数,实在不行再引导用户换个问法。

直接甩给用户一句“无法回答”,体验太差了。做产品,得给用户台阶下。

总结一下,做Agent工程,核心就三件事:结构化输出把数据边界守住,状态图把流程编排做清楚,可观测性把运行状态摸明白。

别上来就堆复杂功能,先把最小图跑通,再一点点加工具、加记忆、加分支。稳扎稳打,比啥都强。

P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/8 12:32:16

whatlanggo vs 其他语言检测库:Go开发者的性能与功能对比

whatlanggo vs 其他语言检测库:Go开发者的性能与功能对比 【免费下载链接】whatlanggo Natural language detection library for Go 项目地址: https://gitcode.com/gh_mirrors/wh/whatlanggo whatlanggo 是一款用 Go 语言编写的自然语言检测库,它…

作者头像 李华
网站建设 2026/8/8 12:32:11

ArcGIS Pro水文分析并行处理优化方案

1. 问题现象与背景分析最近在使用ArcGIS Pro进行水文分析时,不少用户遇到了操作失败的情况。具体表现为:当执行水文工具(如填洼、流向计算、流量累积等)时,程序突然崩溃或长时间无响应。经过排查发现,这与A…

作者头像 李华
网站建设 2026/8/8 12:31:45

Portman源码解析:核心模块与测试注入原理

Portman源码解析:核心模块与测试注入原理 【免费下载链接】portman Port OpenAPI Specs to Postman Collections, inject test suite and run via Newman 👨🏽‍🚀 项目地址: https://gitcode.com/gh_mirrors/po/portman P…

作者头像 李华
网站建设 2026/8/8 12:31:19

APK Installer:Windows上最简单的安卓应用安装解决方案

APK Installer:Windows上最简单的安卓应用安装解决方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 想在Windows电脑上直接安装安卓应用吗?不…

作者头像 李华
网站建设 2026/8/8 12:31:19

MongoKit迁移策略:从旧系统平滑过渡到新数据模型的完整指南

MongoKit迁移策略:从旧系统平滑过渡到新数据模型的完整指南 【免费下载链接】mongokit MongoKit framework try to keep its simplicity when you manage mongodb in python. MongoKit was developed to be fast and light with KISS and DRY in mind. MongoKit bri…

作者头像 李华
网站建设 2026/8/8 12:30:10

Agent Governance Toolkit与SAP集成:企业资源规划中的AI代理治理

Agent Governance Toolkit与SAP集成:企业资源规划中的AI代理治理 【免费下载链接】agent-governance-toolkit AI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI age…

作者头像 李华