Langchain 教程
LangChain 是一个用于开发大规模语言模型(LLM)应用程序的框架。
LangChain 简化了 LLM 应用程序生命周期的每个阶段,让你轻松构建复杂的 Ai 应用程序。
LangChain 官方文档:https://js.langchain.com/
快速开始
一个简单的例子
import { ChatOpenAI } from "@langchain/openai"; // 导入 ChatOpenAI 类,用于与 OpenAI 模型进行交互
import { HumanMessage, SystemMessage } from "@langchain/core/messages"; // 导入 HumanMessage 和 SystemMessage 类,用于创建消息对象
import { StringOutputParser } from "@langchain/core/output_parsers"; // 导入 StringOutputParser 类,用于解析模型输出
// 创建一个新的 ChatOpenAI 实例,配置模型和 API 密钥
const model = new ChatOpenAI({
model: "xxx", // 指定要使用的模型
apiKey: "xxx", // 指定用于身份验证的 API 密钥
configuration: {
baseURL: "xxx" // 指定模型的基本 URL
}
});
// 创建一个消息数组,其中包含系统消息和人类消息
const messages = [
new SystemMessage("你是一个智能助理,你的名字叫小酷"), // 创建系统消息,设置助理的角色和名称
new HumanMessage("你好,你是谁?") // 创建人类消息,模拟用户输入
];
// 调用模型的 invoke 方法,传递消息数组并等待结果
let result = await model.invoke(messages);
// 创建一个新的 StringOutputParser 实例,用于解析模型的输出
const parser = new StringOutputParser();
// 调用解析器的 invoke 方法,传递模型结果并等待解析后的结果
const res = await parser.invoke(result);
// 输出解析后的结果到控制台
console.log(result); // 输出:你好,我是小酷,我是一个智能助理
解析器
如: OutputParsers 是一个输出解析器,用于解析模型的输出
// 创建一个新的 StringOutputParser 实例,用于解析模型的输出
const parser = new StringOutputParser();
// 调用解析器的 invoke 方法,传递模型结果并等待解析后的结果
result = await parser.invoke(result);
// 输出解析后的结果到控制台
console.log(result); // 输出:你好,我是小酷,我是一个智能助理
采用 chain 链的方式
这种方式看起来更加直观,像流水线一样
// ...
// 使用管道操作将模型输出连接到解析器
const chain = model.pipe(parser);
// 调用链的 invoke 方法,传递消息数组并等待结果
const result = await chain.invoke(messages);
// 输出解析后的结果到控制台
console.log(result);
提示词模板
LangChain 提供了一种简单的方式来创建提示词模板,以便更好地控制模型的输出
// 定义系统消息模板
const systemTemplate = "你是一个智能助理,你的名字叫:{name}:";
// 创建一个聊天提示模板,从系统消息和用户消息创建
const promptTemplate = ChatPromptTemplate.fromMessages([
["system", systemTemplate], // 系统消息模板
["user", "{content}"] // 用户消息模板
]);
// 创建一个新的 StringOutputParser 实例,用于解析模型的输出
const parser = new StringOutputParser();
// 使用管道操作将提示模板、模型和解析器连接起来
const chain = promptTemplate.pipe(model).pipe(parser);
// 调用链的 invoke 方法,传递参数对象并等待结果
const result = await chain.invoke({ name: "小酷", content: "你好,你是谁" });
// 输出解析后的结果到控制台
console.log(result);
聊天
简单地构建一个聊天应用程序
上下文历史
有时候聊天需要关联上下文信息,LangChain 提供了一种简单的方式来处理上下文信息
// 引入所需的模块和配置文件
import { ChatOpenAI } from "@langchain/openai"; // 从langchain库中引入ChatOpenAI类
import { HumanMessage } from "@langchain/core/messages"; // 从langchain库中引入HumanMessage类
import { AIMessage } from "@langchain/core/messages"; // 从langchain库中引入AIMessage类
import config from "../config.json" assert { type: "json" }; // 导入配置文件config.json,并断言其类型为json
// 创建一个ChatOpenAI模型实例,并传入配置信息
const model = new ChatOpenAI({
model: config.model.name, // 使用配置文件中的模型名称
apiKey: config.model.apiKey, // 使用配置文件中的API密钥
configuration: {
baseURL: config.model.baseURL // 使用配置文件中的API基础URL
}
});
// 使用invoke方法调用模型,传入一系列对话消息
const result = await model.invoke([
new HumanMessage({ content: "你好,我叫小酷" }), // 创建一个新的HumanMessage实例,表示用户的消息内容
new AIMessage({ content: "你好,今天过得怎么样呢?" }), // 创建一个新的AIMessage实例,表示AI的回复内容
new HumanMessage({ content: "我叫什么" }) // 创建另一个新的HumanMessage实例,表示用户的第二条消息内容
]);
// 将结果输出到控制台
console.log(result); // 打印出模型的回复结果
存储上下文
可以有多种方式来存储上下文信息,比如存储在内存
// 引入所需的模块和配置文件
import { InMemoryChatMessageHistory } from "@langchain/core/chat_history"; // 从langchain库中引入InMemoryChatMessageHistory类
import { ChatPromptTemplate } from "@langchain/core/prompts"; // 从langchain库中引入ChatPromptTemplate类
import { ChatOpenAI } from "@langchain/openai"; // 从langchain库中引入ChatOpenAI类
import { RunnableWithMessageHistory } from "@langchain/core/runnables"; // 从langchain库中引入RunnableWithMessageHistory类
import config from "../config.json" assert { type: "json" }; // 导入配置文件config.json,并断言其类型为json
// 创建一个ChatOpenAI模型实例,并传入配置信息
const model = new ChatOpenAI({
model: config.model.name, // 使用配置文件中的模型名称
apiKey: config.model.apiKey, // 使用配置文件中的API密钥
configuration: {
baseURL: config.model.baseURL // 使用配置文件中的API基础URL
}
});
// 初始化一个空的消息历史记录对象
const messageHistories = {};
// 创建一个对话提示模板
const prompt = ChatPromptTemplate.fromMessages([
["system", `你是一个智能助理,你的名字叫小酷`], // 系统消息,设定助手的角色和名字
["placeholder", "{chat_history}"], // 占位符,用于插入历史对话
["human", "{input}"] // 用户消息,占位符将被实际的用户输入替代
]);
// 将模型与提示模板链接
const chain = prompt.pipe(model);
// 创建一个带有消息历史记录功能的可运行对象
const withMessageHistory = new RunnableWithMessageHistory({
runnable: chain, // 指定要运行的链
getMessageHistory: async (sessionId) => {
// 获取指定会话ID的消息历史记录
if (messageHistories[sessionId] === undefined) {
// 如果没有历史记录,创建一个新的
messageHistories[sessionId] = new InMemoryChatMessageHistory();
}
return messageHistories[sessionId];
},
inputMessagesKey: "input", // 指定输入消息的键名
historyMessagesKey: "chat_history" // 指定历史消息的键名
});
// 配置选项,指定会话ID
const option = {
configurable: {
sessionId: "cool" // 会话ID为"cool"
}
};
// 调用带有消息历史记录的可运行对象,传入用户输入
const result = await withMessageHistory.invoke(
{ input: "你好,你是谁" }, // 第一次用户输入
option // 使用配置选项
);
// 再次调用带有消息历史记录的可运行对象,传入新的用户输入
const result1 = await withMessageHistory.invoke(
{ input: "我刚才问什么" }, // 第二次用户输入
option // 使用相同的配置选项
);
// 将第二次调用的结果输出到控制台
console.log(result1); // 打印出模型的回复结果
管理上下文
由于大模型的限制,你不能一次性传入太多的历史消息,会导致上下文窗口溢出,因此需要管理上下文
import { ChatOpenAI } from "@langchain/openai"; // 引入 ChatOpenAI 类,用于与 OpenAI 的聊天模型交互
import { RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables"; // 引入 RunnablePassthrough 和 RunnableSequence 类,用于创建可运行的序列
import { HumanMessage, AIMessage } from "@langchain/core/messages"; // 引入 HumanMessage 和 AIMessage 类,用于创建人类和 AI 消息
import config from "../config.json" assert { type: "json" }; // 导入配置文件,包含模型名称和 API 密钥
import { ChatPromptTemplate } from "@langchain/core/prompts"; // 引入 ChatPromptTemplate 类,用于创建聊天提示模板
// 创建一个 ChatOpenAI 实例,用于与 OpenAI 模型交互
const model = new ChatOpenAI({
model: config.model.name, // 从配置文件中获取模型名称
apiKey: config.model.apiKey, // 从配置文件中获取 API 密钥
configuration: {
baseURL: config.model.baseURL // 从配置文件中获取模型的基础 URL
}
});
// 创建一个对话提示模板
const prompt = ChatPromptTemplate.fromMessages([
["system", `你是一个智能助理`], // 系统消息,设定助手的角色和名字
["placeholder", "{chat_history}"], // 占位符,用于插入历史对话
["human", "{input}"] // 用户消息,占位符将被实际的用户输入替代
]);
// 过滤消息,只保留最近的 10 条对话记录
const filterMessages = (data) => {
return data.chat_history.slice(-10);
};
// 创建一个可运行的序列,包括消息过滤、提示模板和模型调用
const chain = RunnableSequence.from([
RunnablePassthrough.assign({
chat_history: filterMessages // 过滤消息
}),
prompt, // 应用提示模板
model // 调用模型
]);
// 创建一些示例消息
const messages = [
new HumanMessage({ content: "你好!我是小酷" }), // 人类消息
new AIMessage({ content: "你好!" }), // AI 消息
new HumanMessage({ content: "我喜欢香草冰淇淋" }), // 人类消息
new AIMessage({ content: "不错" }), // AI 消息
new HumanMessage({ content: "2 + 2 等于多少" }), // 人类消息
new AIMessage({ content: "4" }), // AI 消息
new HumanMessage({ content: "谢谢" }), // 人类消息
new AIMessage({ content: "没问题!" }), // AI 消息
new HumanMessage({ content: "玩得开心吗?" }), // 人类消息
new AIMessage({ content: "是的!" }), // AI 消息
new HumanMessage({ content: "那太好了!" }), // 人类消息
new AIMessage({ content: "是的,确实如此!" }) // AI 消息
];
// 调用序列,传入历史对话和新的用户输入
const result = await chain.invoke({
chat_history: messages, // 历史对话
input: "你叫什么名字?" // 新的用户输入
});
// 输出结果
console.log(result);
流式输出
大模型的推理需要一定的时间,不能让用户等待太久,因此需要流式输出
// 引入所需的模块和配置文件
import { InMemoryChatMessageHistory } from "@langchain/core/chat_history"; // 从langchain库中引入InMemoryChatMessageHistory类
import { ChatPromptTemplate } from "@langchain/core/prompts"; // 从langchain库中引入ChatPromptTemplate类
import { ChatOpenAI } from "@langchain/openai"; // 从langchain库中引入ChatOpenAI类
import { RunnableWithMessageHistory } from "@langchain/core/runnables"; // 从langchain库中引入RunnableWithMessageHistory类
import config from "../config.json" assert { type: "json" }; // 导入配置文件config.json,并断言其类型为json
// 创建一个ChatOpenAI模型实例,并传入配置信息
const model = new ChatOpenAI({
model: config.model.name, // 使用配置文件中的模型名称
apiKey: config.model.apiKey, // 使用配置文件中的API密钥
configuration: {
baseURL: config.model.baseURL // 使用配置文件中的API基础URL
}
});
// 初始化一个空的消息历史记录对象
const messageHistories = {};
// 创建一个对话提示模板
const prompt = ChatPromptTemplate.fromMessages([
["system", `你是一个智能助理,你的名字叫小酷`], // 系统消息,设定助手的角色和名字
["placeholder", "{chat_history}"], // 占位符,用于插入历史对话
["human", "{input}"] // 用户消息,占位符将被实际的用户输入替代
]);
// 将模型与提示模板链接
const chain = prompt.pipe(model);
// 创建一个带有消息历史记录功能的可运行对象
const withMessageHistory = new RunnableWithMessageHistory({
runnable: chain, // 指定要运行的链
getMessageHistory: async (sessionId) => {
// 获取指定会话ID的消息历史记录
if (messageHistories[sessionId] === undefined) {
// 如果没有历史记录,创建一个新的
messageHistories[sessionId] = new InMemoryChatMessageHistory();
}
return messageHistories[sessionId];
},
inputMessagesKey: "input", // 指定输入消息的键名
historyMessagesKey: "chat_history" // 指定历史消息的键名
});
// 配置选项,指定会话ID
const option = {
configurable: {
sessionId: "cool" // 会话ID为"cool"
}
};
// 调用带有消息历史记录的可运行对象,传入用户输入
const stream = await withMessageHistory.stream(
{ input: "你好,你是谁" }, // 第一次用户输入
option // 使用配置选项
);
// 流式输出
for await (const chunk of stream) {
console.log("|", chunk.content);
}