【LlamaIndex 教程】一文看懂LlamaIndex用法,为LLMs学习私有知识

这篇具有很好参考价值的文章主要介绍了【LlamaIndex 教程】一文看懂LlamaIndex用法,为LLMs学习私有知识。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【城南 · LlamaIndex 教程】一文看懂LlamaIndex用法,为LLMs学习私有知识

我是卷了又没卷,薛定谔的卷的AI算法工程师「陈城南」(全网平台同名)~ 担任某大厂的算法工程师,带来最新的前沿AI知识,分享 AI 有趣工具和实用玩法,包括 ChatGPT、AI绘图等,欢迎大家交流~

  • 交流「cchengnan113」备注「AI交流」可进裙
  • 知乎「陈城南」:https://www.zhihu.com/people/cchengnan113
  • 公众号「陈城南」

本文是对LlamaIndex (截止版本0.5.17.post1之前,2023.05.01之前)的官方教程进行部分内容学习、翻译和总结,可能存在局限性,最新的LlamaIndex可能存在变化,具体以官网为准。

0 LlamaIndex 总述

LlamaIndex 是一个将大语言模型(Large Language Models, LLMs,后简称大模型)和外部数据连接在一起的工具。大模型依靠上下文学习(Context Learning)来推理知识,针对一个输入(或者是prompt),根据其输出结果。因此Prompt的质量很大程度上决定了输出结果的质量,因此提示工程(Prompt engineering)现在也很受欢迎。目前大模型的输入输出长度因模型结构、显卡算力等因素影响,都有一个长度限制(以Token为单位,ChatGPT限制长度为4k个,GPT-4是32k等,Claude最新版有个100k的)。当我们外部知识的内容超过这个长度时,就无法同时将有效的信息传递给大模型。因此就诞生了 LlamaIndex 等项目。

假设有一个10w的外部数据,我们的原始输入Prompt长度为100,长度限制为4k,通过查询-检索的方式,我们能将最有效的信息提取集中在这4k的长度中,与Prompt一起送给大模型,从而让大模型得到更多的信息。此外,还能通过多轮对话的方式不断提纯外部数据,达到在有限的输入长度限制下,传达更多的信息给大模型。这部分知识可参考:

  • 如何让 ChatGPT(LLMs) 学习更多的私有数据知识?(一)
  • 如何为 ChatGPT(LLMs) 学习更多的私有数据知识?(二)

LLamaIndex的任务是通过查询、检索的方式挖掘外部数据的信息,并将其传递给大模型,因此其主要由x部分组成:

  1. 数据连接。首先将数据能读取进来,这样才能挖掘。
  2. 索引构建。要查询外部数据,就必须先构建可以查询的索引,llamdaIndex将数据存储在Node中,并基于Node构建索引。索引类型包括向量索引、列表索引、树形索引等;
  3. 查询接口。有了索引,就必须提供查询索引的接口。通过这些接口用户可以与不同的 大模型进行对话,也能自定义需要的Prompt组合方式。查询接口会完成 检索+对话的功能,即先基于索引进行检索,再将检索结果和之前的输入Prompt进行(自定义)组合形成新的扩充Prompt,对话大模型并拿到结果进行解析。

1 数据连接器(Data Connectors)

数据连接器,读取文档的工具,最简单的就是读取本地文件。
LLamaIndex 的数据连接器包括

  • 本地文件、Notion、Google 文档、Slack、Discord

具体可参考Data Connectors。

2 索引结构(Index Structures)

LlamaIndex 的核心其实就是 索引结构的集合,用户可以使用索引结构或基于这些索引结构自行建图。

2.1 索引如何工作

两个概念:

  • Node(节点):即一段文本(Chunk of Text),LlamaIndex读取文档(documents)对象,并将其解析/划分(parse/chunk)成 Node 节点对象,构建起索引。
  • Response Synthesis(回复合成):LlamaIndex 进行检索节点并响应回复合成,不同的模式有不同的响应模式(比如向量查询、树形查询就不同),合成不同的扩充Prompt。

索引方式包括

  • List Index:Node顺序存储,可用关键字过滤Node
  • Vector Store Index:每个Node一个向量,查询的时候取top-k相似
  • Tree Index:树形Node,从树根向叶子查询,可单边查询,或者双边查询合并。
  • Keyword Table Index:每个Node有很多个Keywords链接,通过查Keyword能查询对应Node。

不同的索引方式决定了Query选择Node方式的不同。

回复合成方式包括:

  • 创建并提纯(Create and Refine),即线性依次迭代;
  • 树形总结(Tree Summarize):自底向上,两两合并,最终合并成一个回复。

