跳至主要内容

使用 LCEL 构建简单的 LLM 应用程序

在本快速入门中,我们将向您展示如何使用 LangChain 构建一个简单的 LLM 应用程序。该应用程序将把文本从英语翻译成另一种语言。这是一个相对简单的 LLM 应用程序——它只是一个单一的 LLM 调用加上一些提示。尽管如此,这仍然是开始使用 LangChain 的绝佳方式——许多功能只需要一些提示和一个 LLM 调用即可构建!

阅读完本教程后,您将对以下内容有更深入的了解

让我们深入探讨!

设置

安装

要安装 LangChain,请运行

yarn add langchain @langchain/core

有关更多详细信息,请参阅我们的 安装指南

LangSmith

您使用 LangChain 构建的许多应用程序将包含多个步骤,这些步骤包含对 LLM 调用的多次调用。随着这些应用程序变得越来越复杂,能够检查链或代理内部究竟发生了什么变得至关重要。最有效的方法是使用 LangSmith

在上面的链接注册后,请确保设置您的环境变量以开始记录跟踪

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."

# Reduce tracing latency if you are not in a serverless environment
# export LANGCHAIN_CALLBACKS_BACKGROUND=true

使用语言模型

首先,让我们学习如何单独使用语言模型。LangChain 支持许多不同的语言模型,您可以互换使用它们——从下方选择您要使用的模型!

选择您的聊天模型

安装依赖项

yarn add @langchain/openai 

添加环境变量

OPENAI_API_KEY=your-api-key

实例化模型

import { ChatOpenAI } from "@langchain/openai";

const model = new ChatOpenAI({ model: "gpt-4" });

首先,让我们直接使用模型。ChatModel 是 LangChain “可运行对象”的实例,这意味着它们公开了一个用于与它们交互的标准接口。要简单地调用模型,我们可以将消息列表传递给 .invoke 方法。

import { HumanMessage, SystemMessage } from "@langchain/core/messages";

const messages = [
new SystemMessage("Translate the following from English into Italian"),
new HumanMessage("hi!"),
];

await model.invoke(messages);
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "ciao!",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "ciao!",
name: undefined,
additional_kwargs: { function_call: undefined, tool_calls: undefined },
response_metadata: {
tokenUsage: { completionTokens: 3, promptTokens: 20, totalTokens: 23 },
finish_reason: "stop"
},
tool_calls: [],
invalid_tool_calls: []
}

如果我们启用了 LangSmith,我们可以看到此运行被记录到 LangSmith,并且可以查看 LangSmith 跟踪

输出解析器

请注意,模型的响应是 AIMessage。这包含字符串响应以及有关响应的其他元数据。通常情况下,我们可能只想使用字符串响应。我们可以使用一个简单的输出解析器解析出此响应。

首先,我们导入简单的输出解析器。

import { StringOutputParser } from "@langchain/core/output_parsers";

const parser = new StringOutputParser();

使用它的其中一种方法是单独使用它。例如,我们可以保存语言模型调用的结果,然后将其传递给解析器。

const result = await model.invoke(messages);
await parser.invoke(result);
"ciao!"

使用 LCEL 将组件链接在一起

我们还可以将模型“链接”到输出解析器。这意味着此输出解析器将使用模型的输出进行调用。此链接受语言模型的输入类型(字符串或消息列表),并返回输出解析器的输出类型(字符串)。

我们可以使用 .pipe() 方法创建链。.pipe() 方法用于在 LangChain 中将两个元素组合在一起。

const chain = model.pipe(parser);
await chain.invoke(messages);
"Ciao!"

这是使用 LangChain 表达式语言 (LCEL) 将 LangChain 模块链接在一起的简单示例。这种方法有几个优点,包括优化的流式传输和跟踪支持。

现在让我们看看 LangSmith,可以看到这个链条包含两个步骤:首先调用语言模型,然后将结果传递给输出解析器。你可以查看 LangSmith 跟踪记录

