1. LangChain提示词模板基础解析
在构建大语言模型应用时,提示词工程是核心环节。LangChain框架提供的PromptTemplate类,正是为了解决动态提示词构建的痛点。传统硬编码提示词存在维护困难、复用性差的问题,而模板化提示词通过变量插值实现了动态内容生成。
1.1 基础模板构建方法
创建提示词模板最直接的方式是使用PromptTemplate类。以下是典型示例:
from langchain_core.prompts import PromptTemplate # 基础模板示例 basic_template = """请根据以下上下文回答问题: 上下文:{context} 问题:{question} 回答:""" prompt = PromptTemplate.from_template(basic_template)这个模板包含两个变量:context和question。实际使用时,通过format方法传入具体值:
filled_prompt = prompt.format( context="LangChain是一个用于构建大语言模型应用的框架", question="LangChain的主要用途是什么?" )1.2 模板变量进阶用法
LangChain支持更复杂的变量控制:
- 变量类型校验:可以为变量添加类型注解
- 默认值设置:为可选参数提供默认值
- 变量描述:添加说明文档提升可维护性
from typing import Optional advanced_template = PromptTemplate( input_variables=["query", "language"], template="请用{language}回答以下问题:{query}", partial_variables={"style": "专业的技术回答"}, validate_template=True # 启用模板验证 )2. 复合模板构建技术
实际应用中,单一模板往往不能满足复杂需求。LangChain提供了多种模板组合方式。
2.1 字符串拼接式组合
最简单的组合方式是使用加号运算符:
from langchain_core.prompts import PromptTemplate base_prompt = PromptTemplate.from_template("你是一位{role}专家") task_prompt = PromptTemplate.from_template("请解释{concept}的概念") combined_prompt = base_prompt + "\n\n" + task_prompt这种方式的优点是直观,但当模板数量多时维护较困难。
2.2 PipelinePrompt模板管道
对于复杂场景,推荐使用PipelinePromptTemplate:
from langchain_core.prompts import PipelinePromptTemplate # 定义最终模板框架 full_template = """{introduction} {example} {task}""" full_prompt = PromptTemplate.from_template(full_template) # 定义子模板 introduction_template = """你正在模拟{character}的说话风格。""" introduction_prompt = PromptTemplate.from_template(introduction_template) example_template = """示例对话: Q: {sample_q} A: {sample_a}""" example_prompt = PromptTemplate.from_template(example_template) task_template = """现在请回答真实问题: Q: {query} A:""" task_prompt = PromptTemplate.from_template(task_template) # 构建管道 input_prompts = [ ("introduction", introduction_prompt), ("example", example_prompt), ("task", task_prompt) ] pipeline_prompt = PipelinePromptTemplate( final_prompt=full_prompt, pipeline_prompts=input_prompts )这种结构的优势在于:
- 各子模板可独立修改
- 模板间依赖关系清晰
- 支持部分变量预填充
3. 聊天提示词模板
与普通提示词不同,聊天场景需要维护对话历史。LangChain提供了专门的聊天模板。
3.1 基础聊天模板
from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import SystemMessage, HumanMessagePromptTemplate chat_template = ChatPromptTemplate.from_messages([ SystemMessage(content="你是一位专业的技术顾问"), HumanMessagePromptTemplate.from_template("{user_input}") ])3.2 动态对话历史管理
实际对话需要维护上下文:
from langchain_core.prompts import MessagesPlaceholder dynamic_chat_template = ChatPromptTemplate.from_messages([ SystemMessage(content="你是一位有帮助的AI助手"), MessagesPlaceholder(variable_name="history"), HumanMessagePromptTemplate.from_template("{input}") ])使用MessagesPlaceholder可以在运行时插入历史消息列表。
4. 模板中的模板:嵌套技巧
高级应用中,我们需要在模板中嵌套其他模板,实现更灵活的提示词构建。
4.1 变量中的子模板
from langchain_core.prompts import PromptTemplate # 子模板 detail_template = PromptTemplate.from_template( "相关背景:{background}\n具体要求:{requirement}" ) # 主模板 main_template = PromptTemplate.from_template( """任务说明: {task_detail} 请按照上述要求完成工作。""" ) # 组合使用 nested_prompt = main_template.partial( task_detail=detail_template.format( background="项目涉及LangChain框架", requirement="实现动态提示词生成" ) )4.2 条件化模板选择
通过函数实现动态模板选择:
from typing import Dict def get_template(scenario: str) -> PromptTemplate: templates = { "simple": PromptTemplate.from_template("回答:{query}"), "detailed": PromptTemplate.from_template(""" 问题分析:{query} 思考过程:{reasoning} 最终答案:{answer} """) } return templates.get(scenario, templates["simple"]) selected_template = get_template("detailed")5. 实战:构建RAG提示词系统
让我们实现一个完整的检索增强生成(RAG)提示词系统。
5.1 检索阶段提示词
retrieval_template = PromptTemplate.from_template(""" 你是一位专业的研究助理。请根据以下知识片段,提取与问题相关的信息。 知识片段: {context} 问题: {question} 相关信息的摘要: """)5.2 生成阶段提示词
generation_template = ChatPromptTemplate.from_messages([ SystemMessage(content="你是一位技术专家,正在回答用户问题"), HumanMessagePromptTemplate.from_template(""" 根据以下上下文信息回答问题: 上下文: {retrieved_context} 问题: {user_question} 请提供专业、准确的回答: """) ])5.3 完整流程集成
from langchain_core.prompts import PipelinePromptTemplate rag_template = """ 请按照以下步骤回答问题: 1. 信息检索: {retrieval_result} 2. 综合回答: {generation_result} """ rag_prompt = PipelinePromptTemplate( final_prompt=PromptTemplate.from_template(rag_template), pipeline_prompts=[ ("retrieval_result", retrieval_template), ("generation_result", generation_template) ] )6. 模板管理最佳实践
6.1 模板版本控制
建议将模板存储在单独的文件中,与代码分离:
prompts/ ├── retrieval/ │ ├── v1.txt │ └── v2.txt └── generation/ ├── basic.txt └── technical.txt6.2 模板性能监控
记录不同模板的响应质量和耗时:
import time from typing import Dict, Any def track_prompt_performance( template: PromptTemplate, inputs: Dict[str, Any], model ) -> Dict: start_time = time.time() # 执行提示词 prompt = template.format(**inputs) response = model.invoke(prompt) duration = time.time() - start_time return { "template_version": template.metadata.get("version"), "duration": duration, "response_length": len(response), "quality_score": None # 可添加质量评估 }6.3 模板测试方案
建立模板测试套件:
import unittest class TestPrompts(unittest.TestCase): def test_retrieval_template(self): template = load_template("retrieval/v1.txt") test_input = { "context": "测试上下文", "question": "测试问题" } result = template.format(**test_input) self.assertIn("测试问题", result) self.assertNotIn("{context}", result)7. 高级技巧与疑难解答
7.1 处理模板冲突
当多个模板定义相同变量时,可以采用以下策略:
- 命名空间隔离:
user_template = PromptTemplate.from_template("用户:{content}") ai_template = PromptTemplate.from_template("AI:{content}") combined = user_template.partial(content="用户输入") + \ ai_template.partial(content="AI回复")- 变量重命名:
user_template = PromptTemplate.from_template("{user_content}") ai_template = PromptTemplate.from_template("{ai_content}")7.2 动态变量控制
对于不确定的变量集合,可以使用**kwargs展开:
from typing import Dict, Any def safe_format(template: PromptTemplate, **kwargs: Any) -> str: # 只保留模板实际需要的变量 valid_vars = { k: v for k, v in kwargs.items() if k in template.input_variables } return template.format(**valid_vars)7.3 模板缓存优化
频繁创建的模板可以缓存:
from functools import lru_cache @lru_cache(maxsize=100) def get_cached_template(template_text: str) -> PromptTemplate: return PromptTemplate.from_template(template_text)7.4 长文本处理策略
当处理长文本时:
- 分块处理:
from langchain_text_splitters import CharacterTextSplitter splitter = CharacterTextSplitter( chunk_size=1000, chunk_overlap=200 ) chunks = splitter.split_text(long_text) chunk_templates = [ PromptTemplate.from_template(f"文本片段 {i}:\n{chunk}") for i, chunk in enumerate(chunks) ]- 摘要提取:
summary_template = PromptTemplate.from_template(""" 请从以下文本中提取关键信息: {text} 关键点总结: """)8. 模板设计模式
8.1 角色设定模式
def create_role_prompt(role: str, task: str) -> PromptTemplate: return PromptTemplate.from_template(f""" 你是一位专业的{role},正在执行{task}任务。 请按照以下要求操作: {{instructions}} 具体内容: {{content}} """)8.2 链式思考模式
cot_template = PromptTemplate.from_template(""" 问题:{question} 请逐步思考: 1. 理解问题:{step1} 2. 分析关键点:{step2} 3. 寻找解决方案:{step3} 4. 验证方案:{step4} 5. 最终答案:{final_answer} """)8.3 多视角分析模式
multi_view_template = PromptTemplate.from_template(""" 请从以下角度分析问题: 技术角度: {technical_view} 业务角度: {business_view} 用户体验角度: {user_experience_view} 综合建议: {suggestion} """)9. 性能优化技巧
9.1 模板预编译
对于高频使用的模板:
precompiled = { "greeting": PromptTemplate.from_template("你好,{name}!").format, "query": PromptTemplate.from_template("搜索:{keywords}").format } # 快速调用 greeting_msg = precompiled["greeting"](name="张三")9.2 批量处理优化
使用批量生成减少开销:
def batch_format(templates: List[PromptTemplate], inputs: List[dict]): return [ template.format(**input_dict) for template, input_dict in zip(templates, inputs) ]9.3 异步处理
对于大量模板处理:
import asyncio async def async_format(template: PromptTemplate, inputs: dict): loop = asyncio.get_event_loop() return await loop.run_in_executor( None, template.format, **inputs )10. 安全注意事项
- 输入消毒:
import html def safe_format(template: PromptTemplate, **kwargs): sanitized = { k: html.escape(str(v)) for k, v in kwargs.items() } return template.format(**sanitized)- 敏感词过滤:
from some_filter_library import ProfanityFilter filter = ProfanityFilter() def clean_prompt(text: str) -> str: return filter.clean(text)- 长度限制:
MAX_LENGTH = 2000 def validate_prompt(prompt: str) -> bool: return len(prompt) <= MAX_LENGTH11. 调试与测试
11.1 模板验证
def validate_template(template: PromptTemplate): try: # 测试必填变量 dummy_inputs = { var: "test_value" for var in template.input_variables } template.format(**dummy_inputs) return True except KeyError as e: print(f"缺少必要变量:{e}") return False except Exception as e: print(f"模板格式错误:{e}") return False11.2 变量覆盖率检查
def check_coverage(template: PromptTemplate, inputs: dict) -> float: required = set(template.input_variables) provided = set(inputs.keys()) return len(required & provided) / len(required)11.3 模板差异分析
from difflib import unified_diff def compare_templates(template1: str, template2: str): lines1 = template1.splitlines() lines2 = template2.splitlines() return '\n'.join(unified_diff(lines1, lines2))12. 企业级应用建议
12.1 模板注册中心
建立组织内的模板共享机制:
class PromptRegistry: def __init__(self): self._templates = {} def register(self, name: str, template: PromptTemplate): self._templates[name] = template def get(self, name: str) -> PromptTemplate: return self._templates.get(name) def list_all(self) -> Dict[str, str]: return { name: template.template for name, template in self._templates.items() }12.2 模板版本迁移
当模板需要更新时:
def migrate_template( old_template: PromptTemplate, new_template: PromptTemplate, converter: callable ) -> PromptTemplate: """将旧模板的数据迁移到新模板""" return new_template.partial( **converter(old_template.input_variables) )12.3 多语言支持
from typing import Dict class I18nPrompt: def __init__(self, templates: Dict[str, PromptTemplate]): self.templates = templates def get_for_locale(self, locale: str) -> PromptTemplate: return self.templates.get(locale, self.templates["default"])13. 未来演进方向
- 可视化模板编辑器:开发图形界面工具,降低非技术人员使用门槛
- 模板效果分析:建立自动化评估体系,量化不同模板的性能差异
- 智能模板推荐:基于历史数据,推荐最适合当前场景的模板结构
- 版本智能升级:自动检测模板改进点,生成优化建议
在实际项目中,我发现最有效的模板设计流程是:原型设计→A/B测试→数据分析→迭代优化。每个模板都应该有明确的版本记录和变更说明,这对团队协作特别重要。