首页/新闻资讯/正文详情

从零构建AI编码助手:LangGraph与FastAPI实战

发布时间:2026/11/4 14:24:32 来源:云帆数科 栏目:资讯中心
从零构建AI编码助手:LangGraph与FastAPI实战
1. 为什么我要从零造一个编码助手市面上不缺代码问答工具缺的是能把说变成做的东西。我最初做羲和XiheAgent的动机很朴素日常开发里大量重复性任务——批量改接口签名、给新模块补单元测试、根据报错日志定位并修复问题——这些事用纯对话式助手做我得手动复制粘贴、来回确认效率提升有限。真正想要的是一个能读代码库、能规划步骤、能调用工具、能自己验证结果的执行体。羲和这个名字取自上古掌管天文历法的神寓意观测与调度。它的定位很明确一个基于 FastAPI 提供接口、用 LangGraph 编排任务流的 AI 编码助手核心能力覆盖代码问答、任务规划、工具调用、结果校验四个层次。适合谁参考如果你已经会写 Python、了解基本的 LLM 调用但卡在怎么把一次问答升级成多步任务执行这个坎上那这篇内容基本就是我想跟你聊的东西。我踩过的第一个坑就是一开始用最朴素的 while 循环 if-else 来串流程结果状态管理一团乱重试逻辑和分支判断缠在一起改一处崩三处。后来换成 LangGraph 才把节点 边 状态这套模型理顺。所以下面我会重点讲清楚为什么选 LangGraph 而不是裸写循环FastAPI 的目录怎么分层才不烂尾以及 planning 模式在编码任务里到底怎么落地。2. LangGraph 到底解决了裸写循环的哪些痛点2.1 从一问一答到多步执行的本质变化纯问答的链路是线性的用户输入 → 拼 prompt → 调模型 → 返回。但任务执行不是线性的。举个真实例子用户说帮我把 user 模块里所有同步数据库调用改成异步。这个任务至少包含扫描文件、识别同步调用、判断哪些能安全改、逐个改写、跑测试验证、失败回滚。中间任何一步都可能需要回头重做比如测试挂了要回到改写步骤。裸写循环的问题在于这些回头逻辑会变成嵌套的 if-else 和 goto 式的跳转状态散落在各种局部变量里。LangGraph 的核心价值就是把流程显式建模成图节点是执行单元边是流转规则状态是一个贯穿始终的共享数据结构。这样回头重做就变成了一条从验证节点指回改写节点的边逻辑一目了然。2.2 LangGraph 和 LangChain 的区别别再搞混这是被问得最多的问题。我的理解是LangChain 是工具箱LangGraph 是流水线控制器。LangChain 提供的是 LLM 调用、Prompt 模板、输出解析、检索器这些零件LangGraph 提供的是把这些零件按有向图组织起来、并管理状态流转的骨架。在羲和里两者是配合使用的用 LangChain 的组件做单次模型调用和工具封装用 LangGraph 的 StateGraph 做整体编排。如果你只做单轮问答LangChain 的 Chain 就够了一旦涉及条件分支、循环重试、多角色协作就该上 LangGraph。面试里常问的什么时候用 LangGraph我的标准回答是当你的流程需要根据中间结果动态决定下一步走向时。2.3 状态设计整个图的中枢神经LangGraph 里最需要想清楚的就是 State。它本质上是一个 TypedDict定义了所有节点共享的数据字段。羲和的 State 大致长这样from typing import TypedDict, Annotated, Sequence from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[Sequence, add_messages] # 对话历史自动追加 task_plan: list[str] # 规划出的步骤列表 current_step: int # 当前执行到第几步 code_context: dict # 读取到的代码片段 tool_results: list[dict] # 工具调用结果 retry_count: int # 当前步骤重试次数 final_answer: str # 最终输出这里有个关键细节messages字段用了Annotated[..., add_messages]这是 LangGraph 的 reducer 机制。普通字段是覆盖语义新值直接替换旧值而加了 reducer 的字段是合并语义新消息会追加到列表里而不是覆盖。我一开始没注意这点导致对话历史每次都被清空排查了半天才发现是 reducer 没配。提示状态字段能少则少只放真正需要跨节点共享的数据。把临时变量塞进 State 会让图变得难以调试。3. FastAPI 项目目录结构分层没做好后期全是债3.1 我推荐的目录骨架FastAPI 项目最容易犯的错就是所有路由堆在一个 main.py 里。羲和跑起来之后接口有十几类如果一开始不分层后面加个鉴权、加个日志中间件都会牵一发动全身。我最终稳定下来的结构是这样的xihe_agent/ ├── app/ │ ├── main.py # 应用入口注册路由和中间件 │ ├── api/ │ │ ├── deps.py # 依赖注入数据库、鉴权、Agent 实例 │ │ └── v1/ │ │ ├── chat.py # 问答相关接口 │ │ ├── task.py # 任务执行接口 │ │ └── health.py # 健康检查 │ ├── core/ │ │ ├── config.py # 配置管理pydantic-settings │ │ └── logging.py # 日志配置 │ ├── graph/ │ │ ├── state.py # AgentState 定义 │ │ ├── nodes.py # 各个节点函数 │ │ ├── builder.py # 图构建与编译 │ │ └── tools.py # 工具定义 │ ├── schemas/ │ │ └── request.py # 请求/响应模型 │ └── services/ │ └── agent_service.py # 业务逻辑隔离路由和图 ├── tests/ └── pyproject.toml分层的核心原则是路由只负责收参数和返结果业务逻辑放 service图编排放 graph。这样测试的时候可以单独测节点函数不用起整个 HTTP 服务。3.2 依赖注入怎么用才不别扭FastAPI 的Depends是它最优雅的设计之一。羲和里我用它来管理 Agent 实例的生命周期——图编译一次比较耗时不能每个请求都重新编译。做法是在应用启动时编译好图存到 app.state然后通过依赖注入取出来# app/api/deps.py from fastapi import Request def get_agent(request: Request): return request.app.state.agent # app/api/v1/task.py router.post(/execute) async def execute_task(payload: TaskRequest, agentDepends(get_agent)): result await agent.ainvoke({messages: [payload.query]}) return {answer: result[final_answer]}这里有个坑LangGraph 编译出来的图对象是有状态的如果多个请求并发调用同一个图实例状态可能串。我的处理方式是每个请求用独立的初始 State图本身只读不写这样并发是安全的。如果你在节点里改了全局变量那就要小心了。3.3 配置管理别硬编码API Key、模型名、超时时间这些绝对不能写死在代码里。我用 pydantic-settings 做配置支持从环境变量和 .env 文件读取from pydantic_settings import BaseSettings class Settings(BaseSettings): model_name: str gpt-4o api_key: str max_retry: int 3 request_timeout: int 60 class Config: env_file .env settings Settings()好处是类型安全启动时就能发现配置缺失而不是跑到一半才报错。4. Planning 模式在编码任务里的落地方式4.1 为什么编码任务特别需要先规划编码任务有个特点步骤之间有强依赖且错误会累积。如果让模型边想边做第一步理解错了后面全错。Planning 模式的核心思想是先把任务拆成有序的步骤列表再逐步执行每步执行完可以校验。在 LangGraph 里这对应一个典型的规划节点 → 执行节点 → 校验节点的循环结构。规划节点负责把用户意图拆解成步骤执行节点负责做当前步骤校验节点判断是否成功、是否需要重试或重新规划。4.2 规划节点的 prompt 怎么写规划节点的输出必须是结构化的步骤列表不能是自由文本。我用的是让模型输出 JSON 数组然后用 Pydantic 校验PLANNER_PROMPT 你是一个编码任务规划器。把用户的任务拆解成可执行的步骤。 每个步骤必须是一个具体的动作不要有模糊描述。 输出格式为 JSON 数组例如 [读取 user.py 文件, 定位所有同步 db 调用, 逐个改写为异步] 只输出 JSON不要有其他内容。实测下来让模型只输出 JSON比请以 JSON 格式输出效果好很多后者经常会在 JSON 前后加解释性文字。解析的时候我还会加一层容错用正则提取第一个[...]块防止模型偶尔不听话。4.3 执行与校验的循环怎么控制执行节点从task_plan里取current_step对应的步骤调用相应工具把结果写进tool_results。校验节点判断这一步是否成功。这里的关键是重试上限和重新规划的条件要分开单步失败retry_count加一没超过max_retry就重试当前步骤。单步反复失败说明规划本身有问题触发重新规划把失败信息喂回规划节点。全部步骤完成进入汇总节点生成最终答案。用 LangGraph 的条件边来表达就是def should_continue(state: AgentState) - str: if state[current_step] len(state[task_plan]): return summarize if state[retry_count] settings.max_retry: return replan return execute graph.add_conditional_edges(validate, should_continue, { summarize: summarize, replan: planner, execute: executor, })这种写法比裸写循环清晰太多每个分支的走向一眼可见。5. 工具调用让助手真正动手的关键5.1 工具的定义与注册编码助手的工具无非几类读文件、写文件、执行命令、搜索代码。在 LangGraph 里工具可以用 LangChain 的tool装饰器定义然后绑定到模型上from langchain_core.tools import tool tool def read_file(path: str) - str: 读取指定路径的文件内容 with open(path, r, encodingutf-8) as f: return f.read() tool def search_code(keyword: str, root: str .) - list[str]: 在代码库中搜索包含关键词的文件 import subprocess result subprocess.run( [grep, -rl, keyword, root], capture_outputTrue, textTrue ) return result.stdout.strip().split(\n)工具函数的 docstring 非常重要模型就是靠它来判断什么时候该调用哪个工具。我踩过的坑是 docstring 写得太笼统导致模型该调read_file的时候去调了search_code。后来把每个工具的适用场景写清楚准确率明显提升。5.2 工具执行的安全边界让 AI 直接执行命令是有风险的。我的做法是加一层白名单和沙箱只允许执行测试、格式化、静态检查这类命令禁止任何删除、网络请求、系统修改类操作。写文件也限制在项目目录内路径要做规范化校验防止../越界。ALLOWED_COMMANDS {pytest, ruff, mypy, black} def safe_execute(cmd: list[str]): if cmd[0] not in ALLOWED_COMMANDS: raise PermissionError(f命令 {cmd[0]} 不在白名单内) return subprocess.run(cmd, capture_outputTrue, textTrue, timeout30)注意白名单要按前缀匹配而不是精确匹配否则pytest -k test_foo这种带参数的调用会被误拦。5.3 工具结果的压缩与回传工具返回的内容可能很长比如读一个大文件。如果原样塞回上下文token 消耗会爆炸。我的处理是读文件时只返回相关片段用关键词定位前后若干行命令输出只保留末尾若干行和错误信息。这样既保留了关键信息又控制了上下文长度。6. 实测中那些文档不会告诉你的坑6.1 状态字段的 reducer 陷阱前面提过add_messages的 reducer这里再展开说。LangGraph 里如果两个节点并行执行、都要写同一个字段没有 reducer 就会报错或覆盖。我一开始把tool_results定义成普通 list结果并行节点写的时候互相覆盖。改成带 reducer 的写法from operator import add tool_results: Annotated[list, add]这样多个节点的结果会自动拼接。记住一个原则会被多个节点写入的字段一定要配 reducer。6.2 无限循环的防范条件边如果写错图可能陷入死循环。LangGraph 编译时可以设置recursion_limitapp graph.compile() result app.invoke(state, config{recursion_limit: 25})超过限制会抛异常。我建议在开发阶段把这个值设小一点比如 15这样一旦逻辑有问题能快速暴露而不是等到跑了几百步才发现。6.3 流式输出与图执行的配合用户等一个多步任务执行完可能要几十秒没有流式反馈体验很差。FastAPI 里可以用StreamingResponse配合图的astream方法每个节点执行完就推一次进度async def stream_task(query: str): async for event in agent.astream({messages: [query]}): for node_name, node_output in event.items(): yield fdata: {node_name} 完成\n\n前端用 EventSource 接收就能实时看到正在规划正在执行第 2 步这样的进度。这个体验提升非常明显用户不会觉得程序卡死了。6.4 模型输出不稳定的兜底再好的 prompt 也不能保证模型每次都输出合法 JSON。我的兜底策略是三层第一层用 Pydantic 校验第二层用正则提取第三层失败就降级成让模型重新输出一次。三层都失败才报错。实测下来加了兜底之后任务成功率从大概七成提到了九成以上。7. 从问答到执行我个人的几点体会做羲和这段时间最大的感受是AI 编码助手的难点不在模型而在工程。模型能力是现成的但怎么把它的输出可靠地接入真实代码库、怎么管理多步状态、怎么在出错时优雅降级这些才是决定产品能不能用的关键。LangGraph 给我的最大启发是把控制流显式化。以前写 Agent 总想着用一个大 prompt 让模型自己决定一切结果不可控也不可调试。现在把流程拆成节点和边每个环节的输入输出都清清楚楚出问题能定位到具体节点改起来也有针对性。如果你准备动手做类似的东西我的建议是先把最简单的规划 → 执行 → 校验三节点跑通别一上来就搞复杂的多 Agent 协作。等这条主线稳定了再往上加工具、加流式、加重试策略。工程这东西能跑通的最小闭环永远比设计完美的架构更重要。最后分享一个调试小技巧LangGraph 支持把执行过程可视化开发阶段我会把每次运行的图结构导出看一眼确认边的走向符合预期。很多逻辑 bug 光看代码看不出来画出来一眼就发现了。

