Chico Notes
LLM Wiki / RAG

RAG 发布门禁生产实战:Release Manifest、灰度、回滚与审计闭环

把 RAG 的评测报告、变更风险、Hard/Soft Gate、Shadow、Canary、自动暂停和多资产回滚连接成一套可执行、可审计、可恢复的生产发布系统。

持续修订的工程笔记

RAG 系统的发布经常被误解成一次普通应用部署:

代码合并
→ CI 构建通过
→ 部署新容器
→ 发布完成

但一个生产 RAG 版本实际上可能同时改变:

  • Query Rewrite Prompt;
  • Embedding 模型和向量空间;
  • Chunk 策略和索引结构;
  • BM25 字段权重;
  • RRF、Top-K、阈值和过滤条件;
  • Reranker 模型、窗口和 min_score
  • Context Pack 顺序与 Token Budget;
  • Answer Prompt、Guardrail 和 Citation 规则;
  • 模型路由、缓存、价格和超时;
  • Tenant、ACL 和数据源授权边界。

代码部署成功,只能证明软件能够启动;它不能证明:

  • 正确证据仍然能被召回;
  • 高严重度问题没有回归;
  • 无权内容没有进入候选、Context 或 Citation;
  • P95、P99 和单请求成本仍在预算内;
  • 新索引、Prompt、模型和配置可以立即切回;
  • 灰度异常时系统知道应该自动暂停,而不是继续扩大流量。

生产级 Release Gate 的目标不是阻止发布,而是把每次变化变成一个有证据、有边界、有 Owner、有暂停条件、有回滚路径的工程动作。

资料快照:本文基于前文已经建立的 RAG 评测、可观测性、Hybrid Search、Reranker、Query Rewriting 与 MySQL→Elasticsearch 一致性设计,核查截至 2026-08-05。文中的阈值和灰度比例是工程示例,应由真实流量、历史基线、业务严重度和合规要求校准。

RAG 发布门禁生产实战:从变更清单、离线评测、发布门禁、灰度到回滚与复盘

图 1:RAG 发布不是一次容器替换,而是一条包含评测、风险控制、灰度观察和多资产回滚的发布链路。

一句话结论

一个 RAG 版本只有同时满足下面五个条件,才应该进入生产:

  1. Release Manifest 足以复现它。
  2. Baseline 与 Candidate 在同一数据集上完成成对评测。
  3. 安全和关键能力通过 Hard Gate。
  4. 灰度阶段有明确的推进、暂停和回滚阈值。
  5. 旧 Prompt、旧索引、旧模型路由和旧配置仍可立即恢复。

推荐的控制链路是:

Change Request
→ Risk Classification
→ Candidate Build
→ Immutable Release Manifest
→ Offline Paired Evaluation
→ Hard / Soft Gate
→ Shadow
→ Canary 1% / 5% / 10%
→ Full Rollout
→ Online Evaluation
→ Incident / Bad Case
→ Regression Dataset

1. 先看完整发布生命周期

RAG 发布生命周期:从变更分类、候选构建、离线评测、门禁、Shadow、Canary、全量、回滚到坏例回流

图 2:Release Gate 不只存在于 CI。离线评测、Shadow、Canary、持续监控、回滚和坏例回流共同组成完整发布生命周期。

门禁的核心不是“通过或失败”两个结果,而是允许四种决策:

PASS
→ 可以进入下一阶段

CONDITIONAL PASS
→ 带明确风险、Owner 和观察条件进入灰度

PAUSE
→ 停止扩大流量,继续观察或补充样本

BLOCK / ROLLBACK
→ 不允许发布,或立即切回稳定版本

2. RAG Release 和代码 Release 有什么不同

代码发布通常围绕:

Build
Test
Deploy
Health Check
Rollback Binary

RAG 发布还需要管理非代码资产:

资产变化会影响什么典型回滚
Prompt答案格式、拒答、引用、工具调用切回 Prompt Version
Query Plan原始 Query、Rewrite、分解和 Scope关闭 Planner 或切回旧版本
Embedding向量空间和召回分布切回旧索引与旧模型
Chunk检索单位、引用粒度和 ContextAlias 切回旧物理索引
BM25 / RRF候选排序和 Recall配置路由切回
RerankerTop-K、延迟和 GPU 成本熔断或切回旧端点
Context PackerToken、顺序、去重和引用切回旧 Packer 配置
LLM Route输出质量、延迟和成本切回稳定模型 Route
ACL / Filter数据访问边界Fail Closed + 回滚规则
Data Source覆盖、新鲜度和噪声禁用来源或切回旧快照

因此,RAG Release 的发布单元不是一个 Commit,而是:

应用代码 + 索引快照 + 模型身份 + Prompt + 检索配置 + 权限规则 + 评测数据集 + 回滚资产。


3. Release Manifest:先定义“到底发布了什么”

没有 Release Manifest,事故发生后团队通常只知道:

大概是下午发布的;
好像换过 Reranker;
Prompt 应该还是 v7;
索引可能已经切到 v4;
Embedding 用的是哪个 Endpoint 不确定。

一份完整 Manifest 可以是:

