1. 为什么“能跑起来的 AI Demo”和“能上生产的 AI 平台”是两回事
我见过太多团队在 AI 落地这件事上栽跟头。演示阶段一切顺利:本地起个 Python 脚本,调一下大模型接口,前端套个对话框,领导看完点头,项目立项。然后真正要接入业务系统的时候,问题全冒出来了——模型调用散落在各个业务代码里没人管、会话状态存在内存里一重启就丢、多个 AI 能力之间互相调用没有统一协议、权限和审计完全空白、并发一上来接口就开始超时。最后这个“AI 项目”变成了一个谁都不敢碰的黑盒。
这个开源项目的定位就是冲着这个断层去的:面向生产环境的原生 AI 微服务快速开发平台。注意三个关键词——“生产环境”“原生 AI”“微服务”。它不是又一个 AI 套壳工具,也不是把 AI 能力硬塞进传统 CRUD 框架里,而是从架构层面就把 AI 当成一等公民来设计。技术栈上它选了 JDK 21 + Spring Cloud + Vue 3 这套组合,这个选择本身就透露了很多信息,后面我会展开讲。
这篇文章适合谁看?如果你正在做企业级 AI 应用的架构选型,或者你手上有一个 AI 功能要接入现有的微服务体系,又或者你单纯想搞清楚“AI 微服务”到底该怎么拆、怎么管、怎么保证稳定,那这篇内容应该能帮你少走几个月弯路。我会从架构设计、技术选型理由、AI 能力的服务化封装、生产环境的稳定性保障、以及实际落地时的踩坑经验几个维度,把这个平台的设计思路和实操要点讲透。
需要先说明一点:项目正文和关键词给的信息比较有限,所以下面涉及具体实现的部分,我会基于“一个合格的后端架构师在做这类平台时最可能采用的方案”来补充,并明确标注哪些是通用实践、哪些是需要你根据自己项目调整的地方。这样你拿到的不只是一篇介绍,而是一套可以对照落地的思路。
2. 拆解这个平台的核心架构分层与 AI 原生设计
2.1 什么叫“AI 原生”,和“AI 外挂”的本质区别
先把概念理清楚。“AI 外挂”指的是你有一套成熟的业务微服务,然后单独搞一个 AI 服务,业务系统通过 HTTP 调它,AI 服务内部再调大模型。这种模式的问题是:AI 能力是孤岛,它不知道业务上下文,业务系统也不理解 AI 的调用特征(比如长耗时、流式返回、Token 计费)。
“AI 原生”的意思是,AI 相关的关注点被下沉到平台层统一解决。具体体现在几个地方:
- 统一的模型网关层:所有对大模型的调用都经过这一层,负责路由、限流、重试、降级、计费统计、Prompt 模板管理。业务代码里不应该出现任何模型厂商的 SDK 调用。
- 会话与上下文管理作为基础设施:多轮对话的状态、上下文窗口的裁剪策略、历史消息的存储,这些是平台能力,不是每个业务自己实现。
- AI 能力的服务注册与发现:一个“文档摘要”能力、一个“意图识别”能力,都应该像普通微服务一样注册到注册中心,能被其他服务发现和编排。
- 流式响应的一等支持:大模型输出天然是流式的,平台的网关、服务间通信、前端对接都要原生支持 SSE 或 WebSocket,而不是等模型全部生成完再返回。
这个平台把这四件事都做进了底座,所以叫“应用底座”而不是“开发框架”。框架是你按它的规矩写代码,底座是你在这上面搭业务,脏活累活它替你干了。
2.2 分层结构:从接入到模型的全链路
一个生产级的 AI 微服务平台,我理解应该分成这么几层,从下往上说:
基础设施层:注册中心(Nacos 或 Consul)、配置中心、网关(Spring Cloud Gateway)、链路追踪、日志聚合。这部分和传统微服务没区别,但要注意 AI 场景下日志量会大很多,尤其是 Prompt 和响应内容的记录,需要单独设计脱敏和采样策略。
模型接入层:这是 AI 原生的核心。它要屏蔽不同模型提供方的差异——有的走 HTTP、有的走 SDK、有的支持 Function Calling、有的支持多模态。这一层对外暴露统一的接口契约,内部做协议适配。同时它还要管住成本:Token 用量统计、按租户/按应用的配额、超限降级到小模型或直接拒绝。
AI 能力服务层:把原子化的 AI 能力封装成独立微服务。比如 RAG 检索服务、向量化服务、Agent 编排服务、Prompt 管理服务。每个服务职责单一,可以独立扩缩容。这里有个关键设计——能力服务不直接持有模型连接,而是通过模型接入层调用,这样模型切换、灰度、A/B 测试都在一层完成。
业务编排层:面向具体业务场景的组合。比如“智能客服”这个场景,可能需要先调意图识别,再调知识库检索,再调大模型生成,最后调敏感词过滤。这一层用工作流引擎或者编排 DSL 来描述,而不是硬编码。
接入层:对外的 API 网关和 BFF(Backend for Frontend)。前端 Vue 3 应用通过 BFF 拿数据,BFF 负责聚合多个微服务的返回、处理流式转发、做前端需要的裁剪。
这个分层的好处是每一层可以独立演进。模型厂商换了,只动模型接入层;业务场景变了,只动编排层;前端改版,只动 BFF。
2.3 为什么是 JDK 21 而不是 JDK 17 或 8
技术选型里 JDK 21 这个点值得单独说。JDK 21 是 LTS 版本,相比 JDK 17 最大的生产价值在于**虚拟线程(Virtual Threads)**正式转正。
AI 应用的调用特征是什么?大量时间在等 IO——等模型返回、等向量库查询、等外部工具调用。传统平台线程模型下,一个请求占一个线程,线程池就那么大,并发一高就排队。虚拟线程让“一个请求一个线程”的编程模型可以支撑极高的并发,因为阻塞时底层载体线程会被释放。
实测数据上,在 IO 密集型的 AI 网关场景,虚拟线程相比传统线程池,在相同硬件下吞吐量能提升数倍,而且代码不用改成响应式那套复杂的链式写法。对于团队里大部分是写同步代码的工程师来说,这个收益非常实在。
当然有坑:虚拟线程不适合 CPU 密集型任务,也不要在虚拟线程里用 synchronized 做长时间持锁(会 pin 住载体线程)。平台里如果用了本地缓存或者某些老库,需要检查这些点。JDK 21 还带来了分代 ZGC,对 AI 场景下大对象多、内存压力大的情况,停顿时间控制得更好。
2.4 Spring Cloud 在这个平台里承担什么角色
Spring Cloud 这套东西在 AI 平台里不是过时了,而是角色变了。它不再负责业务逻辑,而是负责服务治理的骨架:
- 服务注册发现:AI 能力服务注册上来,编排层才能发现它们。
- 配置中心:Prompt 模板、模型参数、限流阈值这些都应该动态可配,改完不用重启。
- 网关:统一入口,做鉴权、限流、路由、流式转发。
- 熔断降级:模型服务不稳定时,快速失败而不是拖垮整个链路。
- 分布式事务:AI 场景下事务需求相对少,但涉及计费、配额扣减时还是需要。
选型上,Nacos 做注册和配置是当前国内团队最顺手的选择,社区活跃、文档全、和 Spring Cloud Alibaba 集成成熟。Sentinel 做流控降级,配合 Redis 集群做集群限流的数据源,这个组合在高并发场景下经过验证。至于 Spring Cloud Alibaba 某些组件停更的传闻,实际影响的是特定组件的特定功能,核心的 Nacos、Sentinel 依然在维护,选型时关注具体组件版本即可,不必因噎废食。
3. AI 能力怎么拆成微服务:粒度、边界与通信
3.1 拆分粒度:拆太细是灾难,拆太粗是单体
微服务拆分最怕两种极端。拆太细,一个 AI 请求要跨七八个服务,网络开销和故障点成倍增加;拆太粗,又退化成单体,失去了独立扩缩容的意义。
我的经验是,AI 能力服务按资源特征和扩缩容需求来拆,而不是按业务功能拆。举几个例子:
- 向量化服务:CPU/GPU 密集,需要独立扩缩容,单独拆。
- 向量检索服务:内存密集,向量库连接是稀缺资源,单独拆。
- 大模型调用网关:IO 密集,需要统一管控,单独拆。
- Prompt 管理服务:读多写少,可以和其他轻量服务合并。
- Agent 编排服务:CPU 中等,但逻辑复杂,单独拆便于迭代。
判断标准很简单:如果两个能力的资源画像差异大,或者扩缩容节奏不同,就拆开;否则合并。不要为了微服务而微服务。
3.2 服务间通信:同步、异步、流式三套机制
AI 场景下的通信比传统 CRUD 复杂,因为存在流式返回。平台需要同时支持三种模式:
同步请求-响应:适合意图识别、分类、短文本处理这类快速返回的能力。用 OpenFeign 或 Dubbo 都行,Feign 更简单,Dubbo 性能更好。AI 场景下我倾向 Feign,因为调用链清晰、和 Spring Cloud 生态无缝。
异步消息:适合文档批量向量化、长任务处理。用 RocketMQ 或 Kafka,把任务丢进队列,消费者慢慢处理,处理完回调或写状态。这样前端不用干等,用户体验好,服务端也不会被长任务拖垮。
流式传输:大模型生成必须用流式。服务间通信用 SSE 或者 gRPC streaming,网关到前端用 SSE 或 WebSocket。这里有个细节——流式链路上任何一环做了缓冲,用户就会感觉到卡顿。网关要配置不缓冲,Nginx 要关掉 proxy_buffering,服务端要 flush。这些配置漏一个,流式就变成了“等半天然后一次性出来”。
3.3 统一接口契约:让 AI 能力可编排的前提
如果每个 AI 服务的接口长得都不一样,编排层就没法通用化。平台需要定义一套统一的 AI 能力接口契约,我建议至少包含这些字段:
| 字段 | 说明 | 是否必填 |
|---|---|---|
| capabilityId | 能力唯一标识 | 是 |
| inputs | 输入参数,结构化 | 是 |
| context | 会话上下文,含历史消息 | 否 |
| options | 模型选择、温度、最大 Token 等 | 否 |
| stream | 是否流式返回 | 否 |
| callbackUrl | 异步回调地址 | 否 |
| traceId | 链路追踪 ID | 是 |
输出侧统一包含:结果内容、Token 用量、耗时、模型标识、是否被截断、错误码。有了这套契约,编排层才能像搭积木一样组合能力,监控系统才能统一采集指标,计费系统才能统一扣减。
3.4 一个具体的拆分案例:智能问答场景
假设要做企业知识库智能问答,按这个平台的设计,链路是这样的:
- 前端发起问题,BFF 接收,生成 traceId。
- BFF 调编排服务,编排服务按预定义工作流执行。
- 第一步调意图识别服务,判断是知识问答还是闲聊还是转人工。
- 如果是知识问答,调向量化服务把问题转向量。
- 调向量检索服务,从知识库召回相关片段。
- 调 Prompt 管理服务,拿到问答模板,填充召回内容。
- 调模型网关,流式生成回答。
- 流式结果经过敏感词过滤服务(也是流式处理)。
- 通过 BFF 的 SSE 通道推给前端。
每一步都是独立服务,可以独立扩容。向量检索慢了就加检索服务实例,模型网关压力大就加网关实例。这种灵活性是单体架构给不了的。
4. 生产环境的稳定性:AI 平台最容易翻车的地方
4.1 模型调用的超时、重试与降级策略
模型调用是整条链路里最不可控的一环。第三方模型服务可能抖动、可能限流、可能返回慢。如果不在平台层统一处理,每个业务自己写重试逻辑,结果就是重试风暴把模型服务彻底打挂。
平台层的策略应该是:
- 超时分级:连接超时设短(比如 3 秒),读超时按场景设(流式场景要长,比如 60 秒;非流式 30 秒)。超时时间要可配置,不同模型不同。
- 重试要克制:只对幂等且明确可重试的错误重试(如 429、503),重试次数不超过 2 次,且必须带退避(指数退避 + 抖动)。流式请求一旦开始返回就不能重试。
- 降级有预案:主模型不可用时,降级到备用模型;备用也不可用时,返回缓存结果或友好提示,而不是让请求一直挂着。
- 熔断保护:用 Sentinel 对模型调用做熔断,错误率超过阈值直接快速失败,给模型服务恢复的时间。
这里有个容易忽略的点:重试和熔断的阈值要联动。如果熔断已经打开了,重试就没意义,应该直接走降级。平台里要把这两个逻辑串起来。
4.2 流式响应的稳定性:断线、续传与背压
流式响应在生产环境会遇到几个典型问题:
连接中断:用户网络抖动,SSE 连接断了。平台需要支持断点续传——记录已生成的 Token 位置,重连后从断点继续。这要求会话状态持久化,不能只存在内存。
背压:模型生成速度快于前端消费速度,数据在网关堆积。需要做背压控制,前端消费慢时通知上游减速,或者丢弃非关键内容。
多实例下的会话粘性:如果会话状态在服务实例内存里,用户重连到另一个实例就丢了上下文。解决方案是把会话状态外置到 Redis,任何实例都能接管。
流式链路的监控:普通请求看响应时间,流式请求要看首 Token 延迟(TTFT)和 Token 生成速率(TPOT)。这两个指标直接决定用户体验,必须单独监控和告警。
4.3 限流与配额:防止一个租户拖垮所有人
多租户场景下,限流必须做到租户级。一个租户疯狂调用,不能影响其他租户。平台需要:
- 网关层限流:按租户、按接口、按 IP 多维度限流。
- 模型层配额:按租户分配 Token 配额,用完降级或拒绝。
- 并发控制:限制单租户的同时在线请求数。
Sentinel 配合 Redis 集群做集群限流是成熟方案。Redis 存计数器和令牌桶状态,Sentinel 做规则判断。要注意 Redis 本身的高可用,限流组件挂了不能影响主链路,要有本地兜底限流。
4.4 可观测性:AI 链路的追踪比普通微服务难在哪
普通微服务的链路追踪,Span 里记录的是方法调用和耗时。AI 链路的 Span 里还要记录:用了哪个模型、消耗多少 Token、Prompt 模板版本、召回文档 ID、是否命中缓存。这些信息对排查问题和成本分析至关重要。
难点在于内容脱敏。Prompt 和响应里可能包含用户隐私或商业敏感信息,不能明文记日志。平台需要做脱敏处理,或者只记录元数据不记录内容,需要内容时通过采样和授权机制获取。
另外,AI 链路的耗时分布和普通服务完全不同。一个请求 90% 时间花在模型生成上,如果只看总耗时,优化方向会跑偏。必须把模型调用、检索、后处理各阶段拆开监控。
5. 前后端协作与 Vue 3 在 AI 场景下的特殊处理
5.1 前端对接流式接口的正确姿势
Vue 3 对接 SSE 或 WebSocket,很多人第一反应是用 EventSource。但 EventSource 有个硬伤——只支持 GET 请求,不能带自定义 Header。而 AI 接口通常需要传 Authorization、租户 ID 等 Header。
实际项目里更常用的是fetch+ReadableStream手动解析 SSE,或者用@microsoft/fetch-event-source这类库。核心逻辑是:发起 fetch 请求,拿到 response.body 的 reader,循环读取 chunk,按 SSE 格式解析出 data 行,更新到响应式状态。
Vue 3 的响应式系统在这里很顺手——把流式内容绑定到一个 ref,每收到一个 chunk 就更新,界面自动刷新。但要注意更新频率,如果每个 Token 都触发一次渲染,高频输出时会有性能问题。实践中会做节流,比如每 50ms 或每积累一定字符数才更新一次视图。
5.2 会话状态管理:Pinia 还是后端
多轮对话的状态放哪?放前端 Pinia 里,刷新页面就丢;放后端,每次请求都要传上下文,网络开销大。我的建议是混合方案:后端存完整会话历史(持久化到数据库或 Redis),前端只存当前会话的最近几轮,用于快速渲染。新请求时前端把会话 ID 传给后端,后端自己取历史,前端不用每次传全量上下文。
这样既保证了刷新不丢,又减少了传输量。Vue 3 的 Pinia 管理前端会话列表和当前会话,后端通过会话 ID 关联。
5.3 大文本渲染的性能优化
AI 生成的回答可能很长,几千字甚至上万字。如果直接 v-html 渲染,长文本会导致页面卡顿。优化手段包括:
- 虚拟滚动:只渲染可视区域的内容,长对话列表必备。
- Markdown 增量渲染:流式输出时,不要每来一个字符就重新解析整个 Markdown,而是增量解析。
- 代码块高亮延迟:流式过程中代码块可能不完整,等流结束再高亮,避免反复重排。
- 图片懒加载:如果回答里有多模态内容,图片要懒加载。
这些细节不做,功能是能跑,但用户体验会很差,尤其是长回答场景。
6. 落地实操:从零搭建一个 AI 能力服务的完整步骤
6.1 环境准备与依赖版本锁定
先把基础环境列清楚,版本不一致是新手最容易踩的坑:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 21 LTS | 虚拟线程、分代 ZGC |
| Spring Boot | 3.2.x | 支持 JDK 21 |
| Spring Cloud | 2023.0.x | 对应 Boot 3.2 |
| Spring Cloud Alibaba | 2023.0.x.x | Nacos、Sentinel |
| Nacos | 2.3.x | 注册配置中心 |
| Redis | 7.x | 会话、限流、缓存 |
| MySQL | 8.x | 业务数据 |
| Node.js | 20 LTS | 前端构建 |
| Vue | 3.4.x | 前端框架 |
版本锁定用 Maven 的 dependencyManagement 或者 Gradle 的 platform,避免传递依赖冲突。Spring Cloud 和 Boot 的版本对应关系一定要查官方兼容表,差一个小版本都可能启动报错。
6.2 搭建模型网关服务的核心代码结构
模型网关是平台的心脏,代码结构建议这样组织:
model-gateway/ ├── adapter/ # 各模型厂商适配器 │ ├── OpenAiAdapter │ ├── QwenAdapter │ └── ... ├── router/ # 模型路由策略 ├── limiter/ # 限流配额 ├── metrics/ # Token 统计与监控 ├── fallback/ # 降级策略 └── controller/ # 对外统一接口适配器层用策略模式,每个厂商实现统一接口。路由层根据租户配置、模型健康度、成本策略选择具体模型。这样新增一个模型厂商只需要加一个适配器,不改其他代码。
关键接口定义大致长这样:
public interface ModelAdapter { ModelResponse invoke(ModelRequest request); Flux<ModelChunk> invokeStream(ModelRequest request); boolean healthCheck(); String getModelId(); }流式返回用 Reactor 的 Flux,配合 Spring WebFlux 或者 Spring MVC 的 StreamingResponseBody。如果用虚拟线程,同步写法也能支撑高并发,看团队熟悉度选。
6.3 会话服务的存储设计
会话数据分两部分:会话元数据(会话 ID、用户、创建时间、最后活跃时间)和消息列表(角色、内容、时间戳、Token 数)。
存储选型上,元数据放 MySQL,消息列表放 Redis(List 或 Stream 结构),冷数据定期归档到 MySQL 或对象存储。Redis 里按会话 ID 做 key,设置过期时间,活跃会话续期。
要注意上下文窗口裁剪。模型有最大 Token 限制,历史消息不能无限传。策略有几种:保留最近 N 轮、按 Token 数从旧到新裁剪、用摘要压缩早期对话。平台应该把裁剪策略做成可配置,不同场景用不同策略。
6.4 前端工程的目录组织与流式 Hook 封装
Vue 3 项目里,把流式请求封装成 composable 是很好的实践:
// composables/useStreamChat.js import { ref } from 'vue' export function useStreamChat() { const content = ref('') const loading = ref(false) const error = ref(null) async function send(payload) { loading.value = true content.value = '' try { const response = await fetch('/api/chat/stream', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) const reader = response.body.getReader() const decoder = new TextDecoder() let buffer = '' while (true) { const { done, value } = await reader.read() if (done) break buffer += decoder.decode(value, { stream: true }) const lines = buffer.split('\n\n') buffer = lines.pop() for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6) if (data === '[DONE]') return content.value += JSON.parse(data).delta } } } } catch (e) { error.value = e } finally { loading.value = false } } return { content, loading, error, send } }这个 Hook 处理了缓冲、分片、结束标记,业务组件里直接const { content, send } = useStreamChat()就能用。注意 buffer 的处理——网络分片不一定按 SSE 消息边界切,必须自己缓冲拼接。
7. 踩过的坑与经验教训
7.1 虚拟线程不是银弹:这些场景反而更慢
虚拟线程在 IO 密集场景确实强,但有几个坑我实际踩过:
synchronized 导致的 pinning:虚拟线程在 synchronized 块里阻塞时,会占住载体线程,失去虚拟线程的优势。如果代码里有老库用 synchronized 做锁,或者自己写了 synchronized 的缓存,需要换成 ReentrantLock。JDK 21 里可以用-Djdk.tracePinnedThreads=full来检测 pinning。
ThreadLocal 的滥用:虚拟线程数量可能非常多,每个都带 ThreadLocal 副本会吃内存。AI 场景下如果用了 ThreadLocal 存上下文,要评估内存影响,或者改用 ScopedValue(JDK 21 预览特性)。
CPU 密集任务:向量计算、文本处理这类 CPU 密集操作放虚拟线程里没收益,反而增加调度开销。这类任务应该用固定大小的平台线程池。
7.2 流式接口在网关被缓冲:一个配置漏了全白干
这个坑我印象最深。本地测试流式好好的,一上生产就变成“等 30 秒然后一次性出来”。排查了半天,发现是 Nginx 的proxy_buffering默认开着,把 SSE 数据缓冲了。解决要改三处:
- Nginx:
proxy_buffering off;和proxy_cache off; - Spring Cloud Gateway:确认没有配置响应体缓存
- 应用层:每次 write 后 flush
任何一环缓冲,流式体验就没了。上线前一定要在真实网关链路上测流式,不能只测本地。
7.3 Token 计费的坑:流式请求的用量怎么算
非流式请求,模型返回里直接带 usage 字段,好算。流式请求,很多模型在最后一个 chunk 才返回 usage,如果连接提前断了,这次调用的 Token 就统计不到。平台需要做兜底估算——按输入文本长度和输出字符数估算 Token,和实际值对账。
另外要注意缓存命中的计费差异。很多模型对命中缓存的 Prompt 部分收费更低,平台要能识别并分别统计,否则成本核算会偏高。
7.4 多模型切换时的 Prompt 兼容性
不同模型对 Prompt 格式的敏感度不同。同一个 Prompt 在 A 模型上效果好,换到 B 模型可能完全跑偏。平台做模型路由时,不能简单地把同一个 Prompt 发给不同模型,需要按模型维护 Prompt 模板变体。
实践中,Prompt 管理服务要支持模板继承——基础模板定义通用部分,各模型变体覆盖差异部分。切换模型时自动选择对应变体,而不是硬套。
8. 这套底座适合什么样的团队,以及后续怎么扩展
8.1 团队规模与阶段匹配
这套平台不是所有团队都需要。我的判断标准:
- 10 人以下、单一 AI 场景:别上微服务,一个单体应用加个模型调用封装就够了,微服务的运维成本会压垮你。
- 10-50 人、多个 AI 场景:这套底座的价值开始显现,统一模型网关和会话管理能省大量重复工作。
- 50 人以上、AI 是核心业务:必须上,而且要在此基础上做更细的治理,比如按业务线隔离、精细化成本核算。
技术选型上,如果团队 Java 背景强,JDK 21 + Spring Cloud 是顺理成章。如果团队 Python 背景强,可以考虑 Python 服务通过标准协议融入这套微体系,注册到同一个 Nacos,走同一套网关。混合技术栈在 AI 场景很常见,关键是协议统一。
8.2 可以继续扩展的方向
这套底座搭好之后,往上可以长很多东西:
- Agent 编排引擎:把工作流从硬编码升级为可视化编排,支持条件分支、循环、人工介入。
- RAG 增强:接入更多检索策略(混合检索、重排序),支持知识库版本管理和灰度。
- 评测体系:建一套自动化评测,每次 Prompt 或模型变更都跑回归,防止效果退化。
- 成本看板:按租户、按应用、按模型维度展示 Token 消耗和费用,让成本可见可控。
- 多模态支持:图片、音频、视频的输入输出,统一到能力契约里。
我个人在实际搭建这类平台时的体会是,最难的不是技术,是克制。一开始总想什么能力都做进去,结果平台越来越重,业务接入成本越来越高。后来想明白了,底座只做三件事:统一模型接入、统一会话管理、统一治理策略。其他都交给业务自己组合。底座越薄,活得越久。
最后分享一个实用技巧:平台上线初期,一定要做一个影子模式。新模型、新 Prompt 先在影子链路跑,不影响真实用户,对比效果和成本,确认没问题再切流。这个机制能帮你避免很多线上事故,尤其是在模型频繁迭代的阶段。