跳到主要内容

构建生成式 AI 平台:架构、权衡以及真正重要的核心组件

· 阅读需 15 分钟
Tian Pan
Software Engineer

大多数将生成式 AI 技术栈视为模型集成项目的团队,最终都会发现他们实际上构建了——或需要构建——一个平台。模型是最简单的部分。难点在于它周围的一切:将查询路由到正确的模型、可靠地检索上下文、过滤不安全的输出、缓存冗余调用、在由五个 LLM 调用组成的链条中追踪出错原因,以及随着使用规模扩大,防止成本逐月翻倍。

本文讨论的就是这个平台层。不是模型权重,也不是提示词——而是将一个可行的原型与一个你可以放心交付给百万用户的系统区分开来的基础设施。

从最简单可行方案开始

在构建任何东西之前,克制住立即将编排框架、向量数据库、模型路由和缓存组合在一起的冲动。这样做会导致系统极其脆弱,每个组件都是别人的抽象,调试需要同时阅读四个不同库的源码。

一个好的生成式 AI 平台始于一个函数:query → response。仅此而已。对托管模型进行一次 API 调用,或许带有一个系统提示词。先让这个方案在生产环境中跑通。只有当你有了确凿的证据证明你需要它们时——例如特定的失败模式、成本问题、未达标的延迟目标——再添加组件。

这不是一个软性的原则,而是具有实战意义的架构建议。你向生成式 AI 技术栈中添加的每一个组件都会引入延迟、运维复杂度、失败模式和成本。本文中的组件在合适的条件下都值得拥有。而这些合适的条件通常是“生产系统告诉你某些东西坏了”,而不是“这似乎是个好主意”。

上下文增强:RAG 及其周边的构建

检索增强生成(RAG)现在已成为将 LLM 输出锚定在外部知识中的默认模式。基本理念很简单:在调用模型之前,检索相关文档并将其包含在提示词中。但实现决策会迅速变得复杂。

检索层主要有两种方法。 基于术语的搜索(BM25, Elasticsearch)能很好地处理精确关键词匹配,并在处理异常查询时表现稳健。基于嵌入的搜索(Embedding-based search)能处理语义相似性,但需要维护向量索引并仔细选择嵌入模型。生产系统几乎总是两者兼用:一个运行两种检索方法并在重排序(reranking)步骤之前合并结果的混合管道。重排序器——通常是一个对查询-文档对进行联合评分的交叉编码器(cross-encoder)——能显著提高相关性,但每次请求会增加 50–200ms 的延迟。

顺序过滤(Sequential filtering)常被低估。 先运行廉价的过滤器(关键词匹配或元数据过滤),然后只对筛选出的候选结果应用昂贵的重排序器。仅这一种模式,与对整个语料库运行完整交叉编码器相比,就能将检索成本降低 60–70%。

查询重写(Query rewriting)位于管道的最顶端。 用户编写的查询往往含糊不清、依赖上下文且格式不规范。“我们对定价模型是怎么决定的?”在没有对话历史的情况下毫无意义。查询重写步骤——另一个小的 LLM 调用——获取用户的消息和对话上下文,并生成一个清晰、独立的搜索查询。跳过这一步的团队往往会困惑为什么他们的检索质量在不同用户之间表现不一。

对于表格数据,RAG 需要完全不同的方法:Text-to-SQL 转换。模型需要 Schema 上下文,而不是文档块。这在架构上差异巨大,值得作为一个独立的管道来对待,而不是强行塞进同一个检索系统中。

智能体 RAG (Agentic RAG) 进一步扩展了这一模式:模型不再是单一的检索步骤,而是可以决定发出多个搜索查询、使用网页搜索工具或动态获取最新数据。这对于开放式研究任务效果很好,但引入的非确定性使得评估更难,延迟也更难预测。

一个有用的心智模型是:生成式 AI 系统中的上下文构建与传统机器学习中的特征工程(feature engineering)是同一项工作。模型的输出质量直接受限于你提供的上下文质量。在更好的检索、更好的重排序和更好的查询预处理上投入,比频繁更换模型能获得更可靠的回报。

护栏:你需要保护的两个方向

护栏在两个方向上起作用:进入的输入和出去的输出。大多数团队先实现输出护栏,因为失败更显而易见。输入护栏通常被忽略,直到发生安全事件迫使问题得到解决。

