AI 原生架构设计

AI 原生应用的架构设计:模型网关与统一接入、多模型路由与降级、RAG 与向量检索的服务化、Agent 编排与工具调用的可靠性保障,以及推理成本归因、TPM 配额限流与两层缓存优化的完整方案,并附常见踩坑清单,帮助团队把概率性的模型调用纳入确定性的工程治理。

把 LLM 接进业务,很多团队的第一版是"业务代码里直接调 SDK"——然后很快遇到模型换不了、成本失控、超时拖垮主流程、Prompt 散落各处。AI 原生架构的核心不是"用了 AI",而是把模型调用、检索、编排、成本控制做成有边界、可治理、可替换的基础设施。本文给出可落地的分层与关键实现。


1. 什么是 AI 原生架构

1.1 与传统架构的三点差异

AI 原生应用不是"传统应用 + 一个模型调用",它在三个维度上根本不同:

维度传统应用AI 原生应用
依赖特性确定性、低延迟概率性、高延迟(秒级)
成本模型固定(服务器)按 token 计费,随用量线性增长
失败模式报错或超时幻觉、格式错、内容违规(都是"成功"返回)
迭代方式改代码改代码 + 改 Prompt + 换模型 + 调检索

第二点尤其关键:AI 的成本是变量而非固定成本,一次 Prompt 改错可能让账单翻十倍。这决定了架构里必须有一层专门管成本和配额。

1.2 参考分层

L5 应用层     对话 / 搜索 / 助手 / 工作流
L4 编排层     Agent / 工作流 / 工具调用
L3 能力层     RAG 检索 / 记忆 / 评测 / 护栏
L2 模型网关   路由 / 降级 / 缓存 / 配额 / 审计
L1 基础设施   自托管模型 / API / GPU / 向量库

纪律:应用层永远不直接调模型 SDK,必须经过 L2 网关。这是"模型可替换"与"成本可治理"的前提。


2. 模型网关与统一接入

2.1 为什么必须有网关

没有网关时,模型调用会以三种方式失控:

业务代码直接调 SDK 的后果

1. 换模型 = 全仓库改代码      (模型名、参数、SDK 分散在各处)
2. 成本无法归因              (不知道哪个业务花了多少钱)
3. 一家模型挂了 = 业务挂了     (没有降级与多供应商)
4. Prompt 无法统一治理        (版本、审计、敏感词全无着落)

网关把这四件事收敛到一处:统一协议、统一鉴权、统一计量、统一降级。

2.2 网关的核心能力

能力说明
协议统一对外一套 API,内部适配 OpenAI/Anthropic/自托管
路由按业务、按成本、按能力选择模型
降级主模型超时/失败时切换备用模型
缓存相同请求命中缓存,省 token
配额按团队/应用限制 QPS 与 token 预算
审计记录请求、响应、token 数、耗时、成本
护栏输入输出内容安全过滤

2.3 路由与降级的配置

# 模型网关路由配置
routes:
  - name: chat-default
    match: { app: "customer-support", task: "chat" }
    primary:
      provider: anthropic
      model: claude-sonnet
      timeout_ms: 30000
    fallback:
      - provider: openai
        model: gpt-mini
        trigger: [timeout, rate_limit, 5xx]
      - provider: self-hosted
        model: qwen-7b
        trigger: [all_providers_down]
    limits:
      max_tokens_per_request: 4096
      qps: 200
      daily_token_budget: 50000000

  - name: embedding
    match: { app: "*", task: "embedding" }
    primary: { provider: self-hosted, model: bge-m3 }   # 高频低价,自托管
    cache: { enabled: true, ttl: 86400 }                 # 向量可长期缓存

关键设计:把"高价值低频率"的生成任务交给商用大模型,“高频低价值"的嵌入任务交给自托管小模型。这个组合通常能省下 60% 以上的成本。

2.4 缓存的两层策略

LLM 缓存分两层,收益差异极大:

# 第一层:精确缓存(相同请求直接返回),命中率低但零风险
exact_cache_key = sha256(model + prompt + params)
if cached := redis.get(exact_cache_key): return cached

# 第二层:语义缓存(相似请求复用),命中率高但需相似度阈值
query_vec = embed(user_query)
if hit := vector_cache.search(query_vec, threshold=0.96):
    return hit.response   # 阈值必须高,否则答非所问

踩坑点:语义缓存的阈值设低了(如 0.85),会把"退款政策是什么"和"退货政策是什么"当成同一问题,返回错误答案。阈值宁高勿低,且只对事实型问答启用,创作型任务不要缓存。


