LangChain手册(Python版)11模块:提示模板
AI魔法学院
2023-06-16
分享海报

语言模型将文本作为输入——该文本通常被称为提示。通常这不是简单的硬编码字符串,而是模板、一些示例和用户输入的组合。LangChain 提供了几个类和函数来简化提示的构建和使用。

提供了以下文档部分:

  • 入门:概述 LangChain 提供的用于处理和构建提示的所有功能。
  • 操作指南:操作指南的集合。这些突出显示了如何使用我们的提示类实现各种目标。
  • 参考:所有提示类的 API 参考文档。

开始

在本教程中,我们将了解:

  • 提示模板是什么,为什么需要它,
  • 如何创建提示模板,
  • 如何将几个镜头示例传递给提示模板,
  • 如何为提示模板选择示例。

什么是提示模板?

提示模板是指生成提示的可重现方式。它包含一个文本字符串(“模板”),可以从最终用户那里获取一组参数并生成提示。

提示模板可能包含:

  • 语言模型的指令,
  • 一组少量的示例,以帮助语言模型生成更好的响应,
  • 语言模型的问题。

以下代码片段包含一个提示模板示例:

from langchain import PromptTemplate


template = """
I want you to act as a naming consultant for new companies.
What is a good name for a company that makes {product}?
"""

prompt = PromptTemplate(
    input_variables=["product"],
    template=template,
)
prompt.format(product="colorful socks")
# -》 I want you to act as a naming consultant for new companies.
# -》 What is a good name for a company that makes colorful socks?

创建提示模板

您可以使用该类创建简单的硬编码提示PromptTemplate。提示模板可以采用任意数量的输入变量,并且可以格式化以生成提示。

from langchain import PromptTemplate

# An example prompt with no input variables
no_input_prompt = PromptTemplate(input_variables=[], template="Tell me a joke.")
no_input_prompt.format()
# -》 "Tell me a joke."

# An example prompt with one input variable
one_input_prompt = PromptTemplate(input_variables=["adjective"], template="Tell me a {adjective} joke.")
one_input_prompt.format(adjective="funny")
# -》 "Tell me a funny joke."

# An example prompt with multiple input variables
multiple_input_prompt = PromptTemplate(
    input_variables=["adjective", "content"], 
    template="Tell me a {adjective} joke about {content}."
)
multiple_input_prompt.format(adjective="funny", content="chickens")
# -》 "Tell me a funny joke about chickens."

如果您不想input_variables手动指定,您也可以创建一个PromptTemplate使用from_template类方法。将根据传递的langchain自动推断。input_variablestemplate

template = "Tell me a {adjective} joke about {content}."

prompt_template = PromptTemplate.from_template(template)
prompt_template.input_variables
# -》 ['adjective', 'content']
prompt_template.format(adjective="funny", content="chickens")
# -》 Tell me a funny joke about chickens.

您可以创建自定义提示模板,以您想要的任何方式格式化提示。有关详细信息,请参阅自定义提示模板。

模板格式

默认情况下,PromptTemplate会将提供的模板视为 Python f 字符串。您可以通过参数指定其他模板格式template_format:

# Make sure jinja2 is installed before running this

jinja2_template = "Tell me a {{ adjective }} joke about {{ content }}"
prompt_template = PromptTemplate.from_template(template=jinja2_template, template_format="jinja2")

prompt_template.format(adjective="funny", content="chickens")
# -》 Tell me a funny joke about chickens.

目前,PromptTemplate仅支持jinja2和f-string模板格式。如果您想使用任何其他模板格式,请随时在Github页面中提出问题。

验证模板

默认情况下,PromptTemplate将template通过检查是否input_variables匹配中定义的变量来验证字符串template。validate_template您可以通过设置来禁用此行为False

template = "I am learning langchain because {reason}."

prompt_template = PromptTemplate(template=template, 
                                 input_variables=["reason", "foo"]) # ValueError due to extra variables
prompt_template = PromptTemplate(template=template, 
                                 input_variables=["reason", "foo"], 
                                 validate_template=False) # No error

序列化提示模板

您可以将您的文件保存PromptTemplate到本地文件系统中的文件中。langchain会通过文件扩展名自动推断文件格式。目前langchain支持将模板保存为 YAML 和 JSON 文件。

prompt_template.save("awesome_prompt.json") # Save to JSON file
from langchain.prompts import load_prompt
loaded_prompt = load_prompt("awesome_prompt.json")

assert prompt_template == loaded_prompt

langchain还支持从 LangChainHub 加载提示模板,里面包含了一组有用的提示,你可以在你的项目中使用。您可以在此处阅读有关 LangChainHub 及其可用提示的更多信息。


from langchain.prompts import load_prompt

prompt = load_prompt("lc://prompts/conversation/prompt.json")
prompt.format(history="", input="What is 1 + 1?")

