跳转至

10. 系统设计模板

十、系统设计模板

工业级 AI 系统设计架构蓝图与设计方法论

在构建工业级 AI 系统(如高并发检索增强生成系统、自主体执行引擎及多租户 Agent 平台)时,系统设计必须兼顾传统分布式架构的确定性要求与概率性大模型计算的非确定性特征。优秀的系统架构设计应避免堆砌学术概念或沦为单一的传统后端系统变体,而必须围绕“分层控制、状态感知、可观测性及安全治理”构建统一的工程图景。

flowchart TD A["API 接入与网关层 (鉴权、限流、流式网关、会话控制)"] --> B["业务编排与状态层 (Conversation State、路由分支、OODA 循环)"] B --> C["知识与数据检索层 (多路召回、Rerank、向量/元数据混合引擎)"] B --> D["模型调度与路由层 (Token 路由、并发预算、分级回退)"] C --> E["存储与缓存中台 (pgvector / ES、Query Cache、Entity Registry)"] D --> F["运行时治理与可观测中台 (Trace、审计日志、在线评测、ACL 网关)"]

工业级 AI 系统的分层架构体系:

  1. API 接入与网关层(Access & Gateway Layer):负责多租户隔离、高并发限流(Token-based Rate Limiting)、会话状态(Session State)初始化,以及面向客户端的单向流式推送(SSE)或双向长连接(WebSocket)生命周期管理。
  2. 业务编排与状态层(Orchestration & State Layer):作为系统的“神经网络”,控制多步 OODA(Observe-Orient-Decide-Act)循环的执行逻辑,维护共享状态机快照,并根据动态决策执行 Task Handoff。
  3. 知识与数据检索层(Retrieval & Data Layer):实现离线/在线的数据加工与高精检索,包含文档解析清洗管线、多路混合召回引擎(Sparse/Dense Retrieval)以及二次重排(Rerank)决策。
  4. 模型调度与路由层(Model Routing & Inf Layer):负责跨模型服务商的负载均衡、冷启动预热、并发配额(Concurrency Quota)精细控制,以及高成本/高延迟模型的降级容灾流转。
  5. 存储与缓存中台(Persistence & Cache Layer):承载关系型元数据、向量数据、会话 Checkpoint 镜像及多级缓存(Query Cache, Embedding Cache)。
  6. 运行时治理与可观测中台(Governance & Observability Layer):提供跨节点的 Trace 链路追踪、无损 Prompt 版本化管理、实时安全合规审计以及在线/离线回归评测。

高并发检索增强生成(RAG)系统设计蓝图

在企业级场景中,构建 RAG 系统的核心挑战在于:如何将海量异构文档加工为高精准度的可检索资产,并在保证严格多租户权限隔离的前提下,提供亚秒级的端到端问答响应。

1. 离线数据加工与建库链路(Offline Data Pipeline)

离线链路必须采用异步任务驱动的分布式微服务架构,以隔离高耗时的文档处理压力与在线查询压力。

flowchart LR A["文档上传接口"] --> B["对象存储 (S3)"] B --> C["异步任务创建 (Celery / RabbitMQ)"] C --> D["文档解析与 OCR 服务"] D --> E["智能文本切块 (Chunking)"] E --> F["分布式向量化服务 (Embedding Batch)"] F --> G["向量与关系型数据库 (pgvector)"]
  • 异步任务队列:文档解析、OCR、切块及 Embedding 属于重 CPU/GPU 消耗型操作。必须通过分布式消息队列(如 RabbitMQ, Kafka)将任务异步下发至 Worker 集群执行,前端通过 Polling 或 Webhook 接收任务状态。
  • 存储选型与一致性控制:推荐采用 PostgreSQL 加 pgvector 扩展。其核心优势在于:可在单一数据库实例内,以强 ACID 特性同时存储文档原始元数据、关系型权限控制字段(ACL)与高维向量数据,降低了 ES + 向量库“双栈架构”带来的多数据源同步延时与一致性维护成本。但这个选型有规模边界:数据规模达千万级且并发度/QPS较高时,pgvector 的 HNSW/IVFFlat 索引在建图时间、内存占用和查询延迟上就会逼近单机瓶颈——按 Vector Count × Dimensions × 4 bytes × θ 估算,1000 万条 1024 维 float32 向量仅 HNSW 建图内存就要 60GB~100GB,外推到十亿级(百倍数据量)单机内存需求将达 6TB~10TB 量级,工程上已不可行,此时需要评估 Milvus、Weaviate 等专用向量数据库或引入分片方案。