{
  "release_id": "rag-prod-2026-08-05.3",
  "created_at": "2026-08-05T18:30:00+08:00",
  "owner": "rag-platform",
  "change_ticket": "RAG-1842",
  "risk_level": "high",
  "application": {
    "repository": "chicogong/rag-service",
    "commit": "abc123def456",
    "image": "registry.example.com/rag-service:abc123"
  },
  "query": {
    "classifier_version": "query-classifier-v5",
    "planner_prompt_version": "query-plan-v8",
    "rewrite_prompt_version": "rewrite-v11",
    "scope_compiler_version": "scope-v4"
  },
  "retrieval": {
    "index_alias": "kb_chunks",
    "physical_indices": ["kb_chunks_v4"],
    "projection_schema_version": 6,
    "embedding_model_key": "bge-m3|endpoint-a|rev-20260801",
    "bm25_config_version": "bm25-v9",
    "rrf_config_version": "rrf-v7",
    "top_k": {
      "bm25": 80,
      "dense": 80,
      "fusion": 100
    }
  },
  "rerank": {
    "model_key": "bge-reranker-v2-m3|gpu-pool-a|rev-3",
    "config_version": "rerank-v10",
    "window": 50,
    "output_count": 8
  },
  "context": {
    "packer_version": "context-v7",
    "token_budget": 6000,
    "max_chunks_per_document": 2
  },
  "generation": {
    "prompt_version": "answer-v16",
    "model_route": "answer-stable-202608",
    "guardrail_version": "guard-v5",
    "citation_mapper_version": "citation-v4"
  },
  "evaluation": {
    "datasets": [
      "rag-eval-core@2026-08-05.1",
      "rag-eval-regression@2026-08-05.7",
      "rag-eval-safety@2026-08-05.3"
    ],
    "judge_version": "judge-v11",
    "metric_schema_version": "rag-metrics-v6",
    "baseline_release_id": "rag-prod-2026-07-29.2",
    "report_uri": "artifact://rag-release/rag-prod-2026-08-05.3/report.json"
  },
  "rollback": {
    "target_release_id": "rag-prod-2026-07-29.2",
    "runbook": "runbook://rag/release-rollback-v4",
    "verified_at": "2026-08-05T17:30:00+08:00"
  }
}

3.1 Manifest 的三个要求

不可变。

发布后不覆盖原文件,修订应生成新 Release ID。

可解析。

不要只写 Markdown 描述,关键字段必须能被 CI、部署系统和观测系统读取。

可验证。

Manifest 中引用的 Prompt、索引、模型、报告和 Runbook 都必须真实存在。


4. 发布前先做风险分级

RAG 变更风险矩阵:影响范围、回滚难度和安全敏感度决定门禁强度

图 3:Prompt 文案、检索参数、Reranker、索引、Embedding 和权限规则拥有不同风险。风险越高,所需评测覆盖、审批、灰度和回滚资产越严格。

4.1 风险不是由改动行数决定

下面两个改动可能只差一行配置,但风险完全不同:

answer_temperature: 0.1 → 0.0

和:

acl_filter_mode: pre_filter → post_filter

后者可能改变无权文档是否进入候选集、Trace 和 Context,属于 Critical 变化。

4.2 建议风险维度

维度问题
影响范围单 Query、单租户、部分流量还是全局
安全边界是否影响 Tenant、ACL、敏感数据和拒答
数据变化是否需要重切 Chunk、重建向量或迁移索引
回滚时间秒级配置切换,还是数小时重建
模型变化是否改变向量空间、Score 分布或生成行为
成本变化是否新增模型调用、GPU 或大幅 Token
可观测性新链路是否有完整 Trace 与指标
历史先例是否存在同类事故或高严重度 Bad Case

4.3 四级风险

等级示例门禁要求
Low文案、非语义展示、小范围配置基础回归 + 快速灰度
MediumTop-K、阈值、Query Route、缓存Paired Eval + Shadow + Canary
HighReranker、Embedding、Chunk、Index全量离线 + 影子流量 + 分段灰度 + 完整回滚
CriticalTenant、ACL、敏感内容、GuardrailSafety 100% + 双人审批 + Fail Closed + 零容忍

Critical 变化不允许通过 Waiver 抵消安全失败。


5. Change Request 应该包含什么

在运行评测前,变更提出者应回答:

为什么改?
解决哪个 Bad Case 或业务目标?
改动了哪些资产?
预计影响哪些 Query Cohort?
可能退化什么?
如何观察?
如何回滚?
谁是 Owner?

推荐 Schema:

change_request:
  id: RAG-1842
  title: 增加 Reranker Window 以改善多证据问题
  owner: retrieval-team
  risk_level: high

  hypothesis:
    problem: 多证据问题正确 Chunk 已进入 RRF Top-50,但未进入 Rerank Window
    expected_gain: multi_evidence_context_recall 提升
    acceptable_cost: p95 增加不超过 80ms

  affected_assets:
    - reranker_config
    - context_packer

  target_cohorts:
    - multi_evidence
    - policy_comparison

  known_risks:
    - GPU queue time 增加
    - 短 Query 可能无收益
    - 长候选文本导致截断比例上升

  rollback:
    target_release_id: rag-prod-2026-07-29.2
    estimated_seconds: 30

没有清晰假设的改动,很难设计正确评测,也很难解释上线结果。


6. Candidate Build 需要产生哪些 Artifact

