☰
AI应用架构设计实战:分层逻辑、上下文管理与Agent编排
2026/10/7 13:46:09 网站建设 项目流程

1. 从一张架构图说起:为什么AI应用架构值得单独拆解

很多人第一次接触AI应用开发,脑子里想的都是"调个API就完事了"。我刚开始也是这么想的——拿个模型接口,拼个提示词,前端套个对话框,收工。直到真正接手一个要同时服务几千用户的AI应用,才发现事情远没有这么简单:模型响应忽快忽慢、上下文一长就崩、多轮对话状态到处乱飞、成本像脱缰的野马一样往上涨。这时候你才会意识到,AI应用架构设计是一门独立的功夫,它和传统的Web后端架构有大量重叠,但也有自己一套独特的骨架。

所谓"图解AI应用架构设计",核心不是画一张好看的框图,而是把AI应用从用户输入到模型输出这条链路上,每一个环节的职责、边界、数据流向和失败模式都讲清楚。一张合格的AI应用架构图,应该能回答这几个问题:请求进来先经过谁?上下文在哪里拼装?模型调用是同步还是异步?工具调用(Tool Calling)由谁编排?记忆存在哪一层?成本和安全在哪一层拦截?如果这些问题在图上看不出来,那这张图就只是装饰。

这篇文章适合三类人看:一是正在从传统后端转向AI应用开发的工程师,你需要知道哪些老经验能复用、哪些必须重新学;二是负责AI产品落地的技术负责人,你要能判断一个架构方案是否靠谱;三是对AI应用感兴趣但还没动手的开发者,你可以把这篇当成一张"施工图",照着理解每个模块为什么存在。我会尽量用从业者的视角,把每个设计决策背后的"为什么"讲透,而不是丢一堆名词让你自己猜。

需要先说明一点:AI应用架构没有唯一正确答案,它高度依赖你的场景——是To C的聊天产品,还是To B的流程自动化,还是内部的研发提效工具,架构差异非常大。所以下面讲的是一套通用的分层思路和决策框架,你需要在具体项目里做取舍。

2. AI应用架构的分层逻辑:每一层到底在解决什么问题

2.1 为什么AI应用不能只有"前端+模型"两层

最朴素的AI应用就是两层:前端收集用户输入,直接调模型API,拿到结果展示。这种结构在Demo阶段完全够用,但一旦上线就会暴露一堆问题。我列几个真实会遇到的:

  • 密钥暴露:前端直连模型API意味着API Key要下发到浏览器,等于把钱包交给用户。
  • 无法做统一治理:限流、计费、审计、敏感内容过滤,这些都需要一个中间层来统一处理。
  • 上下文管理失控:多轮对话的历史怎么截断、怎么摘要、怎么和知识库拼接,前端做不了。
  • 模型切换成本高:今天用A模型,明天想换B模型,前端直连的话要改一堆代码。

所以一个能上生产的AI应用,通常至少分成四层:接入层、编排层、能力层、基础设施层。这不是为了显得复杂,而是每一层都对应一类明确的职责。下面这张表是我在实际项目中常用的分层对照,你可以直接拿去对照自己的项目:

层级核心职责典型组件失败时的表现
接入层鉴权、限流、协议转换、流式转发API网关、BFF用户被刷爆、密钥泄露
编排层提示词组装、上下文管理、工具调度、多步推理编排引擎、Agent框架答非所问、死循环、状态丢失
能力层模型调用、向量检索、工具执行、内容审核模型网关、RAG服务、工具服务响应慢、检索不准、工具报错
基础设施层缓存、存储、队列、可观测性Redis、向量库、消息队列、日志成本失控、问题无法定位

这张表的价值在于:当你的AI应用出问题时,你可以快速定位是哪一层的锅。比如用户说"回答很慢",可能是接入层没做流式、编排层上下文拼太长、能力层模型本身慢、基础设施层缓存没命中——分层清晰,排查才有方向。

2.2 编排层才是AI应用的"大脑",别把它和业务逻辑混在一起

我见过不少项目把编排逻辑(拼提示词、管上下文、调工具)直接写进业务代码里,结果就是业务代码和AI逻辑纠缠在一起,改一个提示词要动半个服务。正确的做法是把编排层当成一个独立的、可替换的模块。

编排层要干的事,说白了就三件:决定给模型看什么、决定让模型做什么、决定模型做完之后怎么办。

  • "给模型看什么"包括:系统提示词、历史对话、检索到的知识片段、用户当前输入,以及这些内容怎么排序、怎么截断、怎么压缩。
  • "让模型做什么"包括:是直接回答,还是先调用工具,还是走多步推理(比如先规划再执行)。
  • "模型做完之后怎么办"包括:结果要不要二次审核、要不要落库、要不要触发下一步动作。

