Skip to content

消息占位 ​

在做聊天应用时,我们的提示词往往是一串按角色分好的消息

js
[
  SystemMessage {
    "content": "xxx",
  },
  HumanMessage {
    "content": "xxx",
  },  
    
  占位符1
    
  AIMessage {
    "content": "xxx",
  },
    
  占位符2
  
  HumanMessage {
   "content": "xxx",
  }
]

但是可能会遇到下面的问题:

  1. 插入内容不可控:某些对话一开始无法决定内容
  2. 可维护性与可测试性差:某段对话后面是需要进行替换的

消息占位,就是在消息数组中先写一个占位符,之后某段对话定下来后,放到占位符的位置即可。

这里涉及到两个问题:

  1. 如何创建占位符
  2. 占位符放哪里

1. 如何创建占位符

LangChain.js 中提供了一个 MessagesPlaceholder 的工具类:

js
new MessagesPlaceholder("history")

在实例化的时候,histroy 就是该占位符的 key,或者说是名字,后面在做对话替换的时候,可以指定 key 对应的对话是什么。

2. 占位符放哪里

ChatPromptTemplate.fromMessages() 明确支持由“消息模板 + 占位符”组成的形式。

也就是说,以前我们使用 ChatPromptTemplate.fromMessages(),是这么使用的:

js
const spt = SystemMessagePromptTemplate.fromTemplate(
  "你是一位中国的专业导游,请使用中文向游客介绍中国的某些地区的特产"
);

const hpt = HumanMessagePromptTemplate.fromTemplate("我想问:{question}");

// 将上面两个提示词进行一个组合
const chatpt = ChatPromptTemplate.fromMessages([spt, hpt]);

那么现在,你可以在数组中添加占位符,放置的位置取决于你自己的需求:

js
ChatPromptTemplate.fromMessages([
  spt,
  new MessagesPlaceholder("history"),
  hpt
]);

在上面的代码中,我们就创建了一个占位符,放置于 spt 和 hpt 这两个提示词之间。

课堂演示

演示占位符的使用

js
import { AIMessage, HumanMessage } from "@langchain/core/messages";
import {
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    MessagesPlaceholder,
    SystemMessagePromptTemplate,
} from "@langchain/core/prompts";

const pt = ChatPromptTemplate.fromMessages([
    SystemMessagePromptTemplate.fromTemplate("你是一位专业导游,负责用中文向游客介绍北京特产。"),
    new MessagesPlaceholder("history"), // 加入一个占位符
    HumanMessagePromptTemplate.fromTemplate("用户的问题{question}"),
]);

const result = await pt.formatMessages({
    question: "北京有哪些值得推荐的特产",
    history: [new HumanMessage("北京天气怎么样"), new AIMessage("非常好")],
});
console.log("🚀 ~ index.js:11 ~ pt:", pt);
console.log("🚀 ~ index.js:12 ~ result:", result);