一个候选版本至少产生:

release-manifest.json
change-request.yaml
offline-eval-report.json
offline-eval-report.md
case-level-diff.jsonl
safety-report.json
latency-cost-report.json
index-manifest.json
prompt-bundle/
retrieval-config.json
reranker-config.json
rollback-plan.yaml
approval-record.json

建议目录:

release-manifest.json
change-request.yaml
summary.json
case-level-diff.jsonl
safety-report.json
latency-cost.json
index-manifest.json
retrieval-config.json
reranker-config.json
model-route.json
rollback-plan.yaml
rollback-verification.json

Artifact 应有 Hash、创建时间、Owner、Retention 和访问控制。


7. 离线评测必须是 Baseline / Candidate 成对实验

同一批 Case、同一 Scope 和同一时间快照分别运行:

Baseline
Candidate

输出:

Improved
Regressed
Unchanged
New Failure
Fixed Bad Case
Judge Inconsistent

门禁不能只看两个独立平均值。

7.1 为什么 Case-level Diff 更重要

假设整体 NDCG 上升 2%,但:

高频 FAQ +5%
Critical 权限问题出现 1 次越权

平均分不能抵消这次越权。

每个 Case 至少记录:

{
  "case_id": "rag_eval_0042",
  "severity": "high",
  "cohort": "multi_evidence",
  "baseline": {
    "retrieval_recall_at_20": 0.5,
    "faithfulness": 1.0,
    "latency_ms": 910
  },
  "candidate": {
    "retrieval_recall_at_20": 1.0,
    "faithfulness": 1.0,
    "latency_ms": 1040
  },
  "classification": "improved",
  "root_delta": "rerank window 30 → 50"
}

7.2 置信区间与 Effect Size

小数据集的 +0.01 可能只是抽样噪声。

评测报告应包含:

  • Paired Bootstrap CI;
  • 通过率的 Wilson Interval;
  • Effect Size;
  • 非确定性模型的重复运行方差;
  • 高严重度样本的绝对变化。

相关方法见 RAG 评测生产实战


8. Hard Gate:不能被平均分抵消的规则

Hard Gate 用来保护安全、契约和关键能力。

建议包括:

Unauthorized Retrieval Rate = 0
Unauthorized Context Rate = 0
Unauthorized Citation Rate = 0
Critical Safety Pass Rate = 100%
Invalid Citation ID Rate = 0
Trace Contract Pass Rate = 100%
Schema Validation Pass Rate = 100%
High Severity Regression Count = 0
P99 < Hard Deadline
Rollback Verification = passed

8.1 三种 Unauthorized 必须分开

Unauthorized Retrieval

无权内容已经进入候选或 Trace Artifact,即使没有进 Prompt,也可能构成数据暴露。

Unauthorized Context

无权内容进入模型输入,风险更高。

Unauthorized Citation

答案向用户暴露了无权来源或链接。

只检查 Context 不够。

8.2 Fail Closed

如果权限服务、Scope Compiler 或 Policy Engine 异常:

不允许扩大 Scope
不允许跳过 ACL
不允许用缓存中的旧权限继续回答

合理降级是拒答、重试或返回明确错误,而不是“尽量回答”。


9. Soft Gate:质量、延迟和成本之间的权衡

Soft Gate 可以允许小幅波动,但必须有解释、Owner 和灰度观察条件。

常见指标:

维度指标
RetrievalRecall@K、MRR、NDCG、Union Recall
ContextPrecision、Recall、Coverage、Redundancy
AnswerCorrectness、Faithfulness、Citation Accuracy
BehaviorRefusal、Clarification、Degrade Rate
PerformanceP50、P95、P99、Timeout
CostEmbedding、Rerank、LLM、Artifact Storage
Product差评率、追问率、人工升级率

9.1 不要只设全局阈值

应该按 Cohort 设置:

Exact ID
Error Code
Concept
Multi-evidence
Multi-hop
Temporal
Permission-sensitive
Long Context
No Evidence

全局平均值可能掩盖某一类 Query 的明显退化。


10. 一份可执行的 Release Gate 配置

release_gate_version: rag-gate-v5

release:
  id: rag-prod-2026-08-05.3
  baseline_release_id: rag-prod-2026-07-29.2
  risk_level: high
  owner: rag-platform

required_artifacts:
  - release-manifest.json
  - change-request.yaml
  - evaluation/summary.json
  - evaluation/case-level-diff.jsonl
  - evaluation/safety-report.json
  - runtime/index-manifest.json
  - rollback/rollback-plan.yaml
  - rollback/rollback-verification.json

datasets:
  - rag-eval-core@2026-08-05.1
  - rag-eval-regression@2026-08-05.7
  - rag-eval-safety@2026-08-05.3

hard_gates:
  unauthorized_retrieval_rate:
    max: 0
  unauthorized_context_rate:
    max: 0
  unauthorized_citation_rate:
    max: 0
  critical_case_pass_rate:
    min: 1.0
  high_severity_regression_count:
    max: 0
  invalid_citation_rate:
    max: 0
  trace_contract_pass_rate:
    min: 1.0
  schema_validation_pass_rate:
    min: 1.0
  rollback_verification:
    equals: passed
  p99_latency_ms:
    max: 5000