3. RAG 与向量检索服务化

3.1 RAG 链路

RAG(检索增强生成)是让模型基于私有知识回答的标准模式,完整链路:

离线索引                              在线检索
─────────                            ─────────
文档 → 解析 → 分块 → 向量化 → 向量库   查询 → 向量化 → 检索 → 重排 → 拼 Prompt → 生成
                │                                              │
            元数据/权限                                      引用溯源

离线与在线必须解耦:索引更新是批处理(分钟到小时级),在线检索要求毫秒级。把两者耦合在一个服务里,会导致索引重建时检索不可用。

3.2 向量检索服务化

把向量检索做成独立服务,而不是让每个应用各自连向量库:

# 向量检索服务的接口契约
POST /v1/search
{
  "collection": "product-docs",
  "query": "如何申请退款",
  "top_k": 20,
  "filters": {
    "tenant_id": "t-10086",        # 多租户隔离,必须强制
    "acl": ["public", "dept-support"]
  },
  "rerank": true                    # 开启重排提升精度
}

三个必须内建的能力:

  1. 租户与权限过滤:tenant_id 与 acl 过滤必须由服务强制执行,不能依赖调用方传入——否则一次漏传就是数据越权。
  2. 重排(Rerank):向量召回 top-20 后,用交叉编码器精排取 top-5,精度通常提升 15~30%。
  3. 引用溯源:返回每个片段对应的文档 ID 与位置,供前端展示引用、便于排查幻觉。

RAG 的完整模式(分块策略、混合检索、查询改写)可参考 RAG 模式实践 ,向量嵌入本身的质量优化(模型选型、维度、归一化)则直接决定检索上限。

3.3 分块与召回质量

RAG 效果差,八成问题出在分块而非模型。三种策略的取舍:

策略优点缺点适用
固定长度简单、均匀切断语义通用兜底
按结构(标题/段落)语义完整长度不均文档类知识
父子分块检索小、返回大实现复杂精度要求高

父子分块是效果最好的方案:用小块(如 256 token)做检索保证精度,命中后返回其父块(如 2048 token)保证上下文完整。这解决了"小块召回准但上下文不足、大块上下文足但召回不准"的两难。


4. Agent 编排与工具调用

4.1 编排模式

Agent 的本质是"让模型在循环里决定调用哪个工具”。三种主流编排模式:

模式结构适用风险
ReAct思考-行动-观察循环通用任务循环不收敛
Plan-and-Execute先规划再逐步执行多步骤任务计划偏离现实
工作流(Workflow)预定义流程 + 模型填充流程明确的业务灵活性受限

生产环境优先选工作流:流程确定的业务(如客服工单处理)用预定义流程,模型只在需要判断的节点介入。纯 ReAct 的自由度过高,在成本和可靠性上都难以控制。

工作流编排示例(客服工单)

  [分类] → [查订单] → [判断类型] ─┬─ 物流问题 → [查物流] → [生成回复]
                                  ├─ 退款问题 → [查政策] → [生成回复]
                                  └─ 其他     → [转人工]

4.2 工具调用的可靠性

工具调用是 Agent 最容易出事的地方。四道防线:

防线一:Schema 严格校验

{
  "name": "query_order",
  "description": "根据订单号查询订单详情,仅在用户提供了订单号时调用",
  "input_schema": {
    "type": "object",
    "properties": { "order_no": { "type": "string", "pattern": "^ORD-[0-9]{8}-[0-9]{3}$" } },
    "required": ["order_no"],
    "additionalProperties": false
  }
}

pattern 与 additionalProperties: false 能挡掉大量模型幻觉出来的参数。

防线二:幂等与超时

模型可能重复调用同一个工具。所有有副作用的工具(下单、退款、发消息)必须幂等:

def refund(order_no: str, idempotency_key: str) -> dict:
    # 幂等键由编排层生成(同一轮对话同一意图复用)
    if existing := idem_store.get(idempotency_key):
        return existing
    result = payment_client.refund(order_no)
    idem_store.set(idempotency_key, result, ttl=3600)
    return result

防线三:循环与预算上限

agent_guardrails:
  max_iterations: 8              # 最多 8 轮工具调用,防死循环
  max_tokens_per_session: 100000 # 单会话 token 上限
  max_tool_calls: 15             # 工具调用次数上限
  timeout_total_ms: 120000       # 整个会话超时
  on_exceed: return_partial_and_escalate   # 超限时返回部分结果并转人工

防线四:人类确认(Human-in-the-loop)

