嘿,朋友!今天咱们聊聊 LangChain 框架里的一个特别重要的东西:提示词模板(Prompt Templates)。你可能会觉得这玩意听起来有点复杂,但别担心,我会用最直接、最生活化的语言跟你掰扯清楚,就像咱们平时聊天一样。
咱们都知道,跟大语言模型(LLM)打交道,最重要的就是“问问题”——也就是提供“提示词”(Prompt)。你问得好,它就答得好;你问得稀里糊涂,它也可能给你一堆没用的东西。所以,设计一个好的提示词,直接决定了模型输出的质量,甚至可以说是成功的一半。
但是,如果你每次跟模型对话都要从头写一遍长长的提示词,那工作量可就大了。而且,很多时候,你的提示词里总有一些固定的部分,比如“你是一位专业的律师”、“请用中文回答”、“如果你不知道答案,就说不知道”等等。如果这些重复的指令每次都要手动敲,那也太麻烦了。
这时候,提示词模板就派上用场了。你可以把它想象成一个填空题的模板或者邮件模板。它有一个固定的结构和一些占位符(就是那些用大括号 {} 括起来的变量),你可以把这些占位符想象成一个个的“空”,等到真正使用的时候,再把具体的内容填进去。 这样一来,你就能更方便、更高效地生成针对特定任务的提示词了。
为什么我们需要提示词模板?
简单来说,提示词模板有几个特别实用的优点:
- 复用性高: 你可以定义一个通用的模板,然后在不同的场景下重复使用,只需要改动变量部分就行。比如,一个“新闻摘要”模板,你只需要替换新闻内容,就能得到新的摘要。
- 维护方便: 如果你的应用需求变了,需要调整提示词的某个固定指令,你只需要修改模板本身,所有用到这个模板的地方都会跟着更新,不用一个个地去改代码里散落的提示词。
- 结构化强: 模板能让你的提示词更有组织、有逻辑。你可以把指令、上下文、示例、问题等不同部分清晰地划分开来,帮助模型更好地理解你的意图。
- 提高效率: 不用每次都写一堆重复的文本,节省了大量时间,特别是当你处理大量类似任务时,效率立马就上去了。
LangChain 里的两种主要提示词模板
在 LangChain 里面,主要有两种类型的提示词模板,它们分别应对不同的使用场景:
-
PromptTemplate:字符串提示词模板这个是最基础、最简单的模板,主要用于那些接收单个文本字符串作为输入的语言模型。你可以把它看作是一个普通的 Python f-string 或者字符串格式化工具。
怎么设计和应用?
用
PromptTemplate,你定义一个包含占位符的字符串作为模板,然后通过传入变量来填充这些占位符。我们来看个例子:
“`python
from langchain.prompts import PromptTemplate1. 定义模板字符串
比如,我们想让模型讲一个特定主题和形容词的笑话
template_string = “””
你是一个擅长讲笑话的AI助手。
请给我讲一个关于{content}的{adjective}笑话。
“””2. 创建 PromptTemplate 实例
LangChain 会自动识别 {content} 和 {adjective} 为输入变量
joke_prompt = PromptTemplate.from_template(template_string)
3. 填充变量并生成最终提示词
final_prompt = joke_prompt.format(content=”鸡”, adjective=”好笑的”)
print(final_prompt)
“`输出会是这样:
你是一个擅长讲笑话的AI助手。
请给我讲一个关于鸡的好笑的笑话。
看到没?{content}和{adjective}就像填空题的空,我们填上具体的值,就得到了一个完整的提示词。你也可以手动指定input_variables列表,不过from_template方法更省事,它会自己推断变量名。应用场景:
* 简单的文本生成任务,比如文章撰写、段落改写、文本摘要等。
* 信息检索和问答系统,将用户问题和背景信息组合成一个清晰的查询。
* 格式化输出,比如要求模型以 JSON 格式返回数据。 -
ChatPromptTemplate:聊天提示词模板现在的很多大语言模型,比如 GPT-4、Claude、Gemini 这些,它们不是简单地接收一个字符串,而是接收一系列“消息”作为输入。 这些消息通常有不同的“角色”,比如系统(
SystemMessage)、人类(HumanMessage)和 AI (AIMessage)。ChatPromptTemplate就是专门为这种聊天模型设计的。怎么设计和应用?
ChatPromptTemplate通过一个消息列表来构建提示词,每个消息都包含角色和内容,内容部分也可以包含变量。来看个例子,我们想要一个 AI 助手扮演一个专业的跑步教练:
“`python
from langchain.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage1. 定义消息列表,包含不同角色的消息
chat_template = ChatPromptTemplate.from_messages(
[
SystemMessage(content=”你是一位专业的跑步教练,名叫帕沃。你会根据用户的训练目标提供个性化的跑步建议。”), # 系统消息,设定AI的身份和基础行为
HumanMessage(content=”你好,帕沃!我的跑步目标是{goal},你有什么建议吗?”), # 人类消息,用户的提问,包含变量 {goal}
AIMessage(content=”没问题,我会根据你的目标提供详细的训练计划。”), # AI消息,模拟AI之前的回复,用于提供上下文
HumanMessage(content=”我最近感觉{feeling},是不是需要调整一下?”) # 另一条人类消息,展示多轮对话
]
)2. 填充变量并生成最终消息列表
messages = chat_template.format_messages(goal=”半马在2小时内”, feeling=”膝盖有点不舒服”)
print(messages)
“`输出会是一个消息对象列表,就像这样:
[SystemMessage(content='你是一位专业的跑步教练,名叫帕沃。你会根据用户的训练目标提供个性化的跑步建议。'),
HumanMessage(content='你好,帕沃!我的跑步目标是半马在2小时内,你有什么建议吗?'),
AIMessage(content='没问题,我会根据你的目标提供详细的训练计划。'),
HumanMessage(content='我最近感觉膝盖有点不舒服,是不是需要调整一下?')]
这些消息列表可以直接传递给聊天模型进行处理。SystemMessage、HumanMessage、AIMessage的作用:
*SystemMessage(系统消息): 设定 AI 的角色、行为、限制和一些全局的指令。比如“你是一个友好的助手”、“只用中文回答”等等。模型会更严格地遵循系统消息的指令。
*HumanMessage(人类消息): 代表用户的输入或提问。
*AIMessage(AI 消息): 代表 AI 的回复。在多轮对话中,它可以用来给模型提供历史对话上下文,让模型更好地理解当前轮次的对话。通过合理地组合这些消息类型,你可以构建出非常灵活和强大的对话流程。
设计优秀提示词模板的关键点
设计一个好的提示词模板,就像写一份清晰的任务说明书。有几个原则,你记住并用上,能让模型表现得更好:
-
清晰明确,不要模糊:
- 直接告诉模型要做什么,不要让它猜。比如,不要只说“写一段关于 AI 的文字”,而要说“给一个10岁小孩写一段关于人工智能的3句话解释”。 具体化你的需求,模型才能给出你想要的答案。
- 用简单的词句,避免复杂的行话或模棱两可的表达。
-
提供足够的上下文:
- 模型不是神,它没有你的背景知识。你给的信息越多,它理解得就越准。比如,你在做问答系统时,除了问题,把相关的文档或段落也提供给模型。
- 在聊天场景中,历史对话记录就是很重要的上下文。
-
指定输出格式:
- 如果你需要特定的输出格式,比如 JSON、列表、或者只有几句话,一定要在模板里明确提出来。 比如,“请用 JSON 格式返回,键包括 ‘title’ 和 ‘summary’”。
- 这对于后续处理模型的输出非常有帮助,可以和 LangChain 的输出解析器(Output Parsers)结合使用。
-
设定约束和限制:
- 告诉模型什么不能做,或者输出的长度限制。比如,“回答不超过100字”、“不要使用专业术语”、“如果不知道,就说不知道,不要胡编乱造”。
- 这能有效减少模型“幻觉”的出现,让输出更可靠。
-
提供少量示例(Few-Shot Examples):
- 有时候,光靠文字描述很难让模型完全理解你的意图,特别是对于一些需要特定风格或复杂逻辑的任务。这时候,给它几个输入-输出的例子,能让它学得更快、更准。
- LangChain 提供了
FewShotPromptTemplate来支持这种模式。你可以提供一个示例列表,然后让模型根据这些例子来生成新的内容。
“`python
from langchain.prompts import PromptTemplate, FewShotPromptTemplate定义示例
examples = [
{“word”: “开心”, “antonym”: “悲伤”},
{“word”: “快速”, “antonym”: “缓慢”},
]定义每个示例的格式
example_prompt = PromptTemplate(
input_variables=[“word”, “antonym”],
template=”词语: {word}n反义词: {antonym}”,
)定义少样本提示词模板
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
suffix=”词语: {input_word}n反义词:”, # 后缀,包含用户输入和待模型完成的部分
input_variables=[“input_word”],
)填充变量
print(few_shot_prompt.format(input_word=”高大”))
“`模型在看到“词语: 高大n反义词:”后,就会根据前面的例子,大概率输出“矮小”。
-
迭代和测试:
- 第一次写的提示词很少是完美的。 好的提示词是不断测试、调整、优化的结果。你可以多尝试几种不同的措辞,看看哪种效果最好。
- LangChain 这样的框架,加上 LangSmith 这样的工具,能帮你更好地管理和迭代你的提示词。
将提示词模板和 LLM 结合起来
光有模板还不够,我们最终目的是要和语言模型交互。在 LangChain 中,你可以轻松地把这些模板和 LLM 链(Chains)结合起来。
举个简单的例子,我们用 ChatPromptTemplate 和一个聊天模型来做个小应用:
“`python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI # 假设你用的是 OpenAI 的模型,也可以是其他模型
定义一个简单的聊天模板
chat_template = ChatPromptTemplate.from_messages([
(“system”, “你是一个非常擅长写短篇故事的作家。”),
(“human”, “请根据以下主题写一个大约100字的故事:{theme}”),
])
初始化一个聊天模型 (你需要设置你的 API key)
llm = ChatOpenAI(temperature=0.7, model_name=”gpt-3.5-turbo”)
将模板和模型组合成一个链
story_chain = chat_template | llm
调用链来生成故事
response = story_chain.invoke({“theme”: “一只迷路的猫”})
print(response.content)
``在这个例子里,chat_template | llm` 就是 LangChain Expression Language (LCEL) 的一个简单应用,它让不同组件之间的数据流动变得非常直观和灵活。 模板负责生成结构化的提示词,然后这个提示词被送入语言模型,模型再返回生成的内容。
一些进阶用法和注意事项
-
局部填充(Partial Prompt Templates):
有时候你可能不是一次性拿到所有变量。你可以先填充一部分变量,生成一个新的“部分模板”,然后等拿到剩余变量后再完全填充。 这在构建复杂链条时很有用。
“`python
from langchain.prompts import PromptTemplateprompt = PromptTemplate(template=”{foo}{bar}”, input_variables=[“foo”, “bar”])
partial_prompt = prompt.partial(foo=”你好”) # 先填充 foo
print(partial_prompt.format(bar=”世界”)) # 再填充 bar输出: 你好世界
``partial_variables` 参数来填充部分变量,甚至用函数来动态生成部分变量的值,比如插入当前日期。
你也可以在初始化时就用 -
自定义模板:
如果你对 LangChain 提供的PromptTemplate或ChatPromptTemplate不满意,你还可以继承StringPromptTemplate或BaseChatPromptTemplate来自定义自己的模板逻辑。 -
安全问题:
在使用一些高级的模板格式(如 Jinja2)时,需要注意安全问题,避免执行有害代码。LangChain 推荐使用更安全的 f-string 格式化方式。
总之,LangChain 的提示词模板是你在构建 LLM 应用时不可或缺的工具。它能让你的提示词管理起来更方便、更高效,也能帮助你的应用更稳定、更智能。多动手尝试,多思考你的任务需要什么样的结构化提示,你的 AI 应用就能更上一层楼。





评论前必须登录!
注册