soft_gates:
  evidence_recall_at_10:
    max_drop: 0.005
  ndcg_at_10:
    max_drop: 0.01
  context_precision:
    max_drop: 0.01
  faithfulness:
    max_drop: 0.005
  citation_accuracy:
    max_drop: 0.005
  p95_latency_ms:
    max_increase_ratio: 0.15
  cost_per_request:
    max_increase_ratio: 0.10

cohort_gates:
  permission_sensitive:
    pass_rate:
      min: 1.0
  exact_id:
    hit_at_1:
      max_drop: 0
  multi_hop:
    complete_chain_rate:
      max_drop: 0.02

waiver_policy:
  allowed_for:
    - soft_gate
  forbidden_for:
    - unauthorized_access
    - critical_safety
    - invalid_schema
  required_approvers: 2
  max_valid_hours: 24

门禁配置自身也要版本化、评审和测试。


11. Waiver:例外不是绕过门禁

Soft Gate 可能出现合理例外:

Faithfulness 不变
NDCG +4%
P95 +12%
成本 +11%

如果业务认为质量收益值得成本增加,可以申请 Waiver。

一份 Waiver 应包含:

waiver:
  release_id: rag-prod-2026-08-05.3
  gate: cost_per_request
  observed: 0.021
  threshold: 0.020
  reason: 多跳问题完整证据链提升 8.4%
  scope: multi_hop_queries_only
  expires_at: 2026-08-06T18:00:00+08:00
  owner: rag-quality
  approvers:
    - retrieval-lead
    - product-owner
  online_guardrail:
    cost_per_request_max: 0.024
    auto_pause: true

Waiver 必须:

  • 有过期时间;
  • 有作用 Scope;
  • 有在线 Guardrail;
  • 有审批记录;
  • 不能用于越权、安全和无效契约。

12. Shadow:先用真实请求验证,不影响用户

Shadow 模式将真实生产请求复制给 Candidate:

Shadow 适合验证:

  • 真实 Query 分布;
  • 新模型延迟与错误;
  • Candidate 的空召回和降级率;
  • 离线集未覆盖的语言、长度和数据源;
  • 真实成本。

12.1 Shadow 的安全要求

Candidate 仍会接触真实数据,因此:

  • 使用同样或更严格的 ACL;
  • 不允许把输出返回用户;
  • Artifact Retention 遵守生产隐私策略;
  • 不对外部工具执行写操作;
  • 不发送邮件、创建日历或修改业务系统;
  • 对高成本模型设置独立预算。

12.2 Shadow 不是完整 A/B

用户看不到 Candidate,所以无法直接测:

  • 用户满意度;
  • 交互行为;
  • 业务转化。

它主要用于技术质量和生产分布验证。


13. Canary 与自动回滚控制环

RAG 灰度与回滚控制环:稳定版本、Shadow、分段 Canary、全量发布和自动回滚

图 4:稳定版本始终在线,Candidate 逐段放量;每个阶段都拥有推进、暂停和回滚条件。任何 Hard Gate 触发时立即切回已验证资产。

13.1 Canary 的阶段

一个 High Risk 发布可以采用:

Shadow
→ 1%
→ 5%
→ 10%
→ 25%
→ 50%
→ 100%

比例不是重点,重点是每一阶段拥有:

最小样本量
最短观察窗口
推进条件
暂停条件
回滚条件
Owner

13.2 示例阶段配置

canary:
  stages:
    - name: shadow
      traffic_percent: 0
      min_requests: 10000
      min_duration_minutes: 30

    - name: canary_1
      traffic_percent: 1
      min_requests: 2000
      min_duration_minutes: 30

    - name: canary_10
      traffic_percent: 10
      min_requests: 10000
      min_duration_minutes: 60

    - name: canary_50
      traffic_percent: 50
      min_requests: 50000
      min_duration_minutes: 120

    - name: rollout
      traffic_percent: 100

  advance_when:
    hard_gates_passed: true
    high_severity_regressions: 0
    p95_latency_ratio_max: 1.15
    cost_ratio_max: 1.10

  pause_when:
    sample_size_insufficient: true
    judge_disagreement_rate_max: 0.08
    soft_gate_warning_count_max: 2

  rollback_when:
    unauthorized_access_count_min: 1
    critical_failure_count_min: 1
    p99_latency_ms_min: 5000
    error_rate_ratio_min: 2.0

13.3 不要只按时间推进

错误做法:

发布 15 分钟没报警
→ 自动从 1% 升到 50%

如果 15 分钟内只有几十个目标 Cohort Query,样本不足以判断。

推进应同时满足:

Duration
+
Request Count
+
Cohort Coverage
+
Hard Gate
+
Soft Gate

14. Canary 期间应该监控什么

14.1 质量

Empty Retrieval Rate
Evidence Recall Proxy
Citation Coverage
Invalid Citation Rate
Refusal Rate
Clarification Rate
User Negative Feedback
Human Escalation

14.2 安全

Unauthorized Retrieval
Unauthorized Context
Unauthorized Citation
Prompt Injection Detection
Sensitive Data Exposure
Cross-tenant Cache Hit

14.3 性能

P50 / P95 / P99
Timeout Rate
Queue Time
Embedding Latency
Reranker Latency
LLM Time to First Token
Fallback Rate

14.4 成本