输入护栏 处理:

  • PII(个人身份信息)和敏感数据检测:如果你的系统调用外部模型 API,你需要防止用户无意中将医疗记录、凭据或财务信息等私有数据发送给第三方提供商。在 API 调用之前进行自动 PII 检测和脱敏是处理此问题的正确位置。
  • 提示词注入(Prompt injection)和越狱尝试:用户(或通过 RAG 注入的外部内容)可能会试图覆盖你的系统提示词或提取模型内部信息。检测对抗性模式的输入端分类器对此有所帮助,尽管它们并非完全的防御手段。

输出护栏 在模型响应到达用户之前对其进行评估:

  • 空输出或格式错误的输出可能暗示模型拒绝回答、上下文窗口溢出或基础设施错误。
  • 幻觉检测——检查输出中的断言是否得到检索上下文的支持——很难做到完美,但值得进行近似评估。
  • 毒性和违规内容分类器降低了有害输出的尾部风险。

护栏面临的核心矛盾是延迟。每一次检查都会增加开销。两种实用的模式可以降低这种成本:同步运行较轻的检查(正则、小分类器),并在响应发出后异步运行较重的检查(基于 LLM 的评估)。对于输出护栏,在升级到人工介入之前,可以尝试以修改后的温度或不同的模型进行重试。

护栏也会以一种可预见的方式失败:对良性输入过度触发。请根据真实的生产流量而不是合成数据集来调整阈值。误报率(False positive rate)与漏报率(False negative rate)同样重要。

模型路由与网关:流量控制层

一旦你的系统使用了多个模型,你就需要一个网关。一旦你的系统将不同的请求类型路由到不同的模型,你就需要一个路由器。这两者相关但又有所区别。

网关位于你的应用程序代码和你调用的每个模型 API 之间。它提供:

  • 一个屏蔽了特定供应商 API 差异的统一接口
  • 负载均衡和回退策略(如果 Anthropic 返回 503 错误,则尝试 OpenAI)
  • 速率限制和配额强制执行
  • 按团队、产品或客户进行的成本归属
  • 每次调用的集中化日志记录

2026 年的生产级 AI 网关追求亚毫秒级的开销——最优秀的开源方案在每秒数千次请求的情况下,仅增加约 10–15µs 的延迟。这个开销非常低,以至于为了延迟原因而跳过网关不再是一个有意义的权衡。

路由器是网关之上的一层,决定针对特定查询使用哪个模型或管道。两种常见的模式包括:

意图分类:一个轻量级的分类器将查询映射到特定的类别(如“客户支持”、“代码生成”、“文档摘要”),每个类别路由到专门的模型或提示词配置。在你的实际流量上训练的意图分类器,在执行此任务时表现始终优于通用模型。

按成本层级路由:简单的查询发送给更小、更便宜的模型。复杂的查询则升级到尖端模型。这就是“模型级联”在实践中的运作方式——不是由单个路由器预先做出完美决策,而是建立一个管道,让廉价模型首先尝试任务,只有在未通过质量检查时才升级。

据报道,深思熟虑地加入路由机制的团队,在大多数用例中实现了每个查询 45–80% 的成本降低,且没有明显的质量下降。大多数生产系统中的大部分查询都足够简单,较小的模型即可轻松处理。

缓存:最常被忽视的优化手段

GenAI 系统中的缓存分为三个层面,而大多数团队只使用了其中之一。

Prompt 缓存针对共享相同前缀文本(通常是系统提示词或长上下文文档)的查询重用计算。如果你的系统提示词有 2,000 个 Token,并且你每天进行 100,000 次调用,缓存系统提示词前缀将显著降低 Token 处理成本。这在推理供应商层面处理(Anthropic、Google 等原生支持),无需你方增加特殊的架构。

精确缓存存储完整的响应,并为完全相同的查询直接返回结果。这适用于由少量问题驱动大部分流量的 FAQ 类用例。实现简单,在特定环境下命中率高,缓存命中的延迟接近于零。

语义缓存利用嵌入向量相似度将这一理念扩展到相似(而非完全相同)的查询。其命中率高于精确缓存,但引入了一种新的失败模式:返回了一个对于语义相似但有本质区别的查询而言是正确的缓存响应。语义缓存需要仔细调整相似度阈值,并定期审计其返回的内容。工程成本和可靠性风险都是真实存在的——建议仅在精确缓存已经运行良好的情况下再添加语义缓存。

综合来看,这三层缓存可以在不改变模型质量的情况下,为典型的生产负载降低 30–60% 的延迟和成本。

可观测性:针对无法单步调试系统的指标、日志与追踪

调试 GenAI 系统比调试大多数软件都要困难,因为输出是概率性的,管道是多步骤的,而且“它给出了一个错误的答案”并不是一行代码行号。GenAI 的可观测性需要三个要素协同工作。

