Skip to content

📐 系统设计答题模板

面试中系统设计题的标准答题框架,覆盖 LLM 应用最常见的 5 个系统设计题


目录


通用答题框架

无论遇到什么系统设计题,都可以按以下 5 步展开。每步建议时间分配如下(45 分钟面试):

步骤内容建议时间
Step 1需求澄清5 分钟
Step 2高层架构10 分钟
Step 3核心流程10 分钟
Step 4详细设计12 分钟
Step 5扩展讨论8 分钟

Step 1: 需求澄清

目的:明确边界,展示你的思考深度。

功能需求(Functional Requirements):

  • 系统需要做什么?核心用例是什么?
  • 用户是谁?(开发者 / 终端用户 / 内部平台)
  • 输入输出是什么格式?
  • 关键 API 接口长什么样?

非功能需求(Non-Functional Requirements):

  • 延迟:P50 / P99 要求是多少?
  • 吞吐量:QPS / 并发用户数?
  • 可用性:几个 9?
  • 一致性 vs 可用性:倾向哪边?
  • 成本约束:预算范围?
  • 安全合规:数据隐私 / 地域限制?

提问模板

"在开始设计之前,我想确认几个关键问题……"

  1. "系统的日活用户 / QPS 量级大概是多少?"
  2. "对延迟的容忍度是多少?是同步返回还是可以异步?"
  3. "数据量级有多大?文档数量 / 存储大小?"
  4. "是否有成本限制?对模型调用费用的预算?"
  5. "是否有多租户需求?数据隔离要求?"

Step 2: 高层架构

目的:用最简单的图展示系统全貌。

原则

  • 先画核心路径(Happy Path)
  • 标注每个组件的职责(一句话)
  • 标注数据流向(箭头)
  • 暂不深入细节,留到 Step 4

画图模板

用户请求 → [接入层] → [核心逻辑层] → [存储层]

           [外部服务]

Step 3: 核心流程

目的:描述一个典型请求从进到出的完整生命周期。

原则

  • 选一个最重要的用例展开
  • 标注每一步的输入 / 输出
  • 标注可能的失败点和处理方式
  • 说明同步 vs 异步边界

Step 4: 详细设计

目的:挑 2-3 个关键组件深入。

选择标准

  • 最有技术挑战的组件
  • 面试官可能追问的方向
  • 你最擅长的领域

深入内容

  • 数据模型 / Schema
  • 算法选择及理由
  • 技术选型及 trade-off
  • 性能优化手段

Step 5: 扩展讨论

目的:展示全局视野和工程经验。

常见扩展话题

  • 水平扩展:如何支撑 10x 流量?
  • 监控告警:关键指标有哪些?如何设置告警?
  • 成本优化:如何降低模型调用成本?
  • 容灾:单点故障如何避免?
  • A/B 测试:如何验证新模型 / 新策略的效果?
  • 安全:如何防止 Prompt 注入?数据泄露?

模板一:RAG 系统设计

场景:设计一个企业级知识库问答系统,支持对海量文档进行语义检索并生成准确回答。

1. 需求分析

功能需求

ID需求优先级
F1支持上传 PDF/Word/HTML/Markdown 文档P0
F2对文档内容进行语义检索P0
F3基于检索结果生成回答,附带引用来源P0
F4支持多轮对话,理解上下文P1
F5支持文档权限控制(多租户)P1
F6支持增量更新(新文档实时可查)P2

非功能需求

指标要求
检索延迟P99 < 200ms
端到端延迟P99 < 3s(含生成)
吞吐量100 QPS(检索)
可用性99.9%
文档规模100 万篇文档,平均 5000 token/篇
准确率Recall@10 > 95%,Answer 准确率 > 90%

2. 架构图

┌─────────────────────────────────────────────────────────────────────┐
│                          用户 / API 客户端                          │
└──────────────────────────────┬──────────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────────┐
│                        API Gateway / 接入层                          │
│              认证鉴权 · 限流 · 路由 · 请求日志                        │
└──────────────────────────────┬───────────────────────────────────────┘

              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
     ┌────────────┐   ┌────────────┐   ┌────────────┐
     │  文档上传   │   │  检索服务   │   │  生成服务   │
     │  & 处理     │   │ (Retrieval)│   │(Generation)│
     └──────┬─────┘   └──────┬─────┘   └──────┬─────┘
            │                │                 │
            ▼                ▼                 ▼
     ┌────────────┐   ┌────────────┐   ┌────────────┐
     │ 文档处理    │   │ 向量数据库  │   │  LLM API   │
     │ Pipeline    │   │ (Milvus/   │   │ (GPT-4/    │
     │             │   │  Pinecone) │   │  Claude)   │
     └──────┬─────┘   └────────────┘   └────────────┘
            │                ▲
            ▼                │
     ┌────────────┐   ┌────────────┐
     │ 对象存储    │   │ 关键词索引  │
     │ (S3/MinIO) │   │(ES/Meilisearch)│
     └────────────┘   └────────────┘