Embedding Cost
Rerank Pair Count
Rerank GPU Time
LLM Input / Output Tokens
Cache Read / Write
Artifact Storage
Cost per Successful Answer

14.5 分布

按这些维度切分:

Tenant
Language
Query Cohort
Knowledge Base
Data Source
Model Route
Region
Document Type

全局平均值可能掩盖某一租户或语言的严重回归。


15. 自动暂停和自动回滚要分开

Pause

停止继续扩大流量,但保留当前 Canary 比例,用于:

  • 样本量不足;
  • Soft Gate 轻微越界;
  • Judge 分歧较大;
  • 需要人工检查 Case;
  • 指标波动但没有安全问题。

Rollback

立即把所有 Candidate 流量切回稳定版本,用于:

  • 任何越权;
  • Critical Case 回归;
  • 持续错误;
  • P99 超硬上限;
  • 错误引用或敏感信息暴露;
  • 候选资产不可用。

不要因为希望“多看一会”而让 Critical 风险继续暴露。


16. 回滚不是 git revert

RAG 回滚需要同时恢复多种资产。

资产回滚动作
应用切回旧镜像或旧 Commit
PromptPrompt Registry 指向旧版本
Query Plan关闭 Planner 或切回旧 Prompt / Schema
Retrieval Config切回旧 Top-K、RRF 和 Filter 配置
ElasticsearchAlias 原子切回旧物理索引
Embedding使用旧模型与旧向量索引,不混合空间
Reranker切回旧端点,或关闭精排回退 RRF
Context Packer切回旧版本与 Token Budget
LLM Route切回稳定模型和价格配置
Cache使用 Release ID 隔离,避免跨版本污染
Feature Flag关闭 Candidate Route

16.1 回滚资产要在发布前验证

旧索引还存在吗?
旧 Prompt 能读取吗?
旧模型 Endpoint 还在线吗?
Alias 切换权限可用吗?
Feature Flag 能立即生效吗?
缓存是否带 Release ID?

发布前执行一次 Dry Run,记录:

{
  "rollback_target": "rag-prod-2026-07-29.2",
  "verified": true,
  "verified_at": "2026-08-05T17:30:00+08:00",
  "steps": {
    "prompt_switch": "passed",
    "index_alias": "passed",
    "model_route": "passed",
    "feature_flag": "passed"
  },
  "estimated_seconds": 28
}

17. Elasticsearch 索引如何支持零停机回滚

应用只访问稳定 Alias:

kb_chunks

物理索引版本化:

kb_chunks_v3
kb_chunks_v4

切换 Candidate:

POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "kb_chunks_v3",
        "alias": "kb_chunks"
      }
    },
    {
      "add": {
        "index": "kb_chunks_v4",
        "alias": "kb_chunks",
        "is_write_index": true
      }
    }
  ]
}

回滚使用同样的原子操作切回 v3。

17.1 旧索引保留多久

至少覆盖:

Canary 观察窗口
+
回归发现延迟
+
Incident 分析周期
+
安全缓冲

不要在 Alias 切换成功后立即删除旧索引。

17.2 Embedding 模型升级

新的 Embedding 模型通常意味着新的向量空间。

正确做法:

旧模型 + v3 索引
新模型 + v4 索引

错误做法:

同一个 dense_vector 字段混写不同模型生成的向量

回滚必须连同 Query Embedding 模型一起切回。

关于重建与增量追平,见 MySQL 到 Elasticsearch 的一致性


18. Prompt 和模型路由如何回滚

18.1 Prompt Registry

{
  "prompt_name": "rag-answer",
  "active_version": "v16",
  "stable_version": "v15",
  "versions": {
    "v15": {
      "sha256": "...",
      "created_at": "2026-07-29T10:00:00Z"
    },
    "v16": {
      "sha256": "...",
      "created_at": "2026-08-05T10:00:00Z"
    }
  }
}

回滚不是重新编辑 Prompt,而是原子切换 active_version

18.2 Model Route

routes:
  answer-stable:
    primary: model-x-rev-3
    fallback: model-y-rev-2

  answer-candidate:
    primary: model-x-rev-4
    fallback: model-x-rev-3

Canary 只把一部分请求路由到 Candidate。回滚时切回稳定 Route。

18.3 Cache Key 必须包含版本

cache_key =
  tenant_id
  + normalized_query
  + scope_hash
  + release_id

否则 Candidate 的结果可能污染 Baseline,回滚后仍继续返回新版本缓存。


19. Feature Flag 应该控制什么

Feature Flag 不只控制整个版本,也可以控制高风险子能力:

query_rewrite_enabled
multi_query_enabled
reranker_enabled
new_index_enabled
new_prompt_enabled
new_model_route_enabled
web_search_enabled
agentic_retrieval_enabled

推荐能力:

  • 按 Tenant;
  • 按用户组;
  • 按 Query Cohort;
  • 按地域;
  • 按百分比;
  • 支持 Kill Switch;
  • 修改有审计日志;
  • Flag 状态进入 Trace。

每次请求应记录:

{
  "release_id": "rag-prod-2026-08-05.3",
  "feature_flags": {
    "query_rewrite_enabled": true,
    "reranker_enabled": true,
    "new_index_enabled": true
  }
}

20. Release Gate 与可观测性如何连接