您可以在如何序列化提示中了解有关序列化提示模板的更多信息。

将几个镜头示例传递给提示模板

Few shot examples 是一组示例,可以用来帮助语言模型生成更好的响应。

要生成带有少量镜头示例的提示,您可以使用FewShotPromptTemplate. 这个类接受一个PromptTemplate和几个镜头示例的列表。然后它用几个镜头示例格式化提示模板。

在这个例子中,我们将创建一个提示来生成单词反义词。

from langchain import PromptTemplate, FewShotPromptTemplate


# First, create the list of few shot examples.
examples = [
    {"word": "happy", "antonym": "sad"},
    {"word": "tall", "antonym": "short"},
]

# Next, we specify the template to format the examples we have provided.
# We use the `PromptTemplate` class for this.
example_formatter_template = """
Word: {word}
Antonym: {antonym}\n
"""
example_prompt = PromptTemplate(
    input_variables=["word", "antonym"],
    template=example_formatter_template,
)

# Finally, we create the `FewShotPromptTemplate` object.
few_shot_prompt = FewShotPromptTemplate(
    # These are the examples we want to insert into the prompt.
    examples=examples,
    # This is how we want to format the examples when we insert them into the prompt.
    example_prompt=example_prompt,
    # The prefix is some text that goes before the examples in the prompt.
    # Usually, this consists of intructions.
    prefix="Give the antonym of every input",
    # The suffix is some text that goes after the examples in the prompt.
    # Usually, this is where the user input will go
    suffix="Word: {input}\nAntonym:",
    # The input variables are the variables that the overall prompt expects.
    input_variables=["input"],
    # The example_separator is the string we will use to join the prefix, examples, and suffix together with.
    example_separator="\n\n",
)

# We can now generate a prompt using the `format` method.
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示例。

from langchain.prompts.example_selector import LengthBasedExampleSelector


# These are a lot of examples of a pretend task of creating antonyms.
examples = [
    {"word": "happy", "antonym": "sad"},
    {"word": "tall", "antonym": "short"},
    {"word": "energetic", "antonym": "lethargic"},
    {"word": "sunny", "antonym": "gloomy"},
    {"word": "windy", "antonym": "calm"},
]

# We'll use the `LengthBasedExampleSelector` to select the examples.
example_selector = LengthBasedExampleSelector(
    # These are the examples is has available to choose from.
    examples=examples, 
    # This is the PromptTemplate being used to format the examples.
    example_prompt=example_prompt, 
    # This is the maximum length that the formatted examples should be.
    # Length is measured by the get_text_length function below.
    max_length=25,
)

# We can now use the `example_selector` to create a `FewShotPromptTemplate`.
dynamic_prompt = FewShotPromptTemplate(
    # We provide an ExampleSelector instead of examples.
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="Give the antonym of every input",
    suffix="Word: {input}\nAntonym:",
    input_variables=["input"],
    example_separator="\n\n",
)

# We can now generate a prompt using the `format` method.
print(dynamic_prompt.format(input="big"))
# -》 Give the antonym of every input
# -》
# -》 Word: happy
# -》 Antonym: sad
# -》
# -》 Word: tall
# -》 Antonym: short
# -》
# -》 Word: energetic
# -》 Antonym: lethargic
# -》
# -》 Word: sunny
# -》 Antonym: gloomy
# -》
# -》 Word: windy
# -》 Antonym: calm
# -》
# -》 Word: big
# -》 Antonym:

相反,如果我们提供很长的输入,系统
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))
# -》 Give the antonym of every input

# -》 Word: happy
# -》 Antonym: sad
# -》
# -》 Word: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else
# -》 Antonym:

LangChain 附带了一些您可以使用的示例选择器。有关如何使用它们的更多详细信息,请参阅示例选择器。

您可以创建自定义示例选择器,根据您想要的任何条件选择示例。有关如何执行此操作的更多详细信息,请参阅创建自定义示例选择器。

操作指南

如果您是该库的新手,您可能希望从Quickstart开始。

此处的用户指南显示了更高级的工作流程以及如何以不同方式使用该库。

  • 连接到特征存储
  • 如何创建自定义提示模板
  • 如何创建使用少量镜头示例的提示模板
  • 如何使用部分提示模板
  • 如何序列化提示

连接到特征存储

特征存储是传统机器学习的一个概念,它确保输入模型的数据是最新的和相关的。有关更多信息,请参见此处。

在考虑将 LLM 应用程序投入生产时,这个概念非常重要。为了个性化 LLM 应用程序,您可能希望将 LLM 与有关特定用户的最新信息结合起来。特征存储是保持数据最新的好方法,LangChain 提供了一种将该数据与 LLM 结合的简单方法。

