nestjs+langchain:Prompt Template

9 阅读6分钟

书接上文

一、Prompt Template

介绍与分类

Prompt Template 是LangChain中的一个概念,接收用户输入,返回一个传递给LLM的信息(即提示词prompt)。

在应用开发中,固定的提示词限制了模型的灵活性和适用范围。所以,prompt template 是一个模板化的字符串 ,你可以将 变量插入到模板 中,从而创建出不同的提示。调用时:

  • 以 字典 作为输入,其中每个键代表要填充的提示模板中的变量。

  • 输出一个 PromptValue 。这个 PromptValue 可以传递给 LLM 或 ChatModel,并且还可以转换为字符串或消息列表。

有几种不同类型的提示模板:

🔥 PromptTemplate :LLM提示模板,用于生成字符串提示。

🔥 ChatPromptTemplate :聊天提示模板,用于组合各种角色的消息模板,传入聊天模型。

  • XxxMessagePromptTemplate :消息模板词模板,包括:SystemMessagePromptTemplateHumanMessagePromptTemplate、AIMessagePromptTemplate、ChatMessagePromptTemplate等

  • PipelinePrompt :管道提示词模板,用于把几个提示词组合在一起使用。

  • 自定义模板 :允许基于其它模板类来定制自己的提示词模板。

具体使用:PromptTemplate

使用说明

PromptTemplate类,用于快速构建 包含变量 的提示词模板,并通过 传入不同的参数值 生成自定义的提示词。

主要参数介绍:

  • template:定义提示词模板的字符串,其中包含 文本 和 变量占位符(如{name}) ;

  • input_variables: 列表,指定了模板中使用的变量名称,在调用模板时被替换;

  • partial_variables:字典,用于定义模板中一些固定的变量名。这些值不需要在每次调用时被替换。

两种实例化方式

1. 使用构造方法

agents.service.ts

//1.引入
import { PromptTemplate } from '@langchain/core/prompts';

/**
   * 演示 PromptTemplate 的使用
   */
  async demonstratePromptTemplate(): Promise<void> {
    // 2. 定义模板
    // inputVariables 定义了需要传入的参数名
    const promptTemplate = new PromptTemplate({
      template: '请简要描述{topic}的应用。',
      inputVariables: ['topic'],
    });

    // 3. 使用模板生成提示词 (format)
    // format 方法返回格式化后的字符串
    const prompt_1 = await promptTemplate.format({ topic: '机器学习' });
    const prompt_2 = await promptTemplate.format({ topic: '自然语言处理' });

    // 4. 打印结果 
    console.log('提示词1:', prompt_1);
    console.log('提示词2:', prompt_2);

    // 5. (可选) 直接将格式化的提示词发送给 LLM
    // 注意:invoke 通常接收 Message 对象数组,所以我们需要将格式化后的字符串包装成 HumanMessage
    const messages = [new HumanMessage(prompt_1)];
    const response = await this.llm.invoke(messages);
    console.log('LLM 响应:', response.content);
  }
输出结果:
提示词1: 请简要描述机器学习的应用。
提示词2: 请简要描述自然语言处理的应用。
LLM 响应: 机器学习作为人工智能的核心分支,通过数据驱动模型实现自动化决策与预测,其应用已渗透到...
2. fromTemplate

agents.service.ts

const promptTemplate = PromptTemplate.fromTemplate(
      '请给我一个关于{topic}的{type}解释。',
    );

    const prompt = await promptTemplate.format({
      type: '详细',
      topic: '量子力学',
    });

    console.log('提示词1:', prompt);
 输出结果:
 提示词1: 请给我一个关于量子力学的详细解释。
 LLM 响应: 量子力学是描述微观世界(如原子、亚原子粒子等尺度)行为的核心物理理论,...

两种新的结构形式

1. 部分提示词模版
 // 1. 定义模板 + 预填充部分变量(partialVariables)
    const template = new PromptTemplate({
      template: '请评价{product}的优缺点,包括{aspect1}和{aspect2}。',
      inputVariables: ['product', 'aspect2'], // 必须传的变量
      partialVariables: { aspect1: '电池续航' }, // 预填充变量
    });

    const prompt = await template.format({
      product: '智能手机',
      aspect2: '拍照质量',
    });
2. 链式调用 .partial()
 // 1. 先用 fromTemplate 传入「纯字符串模板」
    const baseTemplate = PromptTemplate.fromTemplate(
      '请评价{product}的优缺点,包括{aspect1}和{aspect2}。',
    );
    // 2. ✅ 关键:await 等待 partial 完成
    const template = await baseTemplate.partial({
      aspect1: '电池续航',
    });

    // 3. 正常 format
    const prompt = await template.format({
      product: '智能手机',
      aspect2: '拍照质量',
    });

⚠在nestji中使用langchain时,给模板变量赋值的方法只有format()

具体使用:ChatPromptTemplate

使用说明

ChatPromptTemplate是创建 聊天消息列表 的提示模板。它比普通 PromptTemplate 更适合处理多角

