Notebooks
H
Hugging Face
Rag Llamaindex Librarian

Rag Llamaindex Librarian

zh-CNhf-cookbooknotebooks

用 LlamaIndex 构建一个 RAG 电子书库智能助手

作者: Jonathan Jin

简介

这份教程将指导你如何快速为你的电子书库创建一个基于 RAG 图书助手。 就像图书馆的图书管理员帮你找书一样,这个助手也能帮你从你的电子书里找到你需要的书。

要求

这个助手要做得轻巧尽量在本地运行,而且不要用太多其他的东西。我们会尽量用免费的开源软件,选择那种在本地普通电脑上,比如 M1 型号的 MacBook 上就能运行的模型

组件

我们的解决方案将包括以下组件:

依赖

首先安装依赖库

[ ]
[ ]

设置测试书库

我们接下来要弄个测试用的“书库”。

简单点说,我们的“书库”就是一个放有 .epub 格式电子书文件的文件夹。这个方法很容易就能扩展到像 Calibre 那种带有个 metadata.db 数据库文件的书库。怎么扩展这个问题,我们留给读者自己思考。😇

现在,我们先从古腾堡计划网站下载两本.epub格式的电子书放到我们的书库里。

[ ]

用 LlamaIndex 构建 RAG

使用 LlamaIndex 的 RAG 主要包括以下三个阶段:

  1. 加载,在这个阶段你告诉 LlamaIndex 你的数据在哪里以及如何加载它;
  2. 索引,在这个阶段你扩充加载的数据以方便查询,例如使用向量嵌入;
  3. 查询,在这个阶段你配置一个 LLM 作为你索引数据的查询接口。

以上解释仅是对 LlamaIndex 可实现功能的表面说明。要想了解更多深入细节,我强烈推荐阅读 LlamaIndex 文档中的"高级概念"页面

加载

好的,我们首先从加载阶段开始。

之前提到,LlamaIndex 是专为 RAG 这种混合检索生成模型设计的。这一点从它的SimpleDirectoryReader功能就可以明显看出,它能神奇地免费支持很多种文件类型。幸运的是, .epub 文件格式也在支持范围内。

[ ]

SimpleDirectoryReader.load_data() 将我们的电子书转换成一组 LlamaIndex 可以处理的 Documents

这里有一个重要的事情要注意,就是这个阶段的文档还没有被分块——这将在索引阶段进行。继续往下看...

索引

在把数据加载进来之后,接下来我们要做的是建立索引。这样我们的 RAG 系统就能找到与用户查询相关的信息,然后把这些信息传给语言模型(LLM),以便它能够增强回答的内容。同时,这一步也将对文档进行分块。

在 LlamaIndex 中,VectorStoreIndex 是用来建立索引的一个“默认”工具。这个工具默认使用一个简单、基于内存的字典来保存索引,但随着你的使用规模扩大,LlamaIndex 还支持 多种向量存储解决方案

LlamaIndex 默认的块大小是 1024 个字符,块与块之间有 20 个字符的重叠。如果需要了解更多细节,可以查看 [LlamaIndex 的文档](https://docs.llamaindex.ai/en/stable/optimizing/basic_strategies/basic_strategies.html#chunk-sizes)。

如前所述,我们选择使用 BAAI/bge-small-en-v1.5 生成嵌入,以避免使用默认的 OpenAI(特别是 gpt-3.5-turbo)模型,因为我们需要一个轻量级、可在本地运行的完整解决方案。

幸运的是,LlamaIndex 可以通过 HuggingFaceEmbedding 类方便地从 Hugging Face 获取嵌入模型,因此我们将使用它。

[2]

我们将把这个模型传递给 VectorStoreIndex,作为我们的嵌入模型,以绕过 OpenAI 的默认行为。

[3]

查询

现在我们要完成 RAG 智能助手的最后一部分——设置查询接口。

在这个教程中,我们将使用 Llama 2 作为语言模型,但我建议你试试不同的模型,看看哪个能给出最好的回答。

首先,我们需要在一个新的终端窗口中启动 Ollama 服务器。不过,Ollama 的 Python 客户端不支持直接启动和关闭服务器,所以我们需要在 Python 环境之外操作。

打开一个新的终端窗口,输入命令:ollama serve。等我们这里操作完成后,别忘了关闭服务器!

现在,让我们将 Llama 2 连接到 LlamaIndex,并使用它作为我们查询引擎的基础。

[4]

最终结果

有了这些,我们的基本的 RAG 电子书库智能助手就设置好了,我们可以开始询问有关我们电子书库的问题了。例如:

[29]
Based on the context provided, there are two books available:

1. "Pride and Prejudice" by Jane Austen
2. "Les Misérables" by Victor Hugo

The context used to derive this answer includes:

* The file path for each book, which provides information about the location of the book files on the computer.
* The titles of the books, which are mentioned in the context as being available for reading.
* A list of words associated with each book, such as "epub" and "notebooks", which provide additional information about the format and storage location of each book.
[31]
The main character of 'Pride and Prejudice' is Elizabeth Bennet.

总结和未来可能的提升

我们成功地展示了如何创建一个完全在本地运行的基本 RAG 的电子书库智能助手,甚至在苹果的 Apple silicon Macs 上也能运行。在这个过程中,我们还全面了解了 LlamaIndex 是如何帮助我们简化建立基于 RAG 的应用程序的。

尽管如此,我们其实只是接触到了一些皮毛。下面是一些关于如何改进和在这个基础上进一步发展的想法。

强制引用

为了避免图书馆员的虚构响应,我们怎样才能要求它为其回答提供引用?

使用扩充的元数据

Calibre 这样的电子书库管理工具会为电子书创建更多的元数据。这些元数据可以提供一些在书中文本里找不到的信息,比如出版商或版本。我们怎样才能扩展我们的 RAG 流程,使其也能利用那些不是 .epub 文件的额外信息源呢?

高效索引

如果我们把这里做的所有东西写成一个脚本或可执行程序,那么每次运行这个脚本时,它都会重新索引我们的图书馆。对于只有两个文件的微型测试库来说,这样还行,但对于稍大一点的图书馆来说,每次都重新索引会让用户感到非常烦恼。我们怎样才能让索引持久化,并且只在图书馆内容有重要变化时,比如添加了新书,才去更新索引呢?