2. 在线检索与生成问答链路(Online Query Pipeline)

在线链路的核心在于亚秒级的 P95 延迟控制与绝对可信的权限过滤

flowchart TD A["用户 Query 注入"] --> B["租户鉴权与权限过滤 (Pre-filtering)"] B --> C["多路并发召回 (BM25 + Dense Vector)"] C --> D["混合检索融合 (RRF)"] D --> E["二次重排 (Rerank)"] E --> F["上下文组装与 Prompt 注入"] F --> G["模型流式生成 (SSE)"]
  • 多租户权限硬隔离:必须走 Pre-filtering 而非 Post-filtering,原理和召回空洞问题第六章“标量过滤前置”一节已展开,这里不重复论证。落到 pgvector 上就是一行 SQL:利用 WHERE tenant_id = :tenant_id AND user_role IN (:roles) 结合向量距离索引,实现物理级安全隔离。
  • 多路召回融合与重排:通过 BM25(精确术语召回)与向量检索(高维语义召回)并行查询,采用倒数排序融合(Reciprocal Rank Fusion, RRF)合并两路结果,最后通过 Rerank 模型(如 Cohere / BGE-Rerank)进行相关度精细排序,仅截取最具相关性的 Top-N 块送入大模型,平衡 Token 成本与推理耗时。

3. 容量设计与瓶颈控制指标

高并发 RAG 系统的架构师必须实时监控以下三条系统级控制线: - 在途请求控制线

$\(\text{在途请求数 (Active Requests)} = \text{系统 QPS} \times \text{P95 端到端延迟}\)$

该指标直接决定了 API 网关的并发连接池大小、工作线程数以及模型服务商的并发槽位(TPM/RPM)预留额度。 - 检索扇出压力线

$\(\text{检索总调用量} = \text{系统 QPS} \times (\text{召回通道数} + \text{Rerank 批量数})\)$

在高并发下,双路召回与重排会产生级联的 I/O 扇出,必须为向量库和 Rerank 服务配置独立的并发限流与连接池隔离。 - 多级缓存加速与回源率

$\(\text{回源压力} = \text{原始请求量} \times (1 - \text{Cache Hit Ratio})\)$

系统应在 API 网关层部署 Query Cache(针对完全一致的提问直接返回缓存回答),在检索层部署 Embedding Cache(避免针对相同意图重复执行向量化计算),以实现极低延迟响应并平滑流量洪峰。


物理受控的智能助手与 Tool Calling 系统设计

在允许 AI 助手调用企业内部业务工具的场景中,系统的核心设计原则是:“模型提出建议,服务端执行控制”。必须在宿主系统底层架设防线,严防自然语言的越权注入与失控的物理 side effect。

1. 强类型工具契约与安全注册表(Tool Registry)

所有可供调用的工具必须在平台执行集中注册,声明强类型的输入输出 Schema,并定义严格的安全等级:

{
  "tool_name": "update_order_status",
  "description": "修改特定工单的流转状态",
  "input_schema": {
    "type": "object",
    "properties": {
      "ticket_id": {"type": "string"},
      "new_status": {"type": "string", "enum": ["assigned", "resolved"]}
    },
    "required": ["ticket_id", "new_status"]
  },
  "security_level": "HIGH_WRITE",
  "idempotent": true,
  "timeout_ms": 3000
}

2. 副作用控制与读写分离治理

  • 读写分流:对于只读类工具(如 query_inventory),平台执行快速并发通道;对于写副作用工具(如 cancel_subscription, transfer_funds),平台必须拦截执行,执行严格的安全机制。
  • 幂等性保障:写操作工具在 API 契约层必须强制要求携带 idempotency_key。即使大模型在受控循环中由于超时重试多次触发相同调用,服务端也必须保证该动作仅执行一次。
  • 人工审批中断(Human-in-the-Loop):对于 HIGH_WRITE 等高风险工具调用,Harness 必须挂起当前执行流,同步将状态写入 Redis Checkpoint,向客户端返回 PENDING_APPROVAL 中断信号。在管理员或用户显式点击确认后,平台反序列化恢复执行上下文,沿着图边缘继续推进。

