CI/CD工程实践灰度发布DevOps

AI 应用 CI/CD 流水线设计:把模型、Prompt、代码当成同一个发布单元

2026-09-07 · 约 12 分钟阅读

"周五下午把 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 的一个示例:

# .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 Latency99 分位延迟≤ 上版的 1.5 倍

任何一项不达标,CI 直接红,不允许合并。

四、CD 流水线:灰度发布 + 自动回滚

CD 不再是"kubectl apply"那么简单,因为 AI 应用的"灰度"涉及流量分配和路由切换:

# 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 而非纯文本):

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(或反之)属于重大变更,建议双跑对比期:

# 双跑:新旧模型并行调用,对比输出
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 应用版本管理与灰度发布最佳实践;想了解 LLM 评测集怎么搭,可以看 AI 应用 A/B 测试与效果评估框架。要选用稳定的中转 API 来跑评测流水线,可以去 openairouter.net 比较各家平台的延迟和价格。

找到最适合你的 AI API 中转站

收录 125+ 服务商,按价格、模型、标签一键筛选

查看所有中转站 →