直接聊点实在的。差不多这两年,AI 应用已经过了“套个壳子接个 API 就能讲PPT”的阶段,真正开始往系统化、产品化走了。但一个特别普遍的现象是:很多人搭 AI 应用的时候,还在沿用传统 Web 应用那套思路——前后端分离、数据库加缓存、写一堆接口然后部署,觉得这样就够了。坦白说,不是不能用,但真的跑起来,模型不稳定、token 成本飘忽、请求成功率忽高忽低、一次业务逻辑里面套了三层模型调用等等问题,会非常快地把这套架构打回原形。
我自己做过不少 AI 应用架构设计的方案,最大的感受是,AI 应用本质上是一个“有状态、有成本、会出错”的编排系统。它跟传统 CRUD 服务的确定性不一样:输入相同,输出未必相同;同样的 prompt,今天和明天的结果可能都有细微差别。所以架构设计里要考虑的不只是接口长什么样,还要考虑模型怎么路由、上下文怎么组装、记忆存在哪、外部工具怎么接、出错怎么降级。这篇文章就围绕“图解 AI 应用架构设计”这个话题,把我在设计这类系统时经常用的分层思路、关键部件取舍、一份可落地的实操案例,以及踩坑记录完整拆开来讲。适合正在从单体 Demo 往工程化方向走的开发者,也适合刚接触 AI 应用设计的架构师做参考。
1. 核心思路拆解:AI应用架构到底在解决什么问题
1.1 为什么传统分层架构不够用
传统 Web 架构其实解决的核心问题是稳定的请求-响应循环。用户点一个按钮,后端查数据库,返回一个确定结果,负载可以预测,成本可以估算,出错也无非是 500 或者超时。这套模型非常成熟,所以你很少看到有人为普通的用户注册登录设计一整套所谓的“智能架构”。
但 AI 应用不一样。你在架构里引入大模型之后,第一,它是个外部依赖,而且是个“不稳定”的外部依赖,模型接口可能限流、可能超时、可能明天突然发新版接口废弃参数;第二,模型调用是要花钱的,一次业务请求里如果循环调用三五次,成本就不是线性增长而是成倍往上翻;第三,模型的输出有概率性,同样的 prompt 在不同 temperature 参数下可能天差地别,这就意味着你的业务逻辑必须做很多额外的约束、校验和兜底。
再说数据流。传统应用的数据是结构化的,放MySQL也好、放Redis也好,查询路径是确定的。AI 应用里面很大一块是非结构化数据:文档、对话历史、用户偏好、向量化之后的记忆。处理方式也从“写一条 SQL”变成“切块、向量化、混合检索、重排序”。这些新的组件传统分层架构里没有现成答案,直接硬套的话,很快会在 token 成本和检索质量上撞出血。
所以我个人理解,AI 应用架构设计的本质,是回答一个问题:在模型不确定、成本不可忽视、调用链路可能很长的前提下,怎么组织代码和数据,让系统仍然可控、可扩展、可维护。想清楚这一点,后面所有的分层和选型才有意义。
1.2 一套我觉得好用的四层框架
我一直习惯把 AI 应用拆成四层:接入层、编排层、模型调用层、数据与记忆层。大概可以画成下面这样:
[外部调用方] | v [接入层] -> 身份校验、限流、参数校验、请求审计 | v [编排层] -> 业务逻辑、任务拆解、工作流/Agent循环、工具调用 | +---------> [模型调用层] -> 模型路由、上下文组装、重试与降级 | v [数据与记忆层] -> MySQL/Redis、向量库、文档存储、缓存别小看这张简单的图。我每次帮人做方案评审,第一件事就是把业务往这四层里各归一遍,几乎立刻就能看出来哪里缺东西。
接入层解决的是“谁能调、调到什么程度、数据是否安全进入”的问题。AI 应用最容易被人忽略的一点是,用户输入会直接被拼进 prompt,如果这层不做清洗和校验,后面所有层的基础都不稳。
编排层是核心。业务逻辑往哪放、工作流怎么走、工具调用的顺序和护栏是什么,全在这里。传统 Web 架构里,这块对应的是 service 层;但 AI 应用里多了一个难点——有些流程是运行时由模型决定的,比如 Agent 自己判断下一步该调用哪个工具。此时编排层就要同时背负确定性流程和不确定性决策双重压力。
模型调用层相对薄,但非常重要。它负责统一封装所有模型能力:协议转换、API Key 管理、system prompt 注入、上下文组装、超时重试、多模型切换。哪怕你前期只用一家模型厂商,也建议单独划出这层,否则等你想换供应商或者加一个备用模型的时候,会发现改造成本高得离谱。
数据与记忆层最直观。文档、向量、会话历史、用户属性,都在这层沉淀。为什么单独又放向量库又放缓存?因为 AI 应用的数据访问模式和传统 CRUD 完全不一样,检索频繁、上下文大、要做语义匹配,没有这层专门规划,很容易出现“每来一次请求,就把几十万字文档塞给模型”这种事故。
层与层之间通过清晰的接口通信,每一层都可以独立换实现、独立做压测、独立做降级。这个四层框架是我目前用下来最顺手的,也是后面展开分析的基础。
2. 图解核心部件:接入、编排、模型与数据的选型与配合
2.1 接入层:身份、限流与安全的第一道闸门
接入层的设计,跟普通接口网关大体相似,但有几处细节值得单独说。
首先是限流。传统接口限流主要防的是瞬时峰值,AI 应用的限流还要多算一层“成本阀门”。用户一次提问,背后可能要查向量库、调一次模型、再做一次重排序,模型 API 是按 token 计费的。如果你不在接入层按用户维度限制每天请求次数和单次请求大小,某些异常流量或者测试脚本就能把一个月的预算在半天内烧完。我一般会做两层限流:API 网关做 QPS 限流,业务层做额度限流,后者按 token 预估或实际用量统计。
其次是参数校验。这里不是说校验格式,而是要重点处理“输入长度”。LLM 的输入长度是硬约束,超过上限请求必失败。传统接口你传 10KB 还是 100KB 都能处理,AI 应用则必须在接入层就设置一个最大字符限制,超出之后要么拒绝,要么引导用户做摘要或者分段。但这个限制不能定得太死,我建议根据你实际使用的模型 context windows 倒推,给 prompt 模板、历史对话、检索结果都预留出空间,然后再算出用户输入的合理上限。
还有一层容易被忽略:安全。用户的输入会作为 prompt 的一部分直接交给模型,那么经典的危险操作——例如试图通过 prompt 注入让系统忽略规则、读取内部文件、输出敏感系统提示词——就必须在接入层有所防御。常用的手段有输入关键词黑名单、让系统 prompt 明确输出边界,以及在模型返回后再做一次输出清洗,防止模型被诱导输出内部信息。实际情况下没有绝对的拦截方案,架构上能做的就是多设几道关卡,降低批量自动化攻击的风险。
2.2 编排层:工作流与 Agent,如何做出清醒的选择
编排层是最容易“用力过猛”的一层。很多团队看到 Agent 概念火,什么事都想让模型自己决定下一步。但架构上最基础的一条原则是:确定性优先于灵活性。如果你的业务流程步骤是固定的——先检索、再生成、最后总结——那就老老实实写工作流,不要引入 Agent 循环。Agent 解决的是开放性问题,不是琐事的万金油。
工作流模式的优点是步骤明确、性能可控、便于测试。你可以对每一步单独写单元测试,可以算出最坏情况下的响应时间,可以预估 token 成本。对于规则明确的任务,比如“给定产品文档,生成 FAQ”,工作流几乎永远是更稳的选择。
Agent 模式的优点在于可以处理没有预设路径的任务,比如“帮我把这份合同读一遍,找出所有跟付款相关的条款,并生成风险摘要”。这里模型需要调用文档解析工具、搜索工具、再要读一遍条款判断风险,整个执行路径是动态的。架构上的难点在于必须给 Agent 设置边界,包括最大循环次数、工具调用白名单、单次任务的预算上限,以及当模型反复尝试但始终失败时怎么优雅退出。
我个人的建议是,绝大多数应用先按工作流设计,把工具调用以“可控步骤”的方式嵌进去;只有当确实需要处理多轮规划类任务时,再局部引入 Agent 模式,而不是一上来就搭一个完全自治的 Agent 运行时。这样既保留扩展性,又不会让系统陷入不可预测的失控状态。
2.3 模型调用与数据层:上下文、缓存、向量数据库的三方配合
模型调用层的头等大事是上下文组装。很多应用出问题,不是模型不行,而是喂给模型的上下文太乱。一条清晰的组装规则是:将环境任务说明、对话历史、检索结果、用户当前输入按固定顺序拼装,并保留明确的标记分隔。这样模型才知道哪些是系统指令,哪些是参考资料,哪些是用户原始问题,输出的稳定性和可调试性都会明显提升。
上下文长度也是要持续治理的问题。对话越来越长,如果全部塞给模型,终会暴涨到 context window 上限。常用策略有三种:滑动窗口保留最近几轮,定期对历史会话做摘要,以及把检索结果截断为最相关的若干段。这三种策略可以组合,关键是要在每次请求进来时都重新计算当前上下文长度,并留出安全余量。
缓存的设计很多人会漏掉。AI 应用的响应不是实时的、每次计算都要花钱,所以缓存价值极高。第一级是精确缓存,同一用户同一输入直接命中并复用;第二级是语义缓存,用向量相似度判断两条输入是否表达同一个意思,命中则返回上次结果。语义缓存实现起来也不复杂,只需要把用户输入向量化之后在向量库里做一次相似度搜索。能明显降低重复问答的成本。
向量数据库选型上,开源产品确实很灵活,但托管服务省心。更重要的是要关注向量库支持的检索类型:纯向量检索、关键词过滤、元数据过滤、混合检索,这些能力直接决定了你 RAG 检索质量的天花板。如果文档规模不大,百万级向量以内,很多通用数据库自带的向量插件已经够用;规模再大,再考虑独立向量数据库。
3. 实操案例:从零搭建一个可上线的多层RAG问答服务
3.1 从场景到架构:需求和方案权衡
拿最常见的落地场景来说:企业内部知识库问答。员工提问“出差报销流程是什么”,系统需要从一堆文档里检索相关段落,生成答案,并标注信息来源。
先明确需求约束:第一,答案必须基于文档,不能凭空捏造;第二,端到端响应时间目标不超过 3 秒;第三,初期数据量不大,几百篇文档,几千个切片;第四,团队规模小,希望维护成本低。
基于这些约束,直接排除了微服务方案。微服务确实边界清晰,但对于一个小团队来说,一次搜索链路要跨三四个服务,出问题排查链路太长。选型上我推荐用单体优先,但内部按四层框架做模块隔离,配合一个负责异步任务的调度器。这样做的好处是部署只需要一个进程,调试成本低,后续如果某个模块压力特别大,可以单独抽出来独立部署,演进的路径是通的。
整体架构落地成这样:网关层用现成 API 网关;编排层用 Python 的 FastAPI 实现业务服务,内部按检索模块、提示词模块、生成模块划分;模型调用层接大模型 API,同时预留一个备用模型通道;数据层用 MySQL 存会话记录、向量库存文档切片和向量。
技术栈不唯一。重点不是选了什么中间件,而是每一层都有明确的职责和替换边界。
3.2 数据链路和检索链路的分工与参数设置
数据链路是第一件事。文档进来之后,不能整篇塞给向量库,而是要先切块。切块是 RAG 链路里最影响检索质量的环节,没有之一。切块太大,语义泛化严重,还容易带着很多不相关的内容,token 成本也高;切块太小,语义不完整,检索出来的段落断章取义,答案质量直接崩。
我用下来的经验值,起步按 300 到 500 token 切块比较稳妥,也就是中文环境下大概是 400 到 800 字一个块,这个量级既能容纳相对完整的语义,又不会让上下文变得臃肿。块与块之间要有重叠,通常重叠范围控制在 10% 到 20%,目的是避免一个完整的信息被边界切碎。另外,切块时一定要保留元数据,比如文档名、页码、章节标题,这样后面检索结果的引用来源才能准确生成。
向量化环节,选择的 embedding 模型要跟文档语言匹配,中英文混合场景要用支持多语言的模型,否则检索效果会肉眼可见地差。向量维度会影响后续存储和检索开销,但不一定越高越好,还是以匹配效果优先。
检索链路我通常不走一步嫌疑到底。第一步先用向量检索召回一批候选,候选数量设在 20 左右,保证召回率;第二步再做重排序,把真正相关的排到最前,只保留前 3 到 5 个作为生成上下文。向量检索管粗筛,重排序管精排。没有重排序环节,只靠向量相似度直接拿 top 5,大概率会带进来一两段不相关内容,最后答案质量就打个折扣。
3.3 生成链路与模型调用的工程化细节
检索出上下文之后,接下来的工作就是组装 prompt 并调用模型。这里要特别重视两件事:system prompt 的设计和生成参数的控制。
system prompt 里要明确三件事:角色的边界、任务目标、输出约束。不要只写“你是一个助手”,而是类似“你是一个知识库问答助手,只能根据提供的文档内容回答问题,如果文档中没有对应信息,直接说明无法回答,不允许编造”的风格。输出约束尤其重要,它是对抗幻觉的第一层防线。
具体调用代码结构可以这样组织,核心思路是让页面输入、检索上下文和拼装逻辑互相独立:
def create_messages(question, context, history): system = ( "你是一个企业知识库问答助手。请严格依据以下参考资料回答问题。" "如果参考资料中没有答案,请明确回复'当前知识库无法解答该问题'。" "回答时在末尾标注参考来源编号,格式为[1][2]。" ) user_content = f"参考资料:\n{context}\n\n历史对话:\n{history}\n\n用户问题:{question}" return [ {"role": "system", "content": system}, {"role": "user", "content": user_content}, ]生成参数方面,temperature 不要调得太高。知识库问答这种任务追求的是准确和稳定,我一般设置在 0.2 附近;top_p 也可以压到 0.8 左右。如果是创意写作类任务再调高,问答场景偏离事实的风险会显著上升。
还有一个会踩的坑是重试逻辑。模型返回超时或限流,直接原样重发会导致整条链路阻塞,甚至引发雪崩。正确做法是给模型调用设置超时和最大重试次数,并且重试时应该做指数退避,避免并发重试把模型 API 打爆。如果主模型连续失败,直接切换到备用模型通道,宁可响应质量稍微下降,也不能让用户一直转圈。
3.4 部署控制与监控设计
单体应用不意味着不做部署控制。我的习惯是把生成和检索做成同步接口,把涉及长期任务或者高耗时的操作丢到异步队列。这样可以保证在线服务的响应速度,队列消费者的任务可以批量处理,对模型接口的调用也更平滑。
限流和安全策略也要落到实处。接入层设置 QPS 限流之外,还要按用户维度配置每天的使用额度,并且超限之后要能实时拒绝新请求。另一个不能省的是用量日志。每一次模型调用,都应该记录是哪个用户、调用了哪个模型、输入了多少 token、输出了多少 token、耗时多少,甚至要能回溯到具体的 prompt 内容。没有这些日志,后续排查成本问题和定位 bug 会非常痛苦。
监控指标的选取上,除了常规的接口延迟、错误率,还要关注一个很少人看但极其关键的指标:context 压测率,也就是当前请求上下文长度占模型最大上限的比例。当这个比例接近 1 时,你的系统正在烧大量 token 做低效生成,早晚要出事。把它纳入监控,做周期性的调优。
4. 踩坑记录与排查技巧实录
4.1 高频故障现象、排查过程与根因整理
把这几年我处理过的 AI 应用问题做了个梳理,最常出现的故障和排障路径大概是这样:
| 故障现象 | 可能根因 | 排查思路 | 解决手段 |
|---|---|---|---|
| 答案经常明显错误 | 检索结果质量差、多为不相关内容 | 先看日志里检索命中的文档片段,检查切片是否完整 | 调整切块策略、补充重排序环节 |
| 响应耗时持续超时 | 上下文过大、模型响应慢或缓存没生效 | 监控 context 长度、检查缓存命中率 | 增加截断与摘要策略、启用语义缓存 |
| 成本月度结算暴涨 | 用户高频重试、Agent 循环兜不住 | 按用户维度统计调用次数和 token 用量 | 接入层限流、增加单用户额度、限制最大循环次数 |
| 上游模型偶尔报错 | 模型接口限流或不稳定 | 查看错误码分布、重试策略是否有效 | 增加指数退避、配置备用模型通道 |
| 并发一高就出现连接池错误 | 数据库或向量库连接数不够 | 检查连接池参数和慢查询日志 | 调整连接池上限、优化检索 query |
举一个具体的例子。曾经有个系统,用户反馈答案越来越慢,最后直接全部超时。拉日志发现,上下文长度已经撑到接近两万,因为对话历史没做截断,用户每多问一句,之前所有历史就完整地重发一遍,token 用量呈线性增长。那套方案的修复路径很明确:把历史处理改成滑动窗口,只保留最近五轮;同时对超过三天的会话定期生成摘要,把长期记忆沉淀到摘要里,而不是永远堆原文。改完之后,平均响应时间下降了接近一半,token 成本也降下来了。
这个例子不算什么高深技术,却说明一件事:AI 应用的很多性能问题不是代码写得不好,而是架构策略上缺了控制机制。
4.2 我在架构评审时一定会问的五个问题
后来我再评审团队的 AI 应用方案时,习惯问几个固定问题,几乎成了排查清单。这里直接分享出来:
第一,如果模型接口全挂了,系统怎么走降级?很多方案里,这条链是硬依赖,模型一挂整个业务全挂。哪怕降级方案是“返回一条提示让用户稍后再试”,也必须在架构里存在,并且能自动触发。
第二,有没有按用户维度统计调用量和成本?没有的话,等于在开一辆没有油表的车,什么时候把预算烧完完全没数。
第三,上下文会不会无限膨胀?这个问题几乎每个多轮对话系统都要面对。如果你的架构里没有截断、没有摘要、没有滑动窗口,那未来一定会出问题。
第四,检索结果可控吗?用户问了一句不该问的话,系统会不会返回内部机密?这里需要的不只是 system prompt,还包括检索权限过滤、上下文清洗、输出层的合规检查。
第五,缓冲、重试、排队机制有没有?没有队列保护的模型调用,在流量突发时极易雪崩。
这五个问题如果都能清晰回答,这个架构的稳定性大概就有保障了。
4.3 从架构图到落地的最后一点建议
很多人做设计,画架构图画得很漂亮,一落代码就发现分不清模块边界,最后全写在一起变成大泥球。我一般会在动手写代码之前,先把每个模块暴露的接口定义出来,模块之间只准通过接口沟通,不准跨层直接访问数据表。比如编排层要拿用户会话记录,必须通过数据访问接口拿,而不是直接在服务类里写 SQL。这层约束特别管用,架构图不会因为时间推移变得面目全非。
再一个建议是,架构设计一开始就要为“模型会换”做准备。模型层做统一封装之后,内部尽量不出现某个厂商 SDK 的数据类型直接泄露到外部。你的业务代码只感知标准化的消息格式,底层换成哪个模型都不影响上层逻辑。现在模型迭代速度快得离谱,今天用的主力模型,三个月之后可能就不是最优选择了,没有这层抽象,每次换模型都是一场大手术。
我还想补一条测试建议。AI 应用不能只测接口通不通,还要测输出质量。我会建议在项目中维护一组质量基线测试用例,比如一百个典型问题,每次模型版本变更、检索策略调整之后,批量跑一遍,对比正确答案的召回率和引用可信度。这套基线测试不需要多复杂,但它能让你在一步步调优时,不至于今天改坏了昨天的效果还不自知。
最后再说个容易被忽视的点:先盯着数据链路做架构。我见过太多团队把大部分精力花在模型调用的工程化上,却没花时间把文档清洗、切块、索引结构做好。而实际上,检索结果质量决定了 AI 应用回答质量的天花板,模型参数只是在这个天花板下面做微调。如果你准备设计一个新的 AI 应用架构,我真心建议把数据链路摆在最前面,先把“找得准”这件事想清楚,再谈后面要怎么“答得好”。