3. 核心组件列表

组件职责技术选型
API Gateway认证、限流、路由Kong / Nginx / 自建
文档处理服务解析、分块、向量化LangChain / LlamaIndex
向量数据库存储和检索 embeddingMilvus / Pinecone / Qdrant
关键词索引BM25 全文检索Elasticsearch / Meilisearch
检索服务混合检索 + 重排序自建服务
生成服务Prompt 组装 + LLM 调用自建服务
LLM API大模型推理OpenAI / Claude / 自部署
对象存储原始文档存储S3 / MinIO
元数据库文档元信息、权限PostgreSQL

4. 数据流

文档索引流程

1. 用户上传文档 → API Gateway → 文档上传服务
2. 文档存储到 S3,元信息写入 PostgreSQL
3. 文档处理 Pipeline 启动:
   a. 文档解析(PDF → 纯文本,保留结构)
   b. 文本分块(Chunk Size=512, Overlap=64)
   c. 每个 Chunk 生成 embedding(text-embedding-3-small)
   d. Chunk + embedding 写入向量数据库
   e. Chunk 文本写入 ES 关键词索引
4. 索引完成,文档即可被检索

查询应答流程

1. 用户提问 → API Gateway → 检索服务
2. 检索服务执行混合检索:
   a. 向量检索:query embedding → Top-K=50 from 向量库
   b. 关键词检索:BM25 → Top-K=50 from ES
   c. 融合排序(RRF / 加权合并)→ Top-K=10
   d. 重排序(Cross-encoder Reranker)→ Top-5
3. 生成服务组装 Prompt:
   a. System Prompt + 检索到的 5 个 Chunk + 用户问题
   b. 调用 LLM 生成回答
4. 返回回答 + 引用来源

5. 关键设计决策

5.1 分块策略(Chunking)

策略优点缺点适用场景
固定大小分块实现简单可能切断语义通用文本
语义分块保持语义完整计算开销大结构化文档
递归分块平衡效果和复杂度需调参推荐默认方案
文档结构分块利用标题/段落依赖文档格式PDF/Word
推荐配置:
- Chunk Size: 512 tokens
- Overlap: 64 tokens(约 12.5%)
- 分隔优先级: ["\n\n", "\n", "。", ".", " "]

5.2 检索策略

为什么需要混合检索?

  • 向量检索擅长语义匹配("公司休假政策" ≈ "年假规定")
  • 关键词检索擅长精确匹配(产品型号、人名、数字)
  • 混合检索覆盖率最高

融合算法 — Reciprocal Rank Fusion (RRF)

score(d) = Σ 1 / (k + rank_i(d))
其中 k=60(经验常数),rank_i(d) 是 d 在第 i 个检索器中的排名

5.3 重排序(Reranking)

第一阶段:粗召回(Bi-encoder)→ 快速,Recall 高
第二阶段:精排(Cross-encoder)→ 慢但精准

为什么不在第一阶段就用 Cross-encoder?
→ Cross-encoder 对每个 (query, doc) 对都要计算,O(n) 复杂度
→ 对 100 万文档做 Cross-encoder 排序不现实
→ 所以先用 Bi-encoder 缩小到 Top-50,再用 Cross-encoder 精排

5.4 生成优化

Prompt 模板

你是一个企业知识库助手。请基于以下参考文档回答用户问题。

规则:
1. 只基于参考文档回答,不要编造信息
2. 如果参考文档中没有相关信息,请明确说"未找到相关内容"
3. 在回答中标注引用来源,格式:[来源: 文档名]

参考文档:
{context_chunks}

用户问题:{question}

减少幻觉的手段

  1. 明确指令"不要编造"
  2. 要求引用来源(可验证性)
  3. 温度设低(temperature=0.1)
  4. 加入"不知道就说不知道"的指令

6. 评估体系

维度指标计算方式
检索质量Recall@KTop-K 中包含正确文档的比例
检索质量MRR第一个正确结果的倒数排名
检索质量nDCG考虑排名位置的增益
生成质量Faithfulness回答是否忠于检索内容
生成质量Relevance回答是否回答了问题
生成质量引用准确性引用来源是否正确
端到端人工评估标注员评分(1-5 分)

自动化评估 Pipeline

1. 准备 Golden Dataset(问题 + 标准答案 + 相关文档)
2. 每次模型/策略变更后自动跑评估
3. 对比 Recall、Answer Quality 等指标
4. 回归检测:新版本不能比旧版本差

7. 扩展方案

水平扩展

  • 向量数据库:分片 + 副本(Milvus 支持自动分片)
  • 检索服务:无状态,水平扩展
  • 生成服务:队列 + Worker 池

成本优化

  • 小问题用小模型,复杂问题用大模型(路由策略)
  • 缓存高频问题的回答
  • 批量 embedding 调用(降低 API 成本)
  • 自部署 embedding 模型(高量级时更划算)

监控指标

  • 检索延迟 P50/P99
  • 生成延迟 P50/P99
  • 向量库 QPS 和内存使用
  • LLM Token 消耗量
  • 用户满意度(点赞/点踩)

