在做聊天应用时,我们的提示词往往是一串按角色分好的消息
[SystemMessage {"content": "xxx",},HumanMessage {"content": "xxx",}, 占位符1AIMessage {"content": "xxx",},占位符2HumanMessage {"content": "xxx",}
]
但是可能会遇到下面的问题:
- 插入内容不可控:某些对话一开始无法决定内容
- 可维护性与可测试性差:某段对话后面是需要进行替换的
消息占位,就是在消息数组中先写一个占位符,之后某段对话定下来后,放到占位符的位置即可。
这里涉及到两个问题:
- 如何创建占位符
- 占位符放哪里
1. 如何创建占位符
LangChain.js 中提供了一个 MessagesPlaceholder 的工具类:
new MessagesPlaceholder("history")
在实例化的时候,histroy 就是该占位符的 key,或者说是名字,后面在做对话替换的时候,可以指定 key 对应的对话是什么。
2. 占位符放哪里
ChatPromptTemplate.fromMessages()
明确支持由“消息模板 + 占位符”组成的形式。
也就是说,以前我们使用 ChatPromptTemplate.fromMessages()
,是这么使用的:
const spt = SystemMessagePromptTemplate.fromTemplate("你是一位中国的专业导游,请使用中文向游客介绍中国的某些地区的特产"
);const hpt = HumanMessagePromptTemplate.fromTemplate("我想问:{question}");// 将上面两个提示词进行一个组合
const chatpt = ChatPromptTemplate.fromMessages([spt, hpt]);
那么现在,你可以在数组中添加占位符,放置的位置取决于你自己的需求:
ChatPromptTemplate.fromMessages([spt,new MessagesPlaceholder("history"),hpt
]);
在上面的代码中,我们就创建了一个占位符,放置于 spt 和 hpt 这两个提示词之间。
import {ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,MessagesPlaceholder,
} from "@langchain/core/prompts";
import { HumanMessage, AIMessage } from "@langchain/core/messages";const pt = ChatPromptTemplate.fromMessages([SystemMessagePromptTemplate.fromTemplate("你是一个乐于助人的AI助手"),new MessagesPlaceholder("history"), // 加入了一个占位符HumanMessagePromptTemplate.fromTemplate("用户的问题:{input}"),
]);const res = await pt.formatMessages({input: "你好",history: [new HumanMessage("今天天气怎么样"),new AIMessage("今天天气非常晴朗"),],
});console.log(res);/*
[SystemMessage {"content": "你是一个乐于助人的AI助手","additional_kwargs": {},"response_metadata": {}},HumanMessage {"content": "今天天气怎么样","additional_kwargs": {},"response_metadata": {}},AIMessage {"content": "今天天气非常晴朗","additional_kwargs": {},"response_metadata": {},"tool_calls": [],"invalid_tool_calls": []},HumanMessage {"content": "用户的问题:你好","additional_kwargs": {},"response_metadata": {}}
]
*/