Day 4|AI应用架构设计:从单体Chat到多模型协同系统
上周和一个做 SaaS 的朋友聊天,他说他们团队花了两周把 GPT-4 接进产品,上线第一个月用户反馈炸裂。第二个月开始,问题来了——高峰期 API 调用延迟飙到 8 秒,单月 API 账单六位数,某个第三方模型凌晨挂掉直接让核心功能瘫痪。他苦笑着说:”Chat wrapper 好写,生产级系统难搞。”
这就是今天要聊的主题:AI 应用的架构设计。从一个人、一个 Chat 包装器就能跑的 demo,到一个能扛流量、控成本、有容错的 production 系统,中间差了哪些东西?
第一阶段:单体 Chat 包装器
大多数团队起步都很像:Flask/FastAPI 起一个服务,调一次 OpenAI API,返回结果完事。
from openai import OpenAIfrom fastapi import FastAPIapp = FastAPI()client = OpenAI()@app.post("/chat")asyncdefchat(prompt: str): resp = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": prompt}] )return {"reply": resp.choices[0].message.content}
简单、直观、能用。但这个架构有三个致命缺陷:
-
单点故障:GPT-4 挂了,你的服务就挂了 -
成本失控:所有流量都走最贵的模型 -
性能不可控:没有缓存,同样的问题反复调用 API
第二阶段:模型路由与负载均衡
第一步改进是引入 Model Router。不同请求走不同模型,而不是把所有鸡蛋放在一个篮子里。
from openai import OpenAIimport jsonclassModelRouter:def__init__(self):self.clients = {"gpt4": OpenAI(),"gpt4o_mini": OpenAI(),"claude": OpenAI(base_url="...") # 假设的 Anthropic 端点 }self.rules = [ ("简单问答", self._is_simple_qa, "gpt4o_mini"), ("代码生成", self._is_code_gen, "gpt4"), ("文档分析", self._is_doc_analysis, "claude"), ]defroute(self, prompt: str) -> tuple:for name, detector, model inself.rules:if detector(prompt):return model, self.clients[model]return"gpt4o_mini", self.clients["gpt4o_mini"]def_is_simple_qa(self, prompt: str) -> bool:returnlen(prompt) < 100# 简化的启发式规则
核心思路:小模型干小活,大模型干大活。简单问候、FAQ 类请求走 gpt-4o-mini,成本降到 1/30;复杂推理、代码生成再升舱到 GPT-4 或 Claude。
配合 fallback 机制——主模型返回 429 或 5xx 时,自动降级到次优模型:
asyncdefchat_with_fallback(router, prompt: str, max_retries=2): errors = []for attempt inrange(max_retries + 1):try: model, client = router.route(prompt) resp = client.chat.completions.create( model=model, messages=[{"role": "user", "content": prompt}], timeout=15 )return resp.choices[0].message.contentexcept Exception as e: errors.append(f"{model}: {str(e)}")# 降级策略:下次尝试不同的模型 router.demote(model)raise Exception(f"All models failed: {errors}")
第三阶段:语义缓存——降本提速
你有没有想过,同一个问题被不同用户问了 100 遍,你付了 100 次 API 费用?语义缓存就是解决这个问题的。
普通的 key-value 缓存要求精确匹配,但用户的自然语言表述千变万化。”怎么注册?”和”注册流程是什么?”语义相同,但文本不同。语义缓存用 embedding 做检索,命中语义相近的历史结果就直接返回。
import numpy as npfrom openai import OpenAIclassSemanticCache:def__init__(self, threshold=0.92):self.client = OpenAI()self.cache = [] # [(embedding, response), ...]self.threshold = thresholddef_embed(self, text: str) -> list: resp = self.client.embeddings.create( model="text-embedding-3-small", input=text )return resp.data[0].embeddingdef_cosine_sim(self, a, b) -> float: a, b = np.array(a), np.array(b)return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))defget(self, query: str): q_emb = self._embed(query)for emb, resp inself.cache:ifself._cosine_sim(q_emb, emb) >= self.threshold:return respreturnNonedefset(self, query: str, response: str):self.cache.append((self._embed(query), response))
实测数据:在常见的客服场景中,语义缓存能命中 30%~50% 的请求,延迟从 2~3 秒降到 50ms 以下,API 账单直接腰斩。
第四阶段:多模型协同——小模型预筛选 + 大模型精修
这是目前生产级 AI 系统最流行的范式:两条流水线协作。
用户请求 → 小模型预筛选 → 结果分类 / 路由决策 → 大模型精修 → 最终输出 ↕ 语义缓存
小模型(如 GPT-4o-mini、Llama-3.1-8B)负责快速判断:这个请求是啥类型?需要调用工具吗?命中缓存了吗?大模型只在需要深度推理时才上场。
一个实际案例:某 AI 客服系统,每天 100 万请求。架构如下:
-
Layer 1(路由层):GPT-4o-mini + 语义缓存,处理 70% 的普通问答,P50 延迟 200ms -
Layer 2(推理层):GPT-4o,处理 25% 的复杂查询(多轮对话、情感分析),P50 延迟 1.5s -
Layer 3(深度推理层):Claude Opus 或 o1,处理 5% 的高难度请求(合同审查、代码审计),P50 延迟 5~10s
结果:综合成本降低了 60%,同时核心用户体验没有降级。
流式响应的工程实现
最后提一个常被忽视的工程细节:流式响应(Streaming)。用户对”一个字一个字往外蹦”的体验预期已经形成了标准,如果响应是整段返回的,用户会觉得”卡”。
from fastapi.responses import StreamingResponsefrom openai import OpenAIclient = OpenAI()asyncdefstream_chat(prompt: str): stream = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], stream=True, )for chunk in stream: delta = chunk.choices[0].delta.contentif delta:yieldf"data: {delta}\n\n"@app.get("/chat/stream")asyncdefchat_stream(prompt: str):return StreamingResponse( stream_chat(prompt), media_type="text/event-stream" )
注意:加上缓存的时候,如果命中缓存,需要模拟流式输出(把完整句子切成小段返回),前端才能统一处理 text/event-stream 协议。不然你缓存命中的时候会”静默”——前端等半天没收到流。
总结
今天我们从四个层面拆解了 AI 应用的架构演进:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
明天(Day 5)我们将进入 RAG 的世界——让大模型拥有真正的”长期记忆”,不再受限于上下文窗口。敬请期待。
系列回顾
[第1篇] 大模型应用开发全景:从入门到实战路线图 [第2篇] 提示词工程(上):Prompt设计核心原则与实战技巧 [第3篇] 提示词工程(下):Chain-of-Thought、Few-shot与高级技巧 ← 你在这里 [第5篇] RAG从原理到实战:让大模型拥有「长期记忆」
夜雨聆风