模板二:Agent 平台设计

场景:设计一个通用 AI Agent 平台,支持注册工具、编排多步骤任务、多 Agent 协作。

1. 需求分析

功能需求

ID需求优先级
F1支持注册自定义工具(API/函数/脚本)P0
F2Agent 能自主决定调用哪些工具完成任务P0
F3支持多步骤任务编排(ReAct / Plan-and-Execute)P0
F4记忆系统:短期(会话)+ 长期(持久化)P1
F5多 Agent 协作(主 Agent 分发子任务)P1
F6安全沙箱执行代码 / 工具调用P0
F7可观测性:执行 trace、日志、成本追踪P1

非功能需求

指标要求
任务延迟单步 < 10s,完整任务 < 2min
并发任务支持 1000 并发 Agent 会话
可用性99.9%
工具调用安全沙箱隔离,权限控制
可扩展性新工具注册 < 5 分钟

2. 架构图

┌──────────────────────────────────────────────────────────────┐
│                        用户 / 客户端                         │
└─────────────────────────────┬────────────────────────────────┘


┌──────────────────────────────────────────────────────────────┐
│                        API Gateway                           │
└─────────────────────────────┬────────────────────────────────┘


┌──────────────────────────────────────────────────────────────┐
│                     Agent 调度引擎                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │
│  │ Planner  │  │ Executor │  │ Memory   │  │ Observer │    │
│  │ (规划器)  │  │ (执行器)  │  │ (记忆管理)│  │ (监控器)  │    │
│  └──────────┘  └─────┬────┘  └──────────┘  └──────────┘    │
└────────────────────────┼─────────────────────────────────────┘

            ┌────────────┼────────────┐
            ▼            ▼            ▼
     ┌───────────┐ ┌───────────┐ ┌───────────┐
     │ 工具注册表 │ │ 沙箱执行  │ │  LLM 调用  │
     │ (Registry)│ │ (Sandbox) │ │  (多模型)  │
     └───────────┘ └───────────┘ └───────────┘

            ┌────────────┼────────────┐
            ▼            ▼            ▼
     ┌───────────┐ ┌───────────┐ ┌───────────┐
     │  数据库    │ │  消息队列  │ │  对象存储  │
     │ (Postgres)│ │  (Redis)  │ │   (S3)    │
     └───────────┘ └───────────┘ └───────────┘

3. 核心组件列表

组件职责技术选型
Agent 调度引擎解析意图、规划步骤、协调执行自建(核心)
Planner任务分解、制定执行计划LLM + Chain-of-Thought
Executor逐步执行计划、处理异常自建
Memory Manager短期/长期记忆管理Redis + PostgreSQL
Observer执行监控、trace 收集OpenTelemetry
工具注册表工具元信息、Schema 管理PostgreSQL + 缓存
沙箱执行环境隔离执行代码/API 调用Docker / gVisor / WASM
LLM 服务推理能力多模型路由

4. 数据流

任务执行流程

1. 用户提交任务:"帮我分析这个 CSV 文件并生成报告"
2. Agent 调度引擎接收任务
3. Planner 调用 LLM 生成执行计划:
   - Step 1: 读取 CSV 文件(工具: file_reader)
   - Step 2: 数据分析(工具: python_sandbox)
   - Step 3: 生成图表(工具: python_sandbox)
   - Step 4: 撰写报告(工具: text_generator)
4. Executor 逐步执行:
   a. 从工具注册表获取工具 Schema
   b. 组装工具调用参数
   c. 在沙箱中执行
   d. 收集结果,更新 Memory
   e. 将结果传给下一步
5. Observer 记录每步的 trace、延迟、token 消耗
6. 最终结果返回给用户

5. 关键设计决策

5.1 工具注册机制

json
// 工具注册 Schema
{
  "tool_id": "sql_query",
  "name": "数据库查询",
  "description": "执行只读 SQL 查询并返回结果",
  "parameters": {
    "type": "object",
    "properties": {
      "query": { "type": "string", "description": "SQL 查询语句" },
      "database": { "type": "string", "description": "数据库名" }
    },
    "required": ["query"]
  },
  "permissions": ["read:database"],
  "sandbox": true,
  "timeout_ms": 30000,
  "retry_policy": { "max_retries": 2, "backoff_ms": 1000 }
}

5.2 记忆系统设计

┌─────────────────────────────────────────────┐
│                记忆系统架构                   │
├─────────────┬───────────────────────────────┤
│  工作记忆    │ 当前会话上下文(LLM context)   │
│ (Working)   │ 容量: 模型 context window       │
│             │ 存储: 内存                      │
├─────────────┼───────────────────────────────┤
│  短期记忆    │ 最近 N 轮对话历史              │
│ (Short-term)│ 容量: 最近 50 轮               │
│             │ 存储: Redis TTL=24h            │
├─────────────┼───────────────────────────────┤
│  长期记忆    │ 用户偏好、历史任务、学到的知识   │
│ (Long-term) │ 容量: 无限                     │
│             │ 存储: PostgreSQL + 向量检索      │
└─────────────┴───────────────────────────────┘