在此笔记本中,我们将展示如何将提示模板连接到特征存储。基本思想是从提示模板内部调用特征存储来检索值,然后将这些值格式化为提示。

盛宴

首先,我们将使用流行的开源特征存储框架Feast。

这假设您已经运行了 README 中关于入门的步骤。我们将在入门部分构建该示例,并创建和 LLMChain 以向特定驱动程序写入有关其最新统计数据的注释。

加载盛宴商店

同样,这应该根据 Feast README 中的说明进行设置

from feast import FeatureStore

# You may need to update the path depending on where you stored it
feast_repo_path = "../../../../../my_feature_repo/feature_repo/"
store = FeatureStore(repo_path=feast_repo_path)

提示

在这里,我们将设置一个自定义的 FeastPromptTemplate。此提示模板将接受一个驱动程序 ID,查找他们的统计数据,并将这些统计数据格式化为提示。

请注意,此提示模板的输入只是driver_id,因为这是唯一的用户定义部分(所有其他变量都在提示模板内查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate
template = """Given the driver's up to date stats, write them note relaying those stats to them.
If they have a conversation rate above .5, give them a compliment. Otherwise, make a silly joke about chickens at the end to make them feel better

Here are the drivers stats:
Conversation rate: {conv_rate}
Acceptance rate: {acc_rate}
Average Daily Trips: {avg_daily_trips}

Your response:"""
prompt = PromptTemplate.from_template(template)
class FeastPromptTemplate(StringPromptTemplate):
    
    def format(self, **kwargs) -》 str:
        driver_id = kwargs.pop("driver_id")
        feature_vector = store.get_online_features(
            features=[
                'driver_hourly_stats:conv_rate',
                'driver_hourly_stats:acc_rate',
                'driver_hourly_stats:avg_daily_trips'
            ],
            entity_rows=[{"driver_id": driver_id}]
        ).to_dict()
        kwargs["conv_rate"] = feature_vector["conv_rate"][0]
        kwargs["acc_rate"] = feature_vector["acc_rate"][0]
        kwargs["avg_daily_trips"] = feature_vector["avg_daily_trips"][0]
        return prompt.format(**kwargs)
prompt_template = FeastPromptTemplate(input_variables=["driver_id"])
print(prompt_template.format(driver_id=1001))
Given the driver's up to date stats, write them note relaying those stats to them.
If they have a conversation rate above .5, give them a compliment. Otherwise, make a silly joke about chickens at the end to make them feel better

Here are the drivers stats:
Conversation rate: 0.4745151400566101
Acceptance rate: 0.055561766028404236
Average Daily Trips: 936

Your response:

在链中使用

我们现在可以在链中使用它,成功创建一个链,实现由特征存储支持的个性化

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)
chain.run(1001)
"Hi there! I wanted to update you on your current stats. 
Your acceptance rate is 0.055561766028404236 and your average daily trips are 936. 
While your conversation rate is currently 0.4745151400566101, I have no doubt that with a little extra effort, 
you'll be able to exceed that .5 mark! Keep up the great work! And remember, even chickens can't always cross 
the road, but they still give it their best shot."

构造

上面,我们展示了如何将流行的开源和自我管理功能商店 Feast 与 LangChain 一起使用。我们下面的示例将显示使用 Tecton 的类似集成。Tecton 是一个完全托管的功能平台,旨在通过企业级 SLA 协调完整的 ML 功能生命周期,从转换到在线服务。