把这三件事抽出来单独设计,好处是你可以针对不同场景复用同一套编排引擎。比如同一个电商AI应用,"客服问答"和"商品推荐"用的是不同的提示词和工具集,但底层的上下文管理、工具调度、结果处理逻辑是共享的。这就是编排层独立的价值。

2.3 能力层的关键是"抽象",让模型和工具都可插拔

能力层的设计原则只有一个词:抽象。模型要抽象成统一的调用接口,工具也要抽象成统一的执行接口。这样做的直接好处是,你可以在不改动编排层的前提下,把GPT换成Claude,把本地向量库换成云端向量库,把自研工具换成第三方工具。

模型抽象层(很多人叫它"模型网关")至少要处理这几件事:统一不同厂商的请求格式差异、统一流式和非流式的返回、统一错误码和重试策略、统一计费和用量统计。我踩过的一个坑是:不同厂商对"系统提示词"的支持方式不一样,有的放在messages里role=system,有的放在单独的字段,有的甚至不支持。如果不在网关层抹平这些差异,编排层就要写一堆if-else,非常难维护。

工具抽象层同理。一个工具本质上就是"输入参数→执行→返回结果"的函数,但AI场景下的工具调用有额外要求:参数要用JSON Schema描述清楚(模型靠这个理解怎么调)、执行结果要能转成模型能读的文本、执行失败要能优雅地告诉模型而不是直接崩掉。把这些规范固化在工具抽象层,新增工具就是填一个模板的事。

3. 上下文与记忆的架构设计:AI应用最容易翻车的地方

3.1 上下文窗口不是越大越好,截断策略决定体验上限

很多人以为模型上下文窗口越大越好,恨不得把整本手册都塞进去。实际做下来你会发现,上下文越长,成本和延迟越高,而且模型对中间部分的注意力会下降(这就是业内常说的"lost in the middle"现象)。所以上下文管理的核心不是"塞满",而是"塞对"。

我在项目里常用的上下文组装顺序是这样的,从高优先级到低优先级:

  1. 系统提示词(角色、规则、输出格式约束)——永远保留
  2. 当前用户输入——永远保留
  3. 最近N轮对话原文——保留最近3到5轮
  4. 更早对话的摘要——用模型压缩成一段话
  5. 检索到的知识片段——按相关度排序,取Top K
  6. 工具调用结果——只保留最近一次或必要的

当总长度超过预算时,从优先级最低的开始砍。这个"预算"怎么定?我的经验是:给模型上下文窗口留出30%的余量。比如模型支持128K,你的输入控制在90K以内,剩下的留给模型输出和突发情况。因为输出也是要占token的,很多人算上下文时只算输入,结果输出被截断,用户看到半句话,体验极差。

3.2 短期记忆、长期记忆、工作记忆,三者别混为一谈

AI应用的"记忆"经常被笼统地当成一个东西,其实至少要分三类,它们的存储介质和生命周期完全不同:

  • 短期记忆:当前会话的对话历史,存在Redis或内存里,会话结束就可以清理。特点是读写频繁、数据量小、要求低延迟。
  • 长期记忆:跨会话的用户偏好、历史事实,存在关系库或向量库里,需要持久化。特点是写入少、读取需要检索、要求准确。
  • 工作记忆:当前任务执行过程中的中间状态,比如Agent执行到第几步、已经调用了哪些工具、中间结果是什么。特点是生命周期短但结构复杂,通常存在编排层的状态机里。

把这三类记忆分开设计,最大的好处是成本和性能可控。短期记忆用Redis,长期记忆用向量库,工作记忆用状态机,各司其职。我见过把所有东西都塞进向量库的项目,结果每次对话都要做一次全量检索,延迟高得离谱,而且检索出来的东西经常不相关。

3.3 记忆写入的时机比写入的内容更重要

一个容易被忽略的点是:什么时候把信息写入长期记忆。如果每轮对话都写,向量库会被大量无意义内容污染,检索质量断崖式下降。如果只在会话结束时写,又可能漏掉关键信息。

我的做法是设置一个"记忆写入触发器",满足以下任一条件才写入:

  • 用户明确表达了偏好("我以后都用中文回答")
  • 出现了可复用的事实("我的订单号是XXX")
  • 模型主动判断这段信息值得记住(通过一个轻量的判断提示词)

写入时还要做去重和冲突检测。比如用户先说"我喜欢简洁的回答",后来说"请详细解释",这两条是冲突的,需要以最新的为准,或者标记时间戳让检索时按时间加权。这些细节不做,长期记忆很快就会变成一堆互相矛盾的垃圾。

