( 教学 )Agent 构建 Prompt(提示词)1. 提示词模板 (Prompt Template)
概述
本教程介绍如何使用 LangChain 创建和利用提示词模板。
提示词模板对于生成动态和灵活的提示词至关重要,可以满足各种用例,如对话历史、结构化输出和专门查询。
在本教程中,我们将探索创建 PromptTemplate 对象的方法、应用部分变量、通过 YAML 文件管理模板,以及利用 ChatPromptTemplate 和 MessagePlaceholder 等高级工具来增强功能。
目录
- 概述
- 环境设置
- 创建 PromptTemplate 对象
- 使用 partial_variables
- 从 YAML 文件加载提示词模板
- ChatPromptTemplate
- MessagePlaceholder
参考资料
环境设置
from langchain_opentutorial import set_env
import os
set_env(
{
"SILICONFLOW_API_KEY": "sk-iicnuzmyqazacwyccxiuvrabsntjornquscpjahkroumtrejlm",
"LANGCHAIN_API_KEY": "lsv2_pt_4d17a25d71cc1742e5bbc873dff250fd3b_f270ba14bd",
"LANGFUSE_SECRET_KEY": "sk-lf-46214e7a-04aa-45c8-bdfd255-12be4d38c961",
"LANGFUSE_PUBLIC_KEY": "pk-lf-1915c079-8019-4a16-9df878-d7484594c43b",
"LANGFUSE_HOST": "https://cloud.langfuse.com",
"TAVILY_API_KEY": "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",
"LANGCHAIN_API_KEY": "lsv2_pt_4d17a25d711742e5bsdbc8bb73dff250fd3b_f270ba14bd",
"LANGCHAIN_TRACING_V2": "true",
"LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
"LANGCHAIN_PROJECT": "",
}
)
Environment variables have been set successfully.
让我们设置 ChatOpenAI 与 gpt-4o 模型。
from langchain_openai import ChatOpenAI
# 加载模型
Qwen2_5_7B_Instruct_llm = ChatOpenAI(
temperature=0.1, # 控制输出的随机性和创造性,值越低输出越稳定可预测,值越高输出越有创意但可能偏离预期 (范围: 0.0 ~ 2.0)
model_name="Qwen/Qwen2.5-7B-Instruct", # 硅基流动支持的模型名称
openai_api_key=os.getenv("SILICONFLOW_API_KEY"), # 从环境变量获取API密钥
openai_api_base="https://api.siliconflow.cn/v1" # 硅基流动API的基础URL
)
创建 PromptTemplate 对象
有两种方法可以创建 PromptTemplate 对象。
-
- 使用
from_template()方法
- 使用
-
- 一次性创建
PromptTemplate对象和提示词
- 一次性创建
方法 1. 使用 from_template() 方法
- 使用变量
{variable}定义模板。
from langchain_core.prompts import PromptTemplate
# 定义模板。在这种情况下,{country} 是一个变量
template = "{country}的首都是哪里?"
# 使用 `from_template` 方法创建 `PromptTemplate` 对象
prompt = PromptTemplate.from_template(template)
prompt
PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='What is the capital of {country}?')
您可以通过为变量 country 赋值来完成提示词。
# 创建提示词。使用 `format` 方法为变量赋值
prompt = prompt.format(country="美国")
prompt
'What is the capital of United States of America?'
# 定义模板
template = "{country}的首都是哪里?"
# 使用 `from_template` 方法创建 `PromptTemplate` 对象
prompt = PromptTemplate.from_template(template)
# 创建链
chain = prompt | Qwen2_5_7B_Instruct_llm
# 用您选择的国家名称替换 country 变量
chain.invoke("美国").content
'The capital of the United States of America is Washington, D.C.'
方法 2. 一次性创建 PromptTemplate 对象和提示词
明确指定 input_variables 以进行额外验证。
否则,这些变量与模板字符串中的变量之间的不匹配可能会在实例化时引发异常。
# 定义模板
template = "{country}的首都是哪里?"
# 使用 `PromptTemplate` 对象创建提示词模板
prompt = PromptTemplate(
template=template,
input_variables=["country"],
)
prompt
PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}的首都是哪里?')
# 创建提示词
prompt.format(country="美国")
'美国的首都是哪里?'
# 定义模板
template = "{country1} 和 {country2} 的首都分别是哪里?"
# 使用 `PromptTemplate` 对象创建提示词模板
prompt = PromptTemplate(
template=template,
input_variables=["country1"],
partial_variables={
"country2": "美国" # 以字典形式传递 `partial_variables`
},
)
prompt
PromptTemplate(input_variables=['country1'], input_types={}, partial_variables={'country2': '美国'}, template='{country1} 和 {country2} 的首都分别是哪里?')
prompt.format(country1="北京")
'北京的首都是哪里?美国的首都是哪里?'
prompt_partial = prompt.partial(country2="India")
prompt_partial
PromptTemplate(input_variables=['country1'], input_types={}, partial_variables={'country2': '印度'}, template='{country1} 和 {country2} 的首都分别是哪里?')
prompt_partial.format(country1="北京")
'北京的首都是哪里?印度的首都是哪里?'
chain = prompt_partial | Qwen2_5_7B_Instruct_llm
chain.invoke("美国").content
'美国的首都是华盛顿特区,印度的首都是新德里。'
chain.invoke({"country1": "北京", "country2": "印度"}).content
'北京的首都是北京,印度的首都是新德里。'
使用 partial_variables
使用 partial_variables,您可以部分应用函数。这在有共享变量需要共享时特别有用。
常见的例子是日期或时间。
假设您想在提示词中指定当前日期,将日期硬编码到提示词中或与其他输入变量一起传递可能不太实际。在这种情况下,使用返回当前日期的函数来部分修改提示词会更加方便。
from datetime import datetime
# 打印当前日期
datetime.now().strftime("%B %d")
'January 14'
# 定义返回当前日期的函数
def get_today():
return datetime.now().strftime("%B %d")
prompt = PromptTemplate(
template="今天是{today}。请列出{today}出生的{num}个名人。请指定他们的出生日期。",
input_variables=["num"],
partial_variables={
"today": get_today # 以字典形式传递 `partial_variables`
},
)
# 创建提示词
prompt.format(n=3)
'今天是January 14。请列出14月14日出生的3个名人。请指定他们的出生日期。'
# 创建链
chain = prompt | Qwen2_5_7B_Instruct_llm
# 调用链并检查结果
print(chain.invoke(3).content)
以下是三位出生于1月14日的名人: 1. **戴夫·格罗尔(Dave Grohl)** —— 出生于1969年1月14日。 2. **LL Cool J** —— 出生于1968年1月14日。 3. **杰森·贝特曼(Jason Bateman)** —— 出生于1969年1月14日。
# 调用链并检查结果
print(chain.invoke({"today": "Jan 02", "num": 3}).content)
以下是两位出生于1月2日的名人: 1. ** Cuba Gooding Jr. ** —— 出生于1968年1月2日。 2. ** Taye Diggs ** —— 出生于1971年1月2日。 3. ** Kate Bosworth ** —— 出生于1983年1月2日。
从 YAML 文件加载提示词模板
您可以在单独的 yaml 文件中管理提示词模板,并使用 load_prompt 加载。
from langchain_core.prompts import load_prompt
prompt = load_prompt("prompts/fruit_color.yaml", encoding="utf-8")
prompt
PromptTemplate(input_variables=['fruit'], input_types={}, partial_variables={}, template='{fruit}是什么颜色的?')
prompt.format(fruit="an apple")
'苹果是红色的。'
prompt2 = load_prompt("prompts/capital.yaml")
print(prompt2.format(country="美国"))
请提供关于美利坚合众国首都的信息。
按照以下格式,在300字以内总结首都的特点。
----
[格式]
1. 面积
2. 人口
3. 历史遗迹
4. 地方特产
#答案:
ChatPromptTemplate
ChatPromptTemplate 可用于将对话历史作为提示词包含在内。
消息以元组格式 (role , message ) 结构化,并作为列表创建。
角色
system: 系统设置消息,通常用于与全局设置相关的提示词。human: 用户输入消息。ai: AI 响应消息。
from langchain_core.prompts import ChatPromptTemplate
chat_prompt = ChatPromptTemplate.from_template("{country}的首都是哪里?")
chat_prompt
ChatPromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['country'], input_types={}, partial_variables={}, template='{country}的首都是哪里?'), additional_kwargs={})])
chat_prompt.format(country="美国")
'美国的首都是华盛顿特区。'
from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages(
[
# 角色, 消息
("system", "你是一个友好的 AI 助手,你的名字是 {name}。"),
("human", "很高兴认识你!"),
("ai", "你好!有什么可以帮你的吗?"),
("human", "{user_input}"),
]
)
# 创建聊天消息
messages = chat_template.format_messages(name="Teddy", user_input="你好,我想知道你的名字。")
messages
[SystemMessage(content='你是一个友好的 AI 助手,你的名字是 Teddy。', additional_kwargs={}, response_metadata={}),
HumanMessage(content='很高兴认识你!', additional_kwargs={}, response_metadata={}),
AIMessage(content='你好!有什么可以帮你的吗?', additional_kwargs={}, response_metadata={}),
HumanMessage(content='请问你的名字是什么?', additional_kwargs={}, response_metadata={})]
您可以直接使用上面创建的消息调用 LLM。
llm.invoke(messages).content
'你好,我是 Teddy。有什么我可以帮助你的吗?'
您还可以创建链来执行。
chain = chat_template | llm
chain.invoke({"name": "Teddy", "user_input": "你好,我想知道你的名字。"}).content
'你好,我是 Teddy。有什么我可以帮助你的吗?'
MessagePlaceholder
LangChain 还提供了 MessagePlaceholder,它在格式化期间提供对消息渲染的完全控制。
如果不确定在消息提示词模板中使用哪些角色,或者您想在格式化期间插入消息列表,这将非常有用。
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
chat_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"你是一位专业的对话摘要 AI 助手,你的任务是用要点总结对话内容。",
),
MessagesPlaceholder(variable_name="conversation"),
("human", "请用 {word_count} 个词总结到目前为止的对话。"),
]
)
chat_prompt
ChatPromptTemplate(input_variables=['conversation', 'word_count'], input_types={'conversation': list[typing.Annotated[typing.Union[typing.Annotated[langchain_core.messages.ai.AIMessage, Tag(tag='ai')], typing.Annotated[langchain_core.messages.human.HumanMessage, Tag(tag='human')], typing.Annotated[langchain_core.messages.chat.ChatMessage, Tag(tag='chat')], typing.Annotated[langchain_core.messages.system.SystemMessage, Tag(tag='system')], typing.Annotated[langchain_core.messages.function.FunctionMessage, Tag(tag='function')], typing.Annotated[langchain_core.messages.tool.ToolMessage, Tag(tag='tool')], typing.Annotated[langchain_core.messages.ai.AIMessageChunk, Tag(tag='AIMessageChunk')], typing.Annotated[langchain_core.messages.human.HumanMessageChunk, Tag(tag='HumanMessageChunk')], typing.Annotated[langchain_core.messages.chat.ChatMessageChunk, Tag(tag='ChatMessageChunk')], typing.Annotated[langchain_core.messages.system.SystemMessageChunk, Tag(tag='SystemMessageChunk')], typing.Annotated[langchain_core.messages.function.FunctionMessageChunk, Tag(tag='FunctionMessageChunk')], typing.Annotated[langchain_core.messages.tool.ToolMessageChunk, Tag(tag='ToolMessageChunk')]], FieldInfo(annotation=NoneType, required=True, discriminator=Discriminator(discriminator=, custom_error_type=None, custom_error_message=None, custom_error_context=None))]]}, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a summarization specialist AI assistant. Your mission is to summarize conversations using key points.'), additional_kwargs={}), MessagesPlaceholder(variable_name='conversation'), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['word_count'], input_types={}, partial_variables={}, template='Summarize the conversation so far in {word_count} words.'), additional_kwargs={})])
可以使用 MessagesPlaceholder 添加对话消息列表。
formatted_chat_prompt = chat_prompt.format(
word_count=5,
conversation=[
("human", "你好!我是 Teddy,很高兴认识你。"),
("ai", "很高兴认识你!期待与你合作。"),
],
)
print(formatted_chat_prompt)
系统:你是一位专业的对话摘要 AI 助手,你的任务是用要点总结对话内容。
人类:你好!我是 Teddy,很高兴认识你。
AI:很高兴认识你!期待与你合作。
人类:请用 5 个词总结到目前为止的对话。
# 创建链
chain = chat_prompt | Qwen2_5_7B_Instruct_llm | StrOutputParser()
# 调用链并检查结果
chain.invoke(
{
"word_count": 5,
"conversation": [
(
"human",
"你好!我是 Teddy,很高兴认识你。",
),
("ai", "很高兴认识你!期待与你合作。"),
],
}
)
'Teddy 介绍自己,互相问候。'