先决条件

  • Tecton 部署(在https://tecton.ai注册)
  • TECTON_API_KEY环境变量设置为有效的服务帐户密钥

定义和加载功能

我们将使用Tecton 教程中的 user_transaction_counts 特征视图作为特征服务的一部分。为简单起见,我们只使用一个功能视图;然而,更复杂的应用程序可能需要更多的功能视图来检索其提示所需的功能。

user_transaction_metrics = FeatureService(
    name = "user_transaction_metrics",
    features = [user_transaction_counts]
)

上述要素服务有望应用于实时工作空间。对于此示例,我们将使用“prod”工作区。

import tecton

workspace = tecton.get_workspace("prod")
feature_service = workspace.get_feature_service("user_transaction_metrics")

提示

在这里,我们将设置一个自定义的 TectonPromptTemplate。此提示模板将接受 user_id ,查找他们的统计信息,并将这些统计信息格式化为提示。

请注意,此提示模板的输入只是user_id,因为这是唯一的用户定义部分(所有其他变量都在提示模板内查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate
template = """Given the vendor's up to date transaction stats, write them a note based on the following rules:

1. If they had a transaction in the last day, write a short congratulations message on their recent sales
2. If no transaction in the last day, but they had a transaction in the last 30 days, playfully encourage them to sell more.
3. Always add a silly joke about chickens at the end

Here are the vendor's stats:
Number of Transactions Last Day: {transaction_count_1d}
Number of Transactions Last 30 Days: {transaction_count_30d}

Your response:"""
prompt = PromptTemplate.from_template(template)
class TectonPromptTemplate(StringPromptTemplate):
    
    def format(self, **kwargs) -》 str:
        user_id = kwargs.pop("user_id")
        feature_vector = feature_service.get_online_features(join_keys={"user_id": user_id}).to_dict()
        kwargs["transaction_count_1d"] = feature_vector["user_transaction_counts.transaction_count_1d_1d"]
        kwargs["transaction_count_30d"] = feature_vector["user_transaction_counts.transaction_count_30d_1d"]
        return prompt.format(**kwargs)
prompt_template = TectonPromptTemplate(input_variables=["user_id"])
print(prompt_template.format(user_id="user_469998441571"))
Given the vendor's up to date transaction stats, write them a note based on the following rules:

1. If they had a transaction in the last day, write a short congratulations message on their recent sales
2. If no transaction in the last day, but they had a transaction in the last 30 days, playfully encourage them to sell more.
3. Always add a silly joke about chickens at the end

Here are the vendor's stats:
Number of Transactions Last Day: 657
Number of Transactions Last 30 Days: 20326

Your response:

在链中使用

我们现在可以在链中使用它,成功创建一条链,实现由 Tecton 功能平台支持的个性化

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)
chain.run("user_469998441571")
'Wow, congratulations on your recent sales! Your business is really soaring like a chicken on a hot air balloon! 
Keep up the great work!'

特征形式

最后,我们将使用Featureform一个开源的企业级特征存储来运行相同的示例。Featureform 允许您使用您的基础设施(如 Spark)或本地来定义您的特征转换。

初始化特征形式

您可以按照 README 中的说明在 Featureform 中初始化您的转换和特征。

import featureform as ff

client = ff.Client(host="demo.featureform.com")

提示

在这里,我们将设置一个自定义的 FeatureformPromptTemplate。此提示模板将计算用户每笔交易支付的平均金额。

请注意,此提示模板的输入只是 avg_transaction,因为这是唯一的用户定义部分(所有其他变量都在提示模板内查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate
template = """Given the amount a user spends on average per transaction, 
let them know if they are a high roller. Otherwise, make a silly joke about chickens at the end to 
make them feel better

Here are the user's stats:
Average Amount per Transaction: ${avg_transcation}

Your response:"""
prompt = PromptTemplate.from_template(template)
class FeatureformPromptTemplate(StringPromptTemplate):
    
    def format(self, **kwargs) -》 str:
        user_id = kwargs.pop("user_id")
        fpf = client.features([("avg_transactions", "quickstart")], {"user": user_id})
        return prompt.format(**kwargs)
prompt_template = FeatureformPrompTemplate(input_variables=["user_id"])
print(prompt_template.format(user_id="C1410926"))

在链中使用#

我们现在可以在链中使用它,成功创建一个链,实现由 Featureform 特征平台支持的个性化

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)
chain.run("C1410926")

如何创建自定义提示模板

假设我们希望 LLM 在给定名称的情况下生成函数的英语解释。为完成此任务,我们将创建一个自定义提示模板,将函数名称作为输入,并格式化提示模板以提供函数的源代码。

为什么需要自定义提示模板?

LangChain 提供了一套默认的提示模板,可以用来为各种任务生成提示。但是,在某些情况下,默认的提示模板可能无法满足您的需求。例如,您可能想要为您的语言模型创建一个带有特定动态指令的提示模板。在这种情况下,您可以创建自定义提示模板。

在此处查看当前的一组默认提示模板。

创建自定义提示模板

基本上有两种不同的提示模板可用——字符串提示模板和聊天提示模板。字符串提示模板提供字符串格式的简单提示,而聊天提示模板生成更结构化的提示以与聊天 API 一起使用。

在本指南中,我们将使用字符串提示模板创建自定义提示。

要创建自定义字符串提示模板,有两个要求:

  1. 它有一个 input_variables 属性,该属性公开了提示模板期望的输入变量。
  2. 它公开了一个格式方法,该方法接受与预期的 input_variables 相对应的关键字参数并返回格式化的提示。

我们将创建一个自定义提示模板,将函数名称作为输入并格式化提示以提供函数的源代码。为此,让我们首先创建一个函数,该函数将返回给定函数名称的函数的源代码。

import inspect

def get_source_code(function_name):
    # Get the source code of the function
    return inspect.getsource(function_name)

接下来,我们将创建一个自定义提示模板,将函数名称作为输入,并格式化提示模板以提供函数的源代码。

from langchain.prompts import StringPromptTemplate
from pydantic import BaseModel, validator


class FunctionExplainerPromptTemplate(StringPromptTemplate, BaseModel):
    """ A custom prompt template that takes in the function name as input, and formats the prompt 
template to provide the source code of the function. """

    @validator("input_variables")
    def validate_input_variables(cls, v):
        """ Validate that the input variables are correct. """
        if len(v) != 1 or "function_name" not in v:
            raise ValueError("function_name must be the only input_variable.")
        return v

    def format(self, **kwargs) -》 str:
        # Get the source code of the function
        source_code = get_source_code(kwargs["function_name"])

        # Generate the prompt to be sent to the language model
        prompt = f"""
        Given the function name and source code, generate an English language explanation of the function.
        Function Name: {kwargs["function_name"].__name__}
        Source Code:
        {source_code}
        Explanation:
        """
        return prompt
    
    def _prompt_type(self):
        return "function-explainer"

使用自定义提示模板

现在我们已经创建了一个自定义提示模板,我们可以使用它来为我们的任务生成提示。

fn_explainer = FunctionExplainerPromptTemplate(input_variables=["function_name"])

# Generate a prompt for the function "get_source_code"
prompt = fn_explainer.format(function_name=get_source_code)
print(prompt)
        Given the function name and source code, generate an English language explanation of the function.
        Function Name: get_source_code
        Source Code:
        def get_source_code(function_name):
    # Get the source code of the function
    return inspect.getsource(function_name)

        Explanation:
        

如何创建使用少量镜头示例的提示模板

在本教程中,我们将学习如何创建一个使用少量镜头示例的提示模板。

我们将使用该类FewShotPromptTemplate创建一个使用少量镜头示例的提示模板。这个类要么接受一组例子,要么接受一个ExampleSelector对象。在本教程中,我们将讨论这两个选项。

用例

在本教程中,我们将为带有搜索的自问配置几个镜头示例。

使用示例集

创建示例集

首先,创建一个包含几个镜头示例的列表。每个示例都应该是一个字典,键是输入变量,值是这些输入变量的值。

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate

examples = [
  {
    "question": "Who lived longer, Muhammad Ali or Alan Turing?",
    "answer": 
"""
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali
"""
  },
  {
    "question": "When was the founder of craigslist born?",
    "answer": 
"""
Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952
"""
  },
  {
    "question": "Who was the maternal grandfather of George Washington?",
    "answer":
"""
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball
"""
  },
  {
    "question": "Are both the directors of Jaws and Casino Royale from the same country?",
    "answer":
"""
Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No
"""
  }
]

为几个镜头示例创建格式化程序

配置一个格式化程序,将几个镜头示例格式化为一个字符串。这个格式化程序应该是一个PromptTemplate对象。

example_prompt = PromptTemplate(input_variables=["question", "answer"], template=
"Question: {question}\n{answer}")

print(example_prompt.format(**examples[0]))
Question: Who lived longer, Muhammad Ali or Alan Turing?

Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali

将示例和格式化程序提供给FewShotPromptTemplate

最后,创建一个FewShotPromptTemplate对象。该对象采用少数镜头示例和少数镜头示例的格式化程序。

prompt = FewShotPromptTemplate(
    examples=examples, 
    example_prompt=example_prompt, 
    suffix="Question: {input}", 
    input_variables=["input"]
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))
Question: Who lived longer, Muhammad Ali or Alan Turing?

Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali


