前言
最近在学习大模型应用相关的内容。想着实践是最好的老师,就按照官方文档写了一个 Typescript 版本的 LangChain 调用 OpenAI 的 demo。文章分为两个部份,LangChain 调用 LLMs 的基本流程和代码实现。让初次使用 Langchain 的同学可以少踩坑,一步启动~
LangChain 调用 LLMs 的基本流程
什么是 LangChain
如果你问 chatGPT3.5 ,什么是 Langchain?它会告诉你:
LangChain 是一个通用的编程概念,它指的是一种通过链式调用方法来实现一系列操作的编程风格或范式。在 LangChain 中,每个方法调用都返回一个新的对象或函数,以便可以在其上继续调用其他方法,形成一个链式的操作序列。LangChain 的目的是提高代码的可读性和可维护性。通过使用链式调用,可以将一系列操作连接在一起,使代码更加清晰、简洁,并且易于理解和修改。
好像回答了,但是和我们想要的有点偏差。那么 LangChain 的官方描述是:
LangChain 是一个用于开发由语言模型支持的应用程序的框架。我们相信,最强大和最差异化的应用程序不仅会通过 API 调用语言模型,而且还会:
- 具有数据意识:将语言模型连接到其他数据源
- 是代理的:允许语言模型与其环境交互
LangChain 里有使用到 LangChain 的编程理念。
调用 LLMs 的基本流程
调用过程需要我们理解三个基本概念:PromptTemplate + LLM + OutputParser
流程图:
PromptTemplate
大多数 LLM 应用不会将用户输入直接传递到 LLM。通常,他们会将用户输入添加到较大的文本中,称为提示模板,该文本提供有关当前特定任务的附加上下文。
可以简单理解 PromptTemplate 是对用户输入进行处理和给大模型增加语义环境数据的。
LLM
语言模型有两种类型,在LangChain中称为:
- LLM:这是一种语言模型,它将字符串作为输入并返回字符串
- ChatModels:这是一个语言模型,它将消息列表作为输入并返回消息
我们最熟悉的 LLM 实现是 OpenAI 的 ChatGPT。也是我们例子中展示的大语言模型。
因为国内无法使用 OpenAI 。我们可以使用第三方平台的 api 来间接接入 OpenAI。这里介绍 f2api。进入网页注册帐号登录后就可以获取 openAIApiKey 和请求 URL 了。可以充值一块钱试试效果,请注意问问题的 token 数不要超过一元能买到的最大 token 数。
OutputParser
OutputParsers 将 LLM 的原始输出转换为可在下游使用的格式。 OutputParsers 有几种主要类型,包括:
- 从 LLM 转换文本 -> 结构化信息(例如 JSON)
- 将 ChatMessage 转换为字符串
- 将除消息之外的调用返回的额外信息(如 OpenAI 函数调用)转换为字符串。
对大语言模型的输出进行处理,接入不同的大语言模型需要的处理也不尽相同。LangChain 内置了对 OpenAI 输出的处理。
Coding
注意 Langchain npm 包的安装,我使用的版本是 0.0.167 ,没有指定版本可能会下载到一个 Langchain 同名包,版本大于 ^1.0.0 。
typescript
// index.ts
import { ChatOpenAI } from "langchain/chat_models/openai";
import { RunnableConfig } from "langchain/dist/schema/runnable";
import { ChatPromptTemplate } from "langchain/prompts";
import { BaseOutputParser } from "langchain/schema/output_parser";
/**
* Parse the output of an LLM call to a comma-separated list.
*/
class CommaSeparatedListOutputParser extends BaseOutputParser<string[]> {
lc_namespace: string[];
async parse(text: string): Promise<string[]> {
return text.split(",").map((item) => item.trim());
}
// 此抽象接口未使用但是必须有默认实现
getFormatInstructions(): string {
return "";
}
}
const template = `You are a helpful assistant who generates comma separated lists.
A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
ONLY return a comma separated list, and nothing more.`;
const humanTemplate = "{text}";
/**
* Chat prompt for generating comma-separated lists. It combines the system
* template and the human template.
*/
const chatPrompt = ChatPromptTemplate.fromMessages([
["system", template],
["human", humanTemplate],
]);
const model = new ChatOpenAI({
temperature: 0.7,
// 使用自己申请的,这里展示的是错误的
openAIApiKey: "sk-f2zbU6uhSTMJjpKU9VwnTzCxbbJ8H4bIV7GAw",
configuration: {
// ChatOpenAI 的请求拼接 path 是 /chat/completions ,需要根据完整的请求 url 裁剪得到 baseURL
baseURL: "https://api.f2gpt.com/v1",
defaultHeaders: {
"Content-Type": "application/json",
},
},
});
const parser = new CommaSeparatedListOutputParser();
const chain = chatPrompt.pipe(model).pipe(parser);
const invoke = async (input: any, options?: RunnableConfig): Promise<any> => {
const result = await chain.invoke(input, options);
return result;
};
invoke({ text: "animals" }).then((result) => {
console.log(result);
});
/*
[ 'dog', 'cat', 'bird', 'fish', 'horse' ]
*/