跳到主要内容

构建提取链

先决条件

本指南假设您熟悉以下概念

在本教程中,我们将构建一个链来从非结构化文本中提取结构化信息。

信息

本教程仅适用于支持函数/工具调用的模型

设置

安装

要安装 LangChain,请运行

yarn add langchain

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

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

模式

首先,我们需要描述我们想要从文本中提取的信息。

我们将使用Zod 来定义一个示例模式,该模式提取个人信息。

yarn add zod @langchain/core
import { z } from "zod";

const personSchema = z.object({
name: z.string().nullish().describe("The name of the person"),
hair_color: z
.string()
.nullish()
.describe("The color of the person's hair if known"),
height_in_meters: z.string().nullish().describe("Height measured in meters"),
});

在定义模式时,有两个最佳实践

  1. 记录属性模式本身:此信息将发送到 LLM,并用于提高信息提取的质量。
  2. 不要强迫 LLM 捏造信息!上面我们对属性使用了.nullish(),允许 LLM 在不知道答案的情况下输出nullundefined
信息

为了获得最佳性能,请记录好模式,并确保模型不会在文本中没有可提取信息的情况下被迫返回结果。

提取器

让我们使用上面定义的模式创建一个信息提取器。

import { ChatPromptTemplate } from "@langchain/core/prompts";

// Define a custom prompt to provide instructions and any additional context.
// 1) You can add examples into the prompt template to improve extraction quality
// 2) Introduce additional parameters to take context into account (e.g., include metadata
// about the document from which the text was extracted.)
const prompt = ChatPromptTemplate.fromMessages([
[
"system",
`You are an expert extraction algorithm.
Only extract relevant information from the text.
If you do not know the value of an attribute asked to extract,
return null for the attribute's value.`,
],
// Please see the how-to about improving performance with
// reference examples.
// ["placeholder", "{examples}"],
["human", "{text}"],
]);

我们需要使用支持函数/工具调用的模型。

请查看文档,了解可用于此 API 的一些模型列表。

import { ChatAnthropic } from "@langchain/anthropic";

const llm = new ChatAnthropic({
model: "claude-3-sonnet-20240229",
temperature: 0,
});

const runnable = prompt.pipe(llm.withStructuredOutput(personSchema));

const text = "Alan Smith is 6 feet tall and has blond hair.";
await runnable.invoke({ text });
{ name: "Alan Smith", hair_color: "blond", height_in_meters: "1.83" }
信息

提取是生成式的 🤯

LLM 是生成式模型,因此它们可以做一些非常酷的事情,例如即使提供的单位是英尺,也能正确提取人的身高为米!

我们可以查看 LangSmith 跟踪这里

尽管我们在定义架构时使用了变量名personSchema,但 Zod 无法推断出这个名称,因此不会将其传递给模型。为了帮助 LLM 更好地理解你提供的架构的含义,你也可以给传递给withStructuredOutput()的架构命名。

const runnable = prompt.pipe(
llm.withStructuredOutput(personSchema, { name: "person" })
);

const text = "Alan Smith is 6 feet tall and has blond hair.";

await runnable.invoke({ text });
{ name: "Alan Smith", hair_color: "blond", height_in_meters: "1.83" }

这在许多情况下可以提高性能。

多个实体

在**大多数情况下**,你应该提取实体列表而不是单个实体。

这可以通过在 Zod 中嵌套模型来轻松实现。

import { z } from "zod";

const personSchema = z.object({
name: z.string().nullish().describe("The name of the person"),
hair_color: z
.string()
.nullish()
.describe("The color of the person's hair if known"),
height_in_meters: z.number().nullish().describe("Height measured in meters"),
});

const dataSchema = z.object({
people: z.array(personSchema).describe("Extracted data about people"),
});
信息

这里提取可能不完美。请继续阅读如何使用**参考示例**来提高提取质量,并查看**指南**部分!

const runnable = prompt.pipe(llm.withStructuredOutput(dataSchema));
const text =
"My name is Jeff, my hair is black and i am 6 feet tall. Anna has the same color hair as me.";
await runnable.invoke({ text });
{
people: [
{ name: "Jeff", hair_color: "black", height_in_meters: 1.83 },
{ name: "Anna", hair_color: "black", height_in_meters: null }
]
}
提示

当架构适应**多个实体**的提取时,它也允许模型在文本中没有相关信息的情况下通过提供空列表来提取**没有实体**。

这通常是件**好事**!它允许在实体上指定**必需**的属性,而无需强制模型检测该实体。

我们可以看到 LangSmith 跟踪这里

下一步

现在你已经了解了 LangChain 的提取基础知识,你可以继续学习其他操作指南

  • 添加示例:了解如何使用**参考示例**来提高性能。
  • 处理长文本:如果文本不适合 LLM 的上下文窗口,你应该怎么做?
  • 使用解析方法:使用基于提示的方法来提取不支持**工具/函数调用**的模型。

此页面是否有帮助?


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