開源 AI 食譜文件
使用 LlamaIndex 構建 RAG 電子書“圖書管理員”
並獲得增強的文件體驗
開始使用
使用 LlamaIndex 構建 RAG 電子書“圖書管理員”
作者:Jonathan Jin
引言
本 Notebook 演示瞭如何為您的本地電子書庫快速構建一個基於 RAG 的“圖書管理員”。
回想一下您上次去圖書館時,是如何利用知識淵博的工作人員的專業知識,在圖書館大量的教科書、小說和其他資源中幫助您找到所需內容的。我們的 RAG “圖書管理員”將為我們做同樣的事情,只不過是針對我們自己的本地電子書收藏。
要求
我們希望我們的圖書管理員是輕量級的,並儘可能在本地執行,且依賴項最少。這意味著我們將最大程度地利用開源,並傾向於那些可以在普通硬體上本地執行的模型,例如 M1 Macbooks。
元件
我們的解決方案將包含以下元件
- LlamaIndex,一個用於基於 LLM 的應用程式的資料框架,與 LangChain 不同,它專為 RAG 設計;
- Ollama,一個使用者友好的解決方案,用於在本地執行 Llama 2 等 LLM;
BAAI/bge-base-en-v1.5
嵌入模型,其效能相當不錯,且體積也相當輕量;- Llama 2,我們將透過 Ollama 執行。
依賴項
首先讓我們安裝依賴項。
%pip install -q \ llama-index \ EbookLib \ html2text \ llama-index-embeddings-huggingface \ llama-index-llms-ollama
Ollama 安裝
這些依賴項有助於正確檢測 GPU。
!apt install pciutils lshw
安裝 Ollama。
!curl -fsSL https://ollama.com/install.sh | sh
在後臺執行 Ollama 服務。
get_ipython().system_raw("ollama serve &")
從 Ollama 庫中拉取 Llama2。
!ollama pull llama2
測試書庫設定
接下來,讓我們建立我們的測試“書庫”。
為簡單起見,假設我們的“書庫”只是一個包含 .epub
檔案的巢狀目錄。我們可以很容易地看到這個解決方案可以推廣到,比如,一個帶有 metadata.db
資料庫檔案的 Calibre 書庫。我們將把這個擴充套件留給讀者作為練習。😇
讓我們從 古登堡計劃 中拉取兩個 .epub
檔案作為我們的書庫。
!mkdir -p "./test/library/jane-austen"
!mkdir -p "./test/library/victor-hugo"
!wget https://www.gutenberg.org/ebooks/1342.epub.noimages -O "./test/library/jane-austen/pride-and-prejudice.epub"
!wget https://www.gutenberg.org/ebooks/135.epub.noimages -O "./test/library/victor-hugo/les-miserables.epub"
使用 LlamaIndex 進行 RAG
使用 LlamaIndex 進行 RAG,其核心包括以下幾個主要階段
- 載入,在此階段您告訴 LlamaIndex 您的資料在哪裡以及如何載入;
- 索引,在此階段您增強已載入的資料以便於查詢,例如使用向量嵌入;
- 查詢,在此階段您配置一個 LLM 作為您索引資料的查詢介面。
這個解釋只是 LlamaIndex 功能的冰山一角。要了解更深入的細節,我強烈推薦閱讀 LlamaIndex 文件的“高階概念”頁面。
載入
很自然地,讓我們從載入階段開始。
我之前提到過,LlamaIndex 是專為 RAG 設計的。這一點從它的 SimpleDirectoryReader
結構中立刻顯現出來,它 ✨ 神奇地 ✨ 免費支援了一大堆多模態檔案型別。對我們來說很方便的是,.epub
也在支援的集合中。
from llama_index.core import SimpleDirectoryReader
loader = SimpleDirectoryReader(
input_dir="./test/",
recursive=True,
required_exts=[".epub"],
)
documents = loader.load_data()
SimpleDirectoryReader.load_data()
將我們的電子書轉換為一組 Document
物件,供 LlamaIndex 使用。
這裡需要注意的一個重要事項是,文件在此階段尚未被分塊——這將在索引過程中發生。請繼續閱讀…
索引
載入資料之後是索引資料。這將允許我們的 RAG 流水線查詢與我們查詢相關的上下文,傳遞給我們的 LLM 以增強其生成的響應。文件分塊也在這裡進行。
VectorStoreIndex
是 LlamaIndex 中索引的“預設”入口。預設情況下,VectorStoreIndex
使用一個簡單的記憶體字典來儲存索引,但 LlamaIndex 也支援多種向量儲存解決方案,供您在擴充套件時升級使用。
如前所述,我們將使用 BAAI/bge-small-en-v1.5
來生成我們的嵌入。預設情況下,LlamaIndex 使用 OpenAI(特別是 gpt-3.5-turbo
),考慮到我們希望有一個輕量級、可在本地執行的端到端解決方案,我們希望避免使用它。
幸運的是,LlamaIndex 透過方便的 HuggingFaceEmbedding
類支援從 Hugging Face 檢索嵌入模型,所以我們在這裡使用它。
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embedding_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
我們將其作為嵌入模型傳遞給 VectorStoreIndex
,以規避 OpenAI 的預設行為。
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(
documents,
embed_model=embedding_model,
)
查詢
現在是 RAG 謎題的最後一塊——連線查詢層。
在本教程中,我們將使用 Llama 2,但我鼓勵讀者嘗試不同的模型,看看哪個能產生“最好”的響應。
首先讓我們啟動 Ollama 伺服器。不幸的是,Ollama Python 客戶端 中沒有實際啟動和停止伺服器本身的支援,所以我們必須暫時離開 Python 環境來完成這個操作。
在另一個終端中,執行:ollama serve
。記得在我們完成後終止它!
現在讓我們將 Llama 2 連線到 LlamaIndex,並將其用作我們查詢引擎的基礎。
from llama_index.llms.ollama import Ollama
llama = Ollama(
model="llama2",
request_timeout=40.0,
)
query_engine = index.as_query_engine(llm=llama)
最終結果
至此,我們基本的 RAG 圖書管理員已經建立起來,我們可以開始就我們的書庫提問了。例如:
>>> print(
... query_engine.query(
... "What are the titles of all the books available? Show me the context used to derive your answer."
... )
... )
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.
>>> print(query_engine.query("Who is the main character of 'Pride and Prejudice'?"))
The main character of 'Pride and Prejudice' is Elizabeth Bennet.
結論與未來改進
我們已經演示瞭如何構建一個完全在本地執行的基於 RAG 的基本“圖書管理員”,甚至可以在 Apple 晶片的 Mac 上執行。在此過程中,我們還對 LlamaIndex 進行了“全面巡禮”,瞭解了它如何簡化基於 RAG 的應用程式的設定過程。
儘管如此,我們實際上只觸及了可能性的皮毛。以下是一些關於如何完善和在此基礎上進行構建的想法。
強制引用
為了防範我們的圖書管理員產生幻覺的風險,我們如何要求它為所說的每件事提供引用呢?
使用擴充套件元資料
像 Calibre 這樣的電子書庫管理解決方案會為書庫中的電子書建立額外的元資料。這可以提供諸如出版商或版本等資訊,而這些資訊可能在書本的正文中不易獲得。我們如何擴充套件我們的 RAG 流水線以考慮除 .epub
檔案之外的其他資訊來源?
高效索引
如果我們將這裡構建的所有內容整合到一個指令碼/可執行檔案中,那麼每次呼叫時,生成的指令碼都會重新索引我們的書庫。對於我們只有兩個檔案的微型測試書庫來說,這“沒問題”,但對於任何非小型書庫來說,這很快就會讓使用者感到煩惱。我們如何才能持久化嵌入索引,並僅在書庫內容發生有意義的變化時(例如添加了新書)才更新它們?
< > 在 GitHub 上更新