相关推荐

2026年AI学习生态全景:从PyTorch到Agent框架的系统路线图
2026年AI学习生态全景:从PyTorch到Agent框架的系统路线图

1. 从"工具收集癖"到"生态思维":为什么2026年学AI不能再东一榔头西一棒子我见过太多人学AI的路径是这样的:刷到一条"大模型微调实战"的视频,赶紧收藏;看到有人推荐某个Agent框架,立刻去… · 2026/11/4 14:24:32

烟草商业公司AI落地全景图:23个部门48个场景与2027年路线
烟草商业公司AI落地全景图:23个部门48个场景与2027年路线

1. 烟草商业公司AI落地,为什么值得单独拿出来聊 烟草商业公司这个体系,外面的人看是“专卖专营”,里面的人看是“链条极长、节点极碎”。从烟叶种植收购、复烤加工、卷烟生产、仓储物流、分拣配送,到终端零售、专卖稽查、财务审计… · 2026/11/4 14:24:32

ASR转录质量提升:WER 2.6%与口误修正流水线落地
ASR转录质量提升:WER 2.6%与口误修正流水线落地

做转录这行的都清楚,ASR最让人抓狂的从来不是"识别不出来",而是"识别出来了但错得莫名其妙"。一段四十分钟的访谈,人声清清楚楚,转出来文本里人名错三个、数字错两个、中英混说的地方直接糊成一团&#xff0c… · 2026/11/4 14:23:27

