AI 应用 CI/CD 流水线设计:把模型、Prompt、代码当成同一个发布单元
2026-09-07 · 约 12 分钟阅读
---
title: "AI 应用 CI/CD 流水线设计:把模型、Prompt、代码当成同一个发布单元"
description: "AI应用CI/CD流水线实战:详解代码/Prompt/模型三元组的版本管理、自动化评测门禁、灰度发布与回滚。附GitHub Actions/GitLab CI完整yaml模板、LLM评测门禁脚本与回滚SOP,让AI应用的发布像传统软件一样可审计可回滚,适合DevOps工程师与全栈开发者,含中转站实测数据,附2026年最新API价格,含可直接复用的代码片段,覆盖中转站稳定性对比,是开发者必读的实战指南。"
date: "2026-09-07"
tags: ["CI/CD", "工程实践", "灰度发布", "DevOps"]
---
# AI 应用 CI/CD 流水线设计:把模型、Prompt、代码当成同一个发布单元
"周五下午把 Prompt 改了几个字,周一生产环境用户反馈就崩了,回滚的时候发现根本不知道上一个版本 Prompt 长什么样。"——这是 AI 应用迭代中最常听到的翻车故事。和传统软件相比,AI 应用的发布单元多了一层:Prompt 模板和模型选择也是"代码",也需要走流水线。本文讲清楚怎么把 AI 应用的代码、Prompt、模型配置统一纳入 CI/CD。
一、为什么 AI 应用必须做 CI/CD
传统软件升级,单元测试通过基本就稳了。AI 应用升级则要同时回答三个问题:
1. 代码改了:业务逻辑是否正确(传统测试)
2. Prompt 改了:输出质量是否退化(LLM 评测门禁)
3. 模型换了/参数改了:新模型在新业务上表现是否达标(回归对比)
三个维度任何一个失控都会让线上用户体验抖动。但现实是:多数团队的 Prompt 是某个工程师在 Notion 里随手改的,模型切换是群里一声通知——没有任何审计、回滚、灰度可言。本文要做的就是把这一整套流程工程化。
二、发布单元的三元组:代码、Prompt、模型
一个 AI 应用的"版本",本质上是下面三个东西的笛卡尔积:
```
release_v1.2.3 =
代码 commit: a1b2c3d (业务逻辑)
+ Prompt 模板: prompts/qa/v1.2.3.yaml (system + few-shot)
+ 模型配置: model: gpt-5.6-sol, temperature: 0.3, max_tokens: 1024
```
三者任意一个变化都视为一次发布,都需要:
- 一个唯一的版本号(推荐语义化版本 + Git SHA 后缀)
- 一份对应的评测报告(对比上一版在 LLM 评测集上的得分)
- 一个灰度比例(5% → 25% → 100% 的渐进式切换)
- 一个回滚预案(1 分钟内能切回上一版本)
三、CI 流水线:提交即评测
CI 的核心不是"build pass"就行,而是"这一版能不能在评测集上跑赢基线"。下面是 GitHub Actions 的一个示例:
```yaml
# .github/workflows/ai-cicd.yml
name: AI App CI/CD
on:
push:
branches: [main]
paths:
- 'src/**'
- 'prompts/**' # Prompt 改动也算"代码改动"
- 'config/model.yaml'
jobs:
llm-eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 拉取评测集
run: |
git clone --depth=1 https://github.com/your-org/llm-eval-golden-set.git eval_set
ls eval_set/
- name: 跑离线评测(对比上一版本)
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
python scripts/run_eval.py \
--prompts-dir prompts/ \
--model-config config/model.yaml \
--golden-set eval_set/ \
--baseline-version v1.2.2 \
--candidate-version v1.2.3 \
--output eval_report.json
- name: 质量门禁检查
run: |
python scripts/check_gate.py \
--report eval_report.json \
--min-pass-rate 0.95 \
--max-regression 0.02 \
--max-cost-increase 0.10
- name: 上传评测报告
uses: actions/upload-artifact@v4
with:
name: eval-report
path: eval_report.json
```
关键门禁指标:
| 指标 | 含义 | 推荐阈值 |
|---|---|---|
| Pass Rate | 通过率(评测集答对比例) | ≥ 95% |
| Regression Rate | 相对基线回退比例 | ≤ 2% |
| Cost Increase | 平均单次调用成本涨幅 | ≤ 10% |
| P99 Latency | 99 分位延迟 | ≤ 上版的 1.5 倍 |
任何一项不达标,CI 直接红,不允许合并。
四、CD 流水线:灰度发布 + 自动回滚
CD 不再是"kubectl apply"那么简单,因为 AI 应用的"灰度"涉及流量分配和路由切换:
```python
# deploy/canary.py
import random, time, requests
def route_traffic(user_id, canary_pct=5):
"""根据 user_id 哈希路由到稳定版或灰度版"""
bucket = hash(user_id) % 100
return "canary" if bucket < canary_pct else "stable"
def deploy_canary(version, stages=[5, 25, 50, 100], dwell_minutes=30):
for pct in stages:
print(f"[{version}] 切到 {pct}% 流量,观察 {dwell_minutes} 分钟...")
update_router(version, pct)
time.sleep(dwell_minutes * 60)
metrics = collect_metrics(version, window_min=30)
if not metrics["healthy"]:
print(f"[{version}] 指标异常,自动回滚")
update_router(version, 0)
rollback(version)
return False
print(f"[{version}] 全量上线")
return True
def rollback(version):
"""一键回滚到上一个版本"""
prev = get_previous_version()
update_router_active_version(prev)
print(f"已回滚到 {prev}")
```
灰度阶段建议每阶段至少观察 30 分钟,并关注以下信号:
- 业务指标:转化率、人均对话轮次、付费率
- 质量指标:点赞/点踩率、客诉工单数
- 系统指标:P50/P99 延迟、错误率、Token 总消耗
任何一项偏离基线超过阈值,自动触发回滚。
五、Prompt 的版本管理:别再用 Notion 了
Prompt 是 AI 应用最容易被忽视的"代码",但它的改动频率可能比业务代码还高。推荐用 Git 管理 Prompt:
```
prompts/
├── qa/
│ ├── v1.2.2.yaml # 上一个版本
│ └── v1.2.3.yaml # 当前版本(带 changelog)
├── summarizer/
│ └── v2.0.1.yaml
└── _changelog.md # 记录每个版本的改动原因和评测结论
```
一个 Prompt 文件建议结构化存储(YAML 而非纯文本):
```yaml
version: v1.2.3
model: gpt-5.6-sol
temperature: 0.3
max_tokens: 1024
system: |
你是专业的客服助手,遵循以下规则:
1. 回答必须基于已知信息,禁止编造
2. 不确定时回复"我帮你转人工"
3. 语气友好,简明扼要
few_shots:
- user: "我的订单还没到"
assistant: "请提供订单号,我帮你查询物流状态。"
changelog: "调整第2条规则,从'转人工'改为'转人工客服'"
```
好处:
- 可 diff:每次改动都有 PR 记录,谁改的、改了什么都清楚
- 可回滚:出问题时一行命令回到上一个版本
- 可评测:CI 直接拉对应版本的 Prompt 文件跑离线评测
六、模型切换的灰度策略
从 GPT-5.6 切到 Claude Opus 5(或反之)属于重大变更,建议双跑对比期:
```python
# 双跑:新旧模型并行调用,对比输出
def dual_inference(prompt, user_id):
if is_canary_user(user_id):
# 新模型
response_new = call_model("claude-opus-5", prompt)
# 同时跑旧模型(不返回用户,仅对比)
response_old = call_model("gpt-5.6-sol", prompt)
log_comparison(user_id, prompt, response_new, response_old)
return response_new
else:
return call_model("gpt-5.6-sol", prompt)
```
积累 1-2 周的真实流量数据后,再决定是否全量切换。
七、推荐工具链
| 环节 | 推荐工具 |
|---|---|
| CI 引擎 | GitHub Actions / GitLab CI / Jenkins |
| LLM 评测 | Promptfoo / DeepEval / 自研脚本 |
| Prompt 版本管理 | Git + DVC(大数据集场景) |
| 灰度路由 | 自建(用户ID哈希)+ Istio(服务网格场景) |
| 监控告警 | Prometheus + Grafana + Langfuse |
| 模型切换双跑 | OpenRouter/AI 中转站的"模型别名"功能 |
八、常见反模式
- ❌ Prompt 直接在代码里硬编码:无法独立版本管理
- ❌ CI 只跑传统单测,不跑 LLM 评测:Prompt/模型改动直接绕过质量门禁
- ❌ 灰度发布没有自动回滚机制:出问题靠人肉干预
- ❌ 模型切换一把梭:不做双跑对比,等用户反馈再补救已经晚了
九、总结
AI 应用的 CI/CD 不是"把传统流水线搬过来",而是把 代码 + Prompt + 模型 当成同一个发布单元,走"离线评测门禁 + 灰度发布 + 自动回滚"的标准流程。短期看是增加了一些工程成本,长期看是让 AI 应用的迭代从"靠人肉谨慎"变成"靠系统保障"。
想了解更细的灰度策略,可以看 [AI 应用版本管理与灰度发布最佳实践](/blog/ai-api-version-management-canary-release-guide);想了解 LLM 评测集怎么搭,可以看 [AI 应用 A/B 测试与效果评估框架](/blog/ai-application-ab-testing-evaluation-framework-guide-2026)。要选用稳定的中转 API 来跑评测流水线,可以去 [openairouter.net](https://openairouter.net) 比较各家平台的延迟和价格。