加载数据(数据摄取)
在您选择的LLM能够处理您的数据之前,您首先需要对数据进行处理和加载。这与机器学习领域中的数据清洗/特征工程流程,或传统数据环境中的ETL流程有相似之处。
该数据摄取管道通常包含三个主要阶段:
- 加载数据
- 转换数据
- 索引并存储数据
我们将在后续章节中介绍索引/存储相关内容。本指南主要讨论加载器和转换操作。
在您选择的LLM能够处理您的数据之前,您需要先加载数据。LlamaIndex实现这一点的方式是通过数据连接器,也称为Reader。数据连接器从不同的数据源摄取数据,并将数据格式化为Document对象。一个Document是数据(目前是文本,未来将包括图像和音频)以及关于该数据的元数据的集合。
使用 SimpleDirectoryReader 加载
Section titled “Loading using SimpleDirectoryReader”最容易使用的阅读器是我们的SimpleDirectoryReader,它能够将给定目录中的每个文件转换为文档。该阅读器内置于LlamaIndex中,能够读取多种格式,包括Markdown、PDF、Word文档、PowerPoint演示文稿、图像、音频和视频。
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./data").load_data()使用来自LlamaHub的读取器
Section titled “Using Readers from LlamaHub”由于存在众多可能的数据来源,它们并未全部内置。相反,您可以从我们的数据连接器注册表LlamaHub中下载它们。
在这个示例中,LlamaIndex下载并安装名为DatabaseReader的连接器,该连接器对SQL数据库执行查询,并将结果的每一行作为Document返回:
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 上有数百个连接器可供使用!
除了使用加载器,你也可以直接使用文档。
from llama_index.core import Document
doc = Document(text="text")数据加载完成后,在将其存入存储系统之前,您需要对数据进行处理和转换。这些转换包括分块、提取元数据以及对每个数据块进行嵌入处理。这对于确保数据能够被检索并被大型语言模型优化使用至关重要。
转换输入/输出是 Node 对象(Document 是 Node 的子类)。转换也可以堆叠和重新排序。
我们提供了高级和低级两种API用于文档转换。
索引具有一个 .from_documents() 方法,该方法接受一个文档对象数组,并能正确解析和分块处理它们。然而,有时您可能希望对文档的分割方式拥有更大的控制权。
from llama_index.core import VectorStoreIndex
vector_index = VectorStoreIndex.from_documents(documents)vector_index.as_query_engine()在底层实现中,这会将您的文档拆分为节点对象,这些对象类似于文档(包含文本和元数据),但与它们的父文档存在关联关系。
如果你想自定义核心组件,比如文本分割器,通过这个抽象层你可以传入一个自定义的 transformations 列表或应用到全局的 Settings:
from llama_index.core.node_parser import SentenceSplitter
text_splitter = SentenceSplitter(chunk_size=512, chunk_overlap=10)
# globalfrom llama_index.core import Settings
Settings.text_splitter = text_splitter
# per-indexindex = VectorStoreIndex.from_documents( documents, transformations=[text_splitter])您也可以明确定义这些步骤。
您可以通过两种方式实现:要么将我们的转换模块(文本分割器、元数据提取器等)作为独立组件使用,要么在我们的声明式转换管道接口中组合它们。
让我们按照以下步骤进行操作。
处理文档的一个关键步骤是将它们分割成“块”/节点对象。核心思想是将数据处理成可检索/输入给LLM的小片段。
LlamaIndex 支持多种文本分割器,从基于段落/句子/标记的分割器到基于文件的分割器(如HTML、JSON)。
这些可以单独使用或作为数据摄取管道的一部分。
from llama_index.core import SimpleDirectoryReaderfrom llama_index.core.ingestion import IngestionPipelinefrom llama_index.core.node_parser import TokenTextSplitter
documents = SimpleDirectoryReader("./data").load_data()
pipeline = IngestionPipeline(transformations=[TokenTextSplitter(), ...])
nodes = pipeline.run(documents=documents)您也可以选择为您的文档和节点添加元数据。这可以通过手动方式或使用自动元数据提取器来完成。
以下是关于 1) 如何自定义文档 和 2) 如何自定义节点 的指南。
document = Document( text="text", metadata={"filename": "<doc_file_name>", "category": "<category>"},)要将节点插入向量索引,它应具有嵌入向量。详情请参阅我们的数据摄取流水线或嵌入向量指南。
如果您愿意,可以直接创建节点并将节点列表直接传递给索引器:
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])