记忆检索策略

  • 每次任务开始时,用当前任务描述做向量检索,拉取相关长期记忆
  • 结合短期记忆(最近对话)一起注入 Prompt
  • 记忆总量控制在 context window 的 30% 以内

5.3 安全沙箱

安全层级:
1. 权限控制:每个工具声明所需权限,Agent 需要授权才能调用
2. 输入校验:SQL 注入检测、路径遍历检测、命令注入检测
3. 执行隔离:Docker 容器 / gVisor / WASM 沙箱
4. 资源限制:CPU/内存/网络/磁盘限额
5. 审计日志:所有工具调用记录在案

5.4 多 Agent 协作

┌─────────────┐
│  主 Agent    │  接收用户任务,分解子任务
│  (Orchestrator)│
└──────┬──────┘
       │ 分发子任务
  ┌────┼────┐
  ▼    ▼    ▼
┌────┐┌────┐┌────┐
│ A1 ││ A2 ││ A3 │  专业 Agent(各自擅长不同领域)
│搜索 ││分析 ││写作 │
└──┬─┘└──┬─┘└──┬─┘
   │     │     │
   └─────┼─────┘

   ┌──────────┐
   │ 汇总结果  │  主 Agent 汇总并返回
   └──────────┘

协调模式

  • Sequential:串行执行,前一步输出作为后一步输入
  • Parallel:并行执行独立子任务
  • Hierarchical:主 Agent 分发,子 Agent 独立执行后汇报
  • Debate:多个 Agent 对同一问题给出不同观点,综合判断

6. 扩展讨论

如何处理 Agent 循环 / 跑飞?

  • 设置最大步骤数(如 20 步)
  • 设置总 Token 消耗上限
  • 检测重复动作(相同工具 + 参数调用 3 次 → 中断)
  • 人类介入机制(Human-in-the-Loop)

可观测性指标

  • 每个任务的执行 trace(步骤、耗时、token)
  • 工具调用成功率 / 失败率
  • 平均任务完成步骤数
  • Token 消耗分布
  • 用户满意度

成本优化

  • 简单任务用小模型(GPT-4o-mini),复杂任务用大模型
  • 缓存常见工具调用结果
  • 批量工具调用合并

模板三:模型网关设计

场景:设计一个统一的 LLM API 网关,对接多个模型供应商,提供路由、限流、缓存、计费等能力。

1. 需求分析

功能需求

ID需求优先级
F1统一 API 接口(兼容 OpenAI 格式)P0
F2支持多供应商路由(OpenAI/Claude/自部署)P0
F3请求限流(按用户/按 API Key)P0
F4响应缓存(语义缓存 + 精确缓存)P1
F5用量计费和配额管理P0
F6请求/响应日志记录P1
F7流式响应支持(SSE)P0
F8熔断降级(供应商故障时自动切换)P1

非功能需求

指标要求
网关延迟额外开销 < 50ms
吞吐量10,000 QPS
可用性99.99%
数据一致性计费数据不能丢失

2. 架构图

┌──────────────────────────────────────────────────────────┐
│                    应用 / API 客户端                      │
└─────────────────────────┬────────────────────────────────┘
                          │ (OpenAI 兼容 API)

┌──────────────────────────────────────────────────────────┐
│                    API Gateway (Nginx/Kong)               │
│               TLS 终止 · 负载均衡 · 基础限流               │
└─────────────────────────┬────────────────────────────────┘


┌──────────────────────────────────────────────────────────┐
│                    模型网关核心服务                        │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐│
│  │认证鉴权 │ │路由引擎 │ │限流熔断 │ │ 缓存   │ │ 计费   ││
│  └────────┘ └───┬────┘ └────────┘ └────────┘ └────────┘│
└──────────────────┼───────────────────────────────────────┘

       ┌───────────┼───────────┐
       ▼           ▼           ▼
┌───────────┐┌───────────┐┌───────────┐
│  OpenAI   ││  Claude   ││ 自部署模型  │
│   API     ││   API     ││ (vLLM)    │
└───────────┘└───────────┘└───────────┘

辅助服务:
┌───────────┐┌───────────┐┌───────────┐
│ PostgreSQL││   Redis   ││ClickHouse │
│ (配额/计费)││ (限流/缓存)││ (日志/监控)│
└───────────┘└───────────┘└───────────┘

3. 核心组件列表

组件职责技术选型
认证鉴权API Key 校验、权限验证自建 + Redis
路由引擎根据策略选择模型供应商自建
限流器令牌桶 / 滑动窗口限流Redis + Lua
熔断器供应商健康检测和自动降级自建(滑动窗口)
缓存层精确缓存 + 语义缓存Redis + 向量库
计费服务Token 统计、费用计算异步写入 ClickHouse
日志服务请求/响应全量记录Kafka → ClickHouse