4. 工具调用与Agent编排:从"能调"到"调得稳"

4.1 工具描述写得好不好,直接决定模型调得对不对

工具调用(Tool Calling)看起来很简单:定义几个函数,模型自己决定调哪个。但实际效果好不好,八成取决于工具描述的质量。模型只能通过你给的名称、描述和参数Schema来理解这个工具是干什么的,描述写得含糊,模型就会乱调或者不调。

我总结了几条写工具描述的经验:

  • 名称要动词开头、语义明确:search_orders比order_tool好,send_email比email好。
  • 描述要说清楚"什么时候用"和"什么时候不用":比如"查询订单状态时使用;如果用户只是询问退货政策,不要调用此工具"。
  • 参数描述要给出示例值:order_id的描述写成"订单编号,格式如ORD-20240101-001",模型填错的概率会大幅下降。
  • 参数尽量用枚举而不是自由文本:能限定取值范围的,就不要让模型自由发挥。

下面是一个我实际用过的工具定义示例,你可以感受一下描述的颗粒度:

{ "name": "query_order_status", "description": "根据订单编号查询订单的当前状态和物流信息。当用户询问某个具体订单的进度、是否发货、预计到达时间时使用。如果用户没有提供订单编号,先向用户询问,不要猜测。", "parameters": { "type": "object", "properties": { "order_id": { "type": "string", "description": "订单编号,格式为 ORD-YYYYMMDD-NNN,例如 ORD-20240101-001" } }, "required": ["order_id"] } }

4.2 多工具编排的三种模式,选错了就是灾难

当应用需要调用多个工具时,编排模式的选择非常关键。我把它归纳成三种,各有适用场景:

模式工作方式适用场景风险
单轮单工具模型一次只调一个工具,拿到结果再决定下一步简单查询、步骤明确的流程多步任务轮次多、延迟高
单轮多工具并行模型一次返回多个工具调用,并行执行相互独立的查询(如同时查天气和汇率)工具间有依赖时会出错
规划-执行分离先用模型做规划,再按计划逐步执行复杂多步任务、Agent场景规划错误会导致整条链路失败

我的建议是:能用单轮单工具就别上Agent。很多团队一上来就搞复杂的Agent编排,结果调试成本极高,效果还不稳定。实际上大部分业务场景,单轮单工具加上清晰的提示词就能解决。只有当任务确实需要多步推理、且步骤无法预先确定时,才值得上规划-执行模式。

4.3 Agent死循环的排查与预防

Agent最让人头疼的问题就是死循环:模型反复调用同一个工具,或者在不同工具之间来回横跳,永远不给出最终答案。我遇到过最夸张的一次,Agent连续调了27次搜索工具,把API额度都烧完了。

排查死循环,我一般按这个顺序看:

  1. 看工具返回内容:是不是工具一直返回空结果或错误,导致模型以为没查到、继续查?如果是,要在工具层做"连续失败N次就返回明确失败信号"的处理。
  2. 看提示词约束:有没有明确告诉模型"最多调用几次工具"、"如果信息不足就直接回答"?没有的话补上。
  3. 看状态传递:Agent的中间状态有没有正确传给下一轮?如果每轮都从零开始,模型会重复做同样的事。
  4. 看终止条件:编排层有没有硬性的最大轮次限制?这个必须有,作为兜底。

预防死循环的硬性措施:在编排层设置最大工具调用轮次(我一般设5到8轮)和最大总耗时,超过就强制让模型基于已有信息作答。这个兜底不做,线上迟早出事。

5. 性能、成本与可观测性:上线之后才真正开始

5.1 流式输出不只是体验优化,更是架构要求

很多人把流式输出(Streaming)当成一个前端体验优化,其实它对架构的影响很深。一旦决定用流式,整条链路都要支持流式:接入层要支持SSE或WebSocket、编排层要能处理流式的中断和拼接、能力层要能透传模型的流式响应、前端要能处理"边收边渲染"。

流式带来的一个额外好处是首字延迟(TTFT)大幅降低。用户不需要等模型全部生成完,看到第一个字就开始读,主观感受快很多。但流式也带来新问题:如果流到一半出错怎么办?我的做法是在流式响应里加入结构化的错误事件,前端收到错误事件后展示"生成中断,请重试",而不是让用户对着半句话发呆。

5.2 成本控制的三个抓手:缓存、路由、压缩

