"世界上有一种技术叫Prompt Template,它就像AI的剧本,每一个变量都是一个角色,每一次注入都是一场演出。"
Prompt模板工程(Prompt Template Engineering)是指设计、管理和优化LLM提示词模板的系统化方法。它将Prompt从硬编码的字符串提升为可复用、可配置、可版本化的工程资产。
想象一下,你是一个导演,要拍一部电影。你不会每次拍戏都重新写剧本吧?你会有一个剧本模板,每次只需要换演员、换场景、换台词。
Prompt模板就是AI的剧本模板。你定义好框架,填入变量,AI就能按照你的"剧本"演出。就像周星驰的电影,套路是固定的,但每次都能演出新花样。
| 对比项 | 硬编码Prompt | Prompt模板 |
|---|---|---|
| 复用性 | ❌ 低 | ✅ 高 |
| 可维护性 | ❌ 差 | ✅ 好 |
| 版本管理 | ❌ 困难 | ✅ 容易 |
| A/B测试 | ❌ 复杂 | ✅ 简单 |
| 动态配置 | ❌ 不支持 | ✅ 支持 |
最基本的模板模式,通过变量注入动态内容:
你是{{role}},请用{{style}}的风格分析{{topic}}。
你是技术专家,请用幽默的风格分析AI Agent。
根据条件动态调整Prompt内容:
你是一个{{role}}。
{{#if language == "zh"}}
请用中文回答。
{{else}}
Please answer in English.
{{/if}}
{{#if expertise}}
你的专业领域是:{{expertise}}
{{/if}}
处理列表类型的数据:
分析以下代码问题:
{{#each issues}}
{{@index+1}}. {{this.description}}
严重程度:{{this.severity}}
建议:{{this.suggestion}}
{{/each}}
将Prompt拆分为可复用的片段:
// 基础片段
const rolePrompt = "你是一个专业的{{role}}。"
const stylePrompt = "请用{{style}}的风格回答。"
const contextPrompt = "背景信息:{{context}}"
// 组合模板
const fullPrompt = combine(
rolePrompt,
stylePrompt,
contextPrompt,
"问题:{{question}}"
)
一个完善的变量系统应该支持:
| 类型 | 示例 | 说明 |
|---|---|---|
| 简单变量 | {{name}} | 字符串替换 |
| 嵌套变量 | {{user.name}} | 对象属性 |
| 数组变量 | {{items[0]}} | 数组元素 |
| 过滤器 | {{text | uppercase}} | 格式转换 |
| 默认值 | {{name | default("匿名")}} | 缺省处理 |
OpenClaw的Skill系统大量使用Prompt模板:
// OpenClaw Skill中的Prompt模板示例
module.exports = {
prompts: {
analysis: {
template: `
你是一个{{domain}}专家。
任务:分析以下内容并给出建议。
{{#if context}}
背景信息:
{{context}}
{{/if}}
内容:
{{content}}
请按以下格式输出:
1. 问题分析
2. 根本原因
3. 改进建议
`,
variables: {
domain: { type: 'string', required: true },
context: { type: 'string', required: false },
content: { type: 'string', required: true }
}
}
}
}
一个完整的Prompt模板引擎实现:
import re
from typing import Dict, Any
class PromptTemplate:
def __init__(self, template: str):
self.template = template
self.variables = self._extract_variables()
def _extract_variables(self) -> list:
"""提取模板中的变量"""
pattern = r'\{\{(\w+(?:\.\w+)*)\}\}'
return list(set(re.findall(pattern, self.template)))
def render(self, **kwargs) -> str:
"""渲染模板"""
result = self.template
# 处理简单变量
for key, value in kwargs.items():
pattern = r'\{\{' + re.escape(key) + r'\}\}'
result = re.sub(pattern, str(value), result)
# 处理条件语句
result = self._process_conditions(result, kwargs)
# 处理循环
result = self._process_loops(result, kwargs)
return result.strip()
def _process_conditions(self, template: str, context: Dict) -> str:
"""处理条件语句"""
pattern = r'\{\{#if\s+(\w+)\s*==\s*"([^"]+)"\}\}(.*?)\{\{/if\}\}'
def replace_condition(match):
var_name = match.group(1)
expected = match.group(2)
content = match.group(3)
if context.get(var_name) == expected:
return content
return ''
return re.sub(pattern, replace_condition, template, flags=re.DOTALL)
def _process_loops(self, template: str, context: Dict) -> str:
"""处理循环语句"""
pattern = r'\{\{#each\s+(\w+)\}\}(.*?)\{\{/each\}\}'
def replace_loop(match):
var_name = match.group(1)
item_template = match.group(2)
items = context.get(var_name, [])
result = []
for i, item in enumerate(items):
rendered = item_template
rendered = rendered.replace('{{@index}}', str(i))
if isinstance(item, dict):
for k, v in item.items():
rendered = rendered.replace(f'{{{{this.{k}}}}}', str(v))
else:
rendered = rendered.replace('{{this}}', str(item))
result.append(rendered)
return ''.join(result)
return re.sub(pattern, replace_loop, template, flags=re.DOTALL)
# 使用示例
template = PromptTemplate("""
你是{{role}},请分析以下问题:
{{#each issues}}
{{@index+1}}. {{this}}
{{/each}}
""")
result = template.render(
role="技术专家",
issues=["性能问题", "安全漏洞", "代码质量"]
)
print(result)