4. 数据流

请求处理流程

1. 客户端发送请求(OpenAI 格式)
2. 认证鉴权:校验 API Key → 获取用户信息和配额
3. 缓存检查:
   a. 精确缓存:hash(prompt + model + params) → 命中则直接返回
   b. 语义缓存:embedding similarity > 0.95 → 命中则返回
4. 限流检查:令牌桶算法,超限返回 429
5. 路由引擎选择供应商:
   a. 根据 model 参数映射到供应商列表
   b. 考虑:权重、延迟、成本、健康状态
   c. 选择最优供应商
6. 熔断检查:供应商是否处于熔断状态
7. 转发请求到供应商 API
8. 流式响应透传 / 非流式响应收集
9. 异步写入:
   a. Token 计数 → 计费服务
   b. 请求日志 → ClickHouse
   c. 响应写入缓存
10. 返回响应给客户端

5. 关键设计决策

5.1 路由策略

python
# 路由决策逻辑(伪代码)
def select_provider(request):
    candidates = MODEL_MAPPING[request.model]  # 如 "gpt-4" → [openai, azure]
    
    # 过滤熔断中的供应商
    candidates = [c for c in candidates if not circuit_breaker.is_open(c)]
    
    # 根据策略排序
    if strategy == "latency":
        candidates.sort(key=lambda c: c.avg_latency)
    elif strategy == "cost":
        candidates.sort(key=lambda c: c.cost_per_token)
    elif strategy == "weighted":
        candidates.sort(key=lambda c: c.weight, reverse=True)
    
    return candidates[0]

5.2 限流设计

三层限流:
1. 全局限流:保护后端总容量(如 10000 QPS)
2. 用户限流:按 API Key 限制(如 100 QPS/用户)
3. 模型限流:按模型限制(如 GPT-4 500 QPS)

算法:滑动窗口令牌桶
- 存储在 Redis 中(原子操作,Lua 脚本)
- 返回 X-RateLimit-* 响应头

5.3 缓存策略

缓存类型命中条件存储适用场景
精确缓存hash 完全匹配Redistemperature=0 的请求
语义缓存embedding 相似度 > 0.95Redis + 向量库常见问题
缓存 key 设计:
精确:hash(model + messages + temperature + max_tokens)
语义:embedding(messages[-1]) 最近邻搜索

缓存失效:
- TTL: 24h(可配置)
- 手动清除:按 prefix 清除
- 不缓存:stream=true 的请求

5.4 计费设计

计费模型:
- 按 Token 计费(输入 Token + 输出 Token 分开计价)
- 不同模型不同单价
- 支持预付费(配额)和后付费(账单)

数据流:
请求完成 → 异步发送到 Kafka → 计费服务消费
→ 实时扣减 Redis 中的配额
→ 异步写入 ClickHouse 做账单聚合

6. 扩展讨论

如何支撑 10x 流量?

  • 网关无状态,水平扩展
  • Redis Cluster 分片
  • ClickHouse 分布式表
  • 缓存命中率优化(减少后端调用)

监控关键指标

  • 每个供应商的 QPS、延迟 P50/P99、错误率
  • 缓存命中率(精确 vs 语义)
  • 限流触发率
  • 熔断触发次数
  • Token 消耗量和费用

模板四:多模型 Fallback 系统

场景:设计一个高可用的 LLM 调用层,当主模型不可用时自动降级到备选模型,保证服务连续性。

1. 需求分析

功能需求

ID需求优先级
F1定义模型优先级链(主模型 → 备选模型 → 兜底模型)P0
F2实时健康检查(延迟、错误率)P0
F3自动故障检测和切换(秒级)P0
F4动态路由(基于任务类型选择最优模型)P1
F5降级策略(功能降级 vs 质量降级)P1
F6故障恢复后自动切回主模型P1
F7成本追踪和优化P2

非功能需求

指标要求
故障检测时间< 5s
切换时间< 2s
切换期间可用性99.9%(允许降级)
数据一致性切换不能丢请求

2. 架构图

┌─────────────────────────────────────────────────────┐
│                   应用服务层                         │
└────────────────────────┬────────────────────────────┘


┌─────────────────────────────────────────────────────┐
│                 模型 Fallback 引擎                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐          │
│  │ 健康检查  │  │ 路由决策  │  │ 降级策略  │          │
│  │  Monitor  │  │  Router  │  │ Degrader │          │
│  └──────────┘  └────┬─────┘  └──────────┘          │
│                     │                               │
│  ┌──────────────────┴──────────────────────┐       │
│  │           优先级链 (Priority Chain)       │       │
│  │  L1: GPT-4o  →  L2: Claude 3.5  →  L3: 本地  │ │
│  └─────────────────────────────────────────┘       │
└────────────────────────┬────────────────────────────┘

         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   ┌──────────┐   ┌──────────┐   ┌──────────┐
   │  OpenAI  │   │  Claude  │   │  本地模型  │
   │   API    │   │   API    │   │  (vLLM)  │
   └──────────┘   └──────────┘   └──────────┘

