Use Case Accelerant: Extraction Service

用例加速器:提取服务

7分钟阅读

今天,我们很高兴地宣布我们的最新 OSS 用例加速器:一个 提取 服务。LLM 是从非结构化来源中提取结构化数据的强大工具。我们在过去几个版本中改进了开源 LangChain 库中的 对数据提取的支持,现在我们正在通过一个入门存储库来更进一步,帮助您构建自己的提取应用程序。

入门存储库 包含一个精简的 Web 应用程序,可以扩展它来构建一个自助提取应用程序,您的组织中的非技术人员可以使用该应用程序利用 LLM 的力量来进行数据提取。

我们将在下面更详细地讨论提取服务,但首先,让我们讨论提取用例以及 LLM 如何提供帮助。

提取用例

企业投入大量资源和精力来从非结构化数据源中获取有价值的见解,这些数据源包括 PDF 和 PowerPoint 演示文稿等文档、网站以及产品评论和客户反馈等其他文本信息。

通常部署的提取解决方案倾向于依赖于多种方法的组合,这些方法涉及人员进行的手动工作以及使用手工制作的规则或自定义微调的 ML 模型进行的自动提取。

对于自动化解决方案,公司一直在从基于规则的方法转向基于机器学习 (ML) 的解决方案,认识到 ML 驱动的方案通常在其系统中提供更大的可扩展性和可维护性。

上一代基于 ML 的解决方案的主要问题是,它们通常需要大量的努力来构建和维护,以及大量标记数据来训练模型。

大型语言模型 (LLM) 已成为一种能够帮助推动信息提取应用程序的新型 ML 技术。LLM 可以通过向它们提供适当的指令(以提示的形式)和适当的参考示例来适应特定提取任务。因此,LLM 显著降低了采用 AI 首先生成方法进行信息提取的门槛。

新一代信息提取解决方案将建立在 LLM 之上。此类解决方案仍将涉及人机交互,以向 LLM 提供反馈和指导,以及一些自定义规则和启发式方法来处理边缘情况。此类解决方案仍然需要一个工作流程工具来管理数据提取和验证过程。但此类解决方案将变得比上一代解决方案更加可扩展和可维护。

LLM 来救援

如何使用 LLM 进行信息提取?在这里,我们将概述构建提取服务时应考虑的关键组件和高级和高级注意事项。

原始数据

使用 LLM 提取信息从您想要提取的数据开始,这些数据首先需要转换为文本格式。LangChain 包含 数百个文档加载器,您可以使用这些加载器解析 PDF 等文件并将其转换为文本格式。

加载文本后,您需要决定如何将其呈现给 LLM。最简单的方法是将整个文本呈现给 LLM。对于小文本片段来说,这很好,但对于较长的文本来说,它有几个陷阱。首先,它可能无法完全放入上下文窗口。其次,假设它可以,大多数语言模型在较长的输入上表现更差,因此将所有内容都放入上下文中可能会产生更糟糕的结果。第三,即使结果相当,推理时间也会很长。

一种更复杂的方法包括将文本分割成块,并仅通过 LLM 处理相关的块。当然,这带来了必须决定哪些块相关的复杂性。或者,您可以并行地从所有块中提取内容,这将保证您不会错过任何相关的块。无论哪种方式,您都需要决定如何最好地组合来自各个块的结果以及如何处理跨多个块分解的信息。

描述您想要什么

如果您希望 LLM 有效地提取信息,您需要为它提供您想要提取内容的描述。

这样的描述可以分解为三个关键组件

1. 描述您要提取数据的结构的模式。

2. 提供提取上下文并为 LLM 做好准备的提示。

3. 显示文本提取示例的参考示例。

如何使它发挥作用

所以这些是组件,但您如何让它真正发挥作用?

我们想在这里介绍两个简单但强大的想法。

第一个关键思想是确保 LLM 以正确的格式响应。如果您指示 LLM 在其提示中输出 JSON,它可能并不总是这样做。函数调用已成为一种新的且相对可靠的方法,可以强制 LLM 输出特定格式。我们建议使用它来提高性能。

查看 结构化输出文档,了解显示不同 LLM 的工具/函数调用的高级 LangChain API。

另一个提高性能的技巧是使用参考示例。虽然您可以设置一个没有参考示例的提取问题,但我们发现实践中包含输入和对应输出的示例非常有利。在显示 LLM 如何处理特定情况方面,这些示例往往比指令更有帮助。

我们在 提取用例文档 中包含了更多详细信息,这将帮助您从 LLM 中榨取性能。

该服务

考虑到这一点,我们的 提取服务 到底提供了什么?

