把 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 # 开启重排提升精度
}
三个必须内建的能力:
- 租户与权限过滤:
tenant_id与acl过滤必须由服务强制执行,不能依赖调用方传入——否则一次漏传就是数据越权。 - 重排(Rerank):向量召回 top-20 后,用交叉编码器精排取 top-5,精度通常提升 15~30%。
- 引用溯源:返回每个片段对应的文档 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 成本优化的六个手段
按收益排序:
- 缓存:精确缓存 + 语义缓存,事实型问答命中率可达 30% 以上。
- 模型分级:简单任务用小模型,复杂任务才用大模型。路由时先做难度分类。
- Prompt 压缩:精简系统提示、去掉冗余示例,输入 token 常能砍掉 40%。
- RAG 片段控制:检索返回 top-5 而非 top-20,且对片段去重。
- 流式 + 提前终止:输出满足条件即停止,避免生成冗余内容。
- 自托管高频小模型:嵌入、分类等高频任务自托管,边际成本趋近于零。
推理侧的底层优化(量化、批处理、KV Cache、投机解码)可参考 LLM 推理优化 ,推理服务的架构与容量规划可参考 LLM 推理架构 。
6. 踩坑清单
| 坑 | 后果 | 规避 |
|---|---|---|
| 业务直连模型 SDK | 换模型需全仓库改 | 强制走模型网关 |
| 无语义缓存阈值控制 | 答非所问 | 阈值 > 0.95,仅事实问答 |
| 向量过滤交给调用方 | 数据越权 | 服务端强制租户/ACL 过滤 |
| 索引与检索耦合 | 重建索引时检索不可用 | 离线在线解耦 |
| 纯 ReAct 上生产 | 成本失控、不收敛 | 优先工作流编排 |
| 工具无幂等 | 重复扣款/重复发送 | 幂等键 + 去重表 |
| 无迭代上限 | 死循环烧钱 | max_iterations + 预算上限 |
| 高风险操作无确认 | 误操作无法挽回 | Human-in-the-loop |
| 只看 QPS 不看 token | 成本失控 | TPM + 预算双维度限流 |
| 无成本归因 | 不知钱花在哪 | 按应用/模型/类型打标 |
7. 总结
AI 原生架构的落地可以归纳为四层治理:
- 模型网关:统一接入、路由、降级、缓存、配额、审计——让模型可替换、成本可归因。
- 检索服务化:RAG 离线在线解耦,向量检索内建租户过滤、重排与溯源。
- 编排可靠性:优先工作流,工具调用配 Schema 校验、幂等、迭代上限与人工确认。
- 成本与限流:缓存、模型分级、Prompt 压缩优先,QPS/TPM/预算多维限流。
这套架构的收益不是"更 AI",而是把概率性的模型调用纳入确定性的工程治理——模型可以换、成本可以控、故障可以降级、行为可以审计。做到这些,AI 能力才真正成为可长期运营的基础设施,而不是一个难以维护的实验。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。