健康状态存储:Redis (实时状态) + ClickHouse (历史数据)

3. 核心组件列表

组件职责技术选型
健康检查器定期探测模型可用性自建(定时任务)
路由决策器根据健康状态和策略选择模型自建
降级策略器定义降级行为和质量边界自建
状态存储记录各模型实时健康状态Redis
指标收集延迟、错误率、token 用量Prometheus + ClickHouse
配置中心优先级链、阈值等动态配置etcd / Apollo

4. 数据流

正常请求流程

1. 请求进入 Fallback 引擎
2. 路由决策器查询各模型健康状态(Redis)
3. 选择优先级最高且健康的模型
4. 发送请求 → 返回响应
5. 更新该模型的延迟和成功率指标

Fallback 流程

1. 请求发送到主模型(GPT-4o)
2. 超时 / 5xx 错误 / 限流(429)
3. 触发 Fallback:
   a. 记录主模型失败(更新 Redis 状态)
   b. 检查下一级模型(Claude 3.5)健康状态
   c. 如果健康 → 重试请求到 Claude 3.5
   d. 如果不健康 → 继续下一级(本地模型)
4. 返回响应(标注实际使用的模型)
5. 异步告警:主模型故障通知

恢复流程

1. 健康检查器定期(每 10s)发送探测请求到故障模型
2. 连续 N 次(如 3 次)成功 → 标记为恢复
3. 使用金丝雀策略:先将 10% 流量切回
4. 观察 5 分钟无异常 → 逐步恢复到 100%

5. 关键设计决策

5.1 健康状态机

状态转换图:

  ┌──────┐  连续3次失败   ┌────────┐  探测成功3次  ┌──────────┐
  │ 健康  │──────────────→│  故障   │─────────────→│ 恢复中    │
  │(Healthy)│             │ (Down) │              │(Recovering)│
  └───┬───┘              └────────┘              └─────┬────┘
      │                                                │
      │          5分钟金丝雀无异常                      │
      │←───────────────────────────────────────────────┘
      │                                                │
      │              金丝雀期间出错                      │
      │     ┌──────────────────────────────────────────┘
      │     │
      │     ▼
      │  ┌────────┐
      │  │  故障   │
      │  └────────┘

  ┌───┴────────────┐
  │ 降级 (Degraded) │  错误率 > 30% 但未完全不可用
  └────────────────┘

健康检查指标:
- 主动探测:每 10s 发送简单请求
- 被动检测:实时统计请求错误率
- 综合判断:主动 OR 被动 任一触发 → 状态变更

5.2 路由策略

python
def select_model(request, priority_chain, health_status):
    """选择最优模型"""
    
    # 策略 1:简单优先级(默认)
    for model in priority_chain:
        if health_status[model] in ["healthy", "recovering"]:
            return model
    
    # 策略 2:基于任务类型路由
    task_type = classify_task(request)  # "code" / "creative" / "analysis"
    model_scores = {
        "code": {"gpt-4o": 0.95, "claude": 0.90, "local": 0.70},
        "creative": {"claude": 0.95, "gpt-4o": 0.85, "local": 0.60},
        "analysis": {"gpt-4o": 0.90, "claude": 0.88, "local": 0.75},
    }
    ranked = sorted(model_scores[task_type].items(), key=lambda x: -x[1])
    for model, _ in ranked:
        if health_status[model] in ["healthy", "recovering"]:
            return model
    
    # 策略 3:基于成本
    for model in sorted_by_cost(priority_chain):
        if health_status[model] in ["healthy", "recovering"]:
            return model
    
    return "local_model"  # 最后兜底

5.3 降级策略

降级级别触发条件行为用户感知
L0正常使用主模型
L1主模型延迟升高切换到同级备选延迟略增
L2主模型不可用切换到次级模型质量可能下降
L3所有云端不可用切换到本地模型质量明显下降
L4所有模型不可用返回缓存结果 / 排队等待功能受限

5.4 成本优化

成本感知路由:
1. 维护每个模型的 $/1K token 价格表
2. 简单任务(分类、提取)→ 用便宜模型
3. 复杂任务(推理、创作)→ 用贵模型
4. 设置每日预算上限,超限自动降级到便宜模型

成本计算公式:
  task_cost = input_tokens * input_price + output_tokens * output_price
  daily_budget = sum(all_tasks_cost)
  if daily_budget > threshold:
      auto_downgrade_to_cheaper_model()

6. 扩展讨论

防止级联故障

  • 每个模型供应商独立超时设置
  • Bulkhead 模式:隔离不同供应商的连接池
  • 不要把所有请求同时切到同一个备用模型(可能把它也压垮)

关键监控指标

  • 每个模型的 QPS、延迟、错误率
  • Fallback 触发频率
  • 降级持续时间
  • 每日成本分布
  • 用户体验指标(端到端延迟)

模板五:实时语音 Agent 设计

场景:设计一个实时语音对话 Agent,用户可以像打电话一样与 AI 对话,要求低延迟、自然流畅。