3 查询接口(Query Inference)

3.1 LlamaIndex 使用模板

LlamaIndex 常用使用模版:

  1. 读取文档 (手动添加or通过Loader自动添加);
  2. 将文档解析为Nodes;
  3. 构建索引(从文档or从Nodes,如果从文档,则对应函数内部会完成第2步的Node解析)
  4. [可选,进阶] 在其他索引上构建索引,即多级索引结构
  5. 查询索引并对话大模型
3.1.1 读取文档

使用data loaders读取

from llama_index import SimpleDirectoryReader

# 从文件夹读取
documents = SimpleDirectoryReader(input_dir='./data').load_data()

# 从指定文件读取,输入为List
documents = SimpleDirectoryReader(input_files=['./data/file.txt']).load_data()

或者直接把自己的text改为document文档

from llama_index import Document

# 直接从文本转换
text_list = [text1, text2, ...]
documents = [Document(t) for t in text_list]

文档是轻量化的数据源容器,可以将文档:

  1. 解析为 Node 对象 (见3.1.2)
  2. 直接喂入 Index (见3.1.3),函数内部会完成转化Node过程
3.1.2 解析文档为Node

Node以数据 Chunks 的形式呈现文档,同时 Node 保留与其他 Node 和 索引结构 的关系。

直接解析文档

from llama_index.node_parser import SimpleNodeParser

parser = SimpleNodeParser()

nodes = parser.get_nodes_from_documents(documents)

或者跳过 3.1.1 节文档创建操作,直接手动构建 Node

from llama_index.data_structs.node_v2 import Node, DocumentRelationship

node1 = Node(text="<text_chunk>", doc_id="<node_id>")
node2 = Node(text="<text_chunk>", doc_id="<node_id>")
# set relationships
node1.relationships[DocumentRelationship.NEXT] = node2.get_doc_id()
node2.relationships[DocumentRelationship.PREVIOUS] = node1.get_doc_id()
3.1.3 Index 构建

可以直接将文档构建为 Index,这种简单构建的方式是在 Index 初始化时直接加载 文档

这种方式可以跳过 Node 构建(3.1.2)

from llama_index import GPTSimpleVectorIndex

index = GPTSimpleVectorIndex.from_documents(documents)

或者从 Node 构建 Index(3.1.2的续)

from llama_index import GPTSimpleVectorIndex

index = GPTSimpleVectorIndex(nodes)
多个索引(Index)结构复用 Node

当想在多个索引中,复用一个 Node 时,可以通过定义 DocumentStore 结构,并在添加Nodes时指定 DocumentStore

from gpt_index.docstore import SimpleDocumentStore

docstore = SimpleDocumentStore()
docstore.add_documents(nodes)

index1 = GPTSimpleVectorIndex(nodes, docstore=docstore)
index2 = GPTListIndex(nodes, docstore=docstore)

如果没指定 docstore,则会在创建 Index 时隐式创建一个。

索引中插入文档

也可以将文档插入到索引

from llama_index import GPTSimpleVectorIndex

index = GPTSimpleVectorIndex([])
for doc in documents:
    index.insert(doc)
自定义 LLMs

默认情况,llamaIndex 使用text-davinci-003,也可以用别的构建 Index

from llama_index import LLMPredictor, GPTSimpleVectorIndex, PromptHelper, ServiceContext
from langchain import OpenAI

...

# define LLM
llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-davinci-003"))

# define prompt helper
# set maximum input size
max_input_size = 4096
# set number of output tokens
num_output = 256
# set maximum chunk overlap
max_chunk_overlap = 20
prompt_helper = PromptHelper(max_input_size, num_output, max_chunk_overlap)

service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor, prompt_helper=prompt_helper)

index = GPTSimpleVectorIndex.from_documents(
    documents, service_context=service_context
)
自定义 Prompts

基于使用的Index,llamaIndex 会使用默认的 prompt 模板进行构建 Index(插入 or 创建), 也可以自定义link。

自定义 Embeddings

对于自定义 embedding 的模型,也可以自定义 embedding link。

消费 Predictor

创建 Index、Insert 和 Query 时也会消耗 tokens,link。

存储 Index 下次用
import os.path as osp
index_file = "data/indices/index.json"
if not osp.isfile(index_file):
    # 判断是否存在,不存在则创建
    index = GPTSimpleVectorIndex.from_documents(documents)
    index.save_to_disk(index_file, encoding='utf-8')
else:
    # 存在则 load
    index = GPTSimpleVectorIndex.load_from_disk(index_file)
3.1.4 [可选,进阶] 在索引上继续构建索引

可参考官方教程第4节;

3.1.5 查询索引

