当前位置:   article > 正文

LangChain: 提示词_langchain 提示词

langchain 提示词


在这里插入图片描述

1、提示词模板

所谓提示词Prompt,指对模型的输入。语言模型接受一个文本作为输入,这个文本通常就指的是模板。LangChain提供了一些类和函数,用于构建提示词模板和使用提示词模板:

  • 提示词模板:参数化模型输入
  • 示例选择器:动态选择要包含在提示词中的示例

1.1 什么是提示词模板

从形式上来讲,提示词模板是一个字符串。它可以接受一系列参数,生成不同的模板。一个提示词模板里包含以下内容:

  • 对于语言模型的介绍
  • 一组简洁的示例,帮助语言模型生成一个更好的响应
  • 对语言模型的提问

下面是一个简单的示例:

// 首先导入提示词模板类PromptTemplate
import { PromptTemplate } from "langchain/prompts";

// 传入一个模板,语言模型会自动从模板中推断出输入变量
const prompt = PromptTemplate.fromTemplate(
  `You are a naming consultant for new companies.
What is a good name for a company that makes {product}?`
);

// product是该模板的参数
const formattedPrompt = await prompt.format({
  product: "colorful socks",
});

// 格式化模板后,会得到如下的结果。可以看到,输入的变量被自动添加到了提示词模板变量的位置
/*
  You are a naming consultant for new companies.
  What is a good name for a company that makes colorful socks?
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

1.2 创建一个提示词模板

可以使用上述示例中的PromptTemplate类,创建一个硬编码的提示词模板。提示词模板可以接受任意数量的输入变量,并且可以被格式化来生成模板。下面列举几种生成提示词模板的方法:

首先引入PromptTemplate类:

import { PromptTemplate } from "langchain/prompts";
  • 1
  • 生成无参数的提示词模板
const noInputPrompt = new PromptTemplate({
  inputVariables: [], // 没有参数,inputVariables为空
  template: "Tell me a joke.",
});
const formattedNoInputPrompt = await noInputPrompt.format();

console.log(formattedNoInputPrompt);
// "Tell me a joke."
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 包含一个参数的提示词模板
const oneInputPrompt = new PromptTemplate({
  inputVariables: ["adjective"], // 一个参数:adjective
  template: "Tell me a {adjective} joke."
})
const formattedOneInputPrompt = await oneInputPrompt.format({
  adjective: "funny",
});

console.log(formattedOneInputPrompt);
// "Tell me a funny joke."
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 生成包含多个参数的提示词模板
const multipleInputPrompt = new PromptTemplate({
  inputVariables: ["adjective", "content"], // 多个参数
  template: "Tell me a {adjective} joke about {content}.",
});
// .format参数进行格式化,并传入参数
const formattedMultipleInputPrompt = await multipleInputPrompt.format({
  adjective: "funny",
  content: "chickens",
});

console.log(formattedMultipleInputPrompt);
// "Tell me a funny joke about chickens."
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 使用fromTemplate生成提示词模板。如果你不想手动设定inputVariables,则可以使用fromTemplate来生成提示词模板。
// 编写模板
const template = "Tell me a {adjective} joke about {content}.";

const promptTemplate = PromptTemplate.fromTemplate(template);
console.log(promptTemplate.inputVariables); // 获取模板参数
// ['adjective', 'content']

// 格式化模板
const formattedPromptTemplate = await promptTemplate.format({
  adjective: "funny",
  content: "chickens",
});
console.log(formattedPromptTemplate); // 最终生成的模板
// "Tell me a funny joke about chickens."
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

1.3 对话提示词模板

对话模型接受的输入是一个聊天消息列表,这个消息列表通常被称为对话模型的提示词。聊天消息与原始字符串的区别是:每条消息都与一个角色相关联。例如,在OpenAI的聊天模型中,聊天消息的角色可以是AI,humansystem等,LangChain也针对这些角色分别提供了不同的提示词生成类,如AIMessagePromptTemplate,HumanMessagePromptTemplate,SystemMessagePromptTemplate等。如下为LangChain所提供的提示词模板:

import {
  ChatPromptTemplate,
  PromptTemplate,
  SystemMessagePromptTemplate,
  AIMessagePromptTemplate,
  HumanMessagePromptTemplate,
} from "langchain/prompts";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在调用聊天模型时,可以使用这些类来替换PromptTemplate生成提示词。有时候,为了使用方便,也可以将消息提示模板声明成为一个数组,如:

// 定义两个消息模板:系统模板和人工模板
const systemTemplate = "You are a helpful assistant that translates {input_language} to {output_language}.";
const humanTemplate = "{text}";

// 形成一个聊天模板
const chatPrompt = ChatPromptTemplate.fromMessages([
  ["system", systemTemplate],
  ["human", humanTemplate],
]);

// 格式化消息
const formattedChatPrompt = await chatPrompt.formatMessages({
  input_language: "English",
  output_language: "French",
  text: "I love programming.",
});

console.log(formattedChatPrompt);
// 结果
/*
  [
    SystemMessage {
      content: 'You are a helpful assistant that translates English to French.'
    },
    HumanMessage {
      content: 'I love programming.'
    }
  ]
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

1.4 部分提示词模板举例

  • 字符串形式
  • 函数形式

1.5 提示词模板组合使用

这里我们介绍如何将多个模板组合使用。这对于对部分模板重复使用具有重要作用,其中,PipelinePrompt可以将多个模板进行组合。PipelinePrompt包括两个主要的组成部分:

  • Final prompt:最后返回的提示
  • Pipeline prompts:一个由提示词名称和提示词模板组成的元组,每一个提示词都将会被格式化,并且会作为具有相同名称的变量传递到未来的提示模板。

首先,从langchain/prompts中引入PromptTemplatePipelinePromptTemplate

import { PromptTemplate, PipelinePromptTemplate } from "langchain/prompts";
  • 1

下面,通过PromptTemplate.fromTemplate方法,开始定义多个提示词模板。这里我们定义了四个模板,分别为:

  • fullPrompt:是用于最终会返回的模板,包括三个变量{introduction},{example},{start},当finalPrompt使用这个模板时,pipelinePrompts就应该输入包括这三个变量的模板。
  • introductionPrompt:包含一个变量person
  • examplePrompt:包含两个变量example_q,example_a
  • startPrompt:包含一个变量input
// 全部模板
const fullPrompt = PromptTemplate.fromTemplate(`{introduction}

{example}

{start}`);

const introductionPrompt = PromptTemplate.fromTemplate(
  `You are impersonating {person}.`
);

const examplePrompt =
  PromptTemplate.fromTemplate(`Here's an example of an interaction:
Q: {example_q}
A: {example_a}`);

const startPrompt = PromptTemplate.fromTemplate(`Now, do this for real!
Q: {input}
A:`);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

最后,通过PipelinePromptTemplate创建一个组合模板,并使用.format方法,获得一个格式化的模板:

const composedPrompt = new PipelinePromptTemplate({
  pipelinePrompts: [
    {
      name: "introduction",
      prompt: introductionPrompt,
    },
    {
      name: "example",
      prompt: examplePrompt,
    },
    {
      name: "start",
      prompt: startPrompt,
    },
  ],
  finalPrompt: fullPrompt,
});

const formattedPrompt = await composedPrompt.format({
  person: "Elon Musk",
  example_q: `What's your favorite car?`,
  example_a: "Telsa",
  input: `What's your favorite social media site?`,
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

打印formattedPrompt,可得到如下的结果:

console.log(formattedPrompt);

/*
  You are impersonating Elon Musk.

  Here's an example of an interaction:
  Q: What's your favorite car?
  A: Telsa

  Now, do this for real!
  Q: What's your favorite social media site?
  A:
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以看到,这是一个将三个模板组合得到的模板。将这个模板通过如下方式传入到大语言模型,即可进行问到:

const model = new OpenAI({
    openAIApiKey: OPENAI_API_KEY,
    temperature: 0
})

let result = await model.call(formattedPrompt)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、示例选择器

假如你有一堆选择器,想要自动选择一种包含在提示中,就可以使用示例选择器。示例选择器的接口定义是:

class BaseExampleSelector {
  addExample(example: Example): Promise<void | string>;

  selectExamples(input_variables: Example): Promise<Example[]>;
}
  • 1
  • 2
  • 3
  • 4
  • 5

这里暴露了两个方法:

  • addExample:保存一个示例,以供下一次选择
  • selectExamples:它接受输入变量,返回示例方法的列表

这些示例如何保存和选择,取决于上述方法的具体实现。

2.1 通过长度选择

此示例选择器是根据长度选择要使用的示例。当您担心构建的提示会超过上下文窗口的长度时,这非常有用。对于较长的输入,它将选择较少的示例来包含,而对于较短的输入,它将选择更多的示例。

import { LengthBasedExampleSelector, PromptTemplate, FewShotPromptTemplate } from "langchain/prompts";
  • 1

创建一个提示词模板,它将会被用于格式化示例。

const examplePrompt = new PromptTemplate({
  inputVariables: ["input", "output"],
  template: "Input: {input}\nOutput: {output}",
});
  • 1
  • 2
  • 3
  • 4

创建一个基于长度的LengthBasedExampleSelector选择器,它将会被用于选择一个示例

const exampleSelector = await LengthBasedExampleSelector.fromExamples(
  [
    { input: "happy", output: "sad" },
    { input: "tall", output: "short" },
    { input: "energetic", output: "lethargic" },
    { input: "sunny", output: "gloomy" },
    { input: "windy", output: "calm" },
  ],
  {
    examplePrompt,
    maxLength: 25,
  }
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

创建一个FewShotPromptTemplate模板,它也会被用于示例选择

const dynamicPrompt = new FewShotPromptTemplate({
 // We provide an ExampleSelector instead of examples.
 exampleSelector,
 examplePrompt,
 prefix: "Give the antonym of every input",
 suffix: "Input: {adjective}\nOutput:",
 inputVariables: ["adjective"],
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用一个长度较小的输入,所以它会选择所有的示例。

console.log(await dynamicPrompt.format({ adjective: "big" }));
/*
 Give the antonym of every input

 Input: happy
 Output: sad

 Input: tall
 Output: short

 Input: energetic
 Output: lethargic

 Input: sunny
 Output: gloomy

 Input: windy
 Output: calm

 Input: big
 Output:
 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

这里使用一个长度较长的输入,它只会选择其中一个示例。

const longString =
  "big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else";
console.log(await dynamicPrompt.format({ adjective: longString }));
/*
 Give the antonym of every input

 Input: happy
 Output: sad

 Input: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else
 Output:
 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.2 通过相似度选择

该对象根据与输入的相似性来选择示例。它通过查找与输入具有最大余弦相似度的嵌入示例来实现这一点。

import { OpenAIEmbeddings } from "langchain/embeddings/openai";
import {
  SemanticSimilarityExampleSelector,
  PromptTemplate,
  FewShotPromptTemplate,
} from "langchain/prompts";
import { HNSWLib } from "langchain/vectorstores/hnswlib";

// 创建一个用于示例选择的提示词模板
const examplePrompt = new PromptTemplate({
  inputVariables: ["input", "output"],
  template: "Input: {input}\nOutput: {output}",
});

// 创建一个基于语法相似度SemanticSimilarityExampleSelector的选择器
const exampleSelector = await SemanticSimilarityExampleSelector.fromExamples(
  [
    { input: "happy", output: "sad" },
    { input: "tall", output: "short" },
    { input: "energetic", output: "lethargic" },
    { input: "sunny", output: "gloomy" },
    { input: "windy", output: "calm" },
  ],
  new OpenAIEmbeddings(),
  HNSWLib,
  { k: 1 }
);

// 创建一个FewShotPromptTemplate进行示例选择
const dynamicPrompt = new FewShotPromptTemplate({
  // We provide an ExampleSelector instead of examples.
  exampleSelector,
  examplePrompt,
  prefix: "Give the antonym of every input",
  suffix: "Input: {adjective}\nOutput:",
  inputVariables: ["adjective"],
});

// 使用天气相关的作为输入
console.log(await dynamicPrompt.format({ adjective: "rainy" }));
// 所以,输出也是天气相关
/*
 Give the antonym of every input

 Input: sunny
 Output: gloomy

 Input: rainy
 Output:
 */

// 使用一个测量相关的输入,所以会得到例如tall/short的示例
console.log(await dynamicPrompt.format({ adjective: "large" }));
/*
 Give the antonym of every input

 Input: tall
 Output: short

 Input: large
 Output:
 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/425217
推荐阅读
相关标签
  

闽ICP备14008679号