提示模板

现在我们直接将消息列表传递给语言模型。这个消息列表从哪里来?通常它是由用户输入和应用逻辑组合构建的。应用逻辑通常会获取原始用户输入,并将其转换为可传递给语言模型的消息列表。常见的转换包括添加系统消息或使用用户输入格式化模板。

提示模板是 LangChain 中一个旨在帮助进行这种转换的概念。它们接收原始用户输入并返回可传递给语言模型的数据(提示)。

让我们在这里创建一个提示模板。它将接受两个用户变量:

  • language:将文本翻译成的语言
  • text:要翻译的文本
import { ChatPromptTemplate } from "@langchain/core/prompts";

首先,让我们创建一个字符串,将其格式化为系统消息

const systemTemplate = "Translate the following into {language}:";

接下来,我们可以创建提示模板。它将结合 systemTemplate 和一个用于放置文本的更简单的模板

const promptTemplate = ChatPromptTemplate.fromMessages([
["system", systemTemplate],
["user", "{text}"],
]);

这个提示模板的输入是一个字典。我们可以单独尝试这个提示模板,看看它本身能做什么

const promptValue = await promptTemplate.invoke({
language: "italian",
text: "hi",
});

promptValue;
ChatPromptValue {
lc_serializable: true,
lc_kwargs: {
messages: [
SystemMessage {
lc_serializable: true,
lc_kwargs: {
content: "Translate the following into italian:",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Translate the following into italian:",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
HumanMessage {
lc_serializable: true,
lc_kwargs: { content: "hi", additional_kwargs: {}, response_metadata: {} },
lc_namespace: [ "langchain_core", "messages" ],
content: "hi",
name: undefined,
additional_kwargs: {},
response_metadata: {}
}
]
},
lc_namespace: [ "langchain_core", "prompt_values" ],
messages: [
SystemMessage {
lc_serializable: true,
lc_kwargs: {
content: "Translate the following into italian:",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Translate the following into italian:",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
HumanMessage {
lc_serializable: true,
lc_kwargs: { content: "hi", additional_kwargs: {}, response_metadata: {} },
lc_namespace: [ "langchain_core", "messages" ],
content: "hi",
name: undefined,
additional_kwargs: {},
response_metadata: {}
}
]
}

可以看到它返回了一个 ChatPromptValue,它包含两条消息。如果我们想直接访问这些消息,可以这样做

promptValue.toChatMessages();
[
SystemMessage {
lc_serializable: true,
lc_kwargs: {
content: "Translate the following into italian:",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Translate the following into italian:",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
HumanMessage {
lc_serializable: true,
lc_kwargs: { content: "hi", additional_kwargs: {}, response_metadata: {} },
lc_namespace: [ "langchain_core", "messages" ],
content: "hi",
name: undefined,
additional_kwargs: {},
response_metadata: {}
}
]

现在我们可以将它与上面的模型和输出解析器组合在一起。这将把所有三个组件链在一起。

const llmChain = promptTemplate.pipe(model).pipe(parser);
await llmChain.invoke({ language: "italian", text: "hi" });
"ciao"

如果我们查看 LangSmith 跟踪记录,可以看到所有三个组件都显示在 LangSmith 跟踪记录

结论

就是这样!在本教程中,你学习了如何创建第一个简单的 LLM 应用。你了解了如何使用语言模型、如何解析它们的输出、如何创建提示模板、如何使用 LCEL 将它们链接在一起,以及如何使用 LangSmith 获得对创建的链条的良好可观察性。

这仅仅是成为一名熟练的 AI 工程师所需要学习的内容的冰山一角。幸运的是,我们还有很多其他资源!

有关 LangChain 核心概念的更多信息,请查看详细的 概念指南

如果你对这些概念有更具体的问题,请查看操作指南的以下部分

以及 LangSmith 文档


此页面是否有帮助?


你也可以在 GitHub 上留下详细的反馈 GitHub.