AI应用的成本大头在模型调用。控制成本我一般从三个地方下手:

  • 缓存:完全相同的请求直接返回缓存结果。注意,AI场景下的缓存不能只按输入文本做key,因为同样的输入在不同上下文下结果可能不同。我的做法是把"系统提示词+用户输入+关键上下文摘要"拼起来做key,命中率虽然低一些,但不会返回错误结果。
  • 模型路由:不是所有请求都需要最强的模型。简单分类、格式转换用便宜的小模型,复杂推理才用大模型。路由可以基于规则(按请求类型),也可以基于模型判断(先用小模型判断难度)。
  • 上下文压缩:前面讲过的截断和摘要,本身就是成本控制手段。另外,检索到的知识片段要做去重和精简,别把整篇文档塞进去。

我做过一个粗略的统计:在一个客服场景里,加上缓存和模型路由之后,模型调用成本能降到原来的40%左右,而用户满意度基本没降。这个投入产出比非常值得。

5.3 可观测性:没有日志和追踪,AI应用就是黑盒

传统应用的日志主要记录"发生了什么",AI应用的日志还要记录"模型看到了什么、输出了什么、为什么这么输出"。我建议至少记录这几类信息:

  • 请求级:请求ID、用户ID、时间戳、总耗时、各阶段耗时
  • 编排级:最终拼装的完整提示词、上下文长度、检索到的片段及分数
  • 模型级:调用的模型、输入输出token数、首字延迟、总延迟、是否命中缓存
  • 工具级:调用了哪些工具、参数是什么、返回什么、耗时多少
  • 结果级:最终输出、是否被审核拦截、用户反馈

这些日志的价值在排查问题时体现得淋漓尽致。有一次用户投诉"AI答非所问",我拉出日志一看,发现是检索环节返回了一个相关度极低的片段,模型被这个片段带偏了。如果没有编排级日志,这个问题根本无从查起。

提示:日志里会包含用户输入和模型输出,涉及隐私的内容一定要做脱敏处理,并且明确日志的保留期限。这不是可选项,是合规底线。

6. 一套可落地的AI应用架构参考方案

6.1 中小型AI应用的推荐架构

如果你正在做一个中小型AI应用(日活几千到几万),我推荐这套相对轻量但完整的架构:

  • 接入层:一个API网关负责鉴权和限流,一个BFF负责协议转换和流式转发。
  • 编排层:一个编排服务,内部包含提示词模板管理、上下文组装器、工具调度器、状态机。
  • 能力层:模型网关(统一多模型调用)、RAG服务(向量检索+重排)、工具服务(各业务工具的封装)、审核服务。
  • 基础设施层:Redis做短期记忆和缓存,向量库做长期记忆和知识检索,关系库做业务数据和日志,消息队列做异步任务。

这套架构的组件数量可控,每一层都可以独立部署和扩容。我实际用这套结构支撑过日活几万的应用,稳定性没问题。

6.2 关键配置参数参考

下面这张表是我在多个项目里沉淀下来的参数起点,你可以根据自己的场景调整:

参数推荐起点调整依据
上下文预算占窗口比例70%模型输出长则调低
保留最近对话轮数5轮对话密集则增加
检索Top K5条知识库大则增加,但要做重排
工具最大调用轮次6轮任务复杂则增加,但要有超时兜底
模型调用超时30秒流式场景可放宽
缓存TTL1小时内容时效性强则缩短
首字延迟告警阈值3秒根据用户容忍度调整

这些数字不是金科玉律,但作为起点能帮你少走弯路。关键是每个参数都要有监控和告警,否则调了也不知道效果。

6.3 从Demo到生产的检查清单

最后给一份我每次上线前都会过一遍的清单,你可以对照检查:

  • 密钥是否全部收在服务端,前端无任何模型凭证
  • 是否有限流和配额,防止单用户刷爆
  • 上下文是否有截断和压缩策略,不会超窗口
  • 工具调用是否有最大轮次和超时兜底
  • 是否有流式输出,首字延迟是否可接受
  • 是否有缓存和模型路由,成本是否可控
  • 是否有完整的请求级、编排级、模型级日志
  • 是否有内容审核环节,输出是否合规
  • 是否有降级方案,模型不可用时能否优雅处理
  • 是否有用户反馈入口,能否持续迭代

这份清单看起来长,但每一条背后都是真实踩过的坑。我印象最深的一次是没有做降级方案,模型服务商那边抖动了两小时,我们的应用直接全线不可用,用户投诉铺天盖地。从那以后,降级方案成了我的必选项——哪怕只是返回一句"当前服务繁忙,请稍后再试",也比直接报错强。

架构设计这件事,说到底是在"够用"和"过度设计"之间找平衡。我的经验是:先按最小可用架构跑起来,把可观测性做扎实,然后根据真实数据决定哪里需要加层、哪里需要优化。纸上画得再漂亮的架构图,不经过真实流量的检验,都只是假设。真正好的AI应用架构,是在一次次线上问题的打磨中长出来的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询