默认使用索引为 问答形式,可以不指定额外的参数:

response = index.query("What did the author do growing up?")
print(response)

response = index.query("Write an email to the user given their background information.")
print(response)

也可以额外使用参数,取决于使用的索引类型,见link。

设置模式(mode)

通过加参数可以指定模型,以 ListIndex 为例,可选default默认格式和embedding嵌入特征模式。

  • 如果是default,则是 创建并提纯(create and refine)的顺序迭代通过 Node;
  • 如果是embedding,则根据 top-k 相似的 nodes 进行回复合成。
index = GPTListIndex.from_documents(documents)
# mode="default"
response = index.query("What did the author do growing up?", mode="default")
# mode="embedding"
response = index.query("What did the author do growing up?", mode="embedding")

具体可参考link。

设置回复模式(response_mode)

注意:此选项在GPTreeIndex中不可用/使用。

索引还可以通过response_mode具有以下响应模式:

  • default:对于给定的索引,“创建和完善”通过顺序浏览每个节点的答案;每个节点进行单独的LLM调用。有益于更详细的答案。
  • compact:对于给定的索引,通过填充可以适合最大提示大小的许多节点文本块来“紧凑”在每个LLM调用过程中的提示。如果有太多的块在一个提示中塞满了东西,请通过多个提示来“创建和完善”答案。
  • Tree_summarize:给定一组节点和查询,递归构造树并将根节点作为响应返回。有益于摘要目的。
index = GPTListIndex.from_documents(documents)
# mode="default"
response = index.query("What did the author do growing up?", response_mode="default")
# mode="compact"
response = index.query("What did the author do growing up?", response_mode="compact")
# mode="tree_summarize"
response = index.query("What did the author do growing up?", response_mode="tree_summarize")
设置必需_keywords和dubl_keywords

可以在大多数索引上设置required_keywordsexclude_keywords(除了GPTTreeIndex)。
这能预先滤除不包含 required_keywords或 包含exclude_keywords 的节点,从而减少搜索空间,从而减少LLM调用/成本的时间/数量。

index.query(
    "What did the author do after Y Combinator?", required_keywords=["Combinator"], 
    exclude_keywords=["Italy"]
)
3.1.5 解析回复

query的回复解析,包含回复的text和回复的 sources 来源文章来源地址https://www.toymoban.com/news/detail-461215.html

response = index.query("<query_str>")

# get response
# response.response
str(response)

# get sources
response.source_nodes
# formatted sources
response.get_formatted_sources()

代码简述

# encoding:utf-8
import os
from llama_index import GPTSimpleVectorIndex, SimpleDirectoryReader
from llama_index import (
    GPTKeywordTableIndex,
    SimpleDirectoryReader,
    LLMPredictor,
    ServiceContext
)
from langchain import OpenAI


documents = SimpleDirectoryReader('data').load_data()

os.environ['OPENAI_API_KEY'] = '设置自己的Key'

"""
直接这样可以运行
"""
# GPT Index
index = GPTSimpleVectorIndex.from_documents(documents)
response = index.query("What did the author do growing up?")
print(response)
"""
Response(response='\n\nGrowing up, the author wrote short stories, programmed on an IBM 1401, wrote simple games and a word processor on a TRS-80, studied philosophy in college, learned Lisp, reverse-engineered SHRDLU, wrote a book about Lisp hacking, took art classes at Harvard, and painted still lives in his bedroom at night. He also attended an Accademia where he painted still lives on leftover scraps of ...
tover scraps of canvas, which was all I could afford at the time. Painting still lives is different', doc_id='5ba2ade0-0b8c-4ef7-906d-1ca434606232', embedding=None, doc_hash='6a5d8e0ae90c969305717b2ba8d4bc6296336ef595104d8d474abfff99ed64e3', extra_info=None, node_info={'start': 0, 'end': 15198}, relationships={<DocumentRelationship.SOURCE: '1'>: '5c89fa41-6bf8-4181-a9fa-57b66c3aecc1', <DocumentRelationship.NEXT: '3'>: 'a6444b3f-5fc5-4593-8b3d-f04ffb39a6a6'}), score=0.8242781513247005)], extra_info={'5ba2ade0-0b8c-4ef7-906d-1ca434606232': None})
"""


"""
自定义模型
"""
# # define LLM
llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-davinci-002"))
service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor)
#
# build index
index = GPTKeywordTableIndex.from_documents(documents, service_context=service_context)

response = index.query("What did the author do growing up?")
print(response)