每条 Trace 至少携带:

release_id
baseline_release_id
canary_stage
experiment_cohort
application_commit
index_manifest_version
prompt_version
model_route
reranker_version

这样 Dashboard 才能比较:

Baseline vs Candidate
Stable vs Canary
Release A vs Release B

20.1 不要把 Release ID 作为 Metric 的无限标签

如果 Release 数量很高,应控制 Retention 或将 Release 维度用于短期 Dashboard,而不是永久高基数 Metric。

Trace 和 Artifact 可以保存完整 Release ID;长期聚合可使用:

stable
candidate
canary_stage

详细可观测设计见 RAG 可观测性生产实战


21. Release SLO 与 Telemetry SLO

发布系统本身也应有 SLO。

Release SLO

Gate Evaluation Success Rate
Candidate Build Success Rate
Canary Auto-Pause Latency
Rollback Completion Time
Release Artifact Completeness

Telemetry SLO

Trace Export Success Rate
Release ID Coverage
Candidate / Baseline Correlation Rate
Metric Freshness
Artifact Availability

如果发布系统无法观察 Candidate,就不应该继续扩大流量。


22. CI 中的最小实现

release-gate
├── validate change request
├── build candidate manifest
├── validate required artifacts
├── run baseline
├── run candidate
├── compute deterministic metrics
├── run calibrated judges
├── compare paired cases
├── check hard gates
├── check soft gates
├── verify rollback
├── generate report
└── create deployment approval

22.1 GitHub Actions 示例

name: rag-release-gate

on:
  pull_request:
    paths:
      - "prompts/**"
      - "retrieval/**"
      - "rag/**"
      - "indexes/**"
      - "release/**"

jobs:
  evaluate:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install -r evaluation/requirements.lock

      - name: Validate release manifest
        run: python -m release_gate validate release/release-manifest.json

      - name: Run paired evaluation
        run: |
          python -m evaluation.run \
            --baseline release/baseline-manifest.json \
            --candidate release/release-manifest.json \
            --datasets release/datasets.yaml \
            --output artifacts/eval

      - name: Evaluate gates
        run: |
          python -m release_gate check \
            --config release/release-gate.yaml \
            --report artifacts/eval/summary.json \
            --output artifacts/release-decision.json

      - name: Upload evidence
        uses: actions/upload-artifact@v4
        with:
          name: rag-release-evidence
          path: artifacts/

实际项目应锁定 Action 与依赖版本,并保护评测凭证和生产数据。


23. 门禁决策器的伪代码

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import Any


class Decision(str, Enum):
    PASS = "pass"
    CONDITIONAL = "conditional"
    PAUSE = "pause"
    BLOCK = "block"


@dataclass(frozen=True)
class GateResult:
    decision: Decision
    hard_failures: list[str]
    soft_warnings: list[str]
    required_approvals: int


def evaluate_release(
    report: dict[str, Any],
    config: dict[str, Any],
) -> GateResult:
    hard_failures: list[str] = []
    soft_warnings: list[str] = []

    for metric, rule in config["hard_gates"].items():
        value = report["metrics"].get(metric)
        if value is None or not check_rule(value, rule):
            hard_failures.append(metric)

    if hard_failures:
        return GateResult(
            decision=Decision.BLOCK,
            hard_failures=hard_failures,
            soft_warnings=[],
            required_approvals=0,
        )

    for metric, rule in config["soft_gates"].items():
        value = report["deltas"].get(metric)
        if value is None or not check_rule(value, rule):
            soft_warnings.append(metric)

    if soft_warnings:
        return GateResult(
            decision=Decision.CONDITIONAL,
            hard_failures=[],
            soft_warnings=soft_warnings,
            required_approvals=config["waiver_policy"]["required_approvers"],
        )

    return GateResult(
        decision=Decision.PASS,
        hard_failures=[],
        soft_warnings=[],
        required_approvals=0,
    )

check_rule 必须处理缺失值。对 Hard Gate,缺失指标应该 Fail Closed,而不是视为通过。


24. 审批人到底应该看什么

审批页面不应只显示绿色勾选。

至少展示:

  1. 变更假设与目标 Bad Case;
  2. Release Manifest 差异;
  3. Baseline / Candidate 质量、延迟和成本;
  4. 新增回归和修复样本;
  5. Safety Set 结果;
  6. 未通过的 Soft Gate;
  7. Waiver 原因和过期时间;
  8. Shadow / Canary 计划;
  9. 自动暂停和回滚阈值;
  10. 回滚验证结果。

审批人必须能从报告直接回答:

为什么值得发布?
最大的剩余风险是什么?
异常时谁负责?
多快能回滚?

25. 发布状态机

状态转换应该由系统记录,不能只存在聊天消息或人工记忆中。


26. 发布审计记录

{
  "release_id": "rag-prod-2026-08-05.3",
  "event_id": "evt_release_0092",
  "event_type": "canary_advanced",
  "from_state": "canary_1",
  "to_state": "canary_10",
  "timestamp": "2026-08-05T20:10:00+08:00",
  "actor": {
    "type": "service",
    "id": "release-controller"
  },
  "evidence": {
    "requests": 15240,
    "duration_minutes": 68,
    "hard_gates": "passed",
    "soft_warnings": [],
    "dashboard": "trace://release/rag-prod-2026-08-05.3"
  }
}

