文章目录前言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都有唯一idToolMessage必须带上对应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 一行代码开启记忆实例化一个MemorySavercompile的时候传进去完事。每次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的朋友否则看看零散的博文就够了