一、为什么需要 Prompt 模板

在生产环境中,Prompt 不是一次性撰写,而是需要反复使用、团队协作、持续维护。模板化的 Prompt 管理是 Prompt 工程从"手工作坊"到"工业化生产"的必经之路。

1.1 一次性 Prompt vs 模板化 Prompt

维度一次性 Prompt模板化 Prompt
可复用性
可维护性直接修改版本管理
团队协作个人经验共享规范
质量保证依赖个人自动化检查
调试效率重新调试定位变量问题
A/B 测试不支持原生支持

二、模板系统架构

2.1 分层模板体系

Prompt Template Architecture
├── L0 - Base Templates(基础模板)
   ├── system-base.md(系统基础模板)
   ├── chat-base.md(对话基础模板)
   └── tool-base.md(工具调用模板)

├── L1 - Domain Templates(领域模板)
   ├── customer-service.md(客服)
   ├── code-generation.md(代码生成)
   ├── data-analysis.md(数据分析)
   └── content-writing.md(内容创作)

├── L2 - Task Templates(任务模板)
   ├── sentiment-analysis.md
   ├── text-summarization.md
   ├── question-answering.md
   └── entity-extraction.md

└── L3 - Instance Templates(实例模板)
    ├── review-classification.md
    ├── medical-chatbot.md
    └── ecommerce-QA.md

2.2 模板引擎实现

from string import Template
from typing import Dict, Any, Optional
import json
import hashlib

class PromptTemplate:
    """工业级 Prompt 模板系统"""
    
    def __init__(self, template_id: str, template_str: str, 
                 metadata: Optional[Dict] = None):
        self.id = template_id
        self.template = Template(template_str)
        self.metadata = metadata or {}
        self.version = metadata.get("version", "1.0.0")
        self.created_at = metadata.get("created_at", "")
    
    def render(self, variables: Dict[str, Any]) -> str:
        """渲染模板,注入变量"""
        # 变量预处理
        processed_vars = self._preprocess_variables(variables)
        
        try:
            return self.template.safe_substitute(**processed_vars)
        except KeyError as e:
            raise ValueError(f"缺少必需变量: {e}")
    
    def _preprocess_variables(self, variables: Dict) -> Dict:
        """变量预处理和验证"""
        required = self.metadata.get("required_vars", [])
        processed = {}
        
        for var in required:
            if var not in variables:
                raise ValueError(f"缺少必需变量 '{var}' 的定义")
        
        for key, value in variables.items():
            # JSON 序列化
            if isinstance(value, (dict, list)):
                processed[key] = json.dumps(value, ensure_ascii=False, indent=2)
            else:
                processed[key] = str(value)
        
        return processed
    
    def validate(self, rendered_output: str) -> bool:
        """验证渲染后的 Prompt"""
        checks = self.metadata.get("validation", [])
        for check in checks:
            if check["type"] == "min_length":
                if len(rendered_output) < check["value"]:
                    return False
            elif check["type"] == "contains":
                if check["value"] not in rendered_output:
                    return False
        return True
    
    def get_checksum(self) -> str:
        """模板内容的校验和"""
        return hashlib.md5(self.template.template.encode()).hexdigest()

class TemplateRegistry:
    """模板注册中心"""
    
    def __init__(self):
        self._templates: Dict[str, PromptTemplate] = {}
    
    def register(self, template: PromptTemplate):
        self._templates[template.id] = template
    
    def get(self, template_id: str) -> PromptTemplate:
        if template_id not in self._templates:
            raise KeyError(f"模板 '{template_id}' 未注册")
        return self._templates[template_id]
    
    def list_by_category(self, category: str) -> list:
        return [
            t for t in self._templates.values()
            if t.metadata.get("category") == category
        ]
    
    def search(self, query: str) -> list:
        """搜索模板"""
        results = []
        for t in self._templates.values():
            if query.lower() in t.id.lower():
                results.append(t)
            elif query.lower() in json.dumps(t.metadata).lower():
                results.append(t)
        return results