高风险操作(退款、删除、外发消息)必须经人工确认:

tools:
  - { name: query_order, risk: low,    approval: none }
  - { name: send_email,  risk: medium, approval: confirm_once }  # 首次确认后可自动
  - { name: refund,      risk: high,   approval: always }        # 每次都要人工确认

Agent 在生产环境的部署细节(可观测、评测、灰度)可参考 AI Agent 生产部署 。


5. 推理成本与限流治理

5.1 成本构成与归因

先看清钱花在哪。成本归因的最小维度是应用 × 模型 × 调用类型:

# 成本看板维度
cost_breakdown:
  by_app:
    customer-support: { tokens_in: 42000000, tokens_out: 8000000, cost: 320 }
    doc-search:       { tokens_in: 12000000, tokens_out: 2000000, cost: 45 }
  by_model: { claude-sonnet: 280, self-hosted-embed: 12 }   # 自托管按 GPU 时长折算
  by_type:  { chat: 300, embedding: 25, rerank: 40 }

输入 token 通常是输出 token 的 5~10 倍,而 RAG 场景下输入会进一步膨胀(拼接的检索片段)。所以优化输入比优化输出收益大得多。

5.2 限流与配额

LLM 的限流不是简单的 QPS 限制,要区分维度:

维度限流对象目的
QPS请求数保护下游供应商与自身
TPM每分钟 token控制成本与供应商配额
并发同时在途请求防止长请求堆积
预算每日/每月 token硬性成本上限
# 分层配额:租户 -> 应用
quotas:
  tenant_default:    { tpm: 100000,  daily_tokens: 5000000 }
  tenant_enterprise: { tpm: 1000000, daily_tokens: 100000000 }
  app_overrides:
    customer-support: { tpm: 200000, priority: high }
    internal-test:    { tpm: 10000,  daily_tokens: 500000, priority: low }

优先级 + 排队比"一刀切拒绝"体验更好:高优先级请求优先获得配额,低优先级在超限时排队而非直接失败。

5.3 成本优化的六个手段

按收益排序:

  1. 缓存:精确缓存 + 语义缓存,事实型问答命中率可达 30% 以上。
  2. 模型分级:简单任务用小模型,复杂任务才用大模型。路由时先做难度分类。
  3. Prompt 压缩:精简系统提示、去掉冗余示例,输入 token 常能砍掉 40%。
  4. RAG 片段控制:检索返回 top-5 而非 top-20,且对片段去重。
  5. 流式 + 提前终止:输出满足条件即停止,避免生成冗余内容。
  6. 自托管高频小模型:嵌入、分类等高频任务自托管,边际成本趋近于零。

推理侧的底层优化(量化、批处理、KV Cache、投机解码)可参考 LLM 推理优化 ,推理服务的架构与容量规划可参考 LLM 推理架构 。


6. 踩坑清单

坑后果规避
业务直连模型 SDK换模型需全仓库改强制走模型网关
无语义缓存阈值控制答非所问阈值 > 0.95,仅事实问答
向量过滤交给调用方数据越权服务端强制租户/ACL 过滤
索引与检索耦合重建索引时检索不可用离线在线解耦
纯 ReAct 上生产成本失控、不收敛优先工作流编排
工具无幂等重复扣款/重复发送幂等键 + 去重表
无迭代上限死循环烧钱max_iterations + 预算上限
高风险操作无确认误操作无法挽回Human-in-the-loop
只看 QPS 不看 token成本失控TPM + 预算双维度限流
无成本归因不知钱花在哪按应用/模型/类型打标

7. 总结

AI 原生架构的落地可以归纳为四层治理:

  1. 模型网关:统一接入、路由、降级、缓存、配额、审计——让模型可替换、成本可归因。
  2. 检索服务化:RAG 离线在线解耦,向量检索内建租户过滤、重排与溯源。
  3. 编排可靠性:优先工作流,工具调用配 Schema 校验、幂等、迭代上限与人工确认。
  4. 成本与限流:缓存、模型分级、Prompt 压缩优先,QPS/TPM/预算多维限流。

这套架构的收益不是"更 AI",而是把概率性的模型调用纳入确定性的工程治理——模型可以换、成本可以控、故障可以降级、行为可以审计。做到这些,AI 能力才真正成为可长期运营的基础设施,而不是一个难以维护的实验。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「架构」更多文章

  1. 韧性工程与错误预算:从 SLO 到故障演练
  2. 微前端架构:组合、隔离与独立部署
  3. 数据网格(Data Mesh):领域数据产品与去中心化治理