Question: When was the founder of craigslist born?

Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952


Question: Who was the maternal grandfather of George Washington?

Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball


Question: Are both the directors of Jaws and Casino Royale from the same country?

Are follow up questions needed here: Yes.
Follow up: Who is the director of Jaws?
Intermediate Answer: The director of Jaws is Steven Spielberg.
Follow up: Where is Steven Spielberg from?
Intermediate Answer: The United States.
Follow up: Who is the director of Casino Royale?
Intermediate Answer: The director of Casino Royale is Martin Campbell.
Follow up: Where is Martin Campbell from?
Intermediate Answer: New Zealand.
So the final answer is: No


Question: Who was the father of Mary Ball Washington?

使用示例选择器

将示例输入ExampleSelector

我们将重用上一节中的示例集和格式化程序。但是,我们不是将示例直接提供给FewShotPromptTemplate对象,而是将它们提供给一个ExampleSelector对象。

在本教程中,我们将使用该类
SemanticSimilarityExampleSelector。此类根据与输入的相似性选择少量镜头示例。它使用一个嵌入模型来计算输入和少数镜头示例之间的相似性,以及一个向量存储来执行最近邻搜索。

from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings


example_selector = SemanticSimilarityExampleSelector.from_examples(
    # This is the list of examples available to select from.
    examples,
    # This is the embedding class used to produce embeddings which are used to measure semantic similarity.
    OpenAIEmbeddings(),
    # This is the VectorStore class that is used to store the embeddings and do a similarity search over.
    Chroma,
    # This is the number of examples to produce.
    k=1
)

