根據索引的 RAG 架構的核心優勢在於其高效的檢索能力和可追溯性。不同於向量相似性搜尋需要逐一比較所有記錄的嵌入向量,根據索引的搜尋能直接透過索引存取相關資料,顯著提升檢索速度,尤其在面對大規模資料集時效果更為明顯。這種直接存取的特性也提升了系統的透明度,方便開發者追蹤回應來源,檢驗資料準確性,進而最佳化資料輸入、調整系統組態或替換元件以提升效能。此外,根據索引的 RAG 有助於確保資料完整性和版權控制,精確定位資料來源,有效解決潛在的版權和資料完整性問題。透過 LlamaIndex、Deep Lake 和 OpenAI 等工具的整合,開發者可以快速構建根據索引的 RAG 系統,無需從零開始開發所有功能,從而降低開發成本,加速專案進度。
為什麼使用根據索引的RAG?
根據索引的搜尋將高階的RAG驅動生成式AI提升到另一個層次。它提高了面對大量資料時的檢索速度,從原始的資料區塊轉變為有組織的、可追溯的索引節點。讓我們透過分析根據索引的RAG架構來瞭解根據向量的相似性搜尋和根據索引的搜尋之間的差異。
架構
根據索引的搜尋比根據向量的搜尋更快,因為它直接透過索引存取相關資料,而根據向量的搜尋則是順序比較所有記錄的嵌入向量。在第2章中,我們實作了一個根據向量的相似性搜尋程式,如圖3.1所示:
- 資料收集和準備(Pipeline #1):收集和準備資料。
- 嵌入向量和向量儲存(Pipeline #2):將資料進行嵌入向量處理,並將準備好的資料儲存在向量儲存中。
- 檢索查詢和生成式AI(Pipeline #3):處理使用者輸入,執行根據向量相似性搜尋的檢索,增強輸入,生成回應,並應用效能指標。
這種方法非常靈活,因為它提供了多種實作每個元件的方法,取決於專案的需求。
內容解密:
本段落描述了根據索引的RAG架構的優點和基本流程。它強調了根據索引的搜尋相較於根據向量的搜尋在速度上的優勢,並介紹了實作RAG的三個主要流程。
建構根據索引的RAG的優勢
透過使用LlamaIndex、Deep Lake和OpenAI,我們可以無縫地整合這些工具,而無需從頭開始建立所有必要的函式。這為我們提供了一個堅實的基礎來開始構建。我們將介紹主要的索引型別,如向量索引、樹索引、列表索引和關鍵字索引。然後,我們將構建一個領域特定的無人機技術LLM RAG代理,使用者可以與之互動。
無人機技術LLM RAG代理的建構
我們的目標是準備一個無人機技術的LLM資料集,並在下一章中透過多模態資料進行增強。我們還將透過程式碼來說明主要的索引型別。
本章涵蓋的主題
- 使用LlamaIndex框架和索引方法構建語義搜尋引擎
- 填充Deep Lake向量儲存
- LlamaIndex、Deep Lake和OpenAI的整合
- 評分排名和餘弦相似度指標
- 用於追溯性的元資料增強
- 查詢設定和生成組態
- 自動化檔案排名介紹
- 向量、樹、列表和關鍵字索引型別
內容解密:
本章節將探討如何使用LlamaIndex、Deep Lake和OpenAI構建根據索引的RAG系統,並介紹主要的索引型別和相關應用。
索引在RAG中的作用
索引不僅提高了檢索的速度和精確度,還為RAG模型生成的回應提供了透明度。透過索引,我們可以追溯回應的來源,檢查資料的精確位置和詳細內容。這種能力使得我們能夠改進資料輸入,調整系統組態,或更換元件(如向量儲存軟體和生成模型)以獲得更好的結果。
為什麼根據索引的RAG如此重要?
- 提高檢索速度:根據索引的搜尋直接存取相關資料,大大提高了檢索速度。
- 增強透明度和可追溯性:索引使得RAG模型的輸出結果可以被追溯到原始資料,增強了透明度。
- 改善資料完整性和版權控制:透過索引,我們可以精確地定位資料來源,有助於解決版權和資料完整性的問題。
內容解密:
本段落闡述了索引在RAG系統中的重要性,包括提高檢索速度、增強透明度和改善資料完整性等方面。
在下一章中,我們將進一步探討如何透過多模態資料增強無人機技術LLM資料集,並深入研究RAG驅動的生成式AI的應用。
graph LR A[資料收集和準備] --> B[嵌入向量和向量儲存] B --> C[檢索查詢和生成式AI] C --> D[輸出結果] D --> E[評估和改進]
圖表翻譯: 此圖示展示了RAG系統的基本流程,包括資料收集和準備、嵌入向量和向量儲存、檢索查詢和生成式AI、輸出結果以及評估和改進等步驟。透過這個流程,我們可以構建一個高效的RAG系統,並實作生成式AI的應用。
構建根據RAG的生成式AI管道
在現代人工智慧的發展中,實作根據索引的搜尋將引領我們走向更快、更精確且可追蹤的AI未來。我們將沿用第二章的架構,使用三個管道來確保團隊成員能夠在專業分工的環境下順暢工作。由於我們沿用了第二章的管道,因此將在這些管道中加入來自該章節的功能,如圖3.1所示:
管道元件 #1 與 D2-索引:資料收集與預處理
我們將逐一準備資料來源並將其儲存為單獨的檔案,然後將檔案名稱和位置新增到我們載入向量儲存的後設資料中。這些後設資料將幫助我們將回應追蹤到檢索功能所處理的確切檔案。我們將實作從回應到其所依據資料的直接連結。
管道元件 #2 與 D3-索引:使用 Deep Lake 向量儲存
我們將使用創新的 llama-index-vector-stores-deeplake 套件將資料載入向量儲存中,該套件包含我們在最佳化起始場景中所需的一切:分塊、嵌入、儲存,甚至是LLM整合。這樣,一旦我們有了一個穩固的程式,我們就可以根據需要自訂和擴充套件管道。
管道元件 #3 與 D4-索引:資料集載入與索引
我們將使用 llama-index-vector-stores-deeplake 套件將資料載入資料集中,該套件包含我們開始進行根據索引的檢索和生成所需的一切,包括自動排名和評分。我們將利用 LlamaIndex 與 Deep Lake 來簡化資訊檢索和處理。整合的檢索器將從 Deep Lake 儲存函式庫中高效檢索相關資料,而LLM代理將智慧地合成和互動檢索到的資訊,以生成有意義的洞察或行動。
內容解密:
- 管道元件 #1 專注於資料收集和預處理,確保每個檔案都被單獨儲存並記錄其後設資料,以便於後續的追蹤和檢索。
- 管道元件 #2 使用 Deep Lake 向量儲存技術,將資料轉換為可被高效檢索的形式。這一步驟利用了 llama-index-vector-stores-deeplake 套件的強大功能,實作了資料的分塊、嵌入和儲存。
- 管道元件 #3 進一步將資料載入資料集中,並利用索引技術實作高效的資料檢索和生成。同時,透過引入時間和評分指標來評估輸出的品質。
向量基礎與索引基礎的搜尋與檢索方法比較
特徵 | 向量基礎相似性搜尋與檢索 | 索引基礎向量、樹、列表和關鍵字搜尋與檢索 |
---|---|---|
彈性 | 高 | 中等(預先計算結構) |
速度 | 大型資料集較慢 | 快速且針對快速檢索進行最佳化 |
可擴充套件性 | 受限於即時處理 | 具備處理大型資料集的高可擴充套件性 |
複雜度 | 設定較簡單 | 更複雜,需要索引步驟 |
更新頻率 | 易於更新 | 需要重新索引以進行更新 |
建構無人機技術的語義搜尋引擎和生成式AI代理
在本文中,我們將使用 Deep Lake 向量儲存、LlamaIndex 和 OpenAI 來構建語義索引基礎的搜尋引擎和生成式AI代理引擎。該程式的目標是提供一個根據索引的RAG代理,用於無人機技術的問答。程式將展示無人機如何使用電腦視覺技術來識別車輛和其他物體。
環境安裝
首先,我們需要安裝必要的套件,包括 llama-index-vector-stores-deeplake、deeplake 和 llama-index:
!pip install llama-index-vector-stores-deeplake==0.1.6
!pip install deeplake==3.9.8
!pip install llama-index==0.10.64
接著,我們驗證這些套件是否能夠正確匯入:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.vector_stores.deeplake import DeepLakeVectorStore
內容解密:
- 環境安裝 是構建整個系統的第一步,確保所有必要的套件都正確安裝和組態。
- llama-index-vector-stores-deeplake 套件提供了將資料載入 Deep Lake 向量儲存的功能,簡化了資料的處理和檢索流程。
- 驗證套件匯入 保證了後續程式碼的順利執行,避免了因套件問題導致的錯誤。
無人機技術檔案的收集與準備
在這個章節中,我們將收集並準備與無人機相關的檔案,並附上必要的後設資料,以便能夠將檔案追溯到其原始來源。我們的目標是能夠將回應的內容追溯到檢索到的確切資料片段,以找出其來源。
首先,我們需要建立一個資料目錄來存放這些檔案:
!mkdir data
接下來,我們將使用一個異構的語料函式庫來處理無人機技術資料,並使用 BeautifulSoup
對其進行處理。
import requests
from bs4 import BeautifulSoup
import re
import os
urls = [
"https://github.com/VisDrone/VisDrone-Dataset",
"https://paperswithcode.com/dataset/visdrone",
"https://openaccess.thecvf.com/content_ECCVW_2018/papers/111",
"https://github.com/VisDrone/VisDrone2018-MOT-toolkit",
"https://en.wikipedia.org/wiki/Object_detection",
"https://en.wikipedia.org/wiki/Computer_vision",
# ...
]
def clean_text(content):
# 移除參考文獻和不想要的字元
content = re.sub(r'\[\d+\]', '', content)
content = re.sub(r'[^\w\s\.]', '', content)
return content
def fetch_and_clean(url):
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
content = soup.find('div', {'class': 'mw-parser-output'})
if content is None:
return None
# 移除特定的段落,包括巢狀的
for section_title in ['References', 'Bibliography', 'External links']:
section = content.find('span', id=section_title)
while section:
for sib in section.parent.find_next_siblings():
sib.decompose()
section.parent.decompose()
section = content.find('span', id=section_title)
# 提取並清理文字
text = content.get_text(separator=' ', strip=True)
text = clean_text(text)
return text
except requests.exceptions.RequestException as e:
print(f"從 {url} 抓取內容時出錯:{e}")
return None
# 處理每個 URL 並將其內容寫入單獨的檔案
output_dir = './data/'
os.makedirs(output_dir, exist_ok=True)
for url in urls:
article_name = url.split('/')[-1].replace('.html', '')
filename = os.path.join(output_dir, article_name + '.txt')
clean_article_text = fetch_and_clean(url)
with open(filename, 'w', encoding='utf-8') as file:
file.write(clean_article_text)
print(f"內容(可用的部分)已寫入 './data/' 目錄下的檔案中")
內容解密:
上述程式碼首先建立了一個名為 data
的目錄,用於存放從指定 URL 列表中抓取的內容。程式碼中使用了 requests
和 BeautifulSoup
函式庫來從網頁中提取資料,並對提取的內容進行清理,移除不必要的字元和參考文獻等。清理後的文字被儲存到單獨的 .txt
檔案中,以便後續處理。
載入檔案
現在,我們將使用 SimpleDirectoryReader
類別從 ./data/
目錄中載入檔案。
documents = SimpleDirectoryReader("./data/").load_data()
LlamaIndex
的 SimpleDirectoryReader
類別設計用於處理非結構化資料。它會遞迴掃描目錄並識別所有支援的檔案型別,如 .txt
、.pdf
和 .docx
,然後提取每個檔案的內容並傳回包含文字和後設資料(如檔名和檔案路徑)的檔案物件列表。讓我們來顯示這個檔案列表的第一個條目:
print(documents[0])
輸出結果顯示,目錄讀取器提供了完全透明的資料來源資訊,包括檔案的名稱,如 1804.06985.txt
。
內容解密:
這段程式碼展示瞭如何使用 SimpleDirectoryReader
類別來載入和處理存放於 ./data/
目錄下的檔案。輸出的第一個檔案物件包含了檔案的後設資料和文字內容,展示了資料的原始來源和結構。
建立和填充 Deep Lake 向量儲存
在這個部分,我們將建立一個 Deep Lake
向量儲存並將我們的檔案資料填充到其中。我們將實施一個標準的張量組態,其中包括:
text
(字串):文字是檔案字典中列出的其中一個文字檔案的內容。它將被無縫地分割成有意義的片段,以最佳化處理。
RAG 管道流程
graph LR; A[收集無人機相關檔案] --> B[清理和準備資料]; B --> C[建立 Deep Lake 向量儲存]; C --> D[填充向量儲存]; D --> E[查詢和檢索];
圖表翻譯:
此圖表展示了使用 RAG(檢索增強生成)管道處理無人機相關檔案的流程。首先,收集相關檔案並進行清理和準備。接著,建立一個 Deep Lake
向量儲存,並將準備好的資料填充到其中。最後,透過查詢和檢索操作來利用這些資料。
資料集建立與向量儲存的完整流程
在建立一個根據LlamaIndex和Deep Lake的向量儲存系統時,我們首先需要定義metadata、embedding、以及id等重要組成部分。metadata包含了每個文字區塊的來源資訊,embedding則是利用OpenAI的embedding模型生成的浮點數向量,而id則是自動分配給每個區塊的唯一識別碼。
向量儲存與資料集路徑的定義
首先,我們需要定義向量儲存和資料集的路徑。這裡使用了hub://denis76/drone_v2
作為範例路徑,使用者需要將其替換成自己的帳戶名稱和資料集名稱。
vector_store_path = "hub://denis76/drone_v2"
dataset_path = "hub://denis76/drone_v2"
內容解密:
vector_store_path
和dataset_path
的定義是為了指定向量儲存和資料集的位置。- 使用者需要將
denis76/drone_v2
替換為自己的帳戶名稱和資料集名稱,以確保正確的存取路徑。
建立向量儲存並建立索引
接下來,我們建立一個向量儲存並將其填入資料,最後在檔案上建立索引。
vector_store = DeepLakeVectorStore(dataset_path=dataset_path, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
內容解密:
DeepLakeVectorStore
用於建立向量儲存,overwrite=True
表示如果資料集已存在,則會被覆寫。StorageContext.from_defaults
用於建立儲存上下文,預設使用指定的向量儲存。VectorStoreIndex.from_documents
則是在給定的檔案上建立索引,這個索引將用於後續的查詢和搜尋。
載入資料集並進行視覺化
資料集建立完成後,我們可以將其載入記憶體中,並進行視覺化。
import deeplake
ds = deeplake.load(dataset_path) # 載入資料集
內容解密:
- 使用
deeplake.load
函式載入指定的資料集。 - 資料集可以透過提供的連結線上上進行視覺化,或者在Jupyter Notebook中使用
ds.visualize()
方法進行視覺化。
將資料集轉換為Pandas DataFrame
為了更方便地檢視資料集內容,我們可以將其轉換為Pandas DataFrame。
import json
import pandas as pd
import numpy as np
# 建立一個字典來存放資料
data = {}
for tensor_name in ds.tensors:
tensor_data = ds[tensor_name].numpy()
if tensor_data.ndim > 1:
data[tensor_name] = [np.array(e).flatten().tolist() for e in tensor_data]
else:
if tensor_name == "text":
data[tensor_name] = [t.tobytes().decode('utf-8') if isinstance(t, bytes) else t for t in tensor_data]
else:
data[tensor_name] = tensor_data.tolist()
# 建立Pandas DataFrame
df = pd.DataFrame(data)
內容解密:
- 迴圈遍歷資料集中的每個tensor,並將其資料轉換為合適的格式。
- 如果tensor是多維的,則將其扁平化;如果是文字資料,則進行適當的解碼。
- 最終建立一個Pandas DataFrame,以便於進行資料操作和分析。
顯示特定記錄的詳細資訊
我們可以定義一個函式來顯示特定記錄的詳細資訊。
def display_record(record_number):
record = df.iloc[record_number]
display_data = {
"ID": record["id"] if "id" in record else "N/A",
"Metadata": record["metadata"] if "metadata" in record else "N/A",
"Text": record["text"] if "text" in record else "N/A",
"Embedding": record["embedding"] if "embedding" in record else "N/A"
}
# 顯示記錄的詳細資訊
內容解密:
display_record
函式根據提供的記錄編號,提取相應的記錄並顯示其詳細資訊。- 顯示的資訊包括ID、Metadata、Text和Embedding等欄位。