ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LangGraph与FastAPI构建电商AI Agent智能客服系统实战

LangGraph与FastAPI构建电商AI Agent智能客服系统实战 简介这是一套面向AI工程化落地的电商智能客服系统实战框架专为具备Python与LLM应用开发经验的中高级开发者设计解决电商场景下多步骤业务逻辑如退货与知识密集型对话如售后政策咨询难以端到端协同的问题。资源共76个文件以60个Python核心模块为主涵盖LangGraph智能体编排图、FastAPI路由与服务层、RAG检索器、退货子图逻辑、外部系统工具封装及完整测试用例辅以YAML流程定义、Docker/K8s部署脚本、Swagger文档与运维脚本压缩包仅1.01MB轻量但结构完备。已有12人学习下载。开发者可直接基于E-commerce-Smart-Agent-main主目录分层结构agents/tools/retrievers/schemas等理解工业级AI Agent架构设计复用预置的电商提示词模板库、可追溯审计日志机制及OAuth2.0安全接口规范并通过celery_worker.py与docker-compose.yaml快速启动带状态持久化的智能体服务。 做电商客服系统这件事我前后折腾过好几个方案从最早的纯规则引擎、到检索式问答、再到把大模型接进来做生成式对话每一步都踩了不少坑。这次把一个完整的项目打包整理出来就是基于 LangGraph 和 FastAPI 搭建的电商 AI Agent 框架核心能力从 RAG 知识库问答一路延伸到复杂的退货业务流处理落地成了能直接对接前端、能进生产环境的智能客服系统。如果你正在做 AI Agent 开发、RAG 实战、或者 FastAPI 后端服务这份整理应该能给你省掉很多试错时间。整个项目里最难的不是把模型接进来而是把“问答”升级成“办事”。客服场景里用户不只是问“退货政策是什么”而是直接说“我要退货帮我处理一下”这时候系统就需要理解上下文、查订单、判断条件、走流程、调接口整套动作必须稳定可控这也是我选择 LangGraph 来编排 Agent 状态机的原因。FastAPI 则负责对外暴露接口、管理会话、处理并发底层还接了一套 RAG 知识库用来支撑商品政策类问答。下面我把整个设计思路、关键实现、踩坑教训一次讲清楚。1. 项目整体设计与技术选型思路1.1 电商客服场景的刚需拆解电商智能客服和通用聊天机器人最大的区别在于它必须“办实事”。用户问“你们发货用哪家快递”是查询类问题走 RAG 检索回答就行但用户说“我收到的商品有破损我要退货”就完全不一样了系统得确认订单信息、判断是否在退货期内、生成退货单、通知仓库、跟踪退款状态。这一串动作如果只靠提示词让大模型自由发挥结果一定不可控必须有一套显式的流程编排机制。所以我在设计之初就把系统的能力拆成三层。第一层是知识问答层对应 RAG 知识库负责处理“政策是什么、规则是什么、怎么操作”这类问题第二层是任务执行层对应 Agent 的工具调用负责查订单、创建退货单、修改地址这类确定性操作第三层是流程控制层对应 LangGraph 的图编排负责把多层判断、多步骤流转、异常兜底串起来。三层各司其职又共享同一个会话上下文。这个拆法解决了一个很实际的问题如果把所有能力都塞进一个大 Prompt 里模型输出会变得非常不稳定但如果完全写死规则流程又失去了大模型的语义理解能力。LangGraph 正好能让“确定性流程”和“模型判断”共存在流程节点里调用模型做分类、抽取、生成但流程骨架本身是程序员可控的。1.2 为什么是 LangGraph而不是 LangChain 或纯手写状态机LangChain 大家都很熟但它本质是一个“工具聚合层”适合做链式调用和快速原型到了需要复杂分支、循环、并行、回退、人工介入的场景写起来会非常痛苦。我自己用 LangChain 写过一版意图识别多策略路由代码里塞满了 if-else 和回调函数项目到后期几乎没法维护。LangGraph 解决的核心问题是“状态管理”。它把 Agent 的每一次运行抽象成一张图节点是处理逻辑边是流转条件全局有一个 State 对象在节点之间传递和更新。你可以在任意节点停下来等待人工确认也可以根据上一步的结果动态决定下一步走哪个分支还可以把多轮对话的历史作为状态持久化到外部存储。这些都踩中了复杂业务流程的痛点。至于为什么不手写状态机原因也很简单业务逻辑和模型调用、工具调用交织在一起手写状态机需要自己管理缓存、重试、超时、并发、持久化工作量非常大。LangGraph 虽然也有学习曲线但它把状态管理、图执行、断点续跑这些底层能力封装好了我只要聚焦业务节点本身。1.3 FastAPI 作为服务层的理由FastAPI 在这套系统里的定位是“胶水层”承上启下。向上给前端、小程序、第三方系统提供 HTTP 接口向下调度 LangGraph 图执行、访问 PostgreSQL、Redis、向量库。选它有几个很现实的原因原生 async 支持对接 LLM 这种 IO 密集场景简直天然契合基于 Pydantic 的请求校验和 OpenAPI 文档自动生成前端联调不用再问我要接口文档社区生态大中间件、限流、日志、监控方案都很成熟。我做接口压测的时候对比过 Flask 和 FastAPI并发量上来以后FastAPI 的异步优势非常明显。尤其在 LLM 调用是耗时大头的情况下FastAPI 可以在等待模型返回时继续处理其他请求一个进程能扛住的并发连接数远超同步框架。后面我会专门讲接口层的实现细节包括流式输出和统一响应格式。2. RAG 知识库的搭建与检索调优2.1 电商知识数据的特点与切块策略电商领域的知识库数据来源非常杂商品详情页、优惠规则、物流说明、退换货政策、客服话术、售后工单记录格式从 HTML 到 PDF 到 Excel 都有。我踩过的第一个大坑就是“一股脑全部塞进向量库”结果检索出来的片段牛头不对马嘴。切块策略是 RAG 检索效果的基石。我对比了三种方式固定窗口切块、递归字符切块RecursiveCharacterTextSplitter、基于语义的切块。固定窗口实现最简单但会把语义完整的段落切碎递归字符切块通过按换行符、句号、逗号逐级分割对自然语言文本比较友好语义切块效果最好但需要额外调模型成本高、延迟大。最终我的选择是递归字符切块为主对于商品规格这类结构化内容直接用自定义分隔符按表格行切。这里给一个经过实测的参数组合适用于大多数电商政策文档chunk_size800chunk_overlap150。块太小容易丢失上下文块太大检索召回时噪音多overlap 能保证跨块实体比如“商品名称”和“退换货规则”尽量不被切断。切片之后我还会做一轮清洗把页眉页脚、乱码字符、重复文案去掉这部分对最终效果影响往往比调模型参数还大。2.2 向量化模型选型与向量库对比Embedding 模型我测试过 OpenAI 的 text-embedding-3-small、通义的 text-embedding-v2、国产开源的 bge-m3、gte-large-zh。如果从生产可控和成本角度bge-m3 是个不错的平衡点支持 8000 token 长度、输出 1024 维向量中文效果稳还可以私有化部署不依赖外部接口。不过需要说明如果你更偏向调用成熟 API 链路OpenAI 系也很省心选型时主要权衡部署成本和效果差异。向量库方面我的建议是“先不要为了向量库而引入新的基础设施”。如果你的项目规模不大、查询量不高直接用 PostgreSQL pgvector 插件就够了一套数据库同时存业务数据和向量数据不用维护两套系统。数据量到了千万级、或者需要超高并发检索时再考虑独立的 Milvus 或 Qdrant。我在这个项目里用了 pgvector单表单库就能支撑日常客服查询运维成本低很多。2.3 混合检索与重排解决“向量检索答非所问”只用向量检索做 RAG在电商场景里会频繁遇到一个问题用户问“退货的邮费谁承担”向量检索可能召回“退货流程说明”或“售后联系方式”但正确答案其实藏在某个售后政策的长文本段落里。纯向量的语义匹配会忽略关键词精确匹配和词频信息这时候必须上混合检索。我最终的方案是 BM25 关键词检索 向量检索并行召回再用重排模型Reranker做最终排序。具体做法查询先同时发给 PostgreSQL 的全文检索tsvector和 pgvector两组结果取并集然后交给一个轻量级 rerank 模型打分取 top-k 送入 LLM 生成答案。加入 rerank 之后准确率提升非常明显这一点在长文本知识库场景几乎是必选项。重排模型的推理开销不高百来条候选排序在 CPU 上也就几十毫秒。3. LangGraph 编排退货业务流的设计与实现3.1 退货业务的状态机拆解退货流程是电商客服里最典型、也最需要小心处理的流程。用户发起退货后状态要经过“待审核 → 审核通过/拒绝 → 待用户寄回 → 待仓库收货 → 待退款 → 退款完成”中间还穿插着超时、撤销、补寄、换货等异常分支这些状态如果靠对话模型自由发挥基本等于灾难。我把它建模成一张 LangGraph 状态图。每个业务状态对应图里的一个节点节点之间用条件边连接。例如“退货申请”节点收到用户意图和订单信息后模型抽取必要字段路由到“资格校验”节点校验节点里跑硬规则订单是否在退货期、商品是否在可退类目硬规则通过才进入“人工审核”节点人工确认后系统自动调用退货 API 生成退货单状态切到“待寄回”。这张图的优势在于任何时刻我都能知道当前会话处于什么状态用户消息进来之后系统可以基于当前状态决定下一步动作而不是每次从头理解一遍。比如用户在“待寄回”状态下问“我没有打印机怎么填退货单”Agent 就能直接触发“填写退货单指引”工具而不是重新走一遍退货申请流程。3.2 State 设计与节点实现细节LangGraph 的 State 是全局数据流的核心我在项目里定义了一个包含如下字段的 Stateclass AgentState(TypedDict): messages: Annotated[list, add_messages] user_id: str order_id: str intent: str current_step: str retry_count: int form_data: dict need_human_approval: bool final_response: strmessages字段使用 LangGraph 的add_messagesreducer自动实现消息列表的累加这是多轮对话的基础。current_step记录流程当前节点form_data存放从对话里抽取的表单信息比如退货原因、商品编号、图片凭证等。每个节点函数接收 State返回 State 的部分更新LangGraph 会自动合并。节点实现有一个我特别想强调的点不要在节点里写太重的业务逻辑。尽量把“查数据库”“调 API”“算规则”拆成独立函数或工具在节点里只做编排和调度。这样节点代码很薄一方面方便调试另一方面也方便给后续留出扩展空间。3.3 工具调用与人工审批的接入Agent 要“办事”就不能只靠模型生成文本必须把工具调用接入节点。我在 LangGraph 的节点里定义了tool装饰器包装的工具包括查询订单、创建退货单、查询退款进度、生成退货地址、发送短信通知。工具内部会调用 FastAPI 服务端暴露的内部接口再返回结构化结果给模型。人工审批节点是电商场景绕不开的。大部分退货申请按规则自动通过但涉及金额较大或者用户多次异常退货时需要人工介入。LangGraph 提供了 human-in-the-loop 支持在这个节点用interrupt()挂起图的执行把当前状态和待确认数据发到前端审批台等人工点击“通过”或“拒绝”之后再恢复执行。这个机制非常实用相当于把“机器自动处理”和“人工兜底”无缝接在一个流程里。我实现人工审批后的运行链路是图执行到审批节点 → 调用 interrupt 挂起 → 后端把挂起任务信息写入审批工单表 → 前端展示待办 → 管理员操作后调用 resume 接口 → 图从断点继续执行。整个链路最关键的是要保证幂等性防止同一个审批动作被重复提交导致状态错乱。3.4 多轮上下文与长期记忆客服系统天然是多轮对话用户上一句说“我要退货”下一句可能直接说“订单号是 123456”系统必须能理解“订单号”指代的是退货订单。LangGraph 的messagesreducer 天然解决了短时上下文问题整个对话历史都会作为状态传入模型。长期记忆这块我用的是 LangGraph 的 Checkpointer 机制 PostgreSQL 存储。Checkpointer 会把图执行的每一步状态保存下来即使服务重启也能从上次的断点恢复。同时我在会话表里存了用户维度的长期信息比如用户历史退货次数、偏好地址、常用支付方式每次图开始执行时先加载这些信息注入 State让 Agent 的回答更有针对性。4. FastAPI 接口层与会话管理实现4.1 项目结构与统一响应格式服务端我按模块拆分没有把代码全堆在一个 main.py 里。目录结构大致是app/ ├── api/ │ ├── chat.py │ ├── agent.py │ └── admin.py ├── core/ │ ├── config.py │ └── deps.py ├── schemas/ │ ├── chat.py │ └── order.py ├── services/ │ ├── rag_service.py │ ├── agent_runner.py │ └── order_service.py └── db/ ├── session.py └── models.py接口返回格式从一开始就统一成{ code: 0, data: ..., message: success }不管成功失败都走这个结构。语音客服、小程序、Web 端前端都要对接统一响应格式能少很多沟通成本。这里的code0代表成功非 0 是错误码错误码表单独维护一份文档。4.2 对话接口与 SSE 流式输出大模型生成有一个特点用户等不到完整回复就想看到边输入边输出Web 前端普遍用 SSE 来做流式效果。FastAPI 原生支持StreamingResponse我在/api/chat/stream接口里把 LangGraph 的astream_events输出逐块推送给前端。这里有个具体实现细节不要把 RAG 检索过程和模型生成过程混在一次 SSE 流里。我是分两种事件类型推送的一种是search_result前端可以展示“已找到相关政策”的提示卡片另一种是token对应模型逐字输出。这样用户体验好很多用户能感知到系统在做检索、在读知识库而不是干等。4.3 PostgreSQL 存储与会话恢复所有会话记录和 Agent 状态都存在 PostgreSQL。会话表设计上关注三个部分会话基础信息用户 ID、创建时间、状态、消息明细角色、内容、时间、关联的事件 ID、Agent 运行状态快照LangGraph checkpointer 的序列化数据。会话恢复能力很关键。用户关闭网页再打开需要能继续之前的对话而不是重新开始。我的实现是每次对话请求带上session_id服务端优先从数据库恢复 Agent 状态再走图执行。这里我遇到过一个反序列化兼容问题LangGraph 的 State 结构一旦调整老会话的 checkpointer 数据就可能读不出来后来我在代码里加了一层状态迁移逻辑每次结构变更都带上版本号才彻底解决。4.4 连接池与并发处理FastAPI 的异步能力很强但数据库连接不能按请求数随意创建必须用连接池。我用的是 SQLAlchemy async asyncpg 驱动连接池大小和最大溢出配置为pool_size20, max_overflow20实际压测下来能支撑 300 的并发请求。需要特别注意连接池的配置要和你的数据库 max_connections 匹配否则数据库先成为瓶颈。LLM 调用本身是耗时操作必须设置超时和重试策略。OpenAI 兼容接口的超时我设置了 60 秒重试次数 2 次指数退避。同时为了防止单个用户请求占满服务资源我在接口层加了基于 Redis 的令牌桶限流每个用户每分钟最多 20 次对话请求防止被刷。5. 部署、可观测性与性能调优经验5.1 LangGraph Studio 与本地调试开发阶段强烈建议装一下 LangGraph Studio它能把图的结构、每个节点的状态变化可视化。调试退货流程图的时候我能直接看到当前停留在哪个节点、State 里各字段的值是什么、下一步边怎么走。这比我之前靠打印日志猜状态高效太多。除了 Studio我也在代码里加了一组模拟工具用来在本地生成假的订单数据和退货单方便跑全流程。本地联调我一般起三个服务FastAPI端口 8000、PostgreSQL端口 5432、向量库端口 5433然后用 docker-compose 一把拉起开发链路干净利落。5.2 性能瓶颈分析与缓存策略RAG 链路里最耗时的三个环节是 Embedding 生成、向量检索、LLM 生成。Embedding 生成可以通过缓存显著的降低重复查询的时延用户问的和历史问题高度相似时直接用缓存向量结果。我在 Redis 里存了文本哈希到向量的映射命中率大约在 25% 左右查询响应整体快了不少。向量检索层面当数据量不大时pgvector 的 IVFFlat 索引已经够用数据量大了以后再切换 HNSW 索引。两者区别在于构建时间和查询精度HNSW 的召回更稳内存占用也更高。我建议初期直接用 HNSW减少后续重建索引的麻烦。LLM 生成环节是最大的延迟来源。一个技巧是做流式输出的同时把首 token 时间压到最短另一个技巧是给不同意图分配不同规模的模型。简单问答走小模型比如 7B 参数复杂退货流程走大模型通过意图分类路由到不同模型服务整体成本能降低不少。5.3 结构化日志与调用链追踪线上排障没有日志寸步难行。我引入了结构化日志把每次 LLM 调用的耗时、token 消耗、检索命中的文档 ID、Agent 状态流转路径都记录到日志中心。这样如果用户说“系统回答错了”我能回溯到那一次请求用的什么 Prompt、召回了哪些文档、模型输出了什么快速定位是检索问题还是生成问题。同时我在 FastAPI 中间件里给每个请求生成一个trace_id贯穿 HTTP 请求、LangGraph 图执行、外部 API 调用。配合日志系统可以串联整个调用链排查多轮对话问题变得非常高效。6. 常见问题与避坑实录这部分内容来自我开发过程中反复踩过的坑整理成一张速查表供你参考问题现象根因排查与解决方案RAG 回答答非所问切块太小导致上下文缺失调大 chunk_size增加 overlap增加重排模型LangGraph 节点状态被覆盖多个字段用了同一个 reducer给需要追加的字段统一用 add_messages 或自定义 reducerFastAPI 并发请求时数据库连接耗尽连接池配置和数据库上限不匹配调整 pool_size、max_overflow优化 SQL 查询SSE 流式输出中断代理层缓冲导致前端收不到Nginx 关闭缓冲或调整 proxy_buffering off长时间会话后模型上下文超限messages 列表无限增长实现摘要压缩或滑动窗口截断工具调用失败导致流程卡死没做重试和超时兜底在节点里捕获异常失败后走降级分支或转人工老会话 checkpointer 数据读不出来State 结构变更引入版本号做序列化迁移兼容用户说“好的”导致意图误判多轮语境理解不足让意图识别节点同时输入最近 5 轮消息和当前流程状态举一个具体的完整排查案例。有一次线上用户反馈说“你们说能退但是后台没有退货单”我顺着 trace_id 查到 LangGraph 的执行轨迹发现退货单创建节点执行成功了但后续的“生成退货单号”工具抛了异常异常被我捕获后直接跳到了结束节点没有走重试分支导致流程状态停留在“已完成”但实际业务单没生成。修复方案是在创建退货单工具里增加“先查重再创建”的幂等逻辑并且在节点异常时强制切入人工审批节点而不是静默结束。这个案例让我深刻体会到Agent 系统的失败恢复能力比模型效果更重要。模型输出不完美是常态但流程编排必须保证任何异常情况下都有可追溯、可恢复的路径。7. 项目后续扩展方向与个人经验思考7.1 从退货流程扩展到更复杂的服务场景当前框架只实现了退货一条主流程但状态图的设计是通用的。我后续准备接入换货流程、退款催办、发票申请、物流拦截每个流程都是一个独立的图子模块通过 LangGraph 的父图-子图机制挂载到主 Agent 上。意图识别节点先判断业务类型再路由到对应子图每个子图可以独立测试、独立发布。这样做的好处是业务扩展不会影响主流程稳定性。新增一个流程只需要添加一个子图和几个工具函数其他模块完全不动。我也在考虑把销售场景接入进来比如用户问“有没有适合油性皮肤的洗面奶”Agent 可以通过商品知识库 用户画像做个性化推荐这种“对话式导购”比静态搜索结果转化率高很多。7.2 对 Agent 落地的一点反思做了这个项目我最大的体会是AI Agent 能不能落地关键不在模型多强而在流程设计是否尊重业务现实。很多教程教你把一堆工具塞给 Agent让它自由发挥这在 demo 里看起来很酷一上生产就失控。真正稳定可用的 Agent一定是“流程为主、模型为辅”的——模型负责理解语义、抽取信息、生成话术但流程的控制权永远掌握在业务规则手里。另外不要忽视人工兜底。人机协同不是临时方案而是 Agent 系统的必备能力。哪怕准确率到了 95%那 5% 的异常也需要有确定性的处理路径interrupt 机制加审批台就是我目前觉得最务实的方式。最后再分享一个团队协作层面的建议这类项目一定要重视接口文档和状态定义FastAPI 自动生成的 OpenAPI 文档可以让前端完全自助联调LangGraph 的 State 定义建议写成单独的设计文档作为团队评审的依据。系统的复杂度已经远超个人能 hold 住的范围清晰的接口和状态约定是多人协作的基础。本文还有配套的精品资源点击获取
返回列表