langchain (Components) v0.2文档(14)如何在大模型中使用few shot examples(中英对照)

146 阅读8分钟

This guide covers how to prompt a chat model with example inputs and outputs. Providing the model with a few such examples is called few-shotting, and is a simple yet powerful way to guide generation and in some cases drastically improve model performance.

本指南介绍如何使用示例输入和输出来提示聊天模型。为模型提供一些这样的示例称为少样本训练,这是一种简单但有效的指导生成方法,在某些情况下可以显著提高模型性能。

There does not appear to be solid consensus on how best to do few-shot prompting, and the optimal prompt compilation will likely vary by model. Because of this, we provide few-shot prompt templates like the FewShotChatMessagePromptTemplate as a flexible starting point, and you can modify or replace them as you see fit.

关于如何最好地进行少样本提示,似乎还没有达成共识,最佳提示编译可能因模型而异。因此,我们提供了少样本提示模板(如 FewShotChatMessagePromptTemplate)作为灵活的起点,您可以根据需要修改或替换它们。

The goal of few-shot prompt templates are to dynamically select examples based on an input, and then format the examples in a final prompt to provide for the model.

几次提示模板的目标是根据输入动态选择示例,然后在最终提示中格式化示例以提供给模型。

Note: The following code examples are for chat models only, since FewShotChatMessagePromptTemplates are designed to output formatted chat messages rather than pure strings. For similar few-shot prompt examples for pure string templates compatible with completion models (LLMs), see the few-shot prompt templates guide.

注意:以下代码示例仅适用于聊天模型,因为 FewShotChatMessagePromptTemplates 旨在输出格式化的聊天消息,而不是纯字符串。有关与完成模型 (LLM) 兼容的纯字符串模板的类似少样本提示示例,请参阅少样本提示模板指南。

Fixed Examples

The most basic (and common) few-shot prompting technique is to use fixed prompt examples. This way you can select a chain, evaluate it, and avoid worrying about additional moving parts in production.

最基本(也是常见)的几次提示技术是使用固定提示示例。这样您就可以选择一条链条,对其进行评估,并避免担心生产中的额外移动部件。

The basic components of the template are:

  • examples: A list of dictionary examples to include in the final prompt.
  • 示例:要包含在最终提示中的字典示例列表
  • example_prompt: converts each example into 1 or more messages through its format_messages method. A common example would be to convert each example into one human message and one AI message response, or a human message followed by a function call message.
  • example_prompt:通过其 format_messages 方法将每个示例转换为 1 条或多条消息。一个常见示例是将每个示例转换为一条人类消息和一条 AI 消息响应,或者一条人类消息后跟一条函数调用消息。

Below is a simple demonstration. First, define the examples you'd like to include. Let's give the LLM an unfamiliar mathematical operator, denoted by the "🦜" emoji:

下面是一个简单的演示。首先,定义您想要包含的示例。让我们给 LLM 一个陌生的数学运算符,用“🦜”表情符号表示:

%pip install -qU langchain langchain-openai langchain-chroma

import os
from getpass import getpass

os.environ["OPENAI_API_KEY"] = getpass()

If we try to ask the model what the result of this expression is, it will fail:

如果我们尝试询问模型该表达式的结果是什么,它将失败:

from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0.0)

model.invoke("What is 2 🦜 9?")

API Reference: ChatOpenAI