到了这里,关于【LlamaIndex 教程】一文看懂LlamaIndex用法,为LLMs学习私有知识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文吃透JavaScript中的DOM知识及用法

       DOM : D ocument O bject M odel(文档对象模型),定义了用户操作文档对象的接口,可以说DOM是自HTML将网上相关文档连接起来后最伟大的创新。它使得用户对HTML有了空前的访问能力,并使开发者将HTML作为XML文档来处理。 本文知识导图如下:    DOM是网页的核心结构,无论是

    2023年04月08日
    浏览(51)
  • LLM本地知识库问答系统(二):如何正确使用LlamaIndex索引

    LLM本地知识库问答系统(一):使用LangChain和LlamaIndex从零构建PDF聊天机器人指南        上一篇文章我们介绍了使用LlamaIndex构建PDF聊天机器人,本文将介绍一下LlamaIndex的基本概念和原理。        LlamaIndex(也称为GPT Index)是一个用户友好的界面,可将外部数据连接到大型语

    2024年02月10日
    浏览(44)
  • GPT学习笔记-Enterprise Knowledge Retrieval(企业知识检索)--私有知识库的集成

    openai-cookbook/apps/enterprise-knowledge-retrieval at main · openai/openai-cookbook · GitHub 终于看到对于我解决现有问题的例子代码,对于企业私有知识库的集成。 我对\\\"Retrieval\\\"重新理解了一下,源自动词\\\"retrieve\\\",其基本含义是“取回”,“恢复”,或“检索”。在不同的上下文中,\\\"retriev

    2024年02月11日
    浏览(40)
  • 一文看懂数据仓库

    数据仓库(Data Warehouse)是来自一个或多个不同源的集成数据的中央存储库,通过对数据仓库中的数据分析,可以帮助企业,改进业务流程,控制成本,提高产品质量等。数据仓库的两个主要功能:存储分析数据和处理分析数据。 (1)面向主题性 数据库的特点是面向应用进行数

    2024年02月07日
    浏览(42)
  • 一文看懂-纹理/贴图/材质

    纹理(Texture) 应用于网格表面上的标准位图图像,即3D 对象的 2D 贴图。 贴图(Map) 指的是绘制在对象模型表面上的那些图像数据,其所使用的图像文件称为纹理。贴图还包含纹理图在对象表面的坐标(UV坐标)等其他数据信息。 可以说, 纹理是贴图的子集 。 另外。Map也

    2024年02月08日
    浏览(50)
  • 一文看懂SGPIO协议

    目录 1.简介 2.接口列表 3.时序 3.1 Sclok 3.2 Sload 3.3 Sdataout 3.4 Sdatain 4.应用 串行通用输入输出(SGPIO)是一种串行通用IO信号的方法。通常用于发起方(如主机总线适配器)和目标方(如背板)之间的通信。目标方通常将输出的串行信号转换为多个并行信号,并通过GPIO提供输入信

    2024年01月24日
    浏览(62)
  • 一文看懂EtherCAT总线控制

      大家好,我是华山自控编程的朱老师。今天给大家介绍一种前沿的运动控制技术——EtherCAT 总线控制。作为近年来非常受欢迎的一种运动控制方式, 那么 EtherCAT总线控制究竟有哪些优势呢?我主要列举以下三点:   传输速度特别快。在以太网控制协议中,EtherCAT总线控制协

    2024年02月08日
    浏览(70)
  • 【SBUS】一文看懂SBUS协议

    【STM32】STM32单片机总目录 S.BUS是一个串行通信协议,S.BUS是FUTABA提出的舵机控制总线, S.bus使用RS232C串口的硬件协议作为自己的硬件运行基础。 使用TTL电平,即3.3V。 使用负逻辑,即低电平为“1”,高电平为“0”。 波特率:100000(100k),注意:不兼容波特率115200。 硬件取

    2024年02月14日
    浏览(35)
  • 一文看懂 AIGC 的版权问题

    伴随着 AIGC 技术的强势出圈,大家在惊叹 AI 技术强大的同时,也有越来越多的人开始讨论关于由此带来的版权问题:我们通过 AI 生成的图像属于平台还是个人?目前 AI 作品版权在法律上是如何界定的?又该如何避免引起 AI 版权的纠纷? 今天我想和大家聊聊关于当前 AIGC 作

    2024年02月02日
    浏览(40)
  • 一文看懂分布式存储架构

    目录 一、集中存储结构 二、分布式存储 1 、分布式存储的兴起 2 、分布式存储的重要性 3 、分布式存储的种类和比较 三、分布式理论浅析 1 、一致性和可用性 2 、数据分布 3 、复制 4 、分布式协议 5、跨机房部署 四、分布式文件系统 1、 Google 文件系统( GFS ) 2、 Taobao 文件

    2023年04月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包