Qwen3-VL-8B:如何用AI实现视觉推理与智能交互?
Qwen3-VL-8B:如何用AI实现视觉推理与智能交互?

Qwen3-VL-8B:如何用AI实现视觉推理与智能交互? 【免费下载链接】Qwen3-VL-8B-Thinking-unsloth-bnb-4bit 项目地址: https://ai.gitcode.com/hf_mirrors/unsloth/Qwen3-VL-8B-Thinking-unsloth-bnb-4bit 导语:Qwen3-VL-8B-Thinking模… · 2026/11/4 15:56:52

从零开始学AI22——集成学习
从零开始学AI22——集成学习

集成学习核心思想是“三个臭皮匠,顶个诸葛亮”,通过组合多个弱模型提升整体性能。三大流派:Bagging(如随机森林)并行训练、投票降方差,适合抗噪稳定场景;Boosting(如XGBoost&#xf… · 2026/11/4 15:55:51

Sill 音频管线深度剖析:AAC-ELD 128kbps 编码、10ms 分片与逐包漂移校正的精密同步机制
Sill 音频管线深度剖析:AAC-ELD 128kbps 编码、10ms 分片与逐包漂移校正的精密同步机制

【免费下载链接】sill Any window from your Mac, live on your iPhone or iPad. Touch, Apple Pencil, trackpad and keys. Free, open source, no servers. 项目地址: https://gitcode.com/gh_mirrors/sill1/sill 点击查看 免费下载 Sill 是一款免费、开源的 Mac… · 2026/11/4 15:52:50

1.65 美元通关宝可梦:Awesome Decision Models 的 50 个决策模型游戏与 Demo 完整清单
1.65 美元通关宝可梦:Awesome Decision Models 的 50 个决策模型游戏与 Demo 完整清单

【免费下载链接】awesome-decision-models A curated list of decision models (System One / typed decision models): hosted APIs, open-weight models, runtimes, SDKs, applications, benchmarks, and papers. 项目地址: https://gitcode.com/gh_mirrors/awes/… · 2026/11/4 15:51:50

Hermes Agent容器编排监控工具:Prometheus与Grafana配置
Hermes Agent容器编排监控工具:Prometheus与Grafana配置

Hermes Agent容器编排监控工具:Prometheus与Grafana配置 Hermes Agent是一款功能强大的容器编排监控工具,能够帮助开发者和运维人员轻松实现对容器环境的全面监控。本文将详细介绍如何配置Prometheus与Grafana,以实现对Hermes Agent容器编排… · 2026/11/4 15:50:49

构建智能零售客户服务聊天机器人:Hermes Agent自动问答系统
构建智能零售客户服务聊天机器人:Hermes Agent自动问答系统

构建智能零售客户服务聊天机器人:Hermes Agent自动问答系统 在当今数字化零售环境中,高效的客户服务是提升用户体验和品牌忠诚度的关键。Hermes Agent作为一款强大的AI自动化工具,为构建智能零售客户服务聊天机器人提供了完整的解决方案。本… · 2026/11/4 15:50:49

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码