AIMessage(content='The expression "2 🦜 9" is not a standard mathematical operation or equation. It appears to be a combination of the number 2 and the parrot emoji 🦜 followed by the number 9. It does not have a specific mathematical meaning.', response_metadata={'token_usage': {'completion_tokens': 54, 'prompt_tokens': 17, 'total_tokens': 71}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-aad12dda-5c47-4a1e-9949-6fe94e03242a-0', usage_metadata={'input_tokens': 17, 'output_tokens': 54, 'total_tokens': 71})

Now let's see what happens if we give the LLM some examples to work with. We'll define some below:

现在让我们看看如果我们给法学硕士一些可以使用的例子会发生什么。我们将在下面定义一些:

from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate

examples = [    {"input": "2 🦜 2", "output": "4"},    {"input": "2 🦜 3", "output": "5"},]

API Reference: ChatPromptTemplate | FewShotChatMessagePromptTemplate

Next, assemble them into the few-shot prompt template.

接下来,将它们组装成少镜头提示模板

# This is a prompt template used to format each individual example.
example_prompt = ChatPromptTemplate.from_messages(
    [
        ("human", "{input}"),
        ("ai", "{output}"),
    ]
)
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

print(few_shot_prompt.invoke({}).to_messages())
[HumanMessage(content='2 🦜 2'), AIMessage(content='4'), HumanMessage(content='2 🦜 3'), AIMessage(content='5')]

Finally, we assemble the final prompt as shown below, passing few_shot_prompt directly into the from_messages factory method, and use it with a model:

最后,我们组装最终的提示,如下所示,将 Few_shot_prompt 直接传递到 from_messages 工厂方法中,并将其与模型一起使用:

final_prompt = ChatPromptTemplate.from_messages(
    [        ("system", "You are a wondrous wizard of math."),        few_shot_prompt,        ("human", "{input}"),    ]
)

And now let's ask the model the initial question and see how it does:

现在让我们向模型提出最初的问题,看看它是如何做的:

from langchain_openai import ChatOpenAI

chain = final_prompt | model

chain.invoke({"input": "What is 2 🦜 9?"})

API Reference: ChatOpenAI

AIMessage(content='11', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 60, 'total_tokens': 61}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-5ec4e051-262f-408e-ad00-3f2ebeb561c3-0', usage_metadata={'input_tokens': 60, 'output_tokens': 1, 'total_tokens': 61})

And we can see that the model has now inferred that the parrot emoji means addition from the given few-shot examples!

我们可以看到,该模型现在已经从给定的几个例子中推断出鹦鹉表情符号意味着加法!

Dynamic few-shot prompting 动态几次提示

Sometimes you may want to select only a few examples from your overall set to show based on the input. For this, you can replace the examples passed into FewShotChatMessagePromptTemplate with an example_selector. The other components remain the same as above! Our dynamic few-shot prompt template would look like:

有时您可能希望根据输入从整体集合中仅选择几个示例来显示。为此,您可以将传递到 FewShotChatMessagePromptTemplate 的示例替换为 example_selector。其他组件与上述相同!我们的动态少样本提示模板如下所示:

  • example_selector: responsible for selecting few-shot examples (and the order in which they are returned) for a given input. These implement the BaseExampleSelector interface. A common example is the vectorstore-backed SemanticSimilarityExampleSelector
  • example_selector:负责为给定的输入选择少样本示例(以及返回它们的顺序)。这些示例实现了 BaseExampleSelector 接口。一个常见示例是 vectorstore 支持的 SemanticSimilarityExampleSelector
  • example_prompt: convert each example into 1 or more messages through its format_messages method. A common example would be to convert each example into one human message and one AI message response, or a human message followed by a function call message.
  • example_prompt:通过其 format_messages 方法将每个示例转换为 1 条或多条消息。一个常见的例子是将每个示例转换为一条人类消息和一条 AI 消息响应,或者一条人类消息后跟一条函数调用消息。

These once again can be composed with other messages and chat templates to assemble your final prompt.

这些可以再次与其他消息和聊天模板组合以组合您的最终提示。

Let's walk through an example with the SemanticSimilarityExampleSelector. Since this implementation uses a vectorstore to select examples based on semantic similarity, we will want to first populate the store. Since the basic idea here is that we want to search for and return examples most similar to the text input, we embed the values of our prompt examples rather than considering the keys:

让我们通过 SemanticSimilarityExampleSelector 来看一个示例。由于此实现使用 vectorstore 根据语义相似性选择示例,因此我们首先需要填充该存储。由于这里的基本思想是我们希望搜索并返回与文本输入最相似的示例,因此我们嵌入了提示示例的值,而不是考虑键:

from langchain_chroma import Chroma
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings

examples = [
    {"input": "2 🦜 2", "output": "4"},
    {"input": "2 🦜 3", "output": "5"},
    {"input": "2 🦜 4", "output": "6"},
    {"input": "What did the cow say to the moon?", "output": "nothing at all"},
    {
        "input": "Write me a poem about the moon",
        "output": "One for the moon, and one for me, who are we to talk about the moon?",
    },
]

to_vectorize = [" ".join(example.values()) for example in examples]
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_texts(to_vectorize, embeddings, metadatas=examples)

API Reference: SemanticSimilarityExampleSelector | OpenAIEmbeddings

Create the example_selector 创建 example_selector

With a vectorstore created, we can create the example_selector. Here we will call it in isolation, and set k on it to only fetch the two example closest to the input.

创建向量存储后,我们可以创建 example_selector。这里我们将单独调用它,并在其上设置 k 以仅获取最接近输入的两个示例。

example_selector = SemanticSimilarityExampleSelector(
    vectorstore=vectorstore,
    k=2,
)

# The prompt template will load examples by passing the input do the `select_examples` method
example_selector.select_examples({"input": "horse"})
[{'input': 'What did the cow say to the moon?', 'output': 'nothing at all'}, {'input': '2 🦜 4', 'output': '6'}]

Create prompt template

We now assemble the prompt template, using the example_selector created above.

创建向量存储后,我们可以创建 example_selector。这里我们将单独调用它,并在其上设置 k 以仅获取最接近输入的两个示例

from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate

# Define the few-shot prompt.
few_shot_prompt = FewShotChatMessagePromptTemplate(
    # The input variables select the values to pass to the example_selector
    input_variables=["input"],
    example_selector=example_selector,
    # Define how each example will be formatted.
    # In this case, each example will become 2 messages:
    # 1 human, and 1 AI
    example_prompt=ChatPromptTemplate.from_messages(
        [("human", "{input}"), ("ai", "{output}")]
    ),
)

print(few_shot_prompt.invoke(input="What's 3 🦜 3?").to_messages())

API Reference: ChatPromptTemplate | FewShotChatMessagePromptTemplate

[HumanMessage(content='2 🦜 3'), AIMessage(content='5'), HumanMessage(content='2 🦜 4'), AIMessage(content='6')]

And we can pass this few-shot chat message prompt template into another chat prompt template:

我们可以将这个几次聊天消息提示模板传递到另一个聊天提示模板中:

final_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a wondrous wizard of math."),
        few_shot_prompt,
        ("human", "{input}"),
    ]
)

print(few_shot_prompt.invoke(input="What's 3 🦜 3?"))
messages=[HumanMessage(content='2 🦜 3'), AIMessage(content='5'), HumanMessage(content='2 🦜 4'), AIMessage(content='6')]

Use with an chat model

Finally, you can connect your model to the few-shot prompt.

最后,您可以将模型连接到小样本提示。

chain = final_prompt | ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0.0)

chain.invoke({"input": "What's 3 🦜 3?"})
AIMessage(content='6', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 60, 'total_tokens': 61}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-d1863e5e-17cd-4e9d-bf7a-b9f118747a65-0', usage_metadata={'input_tokens': 60, 'output_tokens': 1, 'total_tokens': 61})