Prompt组件的基本组成
大多数LLM应用程序都不会直接将用户输入传递给LLM,通常,它们会将用户输入添加到一个更大的文本片段中,称为提示模版,该模版提供有关特定任务的附加上下文。并且Prompt是所有AI应用交互的起点,以下是LangChain中一个最基础的聊天应用机器人的运行流程如下:

为了适配不同的 LLM,LangChain 封装了 Prompt 组件,并且 Prompt 组件是高可移植性的,同一个 Prompt 可以支持各种 LLM,在切换 LLM 的时候,无需修改Prompt。在 LangChain 中,Prompt 被分成了两大类:
- Prompt Template:将 Prompt 按照 template 进行一定格式化,针对 Prompt 进行变量处理以及提示词的组合。
- Selectors:根据不同条件去选择不同提示词,或者在不同情况下通过 Selector,选择不同示例去进一步提高 Prompt 支持能力。
本质上 Selectors 只是 Prompt Template 的二次封装,所以在课程中会重点使用 Prompt Template,因为 Selectors 使用范围太窄了,应用场景太小。
对于 Prompt Template,在 LangChain 中,又涵盖了多个子组件,例如:角色提示模板、消息占位符、文本提示模板、聊天消息提示模板、提示、消息等,Prompt Template 的运行流程如下:

不同 Prompt 组件功能的简介
- PromptTemplate:用于创建文本消息提示模板,用于与大语言模型 / 文本生成模型进行交互。
- ChatPromptTemplate:用于创建聊天消息提示模板,一般用于与聊天模型进行交互。
- MessagePlaceholder:消息占位符,在聊天模型中对不确定是否需要的消息进行占位。
- SystemMessagePromptTemplate:用于创建系统消息提示模板,角色为系统。
- HumanMessagePromptTemplate:用于创建人类消息提示模板,角色为人类。
- AIMessagePromptTemplate:用于创建 AI 消息提示模板,角色为 AI。
- PipelinePromptTemplate:用于创建管道消息,管道消息可以将提示模板作为变量进行快速复用。
Prompt 不同方法的功能简介
- partial:用于格式化提示模板中的部分变量。
- format:传递变量数据,格式化提示模板为文本消息。
- invoke:传递变量字典,格式化提示模板为提示。
- to_string:将提示 / 消息提示列表转换成字符串。
- to_messages:用于将消息提示列表转换成消息对象列表。
Prompt 中重载的运算符
-
- 运算符:在 Prompt 组件中,对 + 运算符使用 add 方法进行重写,所以几乎所有 Prompt 组件都可以使用 + 进行组装拼接。
Prompt组件的格式化
在 Prompt 组件中,默认使用 f-string 方法来格式化变量。f-string 是 Python 3.6 以后版本中引入的一种特性,用于在字符串中插入表达式的值,语法简洁,直接利用 {} 花括号包裹变量或者表达式,即可执行简单的运算,性能较好,但是只限用在 Python 中。
例如:在传入的提示模板中,使用 {variable_name} 来定义提示模板内的变量,在模板中定义了多少个变量,调用时就需要传递多少个变量对应的值,如下:
python
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
prompt = PromptTemplate.from_template("请将一个关于{subject}的笑话")
print(prompt.format(subject="程序员"))
jinja2 常被应用于网页开发,与 Flask 和 Django 等框架结合使用。它不仅支持变量替换,还支持其他的控制结构(例如循环和条件语句)以及自定义过滤器和宏等高级功能。此外,它的可用性范围更广,可在多种语境下使用。但与 f-string 不同,使用 jinja2 需要安装相应的库。
python
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
prompt = PromptTemplate.from_template("请将一个关于{{ subject }}的笑话", template_format="jinja2")
print(prompt.format(subject="程序员"))
Prompt使用实例
基础用法
python
from langchain_core.prompts import (
PromptTemplate,
ChatPromptTemplate,
MessagesPlaceholder,
HumanMessagePromptTemplate
)
from datetime import datetime
from langchain_core.messages import AIMessage
prompt = PromptTemplate.from_template("请将一个关于{subject}的冷笑话")
print(prompt.format(subject="程序员"))
prompt_value = prompt.invoke({ "subject": "休息休息吧" })
print(prompt_value.to_string())
print(prompt_value.to_messages())
print("=========================================")
chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是openAI开发的聊天机器人,请根据用户的提问进行回复,当前的时间为:{now}"),
# 有时候可能还有其他的消息,但是不确定
MessagesPlaceholder("chat_history"),
HumanMessagePromptTemplate.from_template("请讲一个关于{subject}的冷笑话")
]).partial(now = datetime.now())
chat_prompt_value = chat_prompt.invoke({
# "now": datetime.now(),
"chat_history": [
("human", "我叫钱多多"),
AIMessage("你好,我是ChatGtp, 有什么可以帮助到你")
],
"subject": "程序员"
})
print(chat_prompt_value)
print(chat_prompt_value.to_string())
字符串提示拼接
代码
python
from langchain_core.prompts import PromptTemplate
prompt = (
PromptTemplate.from_template("请将一个关于{subject}的冷笑话")
+ ", 让我开心下"
+ "\n使用{language}语言。"
)
print(prompt)
print(prompt.format(subject="程序员", language="中文"))
输出:
python
input_variables=['language', 'subject'] template='请将一个关于{subject}的冷笑话, 让我开心下\n使用{language}语言。'
请将一个关于程序员的冷笑话,让我开心下
使用中文语言。
聊天提示拼接
python
from langchain_core.prompts import ChatPromptTemplate
system_chat_prompt = ChatPromptTemplate.from_messages([
("system", "你是OpenAI开发的聊天机器人,请根据用户的提问进行回复,我叫{username}")
])
human_chat_prompt = ChatPromptTemplate.from_messages([
("human", "{query}")
])
chat_prompt = system_chat_prompt + human_chat_prompt
print(chat_prompt.invoke({
"username": "莫小课",
"query": "你好,你是?"
}))
复用提示模版
python
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambda
full_template = PromptTemplate.from_template("""
{example}
{start}
""")
# 描述模版
instruction_prompt = PromptTemplate.from_template("你正在模拟{person}")
# 实例模版
example_prompt = PromptTemplate.from_template("""下面是一个交互例子:
Q:{example_q}
A:{example_a}
""")
# 开始模版
start_prompt = PromptTemplate.from_template("""现在,你是一个真实的人,请回答用户的问题:
Q:{input}
A:
""")
pipeline_prompts = [
("instruction", instruction_prompt),
("example", example_prompt),
("start", start_prompt),
]
def pipeline_prompt_func(inputs: dict):
instruction = instruction_prompt.invoke(inputs).text
example = example_prompt.invoke(inputs).text
start = start_prompt.invoke(inputs).text
return full_template.invoke({
"instruction": instruction,
"example": example,
"start": start
}).text
pipeline_prompt = RunnableLambda(pipeline_prompt_func)
print(pipeline_prompt.invoke({
"person": "雷军",
"example_q": "你最喜欢的汽车是什么?",
"example_a": "小米su7",
"input": "你最喜欢的手机是什么"
}))