引言
在大型语言模型(LLM)驱动的应用开发中,提示(Prompt)的设计与管理是决定模型输出质量的关键环节。一个精心设计的提示能够引导模型生成更准确、更相关、更符合预期的内容。然而,随着应用逻辑的复杂化,硬编码的静态提示变得难以维护和扩展。为了解决这一挑战,LangChain 框架提供了一套强大而灵活的工具——提示词模板(Prompt Templates),旨在帮助开发者以结构化、可重用的方式构建和管理提示。
提示工程的核心理念
在深入了解 LangChain 的具体实现之前,我们有必要先回顾一下提示工程(Prompt Engineering)的基本构成。一个结构良好的提示通常包含以下四个部分 1:
|
组件 |
描述 |
|
指令 (Instructions) |
明确告知模型需要执行的任务,例如“将以下文本翻译成法语”或“根据上下文回答问题”。 |
|
外部信息 (External Information / Context) |
为模型提供额外的知识背景,这些信息可以手动插入,也可以通过向量数据库检索等方式动态获取。 |
|
用户输入 (User Input / Query) |
用户提出的具体问题或请求。 |
|
输出指示器 (Output Indicator) |
标记模型生成内容的开始,引导其以特定格式输出,例如在生成代码时以 import 开头。 |
理解这些组成部分,有助于我们更好地利用 LangChain 的提示词模板来构建高效的提示。
LangChain 提示词模板入门
LangChain 提供了多种类型的提示词模板,以适应不同的应用场景。以下是最核心的三种类型。
1. PromptTemplate:构建简单的字符串提示
PromptTemplate 是最基础的模板类型,适用于那些接受单个字符串输入的完成式模型(Completion-style models),如 OpenAI 的 text-davinci-003。它允许您通过占位符动态地插入变量。
from langchain_core.prompts import PromptTemplate
# 定义一个带有单个占位符的模板
prompt_template = PromptTemplate.from_template(
"你是一位专业的命名顾问。请为一个生产{product}的公司想一个好名字。"
)
# 格式化模板,填充占位符
filled_prompt = prompt_template.format(product="彩色袜子")
print(filled_prompt)
# 输出: 你是一位专业的命名顾问。请为一个生产彩色袜子的公司想一个好名字。
使用 from_template 类方法,LangChain 会自动推断出模板中的输入变量,简化了模板的创建过程。
2. ChatPromptTemplate:为聊天模型设计带角色的提示
与完成式模型不同,聊天模型(如 GPT-4、Claude 3)的输入是一个由多条消息组成的消息列表,每条消息都包含一个角色(system、human 或 ai)和内容。ChatPromptTemplate 正是为了优雅地构建这种结构化输入而设计的。
- System: 系统消息,用于设定 AI 的行为和背景,模型会更严格地遵循这部分指令。
- Human: 用户消息,代表用户的输入。
- AI: AI 消息,代表模型的历史回复,常用于提供对话上下文。
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages([
("system", "你是一位乐于助人的翻译家,能将{input_language}翻译成{output_language}。"),
("human", "{text}")
])
# 格式化聊天模板
formatted_messages = chat_template.format_messages(
input_language="英语",
output_language="法语",
text="I love programming."
)
print(formatted_messages)
# 输出:
# [
# SystemMessage(content=\'你是一位乐于助人的翻译家,能将英语翻译成法语。\'),
# HumanMessage(content=\'I love programming.\')
# ]
3. MessagesPlaceholder:动态插入聊天历史
在构建多轮对话应用时,我们需要将历史对话作为上下文提供给模型。MessagesPlaceholder 允许我们在模板中预留一个位置,用于在运行时动态插入一个消息列表 3。
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage
# 创建一个包含聊天历史占位符的模板
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是一位专业的职业规划导师。"),
MessagesPlaceholder(variable_name="conversation"),
("human", "{current_question}")
])
# 定义历史对话
conversation_history = [
HumanMessage(content="我应该如何准备一场工作面试?"),
AIMessage(content="首先,研究公司背景并练习常见的面试问题。")
]
# 格式化模板,同时传入历史对话和当前问题
formatted_messages = chat_prompt.format_messages(
conversation=conversation_history,
current_question="面试后我应该发送感谢邮件吗?"
)
# 这将生成一个包含系统指令、历史对话和当前问题的完整消息列表
高级用法:Few-Shot 学习与动态示例
当模型难以理解复杂的任务要求时,我们可以通过在提示中提供少量示例(Few-shot Learning)来引导它。LangChain 为此提供了 FewShotPromptTemplate。
FewShotPromptTemplate:提供上下文示例
这种模板允许我们定义一组示例,并将它们与前缀(指令)和后缀(用户输入)结合起来,构建一个信息丰富的提示。
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
# 1. 定义示例
examples = [
{"query": "你怎么样?", "answer": "我从不抱怨,但有时还是会。"},
{"query": "现在几点了?", "answer": "是时候买块表了。"}
]
# 2. 创建示例的格式化模板
example_template = PromptTemplate.from_template("用户: {query}\nAI: {answer}")
# 3. 创建 FewShotPromptTemplate
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_template,
prefix="以下是与一个AI助手的对话节选。这个助手通常很讽刺和机智,能对用户的问题做出创造性和有趣的回答。",
suffix="用户: {query}\nAI:",
input_variables=["query"],
example_separator="\n\n"
)
print(few_shot_prompt.format(query="生命的意义是什么?"))
LengthBasedExampleSelector:动态选择示例
在实际应用中,我们需要考虑模型的最大上下文窗口限制。如果示例过多,可能会导致提示过长。LengthBasedExampleSelector 可以根据输入查询的长度动态选择包含在提示中的示例数量,从而避免超出限制并优化成本。
from langchain_core.prompts.example_selector import LengthBasedExampleSelector
# 创建一个示例选择器,设置最大长度(按单词数计算)
example_selector = LengthBasedExampleSelector(
examples=examples,
example_prompt=example_template,
max_length=50
)
# 创建使用动态选择器的 FewShotPromptTemplate
dynamic_prompt = FewShotPromptTemplate(
example_selector=example_selector, # 使用选择器替代静态示例列表
example_prompt=example_template,
prefix="...",
suffix="...",
input_variables=["query"],
example_separator="\n"
)
# 当查询较长时,模板会自动减少包含的示例数量
最佳实践
为了最大限度地发挥 LangChain 提示词模板的效用,我们建议遵循以下最佳实践:
- 保持一致性:使用模板来标准化提示的结构,确保模型接收到的指令清晰一致,从而提高输出的稳定性和可靠性。
- 选择合适的模板:根据您使用的模型类型(完成式 vs. 聊天式)和任务需求(简单问答 vs. 多轮对话)选择最合适的模板。
- 利用 from_template:优先使用 from_template 方法创建模板,以减少手动指定输入变量的繁琐和出错可能。
- 管理上下文长度:在需要提供大量示例或长对话历史时,务必使用 LengthBasedExampleSelector 或其他策略来动态管理上下文长度,防止超出模型限制。
- 结构化与模块化:将复杂的提示分解为不同的部分(如指令、示例、用户输入),并利用模板的组合功能进行管理,提高代码的可读性和可维护性。
239

被折叠的 条评论
为什么被折叠?