# Select the most similar example to the input.
question = "Who was the father of Mary Ball Washington?"
selected_examples = example_selector.select_examples({"question": question})
print(f"Examples most similar to the input: {question}")
for example in selected_examples:
    print("\n")
    for k, v in example.items():
        print(f"{k}: {v}")
Running Chroma using direct local API.
Using DuckDB in-memory for database. Data will be transient.
Examples most similar to the input: Who was the father of Mary Ball Washington?


question: Who was the maternal grandfather of George Washington?
answer: 
Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball

将示例选择器输入FewShotPromptTemplate

最后,创建一个FewShotPromptTemplate对象。该对象采用示例选择器和少数镜头示例的格式化程序。

prompt = FewShotPromptTemplate(
    example_selector=example_selector, 
    example_prompt=example_prompt, 
    suffix="Question: {input}", 
    input_variables=["input"]
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))
Question: Who was the maternal grandfather of George Washington?

Are follow up questions needed here: Yes.
Follow up: Who was the mother of George Washington?
Intermediate answer: The mother of George Washington was Mary Ball Washington.
Follow up: Who was the father of Mary Ball Washington?
Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
So the final answer is: Joseph Ball


Question: Who was the father of Mary Ball Washington?

如何使用部分提示模板

提示模板是一个带有方法的类.format,该方法接受键值映射并返回字符串(提示)以传递给语言模型。与其他方法一样,“部分”提示模板是有意义的——例如,传递所需值的子集,以创建一个只需要剩余值子集的新提示模板。

LangChain 以两种方式支持这一点:我们允许部分格式化的提示 (1) 带有字符串值,(2) 带有返回字符串值的函数。这两种不同的方式支持不同的用例。在下面的文档中,我们回顾了这两个用例的动机以及如何在 LangChain 中进行。

部分字符串

想要部分提示模板的一个常见用例是,如果您先获得一些变量。例如,假设您有一个需要两个变量的提示模板,foo并且baz. 如果您foo在链中较早获得值,但baz稍后获得值,那么等待两个变量都位于同一位置后再将它们传递给提示模板可能会很烦人。相反,您可以使用值部分提示模板foo,然后传递部分提示模板并使用它。下面是一个这样做的例子:

from langchain.prompts import PromptTemplate
prompt = PromptTemplate(template="{foo}{bar}", input_variables=["foo", "bar"])
partial_prompt = prompt.partial(foo="foo");
print(partial_prompt.format(bar="baz"))
foobaz

您也可以只使用部分变量初始化提示。

prompt = PromptTemplate(template="{foo}{bar}", input_variables=["bar"], partial_variables={"foo": "foo"})
print(prompt.format(bar="baz"))
foobaz

部分函数

另一个常见的用法是对一个函数进行分词。这个用例是当你有一个你知道你总是想以通用方式获取的变量时。一个典型的例子是日期或时间。假设您有一个提示,您总是希望获得当前日期。您不能在提示中对其进行硬编码,并且将其与其他输入变量一起传递有点烦人。在这种情况下,能够使用始终返回当前日期的函数来部分提示是非常方便的。

from datetime import datetime

def _get_datetime():
    now = datetime.now()
    return now.strftime("%m/%d/%Y, %H:%M:%S")
prompt = PromptTemplate(
    template="Tell me a {adjective} joke about the day {date}", 
    input_variables=["adjective", "date"]
);
partial_prompt = prompt.partial(date=_get_datetime)
print(partial_prompt.format(adjective="funny"))
Tell me a funny joke about the day 02/27/2023, 22:15:16

您也可以只使用部分变量初始化提示,这通常在此工作流程中更有意义。

prompt = PromptTemplate(
    template="Tell me a {adjective} joke about the day {date}", 
    input_variables=["adjective"],
    partial_variables={"date": _get_datetime}
);
print(prompt.format(adjective="funny"))
Tell me a funny joke about the day 02/27/2023, 22:15:16

如何序列化提示

通常最好将提示存储为文件而不是 python 代码。这可以使共享、存储和版本提示变得容易。本笔记本介绍了如何在 LangChain 中执行此操作,介绍了所有不同类型的提示和不同的序列化选项。

在高层次上,以下设计原则适用于序列化:

  1. 支持 JSON 和 YAML。我们希望支持在磁盘上人类可读的序列化方法,而 YAML 和 JSON 是这方面最流行的两种方法。请注意,此规则适用于提示。对于其他资产,如示例,可能支持不同的序列化方法。
  2. 我们支持在一个文件中指定所有内容,或者将不同的组件(模板、示例等)存储在不同的文件中并引用它们。对于某些情况,将所有内容存储在文件中是最有意义的,但对于其他情况,最好拆分一些资产(长模板、大型示例、可重用组件)。LangChain 两者都支持。

