Langchain初体验:使用LLM

209 阅读4分钟

构建语言模型应用程序

LLM:从语言模型获取预测

  1. .env文件中设置值OPENAI_API_KEY
VUE_APP_OPENAI_API_KEY="..."
  1. 现在可以在一些输入上调用它:
import { OpenAI } from "langchain/llms/openai";

const model = new OpenAI(
    {
        modelName: "gpt-3.5-turbo",
        openAIApiKey: process.env.VUE_APP_OPENAI_API_KEY,
    },
);

try {
    const res = await model.call(
        "你能否用帮我概括一下鲁迅的《朝花夕拾》"
    );
    this.msg = JSON.stringify(res)
} catch (error) {
    console.log(error);
}

// "《朝花夕拾》是鲁迅以个人的视角回忆童年、青年时期的生活经历和对社会现实的思考,并通过揭示社会的黑暗与人性的扭曲,表达了对旧时代的批判和对新时代的希望。"

提示模板: 管理LLMs的提示

通常当你在应用程序中使用LLM时,你不会直接将用户输入发送到LLM。而是会使用用户输入来构建一个提示,然后将它发送到LLM。

import { PromptTemplate } from "langchain/prompts";

const template = "What is a good name for a company that makes {product}?";
const prompt = new PromptTemplate({
  template: template,
  inputVariables: ["product"],
});

// 现在让我们看看它的工作原理!我们可以调用.format方法进行格式化。
const res = await prompt.format({ product: "colorful socks" });
console.log(res); 
// What is a good name for a company that makes colorful socks?
// 将 product 这个参数拼接到了句子上

链: 在多步骤工作流中组合LLMs和提示

到目前为止,我们只是单独使用了PromptTemplateLLM原语。但是,一个真正的应用程序不仅仅是一个原语,而是它们的组合。

LangChain中的链是由链接组成的,可以是像LLMs这样的原语,也可以是其他chains。链的最核心类型是LLMChain,它由PromptTemplate和LLM组成。

扩展前面的例子:

  1. 构建一个LLMChain,它采用用户输入
  2. 用PromptTemplate格式化它
  3. 将格式化的响应传递给LLM。
import { PromptTemplate } from "langchain/prompts";
import { LLMChain } from "langchain/chains";

// 定义模板字符串,其中包含一个占位符{product}
const template = "What is a good name for a company that makes {product}?";

// 创建一个PromptTemplate实例,设置模板字符串和输入变量inputVariables
const prompt = new PromptTemplate({
  template: template,
  inputVariables: ["product"],
});

// 创建一个LLMChain实例,指定使用的LLM模型和填充好的PromptTemplate
const chain = new LLMChain({ llm: model, prompt: prompt });

// 调用LLMChain的call方法,传入一个包含"product"变量的对象作为参数
// 这样会将"colorful socks"作为替换值填充到模板字符串中,生成新的文本
// { res: { text: 'ColorfulCo Sockery.' } }
const res = await chain.call({ product: "colorful socks" });

Agents: 根据用户输入动态运行链

到目前为止,我们看过的链是以预定顺序运行的。代理不再执行它们使用LLM来确定要执行的操作以及顺序。动作可以是使用工具并观察其输出,或者返回给用户。

  • Tools:执行特定职责的函数。这些职责可能包括:Google 搜索、数据库查询、代码 REPL(Read-Eval-Print Loop,读取-求值-输出循环)、其他链。目前工具的接口是一个期望输入字符串,并返回一个字符串的函数。
  • LLM: 代理使用的语言模型。
  • Agent: 所使用的代理。这应该是一个引用支持代理类的字符串。
import { OpenAI } from "langchain/llms/openai";
import { initializeAgentExecutorWithOptions } from "langchain/agents";
import { SerpAPI } from "langchain/tools";
import { Calculator } from "langchain/tools/calculator";

// 定义tools数组,其中包含两个元素:SerpAPI和Calculator实例
// SerpAPI需要使用VUE_APP_SERPAPI_API_KEY作为API密钥,并指定位置、语言等参数
const tools = [
    new SerpAPI(process.env.VUE_APP_SERPAPI_API_KEY, {
        location: "Austin,Texas,United States",
        hl: "en",
        gl: "us",
    }),
    new Calculator(),
];

// 使用tools数组和model来初始化一个代理执行器(executor)
// 代理执行器的类型是"zero-shot-react-description"
const executor = await initializeAgentExecutorWithOptions(tools, model, {
    agentType: "zero-shot-react-description",
});

console.log("Loaded agent.");

// 定义输入文本(input)
const input =
    "Which team won the 2023 NBA championship?" +
    " Who is Finals MVP?";
console.log(`Executing with input "${input}"...`);

// 使用executor调用代理,并传入输入文本(input)作为参数
// 这将会触发代理模型的执行,生成对输入文本的响应结果
const result = await executor.call({ input });

// The Denver Nuggets won the 2023 NBA championship and Nikola Jokić was the Finals MVP.
// 回答正确
console.log(`Got output ${result.output}`);

Memory: 在链和代理中添加状态

const memory = new BufferMemory()
const chain = new ConversationChain({ llm: model, memory: memory })

const res1 = await chain.call({ input: "Hi! I'm Kyroswu." })
// Hello Kyroswu! I'm an AI developed by OpenAI. It's great to meet you! How can I assist you today?

const res2 = await chain.call({ input: "What's my name?" }); 
// Your name is Kyroswu.
// 回答正确

流媒体

您还可以使用流API,随着生成的单词的流式返回,您希望向用户显示正在生成内容。

import { OpenAI } from "langchain/llms/openai";

const that = this
const chat = new OpenAI({
    modelName: "gpt-3.5-turbo",
    openAIApiKey: process.env.VUE_APP_OPENAI_API_KEY,
    streaming: true,
    callbacks: [
        {
            handleLLMNewToken(token) {
                // 在浏览器中直接逐字更新状态
                that.msg = that.msg + token;
                
                // 在 node 中可以使用 process.stdout.write 逐字输出
                process.stdout.write(token);
            },
        },
    ],
});

await chat.call("Write me a song about sparkling water.");