1. 需求分析

功能需求

ID需求优先级
F1实时音频采集和传输(麦克风输入)P0
F2语音转文字(STT),支持流式识别P0
F3LLM 理解和生成回答P0
F4文字转语音(TTS),支持流式合成P0
F5支持打断(Barge-in)P1
F6多语言支持P1
F7情感识别和表达P2
F8通话录音和转写P1

非功能需求

指标要求
端到端延迟< 800ms(用户说完到听到回复)
STT 延迟< 300ms
LLM 首 Token 延迟< 200ms
TTS 首包延迟< 200ms
音频质量16kHz 采样率,Opus 编码
并发通话10,000 路
可用性99.9%

2. 架构图

┌─────────────────────────────────────────────────────────────────┐
│                       用户设备(浏览器/App)                      │
│  ┌────────┐                              ┌────────┐             │
│  │ 麦克风  │→ 音频采集 → Opus编码 → WebSocket →│ 扬声器  │          │
│  └────────┘                              └────────┘             │
└────────────────────────────┬────────────────────────────────────┘
                             │ WebSocket (双向流式)

┌─────────────────────────────────────────────────────────────────┐
│                      实时通信网关                                │
│              WebSocket 管理 · 房间路由 · 负载均衡                 │
└────────────────────────────┬────────────────────────────────────┘

         ┌───────────────────┼───────────────────┐
         ▼                   ▼                   ▼
┌──────────────┐   ┌──────────────┐   ┌──────────────┐
│   STT 服务    │   │   LLM 服务    │   │   TTS 服务    │
│ (流式语音识别) │   │ (流式文本生成) │   │ (流式语音合成) │
│              │   │              │   │              │
│ Whisper/     │   │ GPT-4o/      │   │ ElevenLabs/  │
│ Deepgram/    │   │ Claude/      │   │ Azure TTS/   │
│ Paraformer   │   │ 自部署       │   │ CosyVoice   │
└──────────────┘   └──────────────┘   └──────────────┘
         │                   │                   │
         └───────────────────┼───────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                      状态管理 & 会话存储                          │
│         Redis (会话状态) · PostgreSQL (历史记录)                   │
└─────────────────────────────────────────────────────────────────┘

3. 核心组件列表

组件职责技术选型
音频采集模块麦克风采集、降噪、VADWeb Audio API / WebRTC
音频编码Opus 编解码libopus
WebSocket 网关双向实时通信Go / Rust 高性能服务
STT 服务流式语音识别Whisper / Deepgram / Paraformer
LLM 服务流式文本生成GPT-4o / Claude / vLLM
TTS 服务流式语音合成ElevenLabs / Azure TTS / CosyVoice
VAD 模块语音活动检测(断句/打断)Silero VAD / WebRTC VAD
会话管理通话状态、上下文维护Redis
录音服务通话录音存储S3 + FFmpeg

4. 数据流

主通话流程(Pipeline 模式)

时间线:
T0: 用户开始说话
    └→ 麦克风采集音频(16kHz, PCM)
    └→ Opus 编码 → WebSocket 发送

T1: 实时通信网关接收音频包
    └→ 转发到 STT 服务

T2: STT 流式识别(每 200ms 返回中间结果)
    └→ VAD 检测到静音 → 确定用户说完了(end-of-speech)
    └→ 返回最终文本

T3: 最终文本发送到 LLM 服务
    └→ LLM 开始流式生成(每收到几个 token 就发送)

T4: LLM 流式输出 → TTS 流式合成
    └→ TTS 收到第一个句子就开始合成
    └→ 合成的音频包实时发送到客户端

T5: 客户端收到音频包 → 播放

目标:T5 - T0 < 800ms

流式 Pipeline 优化(关键!)

传统串行(太慢):
  完整STT → 完整LLM → 完整TTS → 播放
  延迟 = STT + LLM_full + TTS_full ≈ 3-5s ❌

流式 Pipeline(推荐):
  音频 → STT(流式)→ LLM(流式)→ TTS(流式)→ 播放
  每个环节边产出边传递,延迟大幅降低 ✓

更激进的优化:双工模式
  用户说话的同时,Agent 可以在处理之前的对话
  支持打断:用户随时可以说话打断 Agent 的回复

5. 关键设计决策

5.1 低延迟优化

环节优化手段预期延迟
音频传输WebSocket + Opus 编码(低比特率)20-50ms
STT流式识别 + 云端 GPU 推理200-300ms
LLM流式生成 + 小模型优先 + KV Cache100-200ms(首 token)
TTS流式合成(按句子/短语合成)100-200ms(首包)
网络就近部署(边缘节点)20-50ms
总计440-800ms

STT 优化

- 使用流式 ASR,不等用户说完就开始识别
- 中间结果可以提前发送给 LLM 做预处理
- 语言模型解码用 GPU 加速
- 选择低延迟 ASR 服务(如 Deepgram,延迟约 200ms)

LLM 优化