色、多轮次的对话场景。

特点: 支持 System / Human / AI 等不同角色的消息模板对话历史维护

参数类型: 列表参数格式是tuple类型

元组的格式为:(role: str | type, content: str | list[dict] | list[object]),其中 role 是:字符串(如 "system" 、 "human" 、 "ai" )

两种实例化方式

1.使用构造方法

agents.service.ts

import {
  ChatPromptTemplate,
  HumanMessagePromptTemplate,
  SystemMessagePromptTemplate,
} from '@langchain/core/prompts';

const chatPromptTemplate = new ChatPromptTemplate({
  // 👇 这里必须用 promptMessages,不是 messages!
  promptMessages: [
    SystemMessagePromptTemplate.fromTemplate(
      '你是一个AI助手,你的名字叫{name}',
    ),
    HumanMessagePromptTemplate.fromTemplate('我的问题是{question}'),
  ],
  // 手动声明输入变量
  inputVariables: ['name', 'question'],
});

// TS 中 invoke 是异步方法,必须 await
const res = await chatPromptTemplate.invoke({
  name: '小智',
  question: '1+2等于几',
});
console.log('提示词1:', res.messages);
输出结果:
提示词1: [
  SystemMessage {
    "content": "你是一个AI助手,你的名字叫小智",
    "additional_kwargs": {},
    "response_metadata": {}
  },
  HumanMessage {
    "content": "我的问题是1+2等于几",
    "additional_kwargs": {},
    "response_metadata": {}
  }
]
2.fromMessages

agents.service.ts

const chatPromptTemplate = ChatPromptTemplate.fromMessages([
      ['system', '你是一个AI助手,你的名字叫{name}'],
      ['human', '我的问题是{question}'],
]);

// 调用
const res = await chatPromptTemplate.invoke({
  name: '小智',
  question: '1+2等于几',
});
console.log('提示词1:', res.messages);
输出结果同上

模板调用的几种方式

invoke/formatMessages异步(必须 await) ,只有 format同步

通用模板:

// 1. 定义通用聊天模板 
const chatPromptTemplate = ChatPromptTemplate.fromMessages([ 
    ["system", "你是专业的{role}助手"], 
    ["human", "请解答:{question}"] ]
);
1.invoke:返回 ChatPromptValue
const res = await chatPromptTemplate.invoke({
      role: '编程',
      question: '什么是NestJS',
});
2.format:返回纯文本字符串
const res = chatPromptTemplate.format({
      role: '编程',
      question: '什么是NestJS',
});
3.formatMessages:返回消息对象数组BaseMessage[]
const res = await chatPromptTemplate.formatMessages({
      role: '编程',
      question: '什么是NestJS',
});

插入消息列表:MessagesPlaceholder

当你不确定消息提示模板使用什么角色,或者希望在格式化过程中 插入消息列表 时,该怎么办? 这就需要使用 MessagesPlaceholder,负责在特定位置添加消息列表。

// 创建聊天模板
const chatPromptTemplate = ChatPromptTemplate.fromMessages([
  ['system', '你是一个AI助手,你的名字叫{name}'],
  // 消息占位符
  new MessagesPlaceholder('msgs'),
]);

// 准备调用参数
const result = await chatPromptTemplate.invoke({
  name: '小智',
  msgs: [
    new HumanMessage('我的问题是:1 + 2 * 3 = ?'),
    new AIMessage('1 + 2 * 3 = 7'),
  ],
});

少量样本示例的提示词模板

在构建prompt时,可以通过构建一个 少量示例列表 去进一步格式化prompt,这是一种简单但强大的指导生成的方式,在某些情况下可以 显著提高模型性能。少量示例提示模板可以由 一组示例一个负责从定义的集合中选择 一部分示例 的示例选择器构建。

前者:使用ChatPromptTemplate

后者:使用Example selectors(示例选择器)

每个示例的结构都是一个 字典 ,其中 键 是输入变量, 值 是输入变量的值。

ChatPromptTemplate实现

// 1. 定义示例
const examples = [
  { input: '2+2', output: '4', description: '加法运算' },
  { input: '5-2', output: '3', description: '减法运算' },
];

// 2. 把示例转为「用户提问 + AI回答」对话对
const exampleMessages = examples.flatMap((example) => [
  new HumanMessage(`算式:${example.input},请计算并说明`),
  new AIMessage(`结果:${example.output},说明:${example.description}`),
]);

// 3. 构建聊天模板,插入少样本对话
const prompt = ChatPromptTemplate.fromMessages([
  ['system', '你是数学专家,参考对话示例回答问题,格式和示例保持一致'],
  // 插入所有少样本对话
  ...exampleMessages,
  // 用户新问题
  ['human', '算式:{input},请计算并说明'],
]);

// 4. 调用模板生成提示词
const messages = await prompt.invoke({ input: '2*5' });
const response = await this.llm.invoke(messages);
console.log(response.content);
输出结果:
结果:10,说明:乘法运算