系列《AI 应用生产化手册》第 10 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/... 从本篇进入模块三:上线治理(评测让质量可度量、可观测让问题可定位,治理让变更可控)
一、先看问题:最重要的"代码"在裸奔
提示词还躺在代码里的三个真实困境:
- 改完不知道改了什么 ------
DEFAULT_SYSTEM字符串被直接改,没有版本、没有 diff,回滚靠git blame猜。 - dev 和 prod 用同一套提示词------开发时测试的"轻松语气",上线时没换,生产环境语气不搭。
- 提示词影响线上质量,却没有代码的待遇------代码要评审要测试,提示词直接改直接上线。
解法:提示词即代码------提示词放进仓库,用和代码一样的版本管理、评审、回滚流程,并靠模板变量做环境隔离。
核心认知:提示词是对模型行为的"代码",它影响线上质量的方式和代码一样直接。不给提示词上版本管理和评审,等于让最重要的"代码"裸奔。
二、原理
提示词即代码三原则
| 原则 | 落地方式 |
|---|---|
| 版本化 | Git 仓库 + 每次改动升 version 号(回滚靠版本号,不靠记忆) |
| 评审 | 改动走 PR + Review(提示词 = 代码,质量影响同等) |
| 可回滚 | 版本号 + Git tag;出问题一键回退上一版 |
模板化 vs 硬编码(变量优先级必须写死)
bash
"你是 {{ role }}...... 语气:{{ tone }},{{ max_length }} 字以内"
↑ meta.yaml 默认 ↑ env/prod.yaml 覆盖 ↑ env/dev.yaml 覆盖
bash
优先级:meta.yaml 默认值 < env/{env}.yaml 覆盖 < 调用时显式传入
两个工程细节:
- 必填校验 :
required变量缺失直接抛错------禁止"带病渲染"上线 - StrictUndefined:模板里出现未定义变量立刻报错------把"渲染期错误"提前到"构建期"
环境隔离(dev / staging / prod)
| 环境 | 语气 | 长度 |
|---|---|---|
| dev | 轻松、口语化 | 200 字 |
| staging | 专业、友好 | 200 字 |
| prod | 严谨、专业 | 150 字 |
原则:环境覆盖只写"差异",不复制全文。 复制全文 = 三份提示词漂移,改一处忘两处。
工具化对比:Git 仓库 vs Langfuse Prompt Management
| 方案 | 适合场景 | 特点 |
|---|---|---|
| Git 仓库 | 代码评审流、提示词随代码发布 | 版本历史 + 评审 + 回滚与代码同管道 |
| Langfuse Prompt Mgmt | 线上热更新、非工程师参与编辑 | UI 编辑即时生效、内置版本对比/回滚 |
选型逻辑 :工程化阶段用 Git(流程最完整、无额外依赖);需要"非工程师改提示词 / 线上热更新"时再接 Langfuse------Git 是底层,工具是上层,不冲突。
三、动手:搭提示词仓库 + 加载器
bash
git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
source .venv/bin/activate
# 1. 环境隔离演示:dev 与 prod 的渲染差异
python -c "
from app.prompts import load_prompt
print('dev :', load_prompt('chat-system', env='dev').splitlines()[-1])
print('prod:', load_prompt('chat-system', env='prod').splitlines()[-1])"
真实输出(同一份模板,不同环境覆盖):
ini
dev : 3. 语气:轻松、口语化 (max_length=200)
prod: 3. 语气:严谨、专业 (max_length=150)
bash
# 2. 必填校验演示(role 为空应报错)
python -c "from app.prompts import load_prompt; load_prompt('chat-system', role='')"
# 真实报错:ValueError: 提示词 chat-system 缺少必填变量: ['role']
bash
# 3. 应用接入:启动后 /api/chat 自动加载仓库提示词
uvicorn app.main:app --port 8000
# 日志:event=prompt_load prompt=chat-system version=1.0.0 env=dev
版本管理演练(必做)
- 把
prompts/chat-system/meta.yaml的version: 1.0.0改成1.1.0 - 模板里加一句"回答前先确认问题属于知识库范围"
- 跑测试确认渲染正常:
pytest tests/test_prompts.py -q(配套项目 16 个用例) - 体会 :这次改动有版本号、有 diff、可回滚------而之前改
DEFAULT_SYSTEM什么都没有
与观测联动(模块二的价值在这里兑现)
加载器自动打 event=prompt_load(含 version/env):
- Langfuse trace 里能看到每次请求用的哪个版本提示词
- 评测报告可对照"版本 X 的通过率"------提示词版本 = 评测的对照变量
四、真实踩坑
- 改完不升版本号:回滚时找不到版本边界,只能 git blame------每次改动必升
- 覆盖顺序混乱:三层优先级没写死------按"默认 < 环境 < 显式"执行
- 必填校验缺失 :role 为空也渲染上线,模型行为崩了------
required列表必须维护 - 模板错误到线上才炸:变量名拼错运行期才发现------StrictUndefined + 测试兜底
- 一个提示词拆一堆文件:过度抽象------粒度 = "一个业务能力一个文件"
- 生产改提示词不走评审:直接改直接上线------提示词 = 代码,评审流程同等
- (实测)提示词仓库会"顺手"放大安全面:提示词进了仓库、又被 trace 记录,一旦泄露影响面更大------所以模块五(安全)要给提示词加防泄露(输出校验)
五、小结
- 三原则:版本化 / 评审 / 可回滚
- 变量优先级:默认 < 环境 < 显式(写死,别靠记忆)
- 两道安全阀:必填校验 + StrictUndefined------把错误提前到构建期
- 与观测/评测联动:prompt_load 日志让"提示词版本"成为可对照的变量
明天(R02):《灰度发布》------让"提示词/模型的变更"按比例放量,出问题只影响少数用户(含 md5 分桶实测:10000 用户 @10% 命中 10.47%)。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。