还有一个从磁盘加载提示的单一入口点,可以轻松加载任何类型的提示。

# All prompts are loaded through the `load_prompt` function.
from langchain.prompts import load_prompt

提示模板

本节介绍加载 PromptTemplate 的示例。

从 YAML 加载

这显示了从 YAML 加载 PromptTemplate 的示例。

!cat simple_prompt.yaml
_type: prompt
input_variables:
    ["adjective", "content"]
template: 
    Tell me a {adjective} joke about {content}.
prompt = load_prompt("simple_prompt.yaml")
print(prompt.format(adjective="funny", content="chickens"))
Tell me a funny joke about chickens.

从 JSON 加载

这显示了从 JSON 加载 PromptTemplate 的示例。

!cat simple_prompt.json
{
    "_type": "prompt",
    "input_variables": ["adjective", "content"],
    "template": "Tell me a {adjective} joke about {content}."
}
prompt = load_prompt("simple_prompt.json")
print(prompt.format(adjective="funny", content="chickens"))

给我讲一个关于鸡的笑话。

从文件加载模板

这显示了将模板存储在单独的文件中然后在配置中引用它的示例。请注意,键从template变为template_path。

!cat simple_template.txt
Tell me a {adjective} joke about {content}.
!cat simple_prompt_with_template_file.json
{
    "_type": "prompt",
    "input_variables": ["adjective", "content"],
    "template_path": "simple_template.txt"
}
prompt = load_prompt("simple_prompt_with_template_file.json")
print(prompt.format(adjective="funny", content="chickens"))
Tell me a funny joke about chickens.

FewShotPromptTemplate

本节介绍加载少量镜头提示模板的示例。

例子

这显示了存储为 json 的示例的示例。

!cat examples.json
[
    {"input": "happy", "output": "sad"},
    {"input": "tall", "output": "short"}
]

以下是存储为 yaml 的相同示例可能的样子。

!cat examples.yaml
- input: happy
  output: sad
- input: tall
  output: short

从 YAML 加载

这显示了从 YAML 加载几个镜头示例的示例。

!cat few_shot_prompt.yaml
_type: few_shot
input_variables:
    ["adjective"]
prefix: 
    Write antonyms for the following words.
example_prompt:
    _type: prompt
    input_variables:
        ["input", "output"]
    template:
        "Input: {input}\nOutput: {output}"
examples:
    examples.json
suffix:
    "Input: {adjective}\nOutput:"
prompt = load_prompt("few_shot_prompt.yaml")
print(prompt.format(adjective="funny"))
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

如果您从 yaml 文件加载示例,同样会起作用。

!cat few_shot_prompt_yaml_examples.yaml
_type: few_shot
input_variables:
    ["adjective"]
prefix: 
    Write antonyms for the following words.
example_prompt:
    _type: prompt
    input_variables:
        ["input", "output"]
    template:
        "Input: {input}\nOutput: {output}"
examples:
    examples.yaml
suffix:
    "Input: {adjective}\nOutput:"
prompt = load_prompt("few_shot_prompt_yaml_examples.yaml")
print(prompt.format(adjective="funny"))
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

从 JSON 加载

这显示了从 JSON 加载几个镜头示例的示例。

!cat few_shot_prompt.json
{
    "_type": "few_shot",
    "input_variables": ["adjective"],
    "prefix": "Write antonyms for the following words.",
    "example_prompt": {
        "_type": "prompt",
        "input_variables": ["input", "output"],
        "template": "Input: {input}\nOutput: {output}"
    },
    "examples": "examples.json",
    "suffix": "Input: {adjective}\nOutput:"
}   
prompt = load_prompt("few_shot_prompt.json")
print(prompt.format(adjective="funny"))
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

配置中的示例

这显示了直接在配置中引用示例的示例。

!cat few_shot_prompt_examples_in.json
{
    "_type": "few_shot",
    "input_variables": ["adjective"],
    "prefix": "Write antonyms for the following words.",
    "example_prompt": {
        "_type": "prompt",
        "input_variables": ["input", "output"],
        "template": "Input: {input}\nOutput: {output}"
    },
    "examples": [
        {"input": "happy", "output": "sad"},
        {"input": "tall", "output": "short"}
    ],
    "suffix": "Input: {adjective}\nOutput:"
}   
prompt = load_prompt("few_shot_prompt_examples_in.json")
print(prompt.format(adjective="funny"))
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

来自文件的示例提示

这显示了一个加载用于从单独文件格式化示例的 PromptTemplate 的示例。请注意,密钥从example_prompt变为example_prompt_path。

