自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:基础知识]

分类目录:《自然语言处理从入门到应用》总目录


语言模型以文本作为输入,这段文本通常被称为提示(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仅支持jinja2f-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/

相关推荐
热爱跑步的恒川38 分钟前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
阡之尘埃3 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控
孙同学要努力5 小时前
全连接神经网络案例——手写数字识别
人工智能·深度学习·神经网络
Eric.Lee20215 小时前
yolo v5 开源项目
人工智能·yolo·目标检测·计算机视觉
其实吧36 小时前
基于Matlab的图像融合研究设计
人工智能·计算机视觉·matlab
丕羽6 小时前
【Pytorch】基本语法
人工智能·pytorch·python
ctrey_6 小时前
2024-11-1 学习人工智能的Day20 openCV(2)
人工智能·opencv·学习
SongYuLong的博客6 小时前
Air780E基于LuatOS编程开发
人工智能
Jina AI6 小时前
RAG 系统的分块难题:小型语言模型如何找到最佳断点?
人工智能·语言模型·自然语言处理
-派神-6 小时前
大语言模型(LLM)量化基础知识(一)
人工智能·语言模型·自然语言处理