分类目录:《自然语言处理从入门到应用》总目录
语言模型以文本作为输入,这段文本通常被称为提示(Prompt)。通常情况下,这不仅仅是一个硬编码的字符串,而是模板、示例和用户输入的组合。LangChain提供了多个类和函数,以便轻松构建和处理提示。
提示模板的概念
提示模板是指一种可复制的生成提示的方式。它包含一个文本字符串(模板),可以从最终用户处接收一组参数并生成提示。提示模板可能包含以下内容:
- 对语言模型的指令
- 少量示例,以帮助语言模型生成更好的回复
- 对语言模型的问题
以下代码片段是包含了一个提示模板的示例:
dart
from langchain import PromptTemplate
template = """
我希望你能充当新公司的命名顾问。
一个生产{product}的公司的好名字是什么?
"""
prompt = PromptTemplate(
input_variables=["product"],
template=template,
)
prompt.format(product="彩色袜子")
# -> 我希望你能充当新公司的命名顾问。
# -> 一个生产彩色袜子的公司的好名字是什么?
创建提示模板
我们可以使用PromptTemplate
类创建简单的硬编码提示。提示模板可以接受任意数量的输入变量,并且可以进行格式化以生成提示。
dart
from langchain import PromptTemplate
dart
# 没有输入变量的提示示例
no_input_prompt = PromptTemplate(input_variables=[], template="给我讲个笑话。")
no_input_prompt.format()
# -> "给我讲个笑话。"
# 一个输入变量的提示示例
one_input_prompt = PromptTemplate(input_variables=["adjective"], template="给我讲个{adjective}的笑话。")
one_input_prompt.format(adjective="有趣的")
# -> "给我讲个有趣的笑话。"
# 多个输入变量的示例提示
multiple_input_prompt = PromptTemplate(
input_variables=["adjective", "content"],
template="给我讲一个{adjective}的关于{content}的笑话。"
)
multiple_input_prompt.format(adjective="有趣的", content="小鸡")
# -> "给我讲一个有趣的关于小鸡的笑话。"
如果我们不想手动指定input_variables
,还可以使用from_template
类方法创建PromptTemplate
。LangChain将根据传递的template
自动推断input_variables
。
template = "给我讲一个{adjective}的关于{content}的笑话。"
prompt_template = PromptTemplate.from_template(template)
prompt_template.input_variables
# -> ['adjective', 'content']
prompt_template.format(adjective="有趣的", content="小鸡")
# -> 给我讲一个有趣的关于小鸡的笑话。
我们可以创建自定义的提示模板,以任何您想要的方式格式化提示。
模板格式
默认情况下,PromptTemplate
将提供的模板视为Python f-string
。我们可以通过template_format
参数指定其他模板格式:
dart
# 在运行此代码之前,请确保已安装jinja2
jinja2_template = "告诉我一个{{ adjective }}的笑话,关于{{ content }}"
prompt_template = PromptTemplate.from_template(template=jinja2_template, template_format="jinja2")
prompt_template.format(adjective="有趣的", content="鸡")
# -> 告诉我一个有趣的笑话,关于鸡
目前,PromptTemplate
仅支持jinja2
和f-string
模板格式。如果您希望使用其他模板格式,我们可以在GitHub页面上提交需求。
验证模板
默认情况下,PromptTemplate
将通过检查input_variables
是否与模板中定义的变量匹配来验证template
字符串。您可以通过将validate_template
设置为False
来禁用此行为。
dart
template = "我正在学习LangChain,因为{reason}。"
prompt_template = PromptTemplate(template=template, input_variables=["reason", "foo"]) # 由于存在额外的变量而引发ValueError
prompt_template = PromptTemplate(template=template, input_variables=["reason", "foo"], validate_template=False) # 不会引发错误
序列化模板
我们可以将PromptTemplate
保存到本地文件系统中的文件中。LangChain将通过文件扩展名自动推断文件格式。目前,LangChain支持将模板保存为YAML和JSON文件。
dart
prompt_template.save("awesome_prompt.json") # 保存为JSON文件
from langchain.prompts import load_prompt
loaded_prompt = load_prompt("awesome_prompt.json")
assert prompt_template == loaded_prompt
LangChain还支持从LangChainHub加载提示模板,其中包含一系列我们可以在项目中使用的有用提示。
dart
from langchain.prompts import load_prompt
prompt = load_prompt("lc://prompts/conversation/prompt.json")
prompt.format(history="", input="1 + 1等于多少?")
向模板添加Few Shot示例
Few Shot示例是一组可以帮助语言模型生成更好响应的示例。要使用Few Shot示例生成提示,可以使用FewShotPromptTemplate
。此类接受PromptTemplate
和Few Shot示例列表。然后,它使用Few Shot示例格式化提示模板。
在下面示例中,我们将创建一个生成单词反义词的提示。
dart
from langchain import PromptTemplate, FewShotPromptTemplate
# 首先,创建Few Shot示例列表
examples = [
{"word": "happy", "antonym": "sad"},
{"word": "tall", "antonym": "short"},
]
# 接下来,我们指定用于格式化示例的模板。
# 我们使用`PromptTemplate`类来实现这个目的。
example_formatter_template = """Word: {word}
Antonym: {antonym}
"""
example_prompt = PromptTemplate(
input_variables=["word", "antonym"],
template=example_formatter_template,
)
# 最后,创建`FewShotPromptTemplate`对象。
few_shot_prompt = FewShotPromptTemplate(
# 这些是我们要插入到提示中的示例。
examples=examples,
# 这是我们在将示例插入到提示中时要使用的格式。
example_prompt=example_prompt,
# 前缀是出现在提示中示例之前的一些文本。
# 通常,这包括一些说明。
prefix="Give the antonym of every input\n",
# 后缀是出现在提示中示例之后的一些文本。
# 通常,这是用户输入的地方。
suffix="Word: {input}\nAntonym: ",
# 输入变量是整个提示期望的变量。
input_variables=["input"],
# 示例分隔符是我们将前缀、示例和后缀连接在一起的字符串。
example_separator="\n",
)
# 现在,我们可以使用`format`方法生成一个提示。
print(few_shot_prompt.format(input="big"))
# -> Give the antonym of every input
# ->
# -> Word: happy
# -> Antonym: sad
# ->
# -> Word: tall
# -> Antonym: short
# ->
# -> Word: big
# -> Antonym:
选择用于提示模板的示例
如果您有大量示例,可以使用ExampleSelector
选择一部分对语言模型来说最具信息量的示例。这将帮助您生成更有可能获得良好回应的提示。下面,我们将使用LengthBasedExampleSelector
,它根据输入的长度选择示例。当我们担心构建的提示会超过上下文窗口的长度时,这将非常有用。对于较长的输入,它会选择较少的示例进行包含,而对于较短的输入,它会选择更多的示例。我们将继续使用前面部分的示例,但这次我们将使用LengthBasedExampleSelector
来选择示例。
dart
from langchain.prompts.example_selector import LengthBasedExampleSelector
# 这里是一些虚构任务的大量示例,该任务是创建反义词。
examples = [
{"word": "happy", "antonym": "sad"},
{"word": "tall", "antonym": "short"},
{"word": "energetic", "antonym": "lethargic"},
{"word": "sunny", "antonym": "gloomy"},
{"word": "windy", "antonym": "calm"},
]
# 我们将使用`LengthBasedExampleSelector`来选择示例。
example_selector = LengthBasedExampleSelector(
# 这些是可供选择的示例。
examples=examples,
# 这是用于格式化示例的PromptTemplate。
example_prompt=example_prompt,
# 这是格式化示例的最大长度。
max_length=25
# 这是用于获取字符串长度的函数,用于确定包含哪些示例。在这里被注释掉,因为如果没有指定,默认提供了该函数。
# get_text_length: Callable[[str], int] = lambda x: len(re.split("\n| ", x))
)
# 现在,我们可以使用`example_selector`创建`FewShotPromptTemplate`。
dynamic_prompt = FewShotPromptTemplate(
# 我们提供一个ExampleSelector而不是示例。
example_selector=example_selector,
example_prompt=example_prompt,
prefix="给出每个输入的反义词",
suffix="单词:{input}\n反义词:",
input_variables=["input"],
example_separator="\n\n",
)
# 现在,我们可以使用`format`方法生成提示。
print(dynamic_prompt.format(input="big"))
# -> 给出每个输入的反义词
# ->
# -> 单词:happy
# -> 反义词:sad
# ->
# -> 单词:tall
# -> 反义词:short
# ->
# -> 单词:energetic
# -> 反义词:lethargic
# ->
# -> 单词:sunny
# -> 反义词:gloomy
# ->
# -> 单词:windy
# -> 反义词:平静
```python
print(dynamic_prompt.format(input="big"))
# -> 给出每个输入的反义词
# ->
# -> 单词:happy
# -> 反义词:sad
# ->
# -> 单词:tall
# -> 反义词:short
# ->
# -> 单词:energetic
# -> 反义词:lethargic
# ->
# -> 单词:sunny
# -> 反义词:gloomy
# ->
# -> 单词:windy
# -> 反义词:calm
# ->
# -> 单词:big
# -> 反义词:平静
相反,如果我们提供一个非常长的输入,LengthBasedExampleSelector会选择较少的示例包含在提示中。
long_string = "big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else"
print(dynamic_prompt.format(input=long_string))
# -> 给出每个输入的反义词
# ->
# -> 单词:happy
# -> 反义词:sad
# ->
# -> 单词:big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else
# -> 反义词:平静
LangChain附带了一些示例选择器供我们使用,有关如何使用示例选择器,可以参考《自然语言处理从入门到应用------LangChain:提示(Prompts)》系列的后续文章。除此之外,我们还可以创建自定义示例选择器,根据我们想要的任何条件选择示例。
参考文献:
[1] LangChain 🦜️🔗 中文网,跟着LangChain一起学LLM/GPT开发:https://www.langchain.com.cn/
[2] LangChain中文网 - LangChain 是一个用于开发由语言模型驱动的应用程序的框架:http://www.cnlangchain.com/