必须审计:

  • 谁批准;
  • 谁修改 Gate;
  • 谁创建 Waiver;
  • 何时扩大流量;
  • 何时暂停或回滚;
  • 使用了哪些证据。

27. Incident 与 Postmortem 如何回流

一旦回滚,系统自动保存:

Candidate Trace Samples
Baseline / Candidate Pair
Relevant Artifacts
Gate State
Canary Stage
Metric Timeline
Feature Flag Changes
Rollback Timeline

Postmortem 产出:

Root Cause
Detection Gap
Gate Gap
Telemetry Gap
Rollback Gap
Action Items
New Regression Cases
New Safety Cases

每个高严重度事故至少产生一条新的 Regression 或 Safety Case。

这使发布系统随着事故不断变强,而不是每次从零开始排查。


28. 多租户发布策略

不是所有租户必须同时升级。

可以按:

  • 内部租户;
  • 低风险租户;
  • 测试租户;
  • 数据规模;
  • 语言;
  • 合规区域;
  • 产品套餐;
  • 主动加入 Beta 的客户。

逐步扩大。

28.1 Tenant-level Gate

某些回归可能只发生在:

中文长文档
英文 FAQ
某个部门 ACL
某个大知识库
特定地域模型端点

因此 Dashboard 和 Gate 需要 Tenant / Cohort 级切片。

28.2 不允许跨租户学习敏感内容

Shadow 和评测 Artifact 必须保持租户隔离。不要为了构建统一 Judge 数据集,把不同租户的私有内容混入公共样本。


29. 发布节奏与 Freeze Window

高风险索引或模型发布不宜在:

  • 无 Owner 值守时;
  • 上游模型供应商正在变更时;
  • 数据同步异常时;
  • 监控系统不可用时;
  • 重大业务高峰前;
  • 回滚资产即将过期时。

发布前检查系统依赖:

MySQL / Outbox Lag
Elasticsearch Cluster Health
Embedding Endpoint
Reranker GPU Pool
LLM Provider
Trace Collector
Feature Flag Service
Artifact Store

Release Gate 通过不代表所有基础设施都健康。


30. 常见反模式

反模式一:CI 绿了就发布

构建成功不能证明检索和答案质量。

反模式二:只比较平均分

会掩盖安全、关键样本和特定 Cohort 回归。

反模式三:没有 Release Manifest

事故后无法复现版本,也不知道应该切回什么。

反模式四:旧索引切换后立即删除

索引回滚变成重新构建,无法快速恢复。

反模式五:Embedding 模型回滚但索引不回滚

Query 与文档向量空间不一致,结果没有意义。

反模式六:Prompt 回滚靠手工复制旧文本

容易复制错误,应该切换不可变 Prompt Version。

反模式七:Canary 只按时间推进

样本量和目标 Cohort 可能不足。

反模式八:出现安全问题只暂停不回滚

Critical 风险应立即切回稳定版本。

反模式九:Waiver 可以绕过所有门禁

越权和关键安全失败不允许例外。

反模式十:回滚没有 Dry Run

真正事故时才发现旧模型、索引或权限已经不可用。

反模式十一:Feature Flag 不进入 Trace

无法解释某次请求到底启用了哪些新能力。

反模式十二:Bad Case 只写工单

没有进入 Regression Set 的问题会再次出现。


31. 分阶段落地方案

P0:建立可回滚发布基线

  • Release ID;
  • Immutable Manifest;
  • Baseline / Candidate Paired Eval;
  • Safety Hard Gate;
  • Prompt / Retrieval / Model 配置版本化;
  • 稳定 Elasticsearch Alias;
  • Feature Flag;
  • Rollback Runbook;
  • Preview / Shadow;
  • 发布审计记录。

验收标准:

任何生产请求都能追溯到完整 Release Manifest;
任何 Candidate 都能在一分钟内切回已验证版本。

P1:自动化门禁与 Canary

  • Gate YAML;
  • 自动 Case-level Diff;
  • 置信区间;
  • Shadow Traffic;
  • 分段 Canary;
  • 自动 Pause / Rollback;
  • Cohort Dashboard;
  • Waiver Workflow;
  • Rollback Dry Run;
  • Incident Evidence Freeze。

P2:规模化发布控制面

  • 多租户分批发布;
  • 多模型和多地域路由;
  • 自动风险分类;
  • Change Impact Analysis;
  • 在线 Pairwise Evaluation;
  • Release Controller;
  • Policy-as-Code;
  • 自动根因建议;
  • 发布成本预算;
  • 全链路合规审计。

