1. 背景痛点:为什么“随便问”总是翻车
在 GitHub 项目里直接甩一句“帮我写个登录模块”给 Claude,就像把需求丢给刚入职的新人——没有上下文、没有格式、没有边界,返回结果全凭运气。我统计了团队过去 3 个月的 120 次调用记录,发现以下高频翻车现场:
- 响应长度忽长忽短:同样一句“生成单元测试”,最短 12 行,最长 428 行,Code Review 时心态炸裂
- 关键信息缺失:让 Claude 补全接口文档,结果 40% 的返回里缺参数说明,还得人工二次追问
- 风格漂移:项目用 FastAPI,Claude 却给出 Flask 版本,合并进去直接 CI 报错
- Token 浪费:平均每次多余描述占 32% 的输入 token,钱包先扛不住
根因就一句话:提示词没有“骨架”。没有骨架,模型就只能“自由发挥”,效率自然低到尘埃里。
2. 技术对比:结构化提示的 ROI 到底高不高
为了说服老板给时间做 Prompt Engineering,我跑了一组对照实验:同一需求“为仓库 open-issue 生成修复建议”,分别用“口语化提示”与“结构化提示”各跑 50 条,结果如下:
| 指标 | 口语化提示 | 结构化提示 | 提升幅度 |
|---|---|---|---|
| 可直合并 PR 占比 | 18% | 54% | +200% |
| 平均往返轮数 | 3.7 | 1.3 | -65% |
| 单次调用 token 数 | 1,240 | 890 | -28% |
| 开发工时/需求 | 2.1 h | 0.9 h | -57% |
一句话总结:把提示词一次性写“板正”,后期省下的调试时间直接翻倍。换算成人力成本,一个 5 人小组每月能省出 1.2 人/天,ROI 高到老板眉开眼笑。
3. 核心实现:三套模板 + 可运行代码
3.1 模板设计原则
- 角色 + 目标 + 格式 + 边界,四段缺一不可
- 用 XML/JSON 显式分区,降低解析歧义
- 给出 few-shot,让 Claude 先“照抄”再发挥
3.2 经过验证的三套模板
模板 A:Issue 自动分类器
角色:你是 <role>GitHub 仓库维护助手</role> 目标:为下列 Issue 打标签(bug、enhancement、question) 格式:仅返回 JSON,字段 {"number":int,"labels":list} 边界:若信息不足,labels 留空数组 示例: <example> {"number":12,"labels":["bug"]} </example>模板 B:PR 描述生成器
任务:为以下提交 diff 写一段 50~80 字的 PR 描述 语言:中文 必须包含:改动原因 + 影响范围 禁止:口语、感叹句 输出格式:{"title":"xxx","body":"xxx"}模板 C:单元测试补全器
背景:项目用 Python 3.11 + pytest 要求:为下列函数生成 3 条测试用例,覆盖正常 + 异常路径 输出:仅返回代码,不含解释 代码模板: def test_xxx(): ...3.3 Python 示例:把模板跑起来
下面脚本演示如何自动给仓库最新 Issue 打标签,并提交回 GitHub。重点看注释里的参数调优逻辑。
#!/usr/bin/env python3 """ Auto-label GitHub Issues via Claude """ import os import json import requests from anthropic import Anthropic GH_TOKEN = os.getenv("GITHUB_TOKEN") CLAUDE_KEY = os.getenv("CLAUDE_KEY") REPO = "your-name/your-repo" anthropic = Anthropic(api_key=CLAUDE_KEY) def fetch_open_issues(): """抓取最新 10 条 open issue""" url = f"https://api.github.com/repos/{REPO}/issues" headers = {"Authorization": f"token {GH_TOKEN}"} resp = requests.get(url, headers=headers, params={"state": "open", "per_page": 10}) resp.raise_for_status() return resp.json() def build_prompt(issue): """按模板 A 拼装提示词""" return f""" <role>GitHub 仓库维护助手</role> 目标:为下列 Issue 打标签(bug、enhancement、question) 格式:仅返回 JSON,字段 {{"number":int,"labels":list}} 边界:若信息不足,labels 留空数组 示例: <example> {{"number":12,"labels":["bug"]}} </example> Issue 内容: 标题:{issue["title"]} 正文:{issue["body"]} """ def call_claude(prompt): """ temperature=0.2 保证稳定; max_tokens=150 避免废话; top_p=0.9 兼顾一点创造性 """ resp = anthropic.completions.create( model="claude-2", prompt=f"\n\nHuman: {prompt}\n\nAssistant:", max_tokens_to_sample=150, temperature=0.2, top_p=0.9, ) return resp.completion.strip() def apply_label(number, labels): """把标签贴回 GitHub""" if not labels: return url = f"https://api.github.com/repos/{REPO}/issues/{number}/labels" headers = {"Authorization": f"token {GH_TOKEN}", "Accept": "application/vnd.github+json"} data = {"labels": labels} r = requests.post(url, headers=headers, json=data) r.raise_for_status() def main(): issues = fetch_open_issues() for iss in issues: prompt = build_prompt(iss) raw = call_claude(prompt) try: obj = json.loads(raw) apply_label(obj["number"], obj["labels"]) print(f"Issue {obj['number']} labeled {obj['labels']}") except Exception as exc: print("parse error:", exc, raw) if __name__ == "__main__": main()跑通后,把脚本挂到 GitHub Actions 定时执行,就能实现“Issue 自动打标签”小闭环,省下每天 20 分钟的人工筛选。
4. 生产建议:让自动化更稳的三板斧
- 敏感数据脱敏:在 prompt 里显式声明“禁止返回任何个人邮箱、密钥”,并在代码层用正则二次过滤,防止 Claude 偶尔“嘴瓢”。
- 并发限流:Claude 官方默认 60 次/分钟。用
asyncio.Semaphore(40)做软限,留 20 次 buffer;若触发 429,退避策略按 2/4/8 秒指数回退。 - 结果校验:对返回 JSON 先用
pydantic.BaseModel做字段校验,再与本地知识库 diff;字段缺失率 >5% 自动转人工 review,防止脏数据入库。
5. 避坑指南:5 个高频错误及修正方案
把“角色”和“目标”写在一起 → 模型抓不到重点
修正:用 XML 标签显式分区,如<role>、<objective>。忘记给输出长度设上限 → 返回 600 行直接爆 token
修正:在提示末尾加“输出不超过 200 字”或max_tokens=300。few-shot 示例与真实场景分布不一致 → 线下测试 95% 准确率,线上 60%
修正:采样真实数据做示例,保持“难度”一致。temperature 随手设 0.8 求“创意” → 同一条需求跑 3 次 3 个样
修正:生产环境固定 0.2~0.3,创意需求单独开高参数实验。返回代码直接 exec → 被注入风险
修正:先在临时 Docker 容器里跑单元测试,通过再合并到主分支。
6. 进阶思考题
- 如何结合 GitHub CodeQL 结果,让 Claude 在生成补丁时自动规避同类漏洞?
- 当仓库 commit 信息为多语言混杂时,怎样动态调整 prompt 语言字段,保证返回一致?
- 如果要把 prompt 版本做 A/B 管理,你会如何设计实验指标与回滚策略?
把这三个问题想透,你的 Prompt Engineering 就不仅是“写提示词”,而是真正的自动化基础设施。祝你玩得开心,少踩坑,多省时间。