llama_index 从 0 到 1
llama_index 基础设施:数据连接、索引构建、查询接口 高级特性:六大核心功能来增强语言模型处理和响应外部数据的能力 数据连接器 Documents & Nodes (文档与节点)llama_index
LlamaIndex与传统的数据处理方式相比,引入了一系列创新和独特的作用,特别是在处理、索引和检索大规模文本数据方面。
高级数据抽象:LlamaIndex通过Document
和Node
提供了高级的数据抽象,使得复杂数据结构的构建和管理变得更加简单直观。
灵活的数据连接器:它提供了广泛的数据连接器支持,能够轻松接入多种数据源,如文件系统、数据库、网页等,提高了数据处理的灵活性。
向量化搜索能力:LlamaIndex内建支持向量化搜索,这意味着能够基于语义相似性进行高效的信息检索,而不仅仅是基于关键字匹配。
结构化和非结构化数据处理:不仅能处理结构化数据(如数据库表格),也能处理非结构化数据(如文本内容),提供了更全面的数据处理能力。
自定义索引构建:用户可以根据需要自定义索引构建过程,包括文档分块、向量存储配置等,这为特定应用场景下的优化提供了可能。
丰富的查询接口:提供了丰富的查询接口,支持包括文本查询、向量查询等多种方式,满足不同查询需求。
流式响应处理:支持流式响应处理,能够高效处理实时数据流,为构建动态、实时应用提供了强大的基础。
深度学习模型集成:可以轻松集成大型语言模型(如OpenAI的GPT系列),为文本数据的理解和生成提供了深层次的支持。
智能文档解析:内置的智能文档解析能力,可以自动识别和提取文档中的关键信息,简化了数据预处理步骤。
多维度数据关联:支持在节点级别定义数据之间的多种关系,为构建复杂的知识图谱和关联分析提供了强大工具。
高效的数据索引和检索:针对大规模数据集设计,确保了即使在海量数据背景下也能实现快速的数据索引和检索。
易于扩展和定制:提供了丰富的API和定制选项,使得LlamaIndex易于根据具体需求进行扩展和定制。
跨领域应用:由于其灵活和强大的数据处理能力,LlamaIndex适用于多种领域,包括但不限于搜索引擎、推荐系统、知识管理等。
自动化数据管道:简化了数据管道的构建过程,从数据导入、处理到索引构建和查询响应,所有步骤都可以高度自动化。
优化的存储解决方案:通过向量存储和定制化索引策略,优化了数据的存储和检索效率。
支持复杂查询逻辑:能够处理包括布尔查询、范围查询等在内的复杂查询逻辑,提供了强大的查询表达能力。
安全性和隐私保护:在设计上考虑了数据的安全性和隐私保护,支持对敏感数据进行加密和访问
控制。
可扩展的架构设计:LlamaIndex的架构设计考虑到了可扩展性,支持水平扩展以应对不断增长的数据处理需求。
开放源代码和社区支持:作为一个开放源代码项目,LlamaIndex拥有活跃的开发者社区,不断地得到新功能和改进。
直观的管理和监控工具:提供了用于数据索引、查询性能监控的工具,帮助用户优化和管理数据处理流程。
LlamaIndex的这些特点和能力,使其在处理今日海量、复杂数据场景下,相比传统数据处理方法展现出独特的优势,尤其是在数据的理解、检索和智能处理方面。
基础设施:数据连接、索引构建、查询接口
假设有一个巨大的图书馆(这里的图书馆比喻为LLamaIndex),这个图书馆的目标是帮助人们(比喻为大模型,如GPT)找到他们需要的信息。
这个过程分为三个主要步骤:
搬书进图书馆(数据连接):首先,我们需要把很多书(数据)搬进图书馆里。
如果书都在图书馆外面,那么人们就无法借阅这些书了。所以,第一步就是把这些书收集起来,放到图书馆里。
整理书架(索引构建):仅仅把书搬进图书馆还不够,如果这些书随意堆放,当人们需要找到某本特定的书时,将会非常困难。
所以,图书馆工作人员会把书按照类别、作者等信息整理好,放在不同的书架上。
这样当你需要找某本书时,就可以直接去相关的书架上找,这个整理书架的过程就像是建立索引。
索引是帮助你快速找到你需要的书的系统。
提供图书馆目录(查询接口):现在书都整理好了,图书馆还需要提供一个目录,让你知道每本书的位置。
当你要找一本书时,你可以查看这个目录,找到书的具体位置,然后直接去那个位置拿书。
这个目录就像是查询接口,它让你能够通过某种方式(比如书名、作者或者书的类别)来查询你想要的信息,然后告诉你这些信息在哪里可以找到。
所以,整个LLamaIndex的过程就是:把数据(书)搬进来,然后通过建立索引(整理书架)来帮助快速找到数据,最后通过查询接口(图书馆目录)让大模型(人们)可以更容易地获取他们需要的信息。
高级特性:六大核心功能来增强语言模型处理和响应外部数据的能力
A. 自定义文档分块
核心概念:当你有一大块文本需要处理时,直接处理可能会非常困难,尤其是当文本大小超过模型处理能力时。因此,你需要将这大块文本切割成小片段,每个片段称为一个“文本块”。这就像是将一本厚书切分成一章章,使其更易于阅读和理解。 实际操作:在LLamaIndex中,你可以设置每个文本块的大小,比如500个字符,这样就可以根据你的需求来调整文本块的大小,确保它们既不太大也不太小,以便于处理。B. 向量存储
核心概念:为了让计算机“理解”和检索文本,我们通常会将文本转换为数学上的向量(即一串数字)。这些向量可以在向量空间中进行各种操作,比如计算它们之间的相似度。 实际操作:使用ChromaDB这类工具来创建和管理这些向量的集合。你可以在其中存储文本块的向量表示,并在之后快速检索它们。C. 自定义检索
核心概念:检索是根据某种条件(如关键词、主题等)从大量数据中找到所需信息的过程。在这个系统中,检索是基于向量的相似性进行的,意味着你可以找到与你查询条件最相似的文本块。 实际操作:通过设定相似度排名的顶部结果数量(如前5个),你可以自定义如何从你的数据集中检索信息。D. 指定LLM
核心概念:LLM指的是大型语言模型,如OpenAI的模型。你可以根据需要选择不同的语言模型来处理文本数据。 实际操作:在LLamaIndex系统中,你可以指定使用特定的语言模型,如OpenAI的GPT,来分析文本和生成回应。E. 指定响应模式
核心概念:响应模式定义了如何处理和展示查询结果。例如,你可以选择以树状结构展示结果,这有助于理解和导航复杂的信息。 实际操作:设置查询引擎的响应模式为“tree_summarize”,可以让结果以树形摘要的方式展现,使得信息更加组织化和易于理解。F. 指定流式响应
核心概念:流式处理是指系统能够实时处理连续数据流。这对于需要即时反馈的应用场景非常重要。 实际操作:通过设置查询引擎支持流式响应,你可以让系统实时地处理和响应查询请求,而不是等待所有数据都被处理完毕。# 安装特定版本的llama-index、llama-hub和chromadb库以及openai库
!pip install llama-index==0.9.19
!pip install llama-hub==0.0.61
!pip install -q -U chromadb
!pip install openai
# 导入os库,用于设置环境变量
import os
# 设置OpenAI的API密钥环境变量,''内应填入你的OpenAI API密钥
os.environ['OPENAI_API_KEY'] = '淘宝有 5RMB'
# 导入chromadb库,用于向量存储
import chromadb
# 从llama_index库导入VectorStoreIndex和SimpleDirectoryReader,用于创建索引和读取目录数据
from llama_index import VectorStoreIndex, SimpleDirectoryReader
# 从llama_index导入ServiceContext,用于配置服务上下文
from llama_index import ServiceContext
# 从llama_index.vector_stores导入ChromaVectorStore,用于向量存储
from llama_index.vector_stores import ChromaVectorStore
# 从llama_index导入StorageContext,用于配置存储上下文
from llama_index import StorageContext
# 从llama_index.llms导入OpenAI,用于指定使用OpenAI的大型语言模型
from llama_index.llms import OpenAI
# 配置服务上下文,设置文档分块大小为500,指定使用OpenAI的LLM
service_context = ServiceContext.from_defaults(chunk_size=500, llm=OpenAI())
# 创建ChromaDB的持久化客户端
chroma_client = chromadb.PersistentClient()
# 在ChromaDB中创建一个名为"quickstart"的新集合
chroma_collection = chroma_client.create_collection("quickstart")
# 使用刚才创建的集合创建一个向量存储实例
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
# 配置存储上下文,指定使用刚才创建的向量存储
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# 1.docx文档是我自己找的 根据自己需求就行 放在data目录下
# 使用pandoc命令将1.docx文件转换成html格式,并保存到/content/data/2.html路径
!pandoc -s /content/1.docx -o /content/data/2.html
# 读取'data'目录下的文档数据,这一步耗时大约5分钟
documents = SimpleDirectoryReader('data').load_data()
# 使用文档数据创建索引,同时配置服务上下文和存储上下文
index = VectorStoreIndex.from_documents(documents, service_context=service_context, storage_context=storage_context)
# 创建一个查询引擎,设置响应模式为'tree_summarize',并启用流式响应
query_engine = index.as_query_engine(response_mode='tree_summarize', streaming=True)
# 使用查询引擎查询"内容是什么 中文回答我",并获取响应
response = query_engine.query("内容是什么 中文回答我")
# 打印查询的响应流
response.print_response_stream()
数据连接器
官网:https://llamahub.ai/
Simple Directory Reader:用于读取文件系统中的文件夹和文件。
Psychic Reader、DeepLake Reader、Qdrant Reader:针对特定存储或数据库系统设计的读取器。
Discord Reader、Slack Reader:能够从聊天应用程序中读取数据。
MongoDB Reader、Chroma Reader、MyScale Reader:用于从数据库中读取数据。
Faiss Reader、MilvusReader:专门用于读取向量数据库中的数据。
Obsidian Reader、Notion Reader:从特定笔记应用中读取数据。
Github Repo Reader:从GitHub仓库中读取数据。
Google Docs Reader:从Google文档中读取数据。
Twitter Reader、Web Page Reader:分别用于从Twitter和网页中读取数据。
等等…
具体怎么用 上面有案例。
Documents & Nodes (文档与节点)
在LlamaIndex框架中,Document和Node是核心的数据抽象概念,它们帮助处理和组织各种类型的数据以便于索引、查询和分析。这两个概念提供了一种灵活和高效的方式来处理来自不同数据源的信息。
Document:文档
概念:在LlamaIndex中,Document代表了任何形式的数据源的容器。这可以是文本文件、PDF、数据库中的一条记录、API响应或其他任何形式的数据。 存储内容: 文本数据:Document的主体内容,比如一篇文章的文本。 属性数据:与文本数据相关的属性,如作者、创建日期等。 元数据(metadata):关于文档的额外信息,比如文件名、文件路径、文档类别等。 关系数据(relationships):文档与其他文档之间的关系,例如引用、回复等。 示例:from llama_index import Document
book_introductions = [
"《三国演义》讲述了从东汉末年到西晋初年之间的历史故事,重点描述了曹操、刘备、孙权等人物的政治和军事斗争。",
"《红楼梦》是中国古典小说中的巅峰之作,通过贾宝玉、林黛玉等人的爱情悲剧和贾、王、史、薛四大家族的兴衰史,展现了一个广阔的社会生活画卷。"
]
documents = [Document(text=intro) for intro in book_introductions]
这段代码创建了两个Document对象,每个对象包含了列表中的一个字符串作为文本数据。
自定义Document
目的:通过自定义Document,可以为每个文档设置独特的元数据和文档ID,以及在加载数据时通过SimpleDirectoryReader等工具设置文件特定的元数据。 应用场景:这对于后续的数据处理、索引构建和查询非常有用,因为这些元数据和ID可以用来快速检索和识别特定的文档。Node:节点
概念:Node在LlamaIndex中是一个更细粒度的数据单位,它同样可以包含文档中相同类型的数据和属性。Node是构建复杂数据结构的基石,比如文档的结构化表示、知识图谱等。 构建方式: 基于API直接构建:可以直接使用API创建节点,为节点指定文本内容、ID等属性。 基于Document,利用节点解析器(NodeParser)生成:这种方法允许从已有的Document对象生成节点,节点会继承Document的属性。 示例:from llama_index.schema import TextNode
great_wall_node = TextNode(
text="长城是中国古代的军事防御工程,是世界上最为壮观的建筑之一。它东起山海关,西至嘉峪关,全长超过两千公里。",
id_="great-wall-001"
)
这段代码创建了一个TextNode实例,为该节点指定了文本内容和一个唯一标识符ID。
这种节点不仅能够携带关于长城的基础信息,如其历史和重要性的描述,还可以通过进一步定义节点间的关系(如与长城相关的历史事件、附近城市等)来丰富知识图谱的内容,提供更多上下文信息,使得数据不仅仅是孤立存在,而是形成了一个相互连接和增强的信息网络。
自定义Node
目的:通过自定义Node,开发者可以定义节点间的关系,自定义节点ID,以及设置节点的元数据。这对于构建复杂的数据关系和实现高级功能非常重要。 应用场景:例如,建立节点之间的层级关系、前后关系或其他语义关系,这有助于在查询和数据分析时提供更丰富的上下文信息。想象我们正在建立一个关于历史人物及其相互关系的知识图谱。在这个图谱中,每个重要的历史人物都可以被视为一个节点,而这些人物之间的各种关系,比如“朋友”、“敌人”或“盟友”,则通过节点之间的链接来表示。
历史人物节点示例
假设我们的知识图谱聚焦于古罗马的两位著名人物:恺撒和庞培。
from llama_index.schema import TextNode, NodeRelationship, RelatedNodeInfo
# 创建代表恺撒的节点
caesar_node = TextNode(
text="恺撒,全名盖乌斯·尤利乌斯·恺撒,是罗马共和国末期的一位军事将领和政治家,他的行动直接导致了罗马共和国的灭亡和罗马帝国的兴起。",
id_="caesar-123",
metadata={
'出生年': -100,
'死亡年': -44,
'职位': '将军和独裁官'
}
)
# 创建代表庞培的节点
pompey_node = TextNode(
text="庞培,全名狮纳乌斯·庞培·马格努斯,也被称为庞培大帝,是罗马共和国末年的军事和政治领袖。",
id_="pompey-456",
metadata={
'出生年': -106,
'死亡年': -48,
'职位': '将军和政治家'
}
)
这段代码创建了两个TextNode
实例,分别代表恺撒和庞培,每个节点都包含了关于这位人物的简介、一个唯一标识符和一些元数据,如出生年、逝世年和他们的职位。
定义节点间的关系
然后,我们定义恺撒和庞培之间的关系。尽管他们最初是盟友,但随后成为了政治上的对手,这场纷争最终导致了罗马共和国的崩溃。
# 定义恺撒和庞培之间的关系
caesar_node.relationships[NodeRelationship.RIVAL] = RelatedNodeInfo(node_id=pompey_node.id_, metadata={"开始时间": "公元前49年"})
pompey_node.relationships[NodeRelationship.RIVAL] = RelatedNodeInfo(node_id=caesar_node.id_, metadata={"开始时间": "公元前49年"})
这里,我们用NodeRelationship.RIVAL
(竞争关系)来表示他们之间的对抗关系,并通过metadata
来指定这种关系始于公元前49年。
通过使用节点的方式,我们可以以非常精细和灵活的方式构建和表达复杂的数据结构,比如知识图谱。
它不仅能够保存有关个体的详细信息,还能表示个体之间的多种关系,为数据分析、推理和检索提供了丰富的上下文信息。