流式长连接接口设计与底层资源回收

流式对话接口(Streaming API)的系统级难点在于:当网络中断或用户主动取消时,服务端如何确保全链路的异步资源回收,防止孤儿协程(Orphan Goroutines)与 token 盗刷拖垮系统。

1. 传输协议选择(SSE vs. WebSocket)

单向流式对话场景下 SSE 优于 WebSocket 的原因(穿透网关能力、断线重连、运维复杂度)第五章“执行组织”一节已经讲过,结论不变:单向流式对话首选 SSE,只有需要全双工通信(如高频双向音视频、协作白板)时才考虑 WebSocket。10 章要补的是取消传播这一层,也就是下面的 Go 实现。

2. 全链路取消信号传播与背压控制(Context Propagation)

在 Go 语言实现中,必须将 HTTP 请求的 r.Context() 显式传播至最底层的 LLM 客户端、向量库查询及数据库连接池。

func StreamHandler(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithCancel(r.Context())
    defer cancel()

    // 显式将 ctx 传递至底层 LLM 客户端
    stream, err := llmClient.CreateCompletionStream(ctx, req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    for {
        select {
        case <-ctx.Done():
            // 客户端主动断开连接,立即终止下游大模型流,避免 Token 持续消耗
            log.Printf("Client disconnected, releasing resources")
            return
        case chunk, ok := <-stream.Channel():
            if !ok {
                return
            }
            fmt.Fprintf(w, "data: %s\n\n", chunk.Text)
            w.(http.Flusher).Flush()
        }
    }
}
  • 孤儿协程控制:当用户在流式输出第 3 秒关闭浏览器时,r.Context().Done() 触发。若未在底层库传播该 context,底座的下游网络请求将继续生成至结束,导致系统并发资源(Goroutine, File Descriptor)被慢慢耗尽。

多租户 Agent 运行平台(Agent Platform)中台化架构

当企业从单一智能体演进为跨部门多业务场景的 Agent 服务集群时,必须将底座能力彻底中台化,形成统一的 Agent 运行时公共平台(Agent Platform Baselines)

1. 平台核心基础设施组件

中台该沉淀哪些能力(能力注册表、状态与 Checkpoint 服务、记忆治理中心、审计与风控平台)、以及落地顺序,第八章“Agent 平台中台化建设”已经完整展开,这里不重复列。系统设计题里落到 10 章的增量点是:这套中台在物理部署上通常对应 Redis Cluster + PostgreSQL 的状态存储、MCP 网关作为统一接入层,以及跨应用共享的一套 Trace/审计管线——即中台不是抽象概念,而是几个具体可复用的基础设施组件。

2. 系统持续改进与三层评测体系(Evaluation Registry)

为了确保系统的每一次优化(如 Prompt 变更、检索算法微调、依赖注入修改)都是客观且可量化的,平台必须内建三层评测机制: 1. 离线黄金数据集(Golden Evaluation Set):收集核心高频问题、边界测试用例、合规安全样本以及历史上发生过的典型坏例(Bad Cases)。在任何代码或 Prompt 上线前,自动化 CI/CD 流水线必须拉起 Grader 模型或规则引擎执行回归评测,确保核心指标(语义相关度、准确度、无幻觉率)不发生负向漂移。 2. 线上影子评测(Shadow Evaluation):将线上真实 Query 并发复制一份流向待发布版本,在后台执行静默计算,对比两代系统输出的分布差异,执行发布前的最后校验。 3. 闭环失败沉淀管线(Failure Compaction Pipeline):线上用户踩到的 Bad Cases(通过点踩、人工干预介入记录)必须由治理后台自动打标、清洗,并增量合并回离线黄金数据集,实现系统自我纠偏的工程闭环。

通用业务设计模式:状态、适配与并发正确性

系统设计题容易被拆成一串名词:状态机、Adapter、限流、事务。更好的理解方式是把它们放回业务链路:长流程需要知道自己走到哪里,多厂商输入需要先统一语义,热点写入需要守住资源不被重复扣减。

1. 异步长流程使用状态机

“下发安装任务”这类流程的成功不能定义为服务端收到请求,而应以设备完成安装并回执为准:

REQUESTED
→ DOWNLOADING
→ DOWNLOADED
→ VERIFYING
→ INSTALLING
→ INSTALLED / FAILED

每次迁移携带 task_id、版本、时间和幂等条件。事件回执推进正常路径,超时扫描接管卡住的任务,指数退避限制补偿流量。这样即使服务重启,也能从数据库中知道当前任务处于哪个状态,而不是重新猜测。监控覆盖端到端 P95、成功率、状态卡住率和补偿成功率。

2. 多厂商接入使用 Adapter 与 Canonical Schema

flowchart LR A[Vendor A API] --> AA[Adapter A] B[Vendor B API] --> AB[Adapter B] C[Vendor C API] --> AC[Adapter C] AA --> M[Canonical Model] AB --> M AC --> M M --> S[Domain Service]

Adapter 内部消化认证、字段映射、分页、重试和厂商错误,业务层只面对统一模型定义的主键、时间、枚举、来源、版本和去重规则。新增厂商时增加一个 Adapter,核心业务代码不需要遍历所有厂商的特殊字段。公网接入还要有 TLS、签名或 OAuth/mTLS、防重放、最小权限、限流、审计和脱敏。

3. 有长度和 QPS 限制的审核 API

内容先按标题、段落和句子切分,保留原文 Offset 与文档 ID;单段仍超限时再按长度拆分。调用侧使用令牌桶和有界并发,429、5xx 与超时按预算退避重试,参数和鉴权 4xx 直接失败。长期失败进入死信队列,结果按风险等级、命中位置和置信度聚合,并保留人工复核入口。

4. 热点资金操作的正确性

红包、库存和额度扣减都应使用最小货币单位的整数,并以事务或条件更新保证守恒:

检查幂等领取记录
→ 检查剩余数量和金额
→ 原子扣减
→ 写领取记录
→ 提交

随机分配算法只决定数值分布,不能提供并发正确性。高并发场景可以使用 Redis Lua 预扣减并异步落库,但仍需要数据库对账和故障补偿。

5. 匹配与分佣的多阶段决策

达人与商品匹配可以拆为“硬过滤 → 多路召回 → 排序 → 策略约束”:

类目/库存/地域/资格/预算硬过滤
→ 规则、行为、协同过滤、内容向量多路召回
→ 预期转化、受众匹配、履约和质量排序
→ 分佣上限、预算、防刷与结算规则约束

分佣属于激励机制,可以组合基础佣金、达标阶梯、预算上限与退款回冲。上线前通过历史回放验证,线上用小流量实验同时观察成交、ROI、投诉率、退货率、达人留存和佣金成本。纯向量相似度只能回答内容是否接近,无法处理库存、合规和成本约束。

系统设计面试怎么口头表达取舍

系统设计面试考的不是背下架构图,而是能不能把取舍说清楚。几句可以直接用的表达:这里我选 Pre-filtering 而不是 Post-filtering,是因为召回后再过滤会在高权限隔离场景下把 Top-K 结果几乎过滤空,宁可牺牲一点召回上限也要保证权限绝对不能越界。存储上我会先选 pgvector 把架构做简单,但会提前说清楚它的规模边界——数据量到千万级、并发/QPS较高时就要评估切换,因为按建图内存开销公式估算,千万级 1024 维向量的 HNSW 建图内存已要 60GB~100GB,继续往十亿级走会到 6TB~10TB 量级,单机已经扛不住,所以我会提前预留迁移到专用向量库的路径,而不是等出问题再重构。并发控制上我倾向于用 Go 的 context 把取消信号一路传到底,而不是加一层业务层超时判断,因为前者能顺带回收所有下游资源,后者只能治标。遇到不确定的边界条件,我会先说默认方案,再补一句“如果 QPS/数据量/一致性要求变了,我会换成什么”,这比一开始就给出唯一答案更能体现对取舍的掌控。