llamaindex结构图

1 功能

大模型学习的主要是通用数据,而用户可能需要让 ChatGPT 在本地的知识库中寻找答案。

普通用户不太可能训练大模型;由于本地数据格式丰富,内容烦多,且考虑到使用成本和 token 大小限制,也不可能在每次提问时都将所有数据传给 ChatGPT。

llamaindex 提供了解决此问题的方法:通过 ChatGPT 把本地文本转成 Embedding,然后在本地建立数据索引;询问时先在本地查询,再用 ChatGPT 将查询结果合成答案,llamaindex 是用户数据和大模型之间的接口。

2 原理

2.1 模块

llama_index 由三个主要模块组成:

  • 数据模块:用于读取本地或网络数据,并将大块文本切分成 Node 块。
  • 索引和存储模块:将文本块通过 ChatGPT 转换成 Embedding 嵌入表示存储在本地,构建本地知识库。
  • 搜索模块:根据使用者提出的问题,在本地知识库中定位可能的答案,然后将问题和答案传给 ChatGPT 整合出最终答案。

2.2 组织数据

当用户提出问题时,需要与本地知识库进行匹配,如果数据库中内容很多,会花费大量匹配时间。为节约时间,可以对文章中的章、节、文本文件整体内容、目录内容等生成总结,逐层构造树结构,图结构,或者关键字映射表,以节约搜索时间。

llamaindex 提供了各种结构支持,需要开发者自行调用。

2.3 核心概念

  • Node & Index

    Node 指切分后的文本块;Index 索引可以理解为 Node 数据块通过 ChatGPT 转换后在本地的存储方式。索引结构支持 List, Tree, Keyword 方式;除了创建 index 以外,还提供对其中的子块进行增删的编辑操作,以节约 token。另外,除了对纯文本进行索引,还提供图索引,表索引,SQL 中数据索引。

  • Embedding & Vector

    这里的 Embedding 和 Vector 指的都是通过 ChatGPT 转换后的数据;当前版本嵌入的维度是 1536(问题的和 Node 一样长);假设将每个块设成最大 600(Node: chunk size),如果是 18K 大小的文本文件,存储了 utf-8 的中文文字,每字占 3 字节,6000 多字,约使用 10 来个 Node 存储;每个 Node 被转换成 1538 个 float 值,存储在本地,即 Vector store。

  • Query & Response Synthesis

    Query 询问指的是用户提出的问题;Response Synthesis 指的是从索引中定位出可选答案后,组织答案的方法。

3 文档

3.1 文档内容

代码中的 docs 目录数据用于生成网页版的说明文档,也可通过以下网址直接查看文档:

https://gpt-index.readthedocs.io/en/latest/

通过操作界面左上图标可调出帮助目录,操作左下角切换不同版本文档。

3.2 学习路径

文档内容很多,包含文本和源码示例,推荐使用以下顺序阅读文档:

  • gallery: 看别人用该库实现的功能
  • getting_started: 最简单的安装方法和示例
  • guides: 一般用户使用方法
  • use_case: 使用案例(做了什么,怎么做,相对简单)
  • how_to (KEY COMPONENTS): 原理和用法的主索引,从上到下由浅入深(前三项最重要)
  • reference: 细节的详细信息, 大部分是源码自动生成的文档(具体使用时查看)

4 代码分析

  • benchmarks: 用于评测
  • build/dist/scripts: 打包过程中产生的目录文件
  • tests: 测试用例
  • llama_index: 核心源码 (200 多个源码文件)
    • readers: 从各种数据源读入数据的解析工具, 其 file 支持多种模式
    • index, storage, query 等,建议以文档为入口开始学习
  • examples: 分门别类的示例
  • experimental: 一些不重要的实验
  • README.md:示例了最简单的使用方法

4.1 安装

4.1.1 pip 安装

llamaindex 是个 python 库,用 pip 安装即可(需要 Python 3.8 及以上版本)。

1
pip install llama-index

4.1.2 源码安装

由于版本更替太快,建议使用源码安装。

源码地址:https://github.com/jerryjliu/llama_index

5 注意事项

  • 使用 ChatGPT 需要设置代理和 APIKEY
  • 需要指定数据在本地存放的目录
  • 如果需要可以做多个索引
  • 注意安装的版本和源码一致,否则 example 将无法运行
  • 推荐使用最新版本,目前最新版本 0.6.x 的数据模式以及 log 信息都优于之前版本

6 其它

6.1 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from llama_index import SimpleDirectoryReader, PromptHelper, LLMPredictor, ServiceContext
from langchain import OpenAI
import gradio as gr
import os
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, LLMPredictor, ServiceContext
from llama_index import StorageContext, load_index_from_storage

# 环境变量
os.environ['HTTP_PROXY'] = 'http://localhost:7890'
os.environ['HTTPS_PROXY'] = 'http://localhost:7890'
os.environ["OPENAI_API_KEY"] = "xxx"

# 显示更多DEBUG信息
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

## 工具
def construct_index(directory_path):
max_input_size = 4096
num_outputs = 2000
chunk_overlap_ratio = 0.1
chunk_size_limit = 600
prompt_helper = PromptHelper(context_window = max_input_size,
num_output = num_outputs,
chunk_overlap_ratio=chunk_overlap_ratio,
chunk_size_limit=chunk_size_limit)
llm_predictor = LLMPredictor(llm=OpenAI(temperature=0.7, model_name="gpt-3.5-turbo",
max_tokens=num_outputs))
documents = SimpleDirectoryReader(directory_path).load_data()
service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor,
prompt_helper=prompt_helper)
index = GPTVectorStoreIndex.from_documents(documents,service_context=service_context,
prompt_helper=prompt_helper)
index.storage_context.persist() # 保存
return index

## 生成索引
index = construct_index("docs")
## 提问
chatbot("MODS,中文回答")

启动网页界面,默认启动 7860 端口:

1
2
3
4
5
6
7
import gradio as gr

iface = gr.Interface(fn=chatbot,
inputs=gr.inputs.Textbox(lines=7, label="输入您的文本"),
outputs="text",
title="AI 知识库聊天机器人")
iface.launch(share=True)

6.2 我的环境

  • 位置在:/exports/git/llama_index/mine/test.ipynb
  • 运行镜像:docker run --rm -v /exports:/opt/xieyan --name gpt-academic -d --net host -p 8866:8866 -p 7860:7860 -p 8823:22 gpt-academic:xy_04 bash

6.3 源码中的主要代码

  • 对于本地 Embedding 的检索一般在
    • llama_index/indices/query/embedding_utils.py
      • get_top_k_embeddings()
    • llama_index/vector_stores/simple.py
      • SimpleVectorStore:query()
    • 根据根据以上函数内部 Node 遍历时间即可估算其效率
  • 核心示例
    • 最上层 README

6.4 一些想法

  • 是不是按段转更合适
  • 对不同类型文章有不同组织方式,比如知识型,情节推动型...