该服务构建在 FastAPI 和 Postgresql 之上。它公开了一个标准的 REST API,并附带一个 docker-compose 文件,可帮助您快速启动堆栈。该服务是一个精简的 Web 应用程序,可以扩展它来为组织中的非技术人员创建提取应用程序。这实际上是您可以用来快速启动应用程序开发的样板代码。或者,您可以照常使用它用于自己的提取工作流程,而无需进行任何进一步的开发。

该 API 允许定义和持久化“提取器”,其中包含配置 LLM 进行提取所需的关键组件。这些组件包括描述您要提取数据的结构的模式、提供提取上下文并为模型做好准备的提示,以及显示模型一些提取示例的参考示例。

此外,该 API 公开了提取端点,允许您使用现有提取器提交文件以进行提取,以及端点的第二个变体,允许您使用 RemoteRunnable 将服务轻松用作更大的 LangChain 表达式语言 (LCEL) 链的一部分。

该服务预先配置了基于 MIME 类型的解析器,并支持解析 PDF 和 HTML 文件。您可以使用现有的 LangChain 文档加载器和解析器 轻松扩展它以支持其他类型的文件(例如,PowerPoint)。

我们在提取 API 中做出的一个关键决定是,我们将其设计为始终提取多个实体。当从文本中提取信息时,这通常是期望的行为,因为它允许模型在存在的情况下提取多个实体,并且还允许模型在文本不包含相关信息的情况下提取零个实体。

您如何实际使用此服务?

基于以上内容,有一些使用注意事项。您可以使用 JSON 模式来精确定义要提取的内容。您可以指定将被合并以提高提取结果质量的示例。您可以在调用 API 时指定这些内容,也可以在数据库中创建和保存提取器和示例。这将使保存和共享提取器变得容易。在传递文本方面,您可以传递原始文本或二进制文件。

例子

让我们看一个如何使用此服务的示例。

首先,您可以 创建一个提取器

curl -X 'POST' \
  'https://127.0.0.1:8000/extractors' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Personal Information",
  "description": "Use to extract personal information",
  "schema": {
      "type": "object",
      "title": "Person",
      "required": [
        "name",
        "age"
      ],
      "properties": {
        "age": {
          "type": "integer",
          "title": "Age"
        },
        "name": {
          "type": "string",
          "title": "Name"
        }
      }
    },
  "instruction": "Use information about the person from the given user input."
}'

这是在做什么?

首先,我们向服务发送一个 name 参数 - 这只是我们正在创建的提取器的一个简单的人类可读名称,不会被 LLM 使用。同样,description 参数仅用于跟踪目的,不会以任何方式使用。

schema 参数由服务使用。这是 JSON 模式,代表我们尝试提取的对象的模式。我们正在提取一个 Person 模式,它有两个属性,这两个属性都是必需的:age(一个整数)和 name(一个字符串)。

instruction 参数也由服务使用。这些指令与模式和文本一起发送给 LLM,并可以提供有关 LLM 如何运行的额外上下文和说明。

当我们发送它时,我们得到一个与我们刚刚创建的提取器 ID 相对应的响应

{
  "uuid": "32d5324a-8a48-4073-b57c-0a2ebfb0bf5e"
}

注册后,我们可以 调用它

curl -s -X 'POST' \
'https://127.0.0.1:8000/extract' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'extractor_id=32d5324a-8a48-4073-b57c-0a2ebfb0bf5e' \
-F 'text=my name is chester and i am 20 years old. My name is eugene and I am 1 year older than chester.' \
-F 'mode=entire_document' \
-F 'file=' | jq .

我们正在传入一个 extractor_id - 这是从上一步返回的 ID。

我们还传入 text - 这是要从中提取信息的文本。

我们指定 mode=entire_document。这告诉服务从整个文档中提取信息。如果我们要从中提取的文本更大,我们可能需要以不同的方式处理它 - 这就是我们控制该参数的地方。

最后,我们传入一个具有空值的 file。此服务也接受文件上传,但我们在这里不使用它

我们得到了以下响应

{
  "data": [
    {
      "name": "chester",
      "age": 20
    },
    {
      "name": "eugene",
      "age": 21
    }
  ]
}

结论

在这篇博文中,我们介绍了使用 LLM 从非结构化文本中提取结构化数据的概念,介绍了我们完全 开源存储库,该存储库公开了一个服务来执行此操作,并运行了一个关于如何使用它的相对简单的示例。有关更复杂的示例,您可以查看服务的 自述文件。有关如何在不使用此服务的情况下使用 LangChain 进行提取的信息,您可以查看我们更新的 用例文档。在接下来的几周内,我们将为此服务添加一个相对简单的前端,并公开其托管版本。我们很乐意收到任何反馈!

其他资源