三、模板设计原则

3.1 九大黄金法则

法则 1:单一职责
- 一个模板只做一件事
- 例:不要将"情感分类"和"摘要生成"放在一个模板里

法则 2:显式变量
- 所有可变部分必须声明为变量
- 禁止在模板中硬编码业务数据

法则 3:默认值策略
- 每个变量都有合理的默认值
- 默认值应体现最通用的配置

法则 4:版本追踪
- 每个模板必须有版本号
- 变更必须更新版本并记录 changelog

法则 5:降级路径
- 模板必须有 fallback 输出
- 当条件不满足时仍有合理行为

法则 6:边界标注
- 用明确的标记分割模板段落
- 例:=== INSTRUCTIONS ===、=== CONTEXT ===

法则 7:可测试性
- 模板变量应可以被 mock
- 每个模板配套测试用例

法则 8:文档内嵌
- 模板本身要自文档化
- 注释说明每个段落的作用

法则 9:国际化
- 文本内容使用变量占位
- 语言切换只需替换变量值

3.2 模板骨架示例

---
# 模板元数据
id: "qa-domain-expert"
name: "领域专家问答"
version: "2.1.0"
category: "question-answering"
required_vars: ["domain", "question"]
optional_vars: ["context", "tone", "max_length"]
created: "2026-01-15"
updated: "2026-06-01"
---

=== SYSTEM PROMPT ===
你是 ${domain} 领域的专家。
${
  context if context else ""
}

=== INSTRUCTIONS ===
请回答以下问题。要求:
1. 使用专业但不晦涩的语言
2. 优先使用数据支撑观点
3. 如果不确定,明确说明不确定性
4. 回答长度控制在 ${
  max_length if max_length else "500"
} 字以内
5. 语气:${tone if tone else "专业严谨"}

=== USER QUERY ===
${question}

=== OUTPUT FORMAT ===
## 核心回答
<直接回答用户问题>
## 关键依据
<支持回答的依据>
## 补充说明
<注意事项或扩展信息>

四、变量管理

4.1 变量类型体系

from enum import Enum
from typing import Union, List, Optional

class VarType(Enum):
    STRING = "string"
    INTEGER = "integer"
    FLOAT = "float"
    BOOLEAN = "boolean"
    LIST = "list"
    DICT = "dict"
    MARKDOWN = "markdown"
    CODE = "code"

class TemplateVariable:
    """模板变量的定义"""
    
    def __init__(
        self,
        name: str,
        var_type: VarType,
        required: bool = True,
        default: Optional[Any] = None,
        description: str = "",
        validator: Optional[callable] = None,
        examples: List[str] = None
    ):
        self.name = name
        self.type = var_type
        self.required = required
        self.default = default
        self.description = description
        self.validator = validator
        self.examples = examples or []
    
    def validate_value(self, value: Any) -> bool:
        """验证变量值"""
        if value is None and not self.required:
            return True
        if value is None and self.required:
            raise ValueError(f"变量 '{self.name}' 是必需的")
        
        if self.validator:
            return self.validator(value)
        return True

# 变量 schema 定义示例
VARIABLE_SCHEMA = {
    "domain": TemplateVariable(
        name="domain",
        var_type=VarType.STRING,
        required=True,
        description="专业领域名称",
        examples=["机器学习", "量子物理", "金融投资"]
    ),
    "question": TemplateVariable(
        name="question",
        var_type=VarType.STRING,
        required=True,
        description="用户的问题",
        validator=lambda x: len(x) >= 10
    ),
    "max_length": TemplateVariable(
        name="max_length",
        var_type=VarType.INTEGER,
        required=False,
        default=500,
        description="回答最大字数"
    )
}

4.2 变量注入安全

import re

