
AI应用架构设计最近几乎是个人都在聊。但真去搭一套能上线的系统时很多人会发现以前那套服务端架构经验放在大模型应用上怎么都不对劲。我去年帮团队从零搭了一套AI应用基座从最开始在业务代码里直接调API到后来拆出模型网关、Agent编排、事件总线、评估系统中间踩了大量坑。这篇文章就把最终沉淀下来的架构图纸摊开来用图解的方式逐层拆解每一层为什么存在、解决什么问题、有哪些容易踩的坑、以及怎么和传统微服务共存。适合正在做AI应用架构设计、准备引入Agent、被并发和成本问题折磨的团队参考。1. 为什么AI应用架构设计和传统Web应用完全不同1.1 传统架构的确定性假设在AI应用里不成立了先说一个最底层的认知转变。过去做Web后端我们习惯了一套隐含假设输入是可枚举的输出是可预期的同一个请求重复十次返回结果应该一致。哪怕加了缓存、加了AB实验核心请求链路依然是确定性的。这种假设让传统三层架构变得很稳Controller接收参数Service处理业务逻辑DAO读写数据库。一切都可以被单元测试覆盖出了问题可以按调用链一步回溯。但大模型应用打破了这套假设。LLM本身是一个概率采样系统同样的Prompt两次调用可能返回不同的结果。你没法像对MySQL一样对它做事务控制也没法用传统接口回归保证每次行为一致。更麻烦的是模型的推理时间不是稳定的毫秒级而是秒级到几十秒级中间还伴随token消耗的不确定性。这就导致如果直接把LLM调用塞进传统Service层你会发现上下游超时、并发阻塞、出错重试成本飙升最终整个系统被一个“不稳定的函数”拖垮。1.2 AI应用真正要解决的是四个核心矛盾我做架构设计时把问题收敛成四个矛盾不确定性、长尾延迟、上下文状态、成本波动。不确定性要求我们必须在模型输出和业务逻辑之间加一层“翻译”和“校验”不能让带有幻觉的文本直接流向下游。长尾延迟意味着不能用同步阻塞的方式等待模型完整生成必须引入流式输出和异步任务。上下文状态指的是对话历史、向量召回、工具结果这些信息需要在多个节点间传递和持久化而不是像传统请求一样用完即弃。成本波动最容易被忽略但差一个数量级一次复杂Agent任务可能消耗几十万token换算成钱够调用几千次传统API。下面对比一下更能看清楚差异维度传统Web应用AI应用输入结构化参数自然语言、模糊指令输出可预期、可校验概率生成、存在幻觉延迟毫秒级秒级到分钟级状态无状态或DB持久化上下文窗口 向量记忆成本基本固定随Token波动测试断言输出评估分布和效果这个对比表是我在团队内部科普时的常用材料。它说明一件事AI应用架构的本质不是把传统架构加一个AI接口而是围绕“一个不确定的、昂贵的、有记忆的组件”重新设计整个系统的协作方式。这种重新设计就是很多人口中的“AI Native研发范式”。它意味着别把Prompt当作文档而是当作文本协议别把模型调用当成普通接口而是当成需要降级、缓存、监控的特殊外部依赖。2. 一张图看懂AI应用的基础骨架五层解剖这是我在很多分享会上画过的一版架构图。它不涉及具体技术栈但把AI应用必须有的能力边界先圈出来了。用文字画出来大概这个样子用户端 / 业务侧 | v [接入层] HTTP / WebSocket / SSE 流式协议 | v [能力层] 模型网关路由、重试、降级、多模型管理 | v [编排层] Agent运行时规划、记忆、工具调用、多Agent协调 | v [外部资源层] 专业工具API、知识库、数据库、岗位系统 | v [治理层] 可观测性、评估、安全护栏、成本配额这五层之间不是严格的物理分层有时会合并但在逻辑上必须清晰地分开接入层管协议能力层管模型编排层管智能行为资源层管外部依赖治理层管全局质量。2.1 接入层流式协议是第一优先级很多团队第一版AI应用接入层就做错了只提供同步HTTP接口等模型完整返回后一次性给前端。结果体验上就是“打字机变PPT”用户看着空白页面等十秒。正确的做法是尽量使用流式协议。目前最有用的就是SSEServer-Sent Events服务器发送事件它允许服务端持续向客户端推送数据天然适合大模型逐token输出。WebSocket也可以但连接管理和断线重连成本更高。如果是纯文本生成场景SSE优先如果需要双向语音、实时画布协作再考虑WebSocket。接入层还要做好请求载荷设计。除了基本的消息历史和用户输入还需要传递会话ID、用户ID、业务元数据。这些信息会被下游的日志追踪、成本归属、权限校验用到。没提前设计好后面审计时一片混乱。一个容易被忽略的点是超时。SSE本身是长连接正常的HTTP客户端超时设置会直接把请求断开。接入层要区分两类超时首包超时和整体超时。首包超时给模型推理留足够时间比如30到60秒整体超时则要覆盖流式传输全过程比如180秒。我见过有团队用默认的30秒请求超时导致所有带长上下文的模型请求全部失败。2.2 能力层模型网关是“模型界的API网关”能力层最核心的部件是模型网关。它的定位很像微服务里的API网关只不过路由的对象是模型和Prompt。模型网关至少要做四件事统一接入多个模型服务业务代码不直接依赖某个厂商SDK。按任务难度、成本预算做路由比如简单意图分类用小模型复杂代码生成用大模型。自动重试和熔断。模型服务经常出现限流、超时、5xx错误需要内置指数退避重试。Token计量和配额管理。每一个请求用了多少Token归属到哪个业务线都要在此处记账。我推荐把模型网关设计成OpenAI兼容接口。这样内部所有组件都用同一个协议进行调用替换模型时只需要改网关配置不用动业务代码。团队里新来的同学也能很快上手。模型网关还要处理“模型上下文协议”。现在社区里流行MCPModel Context Protocol模型上下文协议这类标准化方案本质是把工具暴露给模型的方式统一起来。架构上不用太迷信某个协议但最好留出适配层让后续接外部工具API时不用每个工具都写一遍解析逻辑。2.3 编排层Agent运行时和上下文管理往上一层是编排层也是Agent架构的主战场。单次模型调用其实不需要编排层但一旦要做工具调用、多步推理、多Agent协作就必须引入Agent运行时。Agent运行时的核心职责有三个规划把用户目标拆解成可执行的步骤。简单场景可以依赖模型自身的ReAct逻辑复杂场景可以用独立的Planner节点。记忆短期记忆放在对话上下文里长期记忆放进向量库做检索召回。架构上要区分会话级记忆和用户级记忆。工具调用模型输出Function Call参数运行时负责执行外部API把结果塞回上下文。这里最大的坑是Agent运行时不能变成一个“微核”什么逻辑都往里装。执行计划、状态存储、工具回调这些都要拆成独立模块。否则Agent逻辑和业务逻辑耦合下一次Prompt升级会牵连整个系统。状态管理特别容易被忽略。Agent任务通常是十几秒到几分钟的长任务进程重启、网络抖动、模型超时随时可能发生。状态不能放在内存里必须落Redis或数据库。每条Agent任务要有一个全局唯一的Trace ID所有Agent节点共享这个ID才能把消息流转串起来。2.4 外部资源层工具API、知识库和数据库Agent需要调用真实世界的能力时就落到外部资源层。工具API是主要入口比如查天气、发邮件、执行SQL、操作文件。知识库提供RAG能力先用向量检索找到相关片段再拼进Prompt。架构上这里要区分两类工具可信工具和不可信工具。可信工具是你自己开发的、返回结构固定的内部API不可信工具是第三方服务可能延迟高、可能挂掉、可能返回脏数据。对不可信工具要做好超时、重试、白名单、参数过滤。知识库的设计也直接影响整体架构。不是所有场景都需要向量库很多业务问题用SQL就能解决。只有在需要语义检索时才上向量检索比如合同问答、文档摘要。向量库本身要设计好索引分段策略分段太小导致上下文不够分段太大导致召回噪音高。我们后来总结了经验按语义段落切分每段控制在200到500个token召回时用MMR最大边际相关去重。2.5 治理层可观测性、评估和安全护栏最后那层治理层是很多AI应用上线后才补的但这恰恰应该从第一天就接上。可观测性不只要有日志还要有完整的调用链追踪。每次LLM调用的Prompt、Completion、Token数、延迟、模型版本、温度参数都要记下来。为什么要记这些因为模型的返回是概率性的线上某个回答“抽风”了如果没有原始Prompt和采集到的上下文你根本无法复盘。评估体系是AI应用架构里晋升为独立模块的一层。传统的断言测试不够用需要构建评估集比如100到500条典型用户问题配上期望的行为标签。每次Prompt改动或模型升级都跑一遍评估集用规则或裁判模型打分。有预算的情况下可以让“小模型给大模型打分”来做快速回归。安全护栏包括输入过滤、输出脱敏、敏感操作二次确认。Agent具备执行真实操作的能力后必须要有人的审批节点。比如Agent要删除一条数据系统应该拦截并请求人工确认这也是架构设计的一部分。3. 从单体模型调用到可扩展的Agent架构我踩过的三个坑理论说再多不如直接讲实际操作里踩过的坑。下面这三个问题是我在架构演进中真实遇到过的也是很多团队从“调用模型”走向“Agent架构”时必然趟过的河。3.1 第一个坑把Prompt当接口结果提示词一发版接口就碎最早我们尝试在业务代码里直接拼Prompt把业务字段用{变量}的方式嵌进去。看起来很方便但维护期就疯了产品提了一个新话术开发改了Prompt结果其他模块还在按旧格式解析模型输出整个链路就崩了。问题的本质是Prompt没有契约化。传统接口有明确的Request/Response schema前端和后端可以各做各的。但Prompt加模型输出的组合一旦没有强校验就是隐形的耦合点改一处碎一片。解决办法是给模型定义结构化输出并且设置后缀校验。让模型输出JSON再用JSON Schema校验校验不通过就重新生成或降级。对于更复杂的场景用Function Call而不是让模型直接回答这样输出走的还是结构化参数业务代码可以像调用普通函数一样使用。经验是Prompt里的每个变量都要像API字段一样有注释、有版本、有折旧淘汰流程。Prompt仓库和代码仓库放一起用PR审查改动。3.2 第二个坑单Agent包打天下重试风暴拖垮上游早期我们做了一个单Agent系统所有任务都由一个Agent循环调用模型直到拼出最终答案。并发稍微上来问题就出现了Agent内部一个环节失败就会整链重试而重试大概率又失败因为模型限流了于是堆出重试风暴把外部模型API的压力进一步放大。后来我们意识到Agent架构和微服务很像核心是隔离失败边界。把任务拆成Planner、Coder、Reviewer多个角色之后每个Agent只负责自己那一段失败时在上游返回不要放任重试。我们给模型调用加了三段退避第一次失败等2秒第二次等8秒第三次直接跳降级模型。更关键的是引入事件驱动的异步消息。Agent之间不要用同步HTTP调用而是发消息到队列里消费方处理完再发结果消息。这样模型API短暂不可用时消息会积压但不会把整个系统阻塞崩溃。3.3 第三个坑并发评估只看QPS没看Token漏斗接手过几次压测后我发现大家评估AI应用并发时都喜欢看每秒请求数但这个指标在AI应用上欺骗性很大。真正的瓶颈不是请求数而是Token吞吐量一次请求可能消耗3000 Token也可能消耗30000 Token差异超过十倍。如果不做Token漏斗分析你会遇到这种情况QPS看起来不高但模型网关的Token消耗先爆了导致上游限流、下游超时。我们后来在模型网关里记录了每个请求的“预估Token数”并在压测时观察分钟级Token消耗曲线据此调整并发上限和上下文压缩策略。上下文窗口也是一个隐形瓶颈。Agent任务里每一轮都要携带上下文上一轮的输出成了下一轮的输入很快就塞满上下文。我们常用的手段是上下文压缩对之前的对话做摘要只保留关键节选超过长度阈值时自动触发“遗忘”策略。4. 图解完整架构实例一个多Agent写代码辅助系统的设计下面用一个实际例子把这些架构思想串起来。假设我们要做一个“AI编程助手”用户给一句话需求系统完成设计、写代码、评审代码三个步骤。这个系统很适合演示多Agent协作的完整设计。4.1 节点拆分Planner、Coder、Reviewer各司其职三个Agent的分工如下Planner接收用户需求拆解成可实施的任务清单规划文件修改范围输出结构化计划。Coder根据计划逐个任务生成代码调用代码检索工具、读取相关文件生成diff。Reviewer审查Coder产出的代码检查是否有明显bug、安全风险、风格问题给出修改意见。这样拆的好处是每个Agent只处理相对单一的任务Prompt可以更聚焦模型输出的稳定性更高而且可以单独为每个节点选择不同的模型。比如Planner用推理能力强的大模型Coder用代码能力出色的模型Reviewer用廉价的小模型也能达到不错效果。4.2 消息流用事件总线解耦Agent间的同步调用在这个系统里三个Agent之间不是直接互相调接口的而是通过一个事件总线协作。事件总线的落地可以是Redis Stream或Kafka核心是让每个Agent异步响应事件处理完再发新事件。流程大概是用户提需求 - 触发 TaskCreated 事件 - Planner 消费事件输出计划 - 发布 PlanReady 事件 - Coder 消费事件生成代码 - 发布 CodeGenerated 事件 - Reviewer 消费事件输出审查意见 - 发布 ReviewCompleted 事件通知用户这个设计带来的直接好处是当Reviewer发现严重问题时可以发布ReviewFailed事件让Coder重新消费并修改而Planner不需要介入。整条链路是事件驱动每个节点的状态通过事件持久化存储天然支持重放和审计。如果某个Agent实例崩溃事件还在队列里重新启动后可以接着消费。这比同步调用舒服得多也特别好做并发扩展哪个环节成为瓶颈就给哪个Agent加消费者实例。4.3 状态恢复与边界条件失败重试、超时降级和人工兜底有了事件总线不代表万事大吉。还需要处理一批边界条件。第一是超时。模型生成代码可能很慢Coder节点的任务超时设为180秒超过后标记失败事件。失败事件进入死信队列由Planner重新决策比如拆成更小的任务再交给Coder。第二是重试。重试策略不能无限次我们规定最多三轮。三轮后仍然失败系统会把任务标记为“需人工介入”通知管理员手动处理。这里的关键是所有重试需要有幂等性。事件本身要带全局唯一ID消费方记录已处理的事件ID防止重复消费导致重复写文件。第三是上下文恢复。每个Agent执行任务时需要恢复必要的上下文比如Coder需要知道Planner的完整计划、自己已生成的代码、当前项目的文件树。这些上下文不应全部塞进模型而是由运行时通过检索和摘要生成。我们给每个任务开一个“上下文存储区”存原始需求、计划、文件快照、gpt日志供每个Agent按需读取。这样的架构跑下来的效果是一次完整的三Agent任务成功率从最初的62%提升到了91%。剩余失败里有一半是因为模型本身能力不足需要人工兜底另外一半是外部工具API异常通过重试机制就能覆盖。5. 架构落地的工程化必备测试、可观测性和成本控制架构图画得再漂亮落地时还是要面对测试、监控、成本这三座大山。缺了任何一座系统迟早出问题。5.1 测试开发LLM应用需要的不是“单测”而是评估回归传统测试在AI应用上只能覆盖很小一部分。你不能用“断言输出等于X”来测模型返回。我们采用的测试分层是单元测试测试工具API、上下文压缩、路由逻辑、状态持久化等确定性代码。集成测试用固定的输入和Mock模型验证Agent流程能正常走通。评估回归构建带标注的评估集每次Prompt更新后跑全套用裁判模型给回答质量打分。灰度对比线上小流量跑新旧Prompt对比用户反馈和任务成功率。我开始做LLM应用测试时也走过弯路试图用“覆盖所有用例”的思路去测Prompt结果维护成本爆炸。后来意识到评估集要少而精覆盖典型用户提问、边界输入、高风险场景每类几十条就够了。关键是每次变更都跑控制“变坏”的速度。5.2 可观测性把每一次LLM调用都当作数据库查询一样记录AI应用的可观测性比传统系统要求更高。除了常规的日志和指标还必须把“模型行为”纳入监控范畴。我们为每次LLM调用生成一条trace包含请求方和业务方标识Prompt全文和输出使用的模型名、版本、采样参数Token消耗和费用预估首包延迟、总延迟、是否流式、重试次数是否有工具调用、调用了哪个工具有了这些trace线上出了任何问题都可以回溯是不是上下文太长导致代答是不是模型限流导致超时是不是某个工具返回脏数据污染了生成。我建议把trace存储和业务日志分开trace单独走一套存储比如ClickHouse或S3冷存储。因为它的量级很大但价值也很高。同时要在监控大盘上放出几个核心指标任务成功率、工具调用成功率、Token消耗趋势、模型响应延迟分位数、上下文长度分布。5.3 成本控制与性能优化缓存、降级、并发配额最后落到钱上。AI应用的成本大头在模型Token而且消费速度远超传统API。我的优化清单按性价比排序Prompt和响应缓存。对完全相同或高度相似的请求用语义缓存适配层复用结果。缓存命中能省下50%以上的成本。模型分级路由。简单问题用便宜的小模型复杂问题才用贵的大模型。我们的经验是约30%的请求可以安全走小模型成本直接下降25%。上下文瘦身。对话历史太长时先摘要向量只召回最相关的片段避免每次请求都传完整历史。并发配额控制。按业务线设置令牌桶防止某个流量冲高的业务消耗完整个模型的配额。合理设置温度。对需要稳定输出的功能把温度降低到0不但在质量上更可控也能减少因随机性导致的重试成本。性能上还有一个很多人忽略的点充分使用流式接口。没有流式的话用户感知不到进展容易反复点击从而产生更多无效请求。引入SSE后用户能在第一时间看到首token等待焦虑大幅降低实际重试率也降了。最后再分享一点我的实际体会这套架构并不是一天搭成的。我经历过直接调用API的“野蛮生长期”也经历过把所有能力塞进一个Agent的“混沌期”最后还是回到分层解耦、事件驱动、状态可恢复这些经典工程原则上。如果让我给正要起步的团队一个建议先别急着上多Agent。先把单Agent跑稳把模型网关、上下文管理、评估体系这三样基础打牢。等单Agent的调用链不再需要人工干预了再逐步拆出Planner和Reviewer引入事件总线让多个Agent协作。每一步演进都要有指标验证否则很容易为了架构而架构最后变成一个无比复杂但没人能维护的玩具。架构设计的初衷不是堆叠技术而是让系统的确定性更高、可维护性更强同时把模型的不确定性控制在可控的边界内。