为什么需要模板复用
团队里的 Prompt 现状通常是:
同事 A 写了个"周报生成 Prompt",用了一次就丢
同事 B 下周也要写周报,从头写一遍
同事 C 也要写,但加了"重点突出数据"的要求,又改一遍
3 个人,3 份 Prompt,90% 内容重复,但没人复用
这背后是 Prompt 管理的三个缺失:
- 没有变量化:数据硬编码在 Prompt 里,换数据就得重写
- 没有版本管理:改一版丢一版,不知道哪个版本效果好
- 没有共享机制:每个人自己造轮子,无法站在彼此肩膀上
Prompt 模板化 解决了第一个问题——用模板代替硬编码。本文解决后两个:复用与参数化。
模板复用的四个层次
层次 1:硬编码(无复用)
你是客服助手。规则:仅基于资料回答。
资料:[今天的产品手册]
问题:怎么退货?
数据、规则、问题全混在一起,换一个问题就得重写。
层次 2:变量化(单次复用)
你是客服助手。规则:仅基于资料回答。
资料:{{资料}}
问题:{{问题}}
用 {{变量}} 占位,换数据只需换变量值。这是 模板化 的层次。
层次 3:参数化(多场景复用)
你是{{角色}}。规则:{{规则}}。
资料:{{资料}}
问题:{{问题}}
输出格式:{{格式}}
连角色、规则、格式都参数化,一个模板适配客服、销售、技术支持多场景。
层次 4:组合复用(组件化)
{{#system_block}}
{{#role_block}}
你是{{角色}}
{{/role_block}}
{{#rule_block}}
规则:{{规则}}
{{/rule_block}}
{{/system_block}}
{{#user_block}}
{{资料}}
{{问题}}
{{/user_block}}
把模板拆成可组合的"块",不同场景拼装不同组合,像搭积木。
四种参数化模式
模式 1:数据参数化(最常用)
把变化的数据抽成变量,固定逻辑结构。
模板:
你是数据分析师。请分析以下数据:
{{data}}
要求:{{requirements}}
输出:{{{format}}}
调用 1(销售分析):
data = 2026年Q1销售表
requirements = 找出增长最快的品类
format = 表格 + 100字总结
调用 2(用户分析):
data = 用户行为日志
requirements = 找出流失用户特征
format = 用户画像 + 留存建议
适用:结构相同、数据不同的批量任务。
模式 2:角色参数化
同一个任务,不同角色产出不同风格。
模板:
你是{{role}}。请评价以下方案:
{{proposal}}
评价标准:{{criteria}}
调用 1(产品经理视角):
role = 资深产品经理,关注用户体验与商业价值
criteria = 用户痛点匹配度 / ROI / 实现成本
调用 2(工程师视角):
role = 资深工程师,关注技术可行性与维护成本
criteria = 架构合理性 / 技术债 / 上线风险
调用 3(法务视角):
role = 法务专家,关注合规与风险
criteria = 数据合规 / 合同风险 / 监管要求
适用:多视角评审、多角色头脑风暴。
模式 3:风格参数化
同一内容,不同风格输出。
模板:
把以下技术内容改写为{{style}}风格:
{{content}}
目标读者:{{audience}}
调用 1(科普):
style = 通俗易懂,用生活比喻
audience = 没技术背景的普通用户
调用 2(专业):
style = 严谨专业,术语准确
audience = 同行工程师
调用 3(营销):
style = 有吸引力,突出价值
audience = 潜在客户
适用:内容多渠道分发(官网/技术博客/营销物料)。
模式 4:流程参数化
同一目标,不同流程深度。
模板:
你是{{role}}。请完成任务:{{task}}
{{#if deep_mode}}
步骤要求:
1. 拆解为子任务
2. 逐步执行
3. 每步给中间结论
4. 最后汇总
{{/if}}
{{#unless deep_mode}}
直接给结论,不展开过程。
{{/unless}}
调用 1(快速模式):
deep_mode = false → 直接答案
调用 2(深度模式):
deep_mode = true → 链式调用展开
适用:简单问题快速答、复杂问题深度解的双模式。
变量设计原则
原则 1:稳定性分层
稳定层(几乎不变):
- 角色定义
- 输出格式
- 安全规则
半稳定层(偶尔变):
- few-shot 示例
- 业务规则
变化层(每次变):
- 输入数据
- 当前问题
参数化时,只把变化层和半稳定层抽成变量,稳定层固化在模板里。这与 Prompt 缓存 的前缀稳定性原则一致——稳定部分靠前,变化部分靠后。
原则 2:变量粒度
✗ 太粗:{{input}}(整段数据塞一个变量)
✓ 适中:{{user_query}} + {{context}} + {{preferences}}
✗ 太细:{{user_name}} + {{user_age}} + {{user_role}} + ...(20 个变量)
经验值:单模板变量数 3-7 个最佳,超过 10 个考虑拆模板。
原则 3:默认值与必填
{
"variables": {
"style": {"default": "专业", "required": false},
"content": {"default": null, "required": true},
"length": {"default": 500, "required": false}
}
}
必填变量缺值时报错,可选变量用默认值兜底。
原则 4:变量类型约束
{
"variables": {
"data": {"type": "array", "itemSchema": {...}}, // 结构化数据
"length": {"type": "integer", "min": 100, "max": 2000},
"style": {"type": "enum", "values": ["专业", "通俗", "营销"]}
}
}
类型约束能在调用前拦截错误输入。
模板引擎实现
基础版:字符串替换
import re
from typing import Any
class PromptTemplate:
def __init__(self, template: str, variables: dict):
self.template = template
self.variables = variables # 变量定义
def render(self, **kwargs) -> str:
# 校验必填
for name, spec in self.variables.items():
if spec.get("required") and name not in kwargs:
raise ValueError(f"缺少必填变量: {name}")
# 填充默认值
values = {}
for name, spec in self.variables.items():
if name in kwargs:
values[name] = kwargs[name]
elif "default" in spec:
values[name] = spec["default"]
else:
values[name] = "" # 可选变量缺值用空串
# 替换 {{变量}}
result = self.template
for name, value in values.items():
result = result.replace(f"{{{{{name}}}}}", str(value))
return result
# 定义模板
report_template = PromptTemplate(
template="""你是{{role}}。请基于以下数据写{{type}}:
数据:{{data}}
要求:{{requirements}}
字数:{{length}}字""",
variables={
"role": {"default": "数据分析师", "required": False},
"type": {"required": True},
"data": {"required": True},
"requirements": {"default": "重点突出,结论先行", "required": False},
"length": {"default": 500, "required": False},
}
)
# 调用
prompt = report_template.render(
role="销售分析师",
type="周报",
data="[销售表]",
length=800
)
print(prompt)
进阶版:支持条件与循环
class AdvancedTemplate:
def __init__(self, template: str, variables: dict):
self.template = template
self.variables = variables
def render(self, **kwargs) -> str:
result = self.template
# 处理条件块 {{#if var}}...{{/if}}
result = re.sub(
r'\{\{#if (\w+)\}\}(.*?)\{\{/if\}\}',
lambda m: m.group(2) if kwargs.get(m.group(1)) else "",
result, flags=re.DOTALL
)
# 处理循环 {{#each items}}...{{/each}}
result = re.sub(
r'\{\{#each (\w+)\}\}(.*?)\{\{/each\}\}',
lambda m: "".join(
m.group(2).replace("{{this}}", str(item))
for item in kwargs.get(m.group(1), [])
),
result, flags=re.DOTALL
)
# 普通变量替换
for name, value in kwargs.items():
result = result.replace(f"{{{{{name}}}}}", str(value))
return result
# 示例:带条件与循环的模板
template = AdvancedTemplate(
template="""你是代码审查员。
{{#if strict}}严格模式:每个问题必须给出修复建议。{{/if}}
审查以下文件:
{{#each files}}
- {{this}}
{{/each}}""",
variables={"strict": {"required": False}, "files": {"required": True}}
)
print(template.render(strict=True, files=["auth.ts", "db.ts"]))
团队模板管理
1. 模板仓库结构
prompt-registry/
├── customer-service/
│ ├── refund.md # 退款问答
│ ├── product-qa.md # 产品问答
│ └── complaint.md # 投诉处理
├── dev/
│ ├── code-review.md
│ ├── bug-analysis.md
│ └── refactor.md
├── writing/
│ ├── weekly-report.md
│ ├── blog-polish.md
│ └── seo-content.md
└── _shared/
├── formats.md # 共享输出格式
└── rules.md # 共享安全规则
2. 版本管理
# refund.md frontmatter
---
id: customer-service/refund
version: 2.1.0
variables:
- name: data
required: true
- name: tone
default: 礼貌专业
changelog:
- 2.1.0: 加入引用来源要求
- 2.0.0: 参数化重构(破坏性变更)
- 1.0.0: 初版
---
调用时锁定版本,避免模板升级破坏现有流程:
template = registry.get("customer-service/refund", version="2.1.0")
prompt = template.render(data="[退款政策]")
3. 模板组合
共享格式 + 业务规则 + 任务模板 = 完整 Prompt
template = compose(
shared["_shared/formats.md"], # 输出格式
shared["_shared/rules.md"], # 安全规则
business["customer-service/refund.md"] # 业务逻辑
)
避免每个模板都重复写格式和规则。
4. A/B 测试
同一任务的两个模板版本,分流调用,统计效果:
v1: 直接给答案
v2: 先反问澄清再答
跑 100 次后看用户满意度:
v1: 72 分
v2: 85 分
→ 选 v2
这与 Prompt 评估 的方法呼应——用数据驱动模板迭代。
常见坑点
坑 1:过度参数化
✗ 一个模板 20 个变量,调用要填半分钟
✓ 固化高频默认值,只留 3-5 个真正多变的变量
坑 2:变量名混乱
✗ {{a}} {{b}} {{c}} → 调用时不知道填什么
✓ {{user_query}} {{context_docs}} {{output_format}}
变量名要自解释。
坑 3:模板与代码耦合
✗ 模板字符串硬编码在 Python 代码里 → 改模板要改代码
✓ 模板放独立 .md 文件 → 产品/运营也能改
坑 4:缺少调用日志
✗ 调用了哪些模板、传了什么参数、效果如何 → 全无记录
✓ 记录调用日志 → 出问题能回溯,迭代有依据
与其他技巧的关系
小结
模板复用与参数化的核心思想是:把 Prompt 当代码资产管,而不是当一次性文本丢。
- 一次定义、多处复用 → 省时间
- 变量化调用 → 适配多场景
- 版本管理 → 可追溯可回滚
- 团队共享 → 沉淀集体智慧
下次写完一个效果好的 Prompt,别急着用完就丢——花 5 分钟参数化、入库、共享,团队每个人都能受益。这才是 Prompt 工程从"个人手艺"走向"团队资产"的关键一步。