class VariableSanitizer:
    """变量清洗安全层"""
    
    @staticmethod
    def sanitize_text(value: str) -> str:
        """清除可能破坏模板结构的字符"""
        # 移除模板变量语法
        value = re.sub(r'\$\{[^}]+\}', '', value)
        # 转义 Markdown 代码块
        value = value.replace('```', '```')
        return value
    
    @staticmethod
    def sanitize_code(value: str) -> str:
        """清理代码变量"""
        # 限制代码长度
        max_code_length = 5000
        return value[:max_code_length]
    
    @staticmethod
    def sanitize_list(value: list, max_items: int = 10) -> list:
        """限制列表长度"""
        return value[:max_items]

五、版本管理

class TemplateVersionManager:
    """模板版本管理器"""
    
    def __init__(self, storage_path: str):
        self.storage_path = storage_path
        self.versions = {}
    
    def save_version(self, template: PromptTemplate, change_log: str):
        """保存新版本"""
        version = template.metadata.get("version", "1.0.0")
        version_path = f"{self.storage_path}/{template.id}/v{version}.json"
        
        version_data = {
            "id": template.id,
            "version": version,
            "content": template.template.template,
            "metadata": template.metadata,
            "change_log": change_log,
            "checksum": template.get_checksum(),
            "saved_at": "2026-06-25T12:00:00Z"
        }
        
        # 保存到存储
        os.makedirs(os.path.dirname(version_path), exist_ok=True)
        with open(version_path, 'w', encoding='utf-8') as f:
            json.dump(version_data, f, ensure_ascii=False, indent=2)
    
    def rollback_to(self, template_id: str, version: str):
        """回滚到指定版本"""
        version_path = f"{self.storage_path}/{template_id}/v{version}.json"
        with open(version_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        return PromptTemplate(
            template_id=data["id"],
            template_str=data["content"],
            metadata=data["metadata"]
        )

六、测试与质量保证

6.1 模板测试框架

class TemplateTestCase:
    def __init__(self, template_id: str, variables: dict, 
                 expected_contains: list = None):
        self.template_id = template_id
        self.variables = variables
        self.expected_contains = expected_contains or []

def run_template_tests(registry: TemplateRegistry, 
                      test_cases: list) -> dict:
    """运行模板测试套件"""
    results = {"passed": 0, "failed": 0, "errors": []}
    
    for case in test_cases:
        try:
            template = registry.get(case.template_id)
            rendered = template.render(case.variables)
            
            # 验证必需内容
            for expected in case.expected_contains:
                if expected not in rendered:
                    raise AssertionError(
                        f"缺少预期内容: {expected}"
                    )
            
            results["passed"] += 1
            
        except Exception as e:
            results["failed"] += 1
            results["errors"].append({
                "template_id": case.template_id,
                "error": str(e)
            })
    
    return results

6.2 模板质量评分卡

质量维度权重检查项
完整性20%变量定义完整、default 覆盖
健壮性20%空变量处理、边界输入
可读性15%注释充分、段落清晰
一致性15%与同类模板格式一致
性能10%变量替换效率
安全20%注入防护、敏感词过滤

七、实战:完整模板系统

# 初始化模板系统
registry = TemplateRegistry()

# 注册基础模板
base_template = PromptTemplate(
    template_id="system-base-v2",
    template_str="""你是一个${role}助手。
${constraints}
""" + """
=== INPUT ===
${user_input}

=== RESPONSE ===
""",
    metadata={
        "version": "2.0.0",
        "category": "base",
        "required_vars": ["role", "user_input"],
        "optional_vars": ["constraints"],
        "created_at": "2026-01-01"
    }
)
registry.register(base_template)

# 使用模板
result = registry.get("system-base-v2").render({
    "role": "编程",
    "constraints": "请使用 TypeScript 回答",
    "user_input": "如何实现一个 Promise 池?"
})

八、总结

工业级 Prompt 模板体系的建设需要系统性思考:

  1. 分而治之 — 四层模板体系:基础→领域→任务→实例
  2. 变量驱动 — 显式声明所有可变部分,配套类型和验证
  3. 工程保障 — 版本管理、测试覆盖、安全检查
  4. 可观测性 — 模板调用日志、性能监控、错误追踪
  5. 团队协作 — 统一的模板注册中心、API 接口、文档

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。