跳转至

加载数据(提取)

在我们选择的 LLM 对我们的原始数据进行处理之前,我们首先需要对原始数据进行简单处理并加载原始数据。这个过程类似于 ML 世界中的数据清理/特征工程流程,或传统数据设置中的 ETL 管道。

数据提取流程通常由三个主要阶段组成:

  • 加载数据
  • 转换数据
  • 索引并存储数据

我们将在后续章节中介绍索引/存储。在本小节中,我们主要讨论加载器和转换过程。

加载器

在我们选择的 LLM 对我们的原始数据进行处理之前,我们需要加载原始数据。LlamaIndex 执行此操作的方式是通过 数据连接器(也称为 Reader )。数据连接器 从不同的数据源提提取数据并将数据格式化为 Document 对象。Document 是数据和有关该数据的元数据的集合。

使用 SimpleDirectoryReader 加载

最容易使用的加载器是 SimpleDirectoryReader,它可以从给定目录中的 每个文件 创建文档 Document 对象。它内置于 LlamaIndex 中,可以读取各种格式,包括 MarkdownPDFWord 文档、PowerPoint 演示文稿、图像、音频和视频。

Python
from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data").load_data()

使用 LlamaHub 的阅读器

由于获取数据的地方太多,因此并非所有数据都内置。相反,您可以从我们的数据连接器注册中心 LlamaHub 下载它们。

在此示例中,LlamaIndex 下载并安装名为 DatabaseReader 的连接器,该连接器针对 SQL 数据库运行查询并将结果的每一行返回为Document:

Python
from llama_index.core import download_loader

from llama_index.readers.database import DatabaseReader

reader = DatabaseReader(
    scheme=os.getenv("DB_SCHEME"),
    host=os.getenv("DB_HOST"),
    port=os.getenv("DB_PORT"),
    user=os.getenv("DB_USER"),
    password=os.getenv("DB_PASS"),
    dbname=os.getenv("DB_NAME"),
)

query = "SELECT * FROM users"
documents = reader.load_data(query=query)

LlamaHub上有数百种连接器可供使用!

直接创建文档

除了使用加载器之外,您还可以直接使用 Document

Python
from llama_index.core import Document

doc = Document(text="text")

数据转换

加载数据后,您需要处理和转换数据,然后将其放入存储系统。这些转换包括 分块提取元数据对每个块提取embedding。这是确保 LLM 能够检索和最佳使用数据所必需的。

转换输入/输出是Node对象(一个 Document 是对应 Node 的子类)。转换也可以堆叠和重新排序。

我们有用于转换文档的高级 API 和低级 API。

高级转换 API

索引有一个 .from_documents() 方法,它接受一个 Document 对象数组,并正确地解析和分块它们。但是,有时你会希望更好地控制文档的拆分方式。

Python
from llama_index.core import VectorStoreIndex

vector_index = VectorStoreIndex.from_documents(documents)
vector_index.as_query_engine()

在底层,这会将您的文档拆分为节点对象,这些对象类似于文档(它们包含文本和元数据)但与其父文档有关系。

如果您想要自定义核心组件,比如文本分割器,通过这个抽象,您可以传入自定义 transformations 列表或应用到全局 Settings

Python
from llama_index.core.node_parser import SentenceSplitter

text_splitter = SentenceSplitter(chunk_size=512, chunk_overlap=10)

# global
from llama_index.core import Settings

Settings.text_splitter = text_splitter

# per-index
index = VectorStoreIndex.from_documents(
    documents, transformations=[text_splitter]
)

低级转换 API

您还可以显式定义这些步骤。

您可以通过使用我们的转换模块(文本分割器、元数据提取器等)作为独立组件来实现这一点,或者在我们的声明性转换流程接口中组合它们。

让我们来看看下面的步骤。

将文档拆分成节点

处理文档的关键步骤是将它们拆分为 “块”/Node 对象。关键思想是将数据处理成可以检索/提供给 LLM 的小块

LlamaIndex 支持各种文本分割器,从基于段落/句子/标记的分割器到基于文件的分割器,如 HTML、JSON。

它们可以单独使用,也可以作为摄取管道的一部分使用。

Python
from llama_index.core import SimpleDirectoryReader
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import TokenTextSplitter

documents = SimpleDirectoryReader("./data").load_data()

pipeline = IngestionPipeline(transformations=[TokenTextSplitter(), ...])

nodes = pipeline.run(documents=documents)

添加元数据

我们还可以选择将元数据添加到文档和节点。这可以手动完成,也可以使用自动元数据提取器完成。

下面的指南介绍了 1)如何自定义文档和 2)如何自定义节点。

Python
document = Document(
    text="text",
    metadata={"filename": "<doc_file_name>", "category": "<category>"},
)

添加嵌入embedding

要将节点插入向量索引,它应该具有嵌入embedding。有关更多详细信息,请参阅我们的提取管道或嵌入指南。

直接创建并传递节点

如果我们愿意,您可以直接创建节点并将节点列表直接传递给索引器:

Python
from llama_index.core.schema import TextNode

node1 = TextNode(text="<text_chunk>", id_="<node_id>")
node2 = TextNode(text="<text_chunk>", id_="<node_id>")

index = VectorStoreIndex([node1, node2])