32. 上线检查清单

  • 是否为本次发布生成唯一 Release ID?
  • Release Manifest 是否包含代码、索引、模型、Prompt 和配置版本?
  • Manifest 引用的 Artifact 是否真实存在并有 Hash?
  • 是否记录变更假设、目标 Bad Case 和 Owner?
  • 风险等级是否基于影响范围、回滚难度和安全边界?
  • Baseline 与 Candidate 是否使用相同 Dataset Version?
  • 是否输出 Case-level Improved / Regressed?
  • 是否检查置信区间和 Effect Size?
  • Unauthorized Retrieval / Context / Citation 是否全部为 0?
  • Critical Safety Case 是否 100% 通过?
  • High Severity Regression 是否为 0?
  • Trace 和 Schema Contract 是否完整?
  • Soft Gate 是否按 Query Cohort 分层?
  • Waiver 是否只允许 Soft Gate?
  • Waiver 是否有 Owner、审批、Scope 和过期时间?
  • Shadow 是否不会执行外部写操作?
  • Canary 每阶段是否有最小样本量和最短观察时间?
  • 是否分别定义 Advance、Pause 和 Rollback 条件?
  • 安全问题是否触发立即回滚?
  • 稳定版本是否始终在线?
  • 旧 Prompt、旧模型和旧索引是否仍可读取?
  • Elasticsearch 是否通过 Alias 切换?
  • Embedding 模型和向量索引是否成对切换?
  • Cache Key 是否包含 Release ID?
  • Feature Flag 状态是否进入 Trace?
  • 是否对 Tenant、语言和 Query Cohort 分层监控?
  • Release Dashboard 是否覆盖质量、安全、延迟和成本?
  • Rollback 是否做过 Dry Run?
  • 发布状态转换是否有审计记录?
  • Incident 是否自动冻结 Trace 和 Artifact?
  • 新 Bad Case 是否进入 Regression / Safety Set?
  • 旧资产的 Retention 是否覆盖观察与事故发现窗口?
  • 发布系统和 Telemetry 本身是否有 SLO?

总结

RAG Release Gate 的真正作用,不是给 CI 增加一个绿色勾选,而是建立一条可以解释和控制风险的证据链:

Change Request
→ 明确为什么改、影响什么、谁负责

Release Manifest
→ 冻结代码、索引、模型、Prompt 和配置

Paired Evaluation
→ 证明 Candidate 相对 Baseline 的变化

Hard / Soft Gate
→ 把安全零容忍与质量权衡分开

Shadow / Canary
→ 在真实分布中逐步获得证据

Pause / Rollback
→ 异常时停止风险扩散并切回稳定资产

Observability / Audit
→ 解释每次请求和每个发布决策

Incident / Bad Case
→ 把失败沉淀到下一次门禁

最重要的工程原则是:

发布的目标不是证明新版本完美,而是确保它的风险可识别、可限制、可暂停、可回滚,并且每一次失败都会变成下一次发布前必须通过的测试。

相关阅读

讨论

继续讨论这篇笔记

有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。

On this page

一句话结论1. 先看完整发布生命周期2. RAG Release 和代码 Release 有什么不同3. Release Manifest:先定义“到底发布了什么”3.1 Manifest 的三个要求4. 发布前先做风险分级4.1 风险不是由改动行数决定4.2 建议风险维度4.3 四级风险5. Change Request 应该包含什么6. Candidate Build 需要产生哪些 Artifact7. 离线评测必须是 Baseline / Candidate 成对实验7.1 为什么 Case-level Diff 更重要7.2 置信区间与 Effect Size8. Hard Gate:不能被平均分抵消的规则8.1 三种 Unauthorized 必须分开8.2 Fail Closed9. Soft Gate:质量、延迟和成本之间的权衡9.1 不要只设全局阈值10. 一份可执行的 Release Gate 配置11. Waiver:例外不是绕过门禁12. Shadow:先用真实请求验证,不影响用户12.1 Shadow 的安全要求12.2 Shadow 不是完整 A/B13. Canary 与自动回滚控制环13.1 Canary 的阶段13.2 示例阶段配置13.3 不要只按时间推进14. Canary 期间应该监控什么14.1 质量14.2 安全14.3 性能14.4 成本14.5 分布15. 自动暂停和自动回滚要分开PauseRollback16. 回滚不是 git revert16.1 回滚资产要在发布前验证17. Elasticsearch 索引如何支持零停机回滚17.1 旧索引保留多久17.2 Embedding 模型升级18. Prompt 和模型路由如何回滚18.1 Prompt Registry18.2 Model Route18.3 Cache Key 必须包含版本19. Feature Flag 应该控制什么20. Release Gate 与可观测性如何连接20.1 不要把 Release ID 作为 Metric 的无限标签21. Release SLO 与 Telemetry SLORelease SLOTelemetry SLO22. CI 中的最小实现22.1 GitHub Actions 示例23. 门禁决策器的伪代码24. 审批人到底应该看什么25. 发布状态机26. 发布审计记录27. Incident 与 Postmortem 如何回流28. 多租户发布策略28.1 Tenant-level Gate28.2 不允许跨租户学习敏感内容29. 发布节奏与 Freeze Window30. 常见反模式反模式一:CI 绿了就发布反模式二:只比较平均分反模式三:没有 Release Manifest反模式四:旧索引切换后立即删除反模式五:Embedding 模型回滚但索引不回滚反模式六:Prompt 回滚靠手工复制旧文本反模式七:Canary 只按时间推进反模式八:出现安全问题只暂停不回滚反模式九:Waiver 可以绕过所有门禁反模式十:回滚没有 Dry Run反模式十一:Feature Flag 不进入 Trace反模式十二:Bad Case 只写工单31. 分阶段落地方案P0:建立可回滚发布基线P1:自动化门禁与 CanaryP2:规模化发布控制面32. 上线检查清单总结相关阅读