!cat example_prompt.json
{
    "_type": "prompt",
    "input_variables": ["input", "output"],
    "template": "Input: {input}\nOutput: {output}" 
}
!cat few_shot_prompt_example_prompt.json 
{
    "_type": "few_shot",
    "input_variables": ["adjective"],
    "prefix": "Write antonyms for the following words.",
    "example_prompt_path": "example_prompt.json",
    "examples": "examples.json",
    "suffix": "Input: {adjective}\nOutput:"
}   
prompt = load_prompt("few_shot_prompt_example_prompt.json")
print(prompt.format(adjective="funny"))
Write antonyms for the following words.

Input: happy
Output: sad

Input: tall
Output: short

Input: funny
Output:

PromptTempalte 与 OutputParser

这显示了从文件加载提示以及 OutputParser 的示例。

! cat prompt_with_output_parser.json
{
    "input_variables": [
        "question",
        "student_answer"
    ],
    "output_parser": {
        "regex": "(.*?)\\nScore: (.*)",
        "output_keys": [
            "answer",
            "score"
        ],
        "default_output_key": null,
        "_type": "regex_parser"
    },
    "partial_variables": {},
    "template": "Given the following question and student answer, provide a correct answer 
and score the student answer.\nQuestion: {question}\nStudent Answer: {student_answer}\nCorrect Answer:",
    "template_format": "f-string",
    "validate_template": true,
    "_type": "prompt"
}
prompt = load_prompt("prompt_with_output_parser.json")
prompt.output_parser.parse("George Washington was born in 1732 and died in 1799.\nScore: 1/2")
{'answer': 'George Washington was born in 1732 and died in 1799.',
 'score': '1/2'}

提示

此处的参考指南都与使用提示的对象有关。

  • 提示模板
  • 示例选择器
  • 输出解析器

提示模板

提示模板类。

虚伪的 模型 langchain.prompts。基本聊天提示模板[来源]格式(** kwargs :任何 ) → str[来源]

使用输入格式化提示。

参数

kwargs – 要传递给提示模板的任何参数。

退货

格式化的字符串。

例子:

prompt.format(variable1="foo")

abstract format_messages ( ** kwargs : Any ) → 列表[
langchain.schema.BaseMessage ][来源]

将 kwargs 格式化为消息列表。

format_prompt ( ** kwargs : Any ) →
langchain.schema.PromptValue[来源]

创建聊天消息。

虚伪的 模型 langchain.prompts。基本提示模板[来源]

所有提示模板的基类,返回提示。

field input_variables : List [ str ] [必需]

提示模板期望的变量名称列表。

字段 output_parser :可选[
langchain.schema.BaseOutputParser ] = None

如何解析在此格式化提示上调用 LLM 的输出。

dict ( ** kwargs : Any ) → 字典[来源]

返回提示的字典表示。

抽象 格式( ** kwargs : Any ) → str[来源]

使用输入格式化提示。

参数

kwargs – 要传递给提示模板的任何参数。

退货

格式化的字符串。

例子:

prompt.format(variable1="foo")

抽象 格式提示(** kwargs :任何 ) →
langchain.schema.PromptValue[来源]

创建聊天消息。

partial ( ** kwargs : Union [ str , Callable [ [ ] , str ] ] ) →
langchain.prompts.base.BasePromptTemplate[来源]

返回提示模板的一部分。

保存文件路径:联合[路径库路径,海峡] ) → 无[来源]

保存提示。

参数

file_path – 保存提示的目录路径。

示例:.. 代码块:: python

prompt.save(file_path=”path/prompt.yaml”)

虚伪的 模型 langchain.prompts。聊天提示模板[来源]格式(** kwargs :任何 ) → str[来源]

使用输入格式化提示。

参数

kwargs – 要传递给提示模板的任何参数。

退货

格式化的字符串。

例子:

prompt.format(variable1="foo")

format_messages ( ** kwargs : Any ) → 列表[
langchain.schema.BaseMessage ][来源]

将 kwargs 格式化为消息列表。

partial ( ** kwargs : Union [ str , Callable [ [ ] , str ] ] ) →
langchain.prompts.base.BasePromptTemplate[来源]

返回提示模板的一部分。

保存文件路径:联合[路径库路径,海峡] ) → 无[来源]

保存提示。

参数

file_path – 保存提示的目录路径。

示例:.. 代码块:: python

prompt.save(file_path=”path/prompt.yaml”)

虚伪的 模型 langchain.prompts。FewShotPrompt模板[来源]

包含少量镜头示例的提示模板。

字段 example_prompt :
langchain.prompts.prompt.PromptTemplate [必需]

PromptTemplate 用于格式化单个示例。

字段 example_selector :可选[
langchain.prompts.example_selector.base.BaseExampleSelector ] = None

ExampleSelector 选择要格式化为提示的示例。应提供此或示例。

字段 example_separator : str = '\n\n'

用于连接前缀、示例和后缀的字符串分隔符。

字段 示例

© THE END

转载请联系本网站获得授权

投稿或版权问题请加微信:skillupvip