- 流式生成,每生成一个句子就发给 TTS
- 短回答优先:System Prompt 中要求简洁回答
- Speculative decoding(投机采样)加速
- KV Cache 复用(同一会话内)

TTS 优化

- 流式合成:收到第一个句子就开始合成,不等全部文本
- 分句策略:句号/逗号/问号处分割
- 音频流式传输:合成一个 chunk 就发送一个
- 预合成常用回复("好的"、"明白了")

5.2 打断(Barge-in)处理

打断检测流程:
1. VAD 持续检测用户是否在说话
2. 如果 Agent 正在播放回复,用户开始说话:
   a. VAD 检测到语音活动
   b. 立即停止 TTS 输出
   c. 清空 TTS 缓冲区
   d. 开始新的 STT 识别
3. LLM 需要理解打断上下文:
   a. 将"用户打断了上一轮回复"作为上下文
   b. 根据用户新输入重新生成回答

实现细节:
- VAD 灵敏度要调好:太灵敏→误触发,太迟钝→打断延迟
- 建议使用 Silero VAD(准确率高,延迟低)
- 打断阈值:连续 300ms 检测到语音 → 触发打断

5.3 WebSocket 协议设计

json
// 客户端 → 服务端
{"type": "audio", "data": "<base64_opus_chunk>", "seq": 1}
{"type": "control", "action": "start_call"}
{"type": "control", "action": "end_call"}

// 服务端 → 客户端
{"type": "stt_partial", "text": "你好,我想"}
{"type": "stt_final", "text": "你好,我想了解一下"}
{"type": "llm_token", "text": "好的,"}
{"type": "llm_token", "text": "关于这个问题"}
{"type": "tts_audio", "data": "<base64_audio_chunk>", "seq": 1}
{"type": "control", "action": "turn_end"}
{"type": "control", "action": "interrupted"}

5.4 并发架构

每路通话的资源消耗:
- WebSocket 连接:1 个
- STT 算力:~0.1 GPU(流式,非持续占用)
- LLM 算力:共享(流式,利用率高)
- TTS 算力:~0.05 GPU
- 内存:~50MB/路(会话状态 + 缓冲区)

10,000 路并发需要:
- WebSocket 网关:10-20 台(Go/Rust,每台 1000+ 连接)
- STT 集群:约 1000 GPU(或使用云服务如 Deepgram)
- LLM 集群:取决于模型大小(使用 vLLM + 多卡)
- TTS 集群:约 500 GPU(或使用云服务)

6. 扩展讨论

多语言支持

  • STT:使用多语言模型(Whisper large-v3 支持 100+ 语言)
  • LLM:天然支持多语言
  • TTS:每个语言需要独立的声音模型
  • 语言检测:自动检测用户语言,切换 TTS 声音

情感识别和表达

  • STT 扩展:识别语调、语速、情绪
  • LLM Prompt:根据用户情绪调整回答风格
  • TTS 扩展:支持不同情感的语音合成

监控指标

  • 端到端延迟分布
  • 各环节延迟分布(STT/LLM/TTS)
  • 打断率
  • 通话质量评分(MOS)
  • 掉线率
  • 并发通话数

成本优化

  • STT/TTS 使用云服务时,按分钟计费,注意控制通话时长
  • LLM 用小模型处理简单对话,大模型处理复杂推理
  • 闲时自动缩容
  • 缓存常见对话模式的 TTS 结果

附录:答题技巧总结

面试沟通技巧

阶段技巧
开头先花 2-3 分钟问清楚需求,不要急于画图
画图从高层到细节,先框后线,边画边讲
讨论主动提出 trade-off,展示工程思维
收尾总结核心设计决策,提出未来改进方向

常见追问及应对

追问方向应对策略
"如何处理 XX 万 QPS?"先估算单机容量,再算需要多少实例,说明如何水平扩展
"如果 XX 挂了怎么办?"冗余 + Fallback + 告警 + 降级
"如何保证数据一致性?"讨论 CAP 权衡,说明选择 CP 还是 AP
"成本怎么优化?"缓存 + 小模型 + 按需扩缩容 + 批处理
"如何监控系统健康?"关键指标 + 告警规则 + Dashboard + Trace

LLM 系统设计特有关注点

关注点说明
Token 成本模型调用按 token 计费,成本是核心约束
延迟链路STT + LLM + TTS 串行,每一段都影响总延迟
模型幻觉需要设计机制减少和检测幻觉
Context Window有限的上下文窗口,需要管理历史信息
模型版本管理模型更新频繁,需要灰度和回滚机制
安全合规Prompt 注入防护、数据隐私、内容审核

📝 使用建议

  1. 面试前通读一遍,理解每个模板的核心思路
  2. 重点记忆架构图和关键设计决策
  3. 根据面试官的追问方向灵活调整深入的内容
  4. 多练习手画架构图(白板面试需要)
  5. 每个模板准备 1-2 个你最熟悉的技术细节作为"亮点"

LLM 应用 & Agent 开发面试准备