指标告诉你系统是否健康:

  • 吞吐量和错误率(常规指标)
  • 按组件拆分的延迟:首字时间 (TTFT)、Token 生成速度(每秒 Token 数)、总响应延迟
  • 每个请求、每个用户、每个模型的成本
  • 质量指标:幻觉率、防护栏触发率、检索相关性得分

日志记录了每个请求发生的具体情况:

  • 完整的输入上下文(查询、检索到的文档、系统提示词)
  • 防护栏处理前后的模型输出
  • 调用了哪个模型,使用了哪些参数
  • 触发了哪些防护栏以及它们标记了什么内容

大规模的日志存储非常昂贵。要预先决定适合你预算的采样率——如果你的检索和质量指标已经为你提供了信号,通常没必要记录 100% 的流量日志。

追踪将执行路径可视化地呈现在你的管道中。对于一个五步管道(查询重写 → 检索 → 重排序 → 模型调用 → 输出校验),你需要每一步的时间消耗、成本以及输入/输出,以便诊断故障。如果你只测量端到端延迟,那么一个缓慢的重排序器是不可见的。带有 AI 专用语义约定的 OpenTelemetry 是这一领域新兴的标准。

实际的目标是能够回答:“对于这个得到了糟糕响应的特定用户请求,管道中的每个步骤分别做了什么,哪里出了问题?”如果你无法在十分钟内回答这个问题,说明你的可观测性尚不完善。

编排:晚点加,别太早

编排框架(LangChain、LangGraph、LlamaIndex 等)让组件连接、定义 Agent 工作流并在流水线中构建条件逻辑变得更加容易。它们很有用。但它们也经常在被真正需要之前就被引入,而且当框架的抽象层内部出现问题时,调试体验比调试你自己的代码要糟糕得多。

引入编排框架的时机是:

  • 你正在构建具有条件分支和循环的图结构工作流
  • 你需要具备工具使用和动态路由能力的 Agent 行为
  • 协调逻辑确实复杂到如果你自己动手实现需要花费数周时间

对于简单的流水线——例如具有固定检索步骤、护栏(guardrail)检查和单次模型调用的 RAG ——几个函数和一些共享状态比使用框架更清晰、更快且更易于调试。先写代码。当代码开始显得力不从心时,再引入框架。

在评估编排框架时,生产环境中真正关键的指标是:追踪单个步骤有多容易、它如何处理每个阶段的故障、它是否原生支持流式输出,以及它在并发负载下的表现如何。原型设计阶段的易用性对生产环境成功的预测作用比你想象的要小。

写入操作属于不同的风险类别

到目前为止描述的架构处理的是只读操作:查询模型、检索文档、生成响应。当你的系统开始执行写入操作时——修改数据库、调用会改变状态的 API、发送消息——你就跨入了另一个风险等级。

写入操作是提示词注入攻击(prompt injection attacks)变得危险的地方。如果攻击者控制了你系统将读取的内容(RAG 语料库中的文档、用户提交的表单、外部网页),他们就可以注入指令,导致你的 Agent 执行非预期的操作。一个可以处理退款的 客服 Agent 与一个只能回答问题的 Agent 相比,其攻击面有着显著的不同。

在启用写入操作之前,请务必明确以下问题的答案:如果此操作被意外触发,爆炸半径(blast radius)有多大?对于高影响操作,存在什么样的人工审批检查点?存在什么样的回滚路径?什么样的监控能够捕获异常的操作频率?

赋予 Agent 更多能力的直觉通常是正确的——这就是你实现有用自动化的方式。慢下来并对破坏性或不可逆的操作添加审核关卡的直觉也是正确的。这两者可以同时成立。

平台随着问题的明确而演进

生成式 AI 平台不是预先设计出来的。它是随着你遇到真实的生产问题而一步步组装起来的。相比于在发布任何产品之前从零开始构建完整平台的团队,那些先发布简单系统、观察哪里会出问题、然后添加组件来解决特定故障的团队,通常发布速度更快,学到的东西也更多。

演进路线大致如下:原始 API 调用 → 当模型知识不足时添加检索 → 当成本账单惊人时添加缓存 → 当你使用多个模型且 API 接口混乱时添加网关 → 当发生内容事故时添加护栏 → 当发现大多数尖端模型调用其实很简单时添加路由 → 当你无法调试生产环境故障时添加结构化可观测性 → 当你的流水线超出函数调用的承载能力时添加编排。

每一步都以真实的投入换取真实的价值。在这种过程中产生的平台通常比预先设计的平台更经得起实战考验,且更少过度工程化。请以这种方式进行构建。

References:Let's stay in touch and Follow me for more thoughts and updates