ARTICLE DETAIL

资讯详情

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

AI应用架构设计:从传统分层到Agent与MCP的生产实践

AI应用架构设计:从传统分层到Agent与MCP的生产实践 1. 从一张架构图说起为什么AI应用不能照搬传统分层很多人第一次接触AI应用架构设计脑子里浮现的还是经典的三层架构前端、后端、数据库。这套东西在过去二十年里确实好用业务逻辑写清楚接口定义好数据存进去基本就稳了。但一旦把LLM和Agent塞进来这套分层立刻就不够用了。原因很直接传统后端的输出是确定的输入A必然得到B而LLM的输出是概率性的同样的输入可能得到三种不同的回答甚至同一个问题问两次结果都不一样。你没法用“接口契约”去约束一个概率模型也没法用“事务回滚”去撤销一次已经发生的模型调用。这就是为什么AI应用架构必须重新设计——它不是把LLM当成一个普通服务挂上去而是要把不确定性当成一等公民来对待。我见过不少团队一开始的做法是后端加一个/chat接口里面调一下模型API返回结果给前端。Demo阶段没问题一旦上生产就崩——并发一上来模型调用超时、Token消耗失控、上下文丢失、工具调用乱序各种问题全冒出来。这不是代码写得不好而是架构层面缺了东西。这篇内容想做的事情是把“AI应用架构设计”这件事拆开讲清楚。我会从核心组件、Agent架构、MCP协议、并发与安全、以及实际落地时的踩坑经验几个角度展开尽量用图解式的思路把每一层的职责和边界说透。适合正在做AI应用开发、准备从Demo走向生产、或者想系统理解Agent架构的工程师参考。不管你是后端转过来的还是运维想补AI这块都能找到能直接用的东西。2. AI应用架构的核心分层与各层职责2.1 为什么传统MVC在这里会失效先说说传统MVC为什么在AI应用里不好使。MVC的核心假设是Controller接收请求、Model处理业务、View渲染结果三者职责清晰数据流是单向且确定的。但AI应用里Controller拿到用户输入后往往需要先做意图识别、再决定要不要调用工具、工具返回后还要再喂给模型做二次推理最后才生成回复。这个链路是动态的不是固定的。更麻烦的是Model层在AI应用里变成了“模型调用上下文管理工具编排”的混合体它既不是纯业务逻辑也不是纯数据访问。你硬套MVC最后会发现Controller里塞满了Prompt拼接Model里塞满了API调用View层还要处理流式输出。所以AI应用架构需要重新分层我一般会把它拆成五层接入层、编排层、模型层、工具层、数据层。2.2 五层架构的职责边界接入层负责协议转换和流量控制。用户可能从Web、App、API、甚至IM工具进来接入层要把这些请求统一成内部格式同时做限流、鉴权、会话绑定。这一层的关键是“快”不要在这里做任何模型相关的事情。编排层是整个架构的大脑。它决定一次请求要走什么流程是直接问答还是需要调用工具还是需要多轮推理。编排层里通常会有Agent Runtime、Prompt模板管理、上下文窗口管理、以及路由逻辑。这一层最复杂也最容易出问题。模型层负责和LLM打交道。它要处理模型选型、API调用、重试、降级、Token计数、流式解析。注意模型层不应该关心业务逻辑它只负责“把Prompt发出去把结果拿回来”。工具层是所有外部能力的集合。搜索、数据库查询、代码执行、第三方API都封装成工具。工具层的关键是“标准化”每个工具要有清晰的输入输出schema否则模型不知道怎么调。数据层除了传统数据库还要考虑向量库、缓存、会话历史存储。向量库用于RAG缓存用于减少重复调用会话历史用于多轮对话。这三者的读写模式完全不同不能混在一起设计。提示很多团队把向量库和业务数据库放在同一个实例里结果向量检索的负载把业务查询拖垮。建议物理隔离至少用不同的连接池。2.3 各层之间的数据流与契约层与层之间要有明确的契约。接入层到编排层传的是标准化的请求对象包含用户ID、会话ID、输入文本、附件等。编排层到模型层传的是Prompt和参数模型层返回的是原始响应和Token消耗。编排层到工具层传的是工具名和参数工具层返回结构化结果。这里有个容易忽略的点错误处理。模型调用可能超时工具调用可能失败编排层要能区分“可重试错误”和“不可重试错误”。比如模型超时可以重试但工具返回“参数不合法”就不能重试应该直接把错误信息喂回给模型让它重新生成参数。这个逻辑必须在编排层实现不能丢给模型层或工具层。3. Agent架构从单轮到多轮从被动到主动3.1 Agent和普通LLM调用的本质区别普通LLM调用是“一问一答”你给Prompt它给回复结束。Agent不一样Agent有目标、有记忆、有工具、能循环。你给Agent一个任务它会自己决定先做什么、再做什么中间可能调用多个工具最后才给出结果。这个区别在架构上意味着什么意味着Agent需要一个运行时环境。这个运行时要做几件事维护状态当前任务进行到哪一步、管理工具注册表、处理循环终止条件、以及做错误恢复。没有这个运行时Agent就是一堆散落的API调用。我见过有人用简单的while循环实现Agent跑几个简单任务没问题但一旦任务复杂、工具多了循环就失控了——要么死循环要么提前退出要么工具调用顺序乱了。所以Agent Runtime是必须的它不是过度设计而是生产环境的刚需。3.2 Agent Runtime的关键组件一个可用的Agent Runtime至少包含这几个部分状态机记录当前处于哪个阶段是思考、行动、还是观察。每次循环都要更新状态。工具注册表所有可用工具的元数据包括名称、描述、参数schema。模型根据这个来决定调哪个工具。上下文管理器管理对话历史和中间结果决定哪些信息要保留、哪些要截断。因为上下文窗口有限不能什么都往里塞。终止条件什么时候停止循环。可以是任务完成、达到最大轮数、或者模型明确表示结束。错误处理器工具调用失败时怎么办是重试、跳过、还是把错误返回给模型。这些组件不需要很重但必须有。我一般建议用现成的Agent框架起步比如LangChain、LlamaIndex、或者国内的扣子这类平台先把流程跑通再根据实际需求做定制。不要一上来就自己造轮子除非你有非常特殊的场景。3.3 多Agent协作的架构模式当任务复杂到单个Agent搞不定时就需要多Agent协作。常见的模式有三种主管模式、流水线模式、辩论模式。主管模式是一个主Agent负责拆解任务分给子Agent执行最后汇总结果。这种模式适合任务可以明确分解的场景比如“先查数据、再分析、再写报告”。流水线模式是多个Agent按顺序执行每个Agent的输出是下一个的输入。适合流程固定的场景比如内容审核先过敏感词Agent再过质量Agent最后过格式Agent。辩论模式是多个Agent对同一问题给出不同答案然后由一个裁判Agent选最优。适合需要高质量决策的场景但成本高一般不用在实时交互里。选哪种模式取决于任务的可分解性和对延迟的要求。主管模式灵活但延迟高流水线模式快但不够灵活辩论模式质量高但成本高。实际项目里往往是混合使用。4. MCP协议工具调用的标准化尝试4.1 MCP解决了什么问题在没有MCP之前每个AI应用接工具都是自己定义一套接口。你接搜索是一个写法接数据库是另一个写法接第三方API又是另一个写法。模型要调工具得先知道每个工具的调用格式这就导致Prompt里要写大量工具说明而且换个模型可能就不兼容了。MCPModel Context Protocol想解决的就是这个问题定义一套标准协议让工具的描述、调用、返回都有统一格式。模型不需要知道具体工具怎么实现只需要按MCP的规范去调用。工具提供方也不需要关心上层用的是什么模型只要实现MCP接口就行。这个思路很像当年的USB标准——不管你是键盘、鼠标还是U盘接口统一了插上就能用。MCP对AI应用的意义类似它让工具生态可以独立发展不用和特定模型绑定。4.2 MCP的核心概念与工作流程MCP里有几个核心概念Server、Client、Resource、Tool、Prompt。Server是工具提供方它暴露自己的能力。Client是AI应用它连接Server并调用能力。Resource是Server提供的静态数据比如文件、数据库记录。Tool是可执行的操作比如搜索、计算。Prompt是预定义的模板方便Client直接使用。工作流程大致是Client启动时连接Server获取Server的能力列表有哪些Tool、哪些Resource。运行时Client把用户请求和可用工具列表一起发给模型模型决定调哪个工具Client通过MCP协议调用Server拿到结果后再喂给模型。这个流程的关键是“能力发现”——Client不需要硬编码工具信息而是动态从Server获取。这样新增工具时只要Server更新Client不用改代码。4.3 实际接入MCP时的坑MCP听起来很美但实际接入时有几个坑要注意。第一工具描述的质量直接决定模型能不能调对。如果工具描述写得含糊模型就会调错工具或者传错参数。我一般建议工具描述要包含这个工具做什么、什么时候用、参数是什么意思、返回什么格式。越详细越好宁可啰嗦也不要含糊。第二MCP Server的稳定性。如果Server挂了Client要有降级方案不能整个应用都不可用。我一般会在Client侧做工具调用的超时和熔断Server不可用时返回一个明确的错误让模型知道这个工具暂时不可用。第三权限控制。MCP Server可能暴露敏感操作比如数据库写入。Client侧要有权限校验不能什么请求都转发给Server。这个校验应该在Client做而不是依赖Server因为Server可能被多个Client共用。第四版本兼容。MCP协议还在演进不同版本的Server和Client可能不兼容。接入前要确认版本匹配否则会出现“能连上但调不通”的情况。5. 并发、Token与成本生产环境的硬约束5.1 AI Agent怎么扛并发这是被问得最多的问题之一。传统后端扛并发靠的是无状态服务和水平扩展但AI Agent是有状态的而且每次调用都要等模型返回延迟高。这就导致并发能力受限于模型API的速率限制和响应时间。我的经验是分三层来扛第一层是接入层限流。按用户、按会话、按接口做限流防止单个用户把配额占满。这一层用传统的令牌桶或漏桶算法就行。第二层是请求队列。Agent请求进来后不直接调模型而是进队列由工作线程按模型API的速率限制来消费。这样可以把突发流量削峰避免被模型API限流。第三层是结果缓存。相同或相似的请求可以复用结果。比如FAQ类问题第一次调完模型后把结果缓存起来后续直接返回。缓存key可以用输入文本的哈希加上用户上下文。注意缓存AI结果要谨慎因为同样的输入在不同上下文下可能需要不同回答。我一般只对明确无状态的请求做缓存比如“解释什么是MCP”这种。5.2 Token消耗的监控与优化Token就是钱不监控Token消耗的AI应用就是在烧钱。我一般会在模型层做几件事每次调用记录输入Token、输出Token、总Token按用户、按会话、按接口维度聚合。设置Token预算单个会话超过阈值就告警或降级。优化Prompt去掉冗余说明用更短的表达。有时候一个Prompt精简20%效果不变成本直接降两成。控制上下文长度不要把所有历史都塞进去。可以用摘要代替原文或者只保留最近N轮。这里有个细节不同模型的Token计算方式不一样中文和英文的Token比例也不同。做成本估算时要用实际模型的Tokenizer来算不能拍脑袋。5.3 模型选型与降级策略生产环境不能只依赖一个模型。我一般会配置主模型和备用模型主模型不可用或超时时自动切到备用。备用模型可以是更小、更快、更便宜的版本虽然效果差一点但至少服务不中断。选型时要考虑几个维度效果、延迟、成本、上下文窗口、是否支持工具调用。不是越贵越好而是要看场景。比如意图识别用一个小模型就够了复杂推理才需要大模型。降级策略要提前设计好不能等出事了再想。我一般会定义几个降级级别正常用主模型主模型超时用备用模型备用也挂了就返回兜底话术。每一级都要有明确的触发条件和恢复条件。6. 安全与可观测性容易被忽视的两块6.1 Agent安全不只是Prompt注入Agent安全是个大话题很多人只想到Prompt注入其实远不止。Prompt注入只是其中一种还有工具滥用、数据泄露、权限越界、以及Agent被诱导执行危险操作。工具滥用是指模型被诱导调用不该调的工具。比如一个查询工具被诱导成删除工具。防范方法是在工具层做权限校验每个工具调用都要检查当前用户是否有权限不能只依赖模型判断。数据泄露是指Agent在回复中带出了不该带出的信息。比如RAG检索到了其他用户的私有数据。防范方法是在检索层做权限过滤确保只检索当前用户有权限的数据。权限越界是指Agent执行了超出其职责的操作。比如一个客服Agent试图修改订单金额。防范方法是最小权限原则Agent只拥有完成其任务所需的最小权限。Agent被诱导是指通过多轮对话逐步引导Agent做出危险行为。这种最难防因为单轮看起来都正常。防范方法是做行为审计记录所有工具调用异常行为告警。6.2 可观测性日志、追踪与评估AI应用的可观测性和传统应用不一样。传统应用看QPS、延迟、错误率就够了AI应用还要看模型效果、Token消耗、工具调用成功率、以及用户满意度。我一般会做三层可观测性第一层是基础监控QPS、延迟、错误率和传统应用一样。第二层是AI专项监控Token消耗、模型调用成功率、工具调用成功率、上下文长度分布。第三层是效果评估用LLM as Judge的方式自动评估回复质量或者用人工抽检。评估指标包括相关性、准确性、完整性、安全性。追踪方面每次请求要有完整的Trace从接入层到编排层到模型层到工具层每一跳都要记录。这样出问题时能快速定位是哪一层的问题。6.3 评估与迭代的闭环AI应用不是上线就完了需要持续迭代。迭代的依据是评估结果。我一般会建立一个评估集包含典型问题和边界情况每次改动后跑一遍评估集看效果有没有下降。评估集要覆盖几类场景正常问答、多轮对话、工具调用、异常输入、以及安全测试。每类场景都要有明确的通过标准。迭代时要注意Prompt改动可能影响其他场景。比如你为了修复A问题改了Prompt结果B问题变差了。所以每次改动都要全量评估不能只看单点。7. 从Demo到生产我踩过的那些坑7.1 上下文丢失与截断策略最早做多轮对话时我直接把所有历史都塞进Prompt结果很快就超上下文窗口了。后来改成只保留最近N轮但又出现了“用户前面说过的信息后面忘了”的问题。最后的方案是分层保留最近几轮保留原文更早的做摘要关键信息比如用户ID、订单号单独提取出来始终保留。这样既控制了长度又不丢关键信息。摘要也有讲究不能简单截断要用模型生成摘要。但摘要本身也要消耗Token所以摘要的频率要控制不能每轮都重新摘要。7.2 工具调用乱序与参数错误Agent调工具时经常出现两个问题一是调用顺序不对二是参数格式不对。调用顺序问题通常是因为工具描述不够清晰模型不知道先调哪个。解决方法是在工具描述里写明依赖关系比如“调用B之前必须先调用A”。参数格式问题通常是schema定义不够严格。我一般会用JSON Schema严格定义参数类型、格式、枚举值并在工具层做校验不合法就返回明确错误让模型重试。还有一个坑是工具返回结果太长把上下文撑爆了。解决方法是在工具层做结果截断或摘要只返回关键信息。7.3 模型幻觉与兜底设计模型幻觉是绕不开的问题。我的经验是不要试图完全消除幻觉而是要做好兜底。兜底策略包括关键信息要求模型引用来源没有来源就不回答对高风险操作要求二次确认对不确定的回答明确标注“我不确定”。另外RAG可以显著降低幻觉但前提是检索质量要高。检索不到相关内容时宁可让模型说“我不知道”也不要让它编。7.4 上线前的检查清单最后分享一个我常用的上线检查清单模型API是否有降级方案Token消耗是否有监控和告警工具调用是否有权限校验上下文长度是否有控制是否有评估集和回归测试是否有完整的Trace和日志是否有安全测试Prompt注入、工具滥用是否有兜底话术和错误处理是否有成本预算和限额是否有用户反馈渠道这个清单不是一次性的每次大改动后都要重新过一遍。AI应用的变化太快今天的检查项明天可能就不够了。我个人在实际项目中的体会是AI应用架构设计最难的从来不是技术选型而是对不确定性的管理。传统软件追求确定性AI应用要学会和不确定性共处。把不确定性限制在可控范围内把确定性留给架构这才是AI应用架构设计的核心。
返回列表