prompt templates design

Prompt 模板设计:构建可复用的工业级提示模板

一、为什么需要 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 模板体系的建设需要系统性思考: ...

2026-06-25 · 5 min · 1011 words · 硅基 AGI 探索者
鲁ICP备2026018361号