Posted on

在LlamaIndex中使用索引(Index)

甚麼是索引(Index)

在 LlamaIndex 中,索引是一種資料結構,用於組織和存儲來自各種數據來源的信息,使搜索變得更加容易。索引是建立在一組節點(Node)之上的。節點(Node)是 LlamaIndex 的基本單位,一種包含一段文本的資料結構。每當提供一個文件時,可以將其分割成多個片段並存儲在節點中。

索引類型

LlamaIndex 提供不同類型的索引,以下是要學習的一些類型:

List Index

將節點存儲為像鏈表結構那樣的順序鏈。默認情況下,它會從所有節點中獲取數據並作為響應的一部分發送。

可以使用基於嵌入的查詢來獲取前 k 個節點,或者添加關鍵字過濾器進行查詢。

Vector Store Index

向量存儲索引將每個節點及其對應的嵌入存儲在一個向量存儲中。在查詢向量索引時,它總是提供與查詢最相關的前 k 個最相似的節點。

Tree Index

樹形索引從一組節點建立一個分層的樹狀結構。

在內部,樹是通過摘要提示形成的。它以一系列文本文件作為輸入,然後以自下而上的方式建立樹形索引,其中每個父節點是其下方節點的摘要。

查詢樹形索引涉及從根節點向下到葉節點的過程。默認情況下(child_branch_factor=1),查詢在給定父節點的情況下選擇一個子節點。如果 child_branch_factor=2,則查詢在每一層選擇兩個子節點。

Keyword Table Index

GPTKeywordTableIndex 實現從索引的節點中提取關鍵字,並使用這些關鍵字來查找相關的文檔。當我們提出問題時,這個實現首先會從問題中生成關鍵字。接著,索引會搜尋相關的文檔並將它們發送給大語言模型(LLM)。

Knowledge Graph Index

官方教學文件: https://docs.llamaindex.ai/en/stable/examples/index_structs/knowledge_graph/KnowledgeGraphDemo/

KnowledgeGraphIndex類別透過自動從文本中提取實體和關係識別來簡化 RAG 知識圖構建,消除複雜的手動解析。它還提供了客製化的靈活性,可讓您根據您的特定需求定製圖形結構和推理規則。知識圖捕捉了實體之間豐富的關係,使得 RAG 中的查詢和推理比向量資料庫更加精確、多樣化和複雜。

從技術上講,KG 提供比 Vector DB 更多的 precise 輸出,KG 還支援比 Vector DB 更多的 diverse 和complex 查詢。此外,KG 比 Vector DB 具有更好的 reasoning 和推理功能……但通常情況下,KGs 與 Vector DBs 的比較是蘋果與柳丁的遊戲。

知識圖譜最適合具有清晰 relationships 的文檔,而向量資料庫則與基於 similarity 的上下文更相關。因此,在 KG 和 Vector DB 之間進行選擇取決於 RAG 專案的具體要求和目標。

何時使用特定的索引

列表索引 當您的文檔數量不多時,ListIndex 是理想的選擇。與其嘗試找到相關數據,索引會將所有片段連接起來並全部發送給大語言模型(LLM)。如果結果文本太長,索引會分割文本並請 LLM 精煉答案。

當使用“embedding”參數時,它與 VectorStoreIndex 非常相似,區別在於列表索引會發送所有匹配的節點而無需任何門檻,而 VectorStoreIndex 只有在節點達到某個匹配分數門檻時才會發送。

向量索引 當我們希望獲取通過一定匹配分數門檻的前 K 個相關文檔時,可以使用 Vector Index。

樹形索引 當處理基於摘要的任務時,樹形索引(Tree Index)非常有用。

關鍵字表索引 在 Keyword Table Index 中,每個節點都會被發送到 LLM 以生成關鍵字。將每個文檔發送給 LLM 會大幅增加索引成本。這比其他索引更慢且更昂貴。因此,除非使用此索引所提供的結果遠好於其他索引,否則不建議使用。

Posted on

使用LlamaIndex載入文檔

YouTube 文件載入器

將 YouTube 影片的文字記錄轉換為文件格式

from llama_index.core import download_loader
# 載入環境變數
from dotenv import load_dotenv 
load_dotenv()

YoutubeTranscriptReader = download_loader("YoutubeTranscriptReader")

loader = YoutubeTranscriptReader()
youtube_documents = loader.load_data(ytlinks=['https://www.youtube.com/watch?v=nHcbHdgVUJg&ab_channel=WintWealth'])

會得到如下格式的json資料

[Document(id_='nHcbHdgVUJg', embedding=None, metadata={'video_id': 'nHcbHdgVUJg'}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text="I'm a Commerce graduate.......", start_char_idx=None, end_char_idx=None, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n')]

載入PDF文件

使用下面的程式碼可以讀取本地端的pdf文件,請確保該檔案存在

from pathlib import Path
from llama_index.core import download_loader

PDFReader = download_loader("PDFReader")

loader = PDFReader()

pdf_document = loader.load_data(file=Path('./sample.pdf'))

會產生如下的json檔案

[Document(id_='c63920fc-1f19-4112-ab6a-d18aa193c037', embedding=None, metadata={'page_label': '1', 'file_name': 'sample.pdf'}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text=' \n \n \n \n \n \nLangChain 技术解密: \n构建大模型应用的全景指南 \n \n \n王浩帆 编著 \n \n \n \n \n \n \n \n \n \n \n \n \n', start_char_idx=None, end_char_idx=None, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'), ......]

載入Notion筆記本

from llama_index.core import download_loader
import os

NotionPageReader = download_loader('NotionPageReader')

integration_token = "your-notion-token"
database_id = "your-database-id"
reader = NotionPageReader(integration_token=integration_token)
notion_documents = reader.load_data(database_id=database_id)

建立對話機器人

import os
from llama_index.core import VectorStoreIndex

all_documents = youtube_documents + pdf_document
index = VectorStoreIndex.from_documents(all_documents)

對話測試

query_engine = index.as_query_engine()
response = query_engine.query("介紹LangChain")
print(response)

LangChain是一个基于大语言模型的应用程序开发框架,旨在简化创建大模型应用程序的过程。它提供了一套完整的工具、组件和接口,使开发者能够轻松地利用大语….

可得到以上回應
Posted on

LlamaIndex的基礎元件

基礎元件

LlamaIndex 的基礎元件包括:

  1. Nodes(節點):LlamaIndex 的基本單位,是一個包含一段文本的資料結構。當提供一個文件時,可以將其分割成多個片段並存儲在節點中。
  2. Document Loader(文檔加載器):用於從各種來源(如網頁、YouTube 視頻、PDF 等)提取數據的接口。LlamaIndex 支持多種文檔加載器,用於不同類型的數據源。
  3. Indexes(索引):在 LlamaIndex 中,索引是一種組織和存儲來自各種數據源信息的資料結構,使得搜索變得更加容易。索引是建立在多個節點之上的。LlamaIndex 提供不同類型的索引,方便應對不同的使用場景。
  4. Retrievers(檢索器):在 LlamaIndex 中,檢索器幫助從索引中基於給定的查詢檢索一組節點。它類似於一個搜索工具,從大型數據集中找到相關信息以回答用戶的問題。LlamaIndex 提供不同類型的檢索器,以應對不同的檢索需求。
  5. Query Engines(查詢引擎):在 LlamaIndex 中,查詢引擎處理用戶輸入的查詢,與底層數據結構(如索引)交互,並返回一個綜合的響應。LlamaIndex 提供不同類型的查詢引擎,以應對不同的查詢處理需求。

載入資料

使用SimpleDirectoryReader來載入本地端資料

from llama_index import SimpleDirectoryReader

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

將資料分割成節點

節點是基本的資料結構,用於保存輸入。我們將使用以下程式碼將上述輸入分割成多個節點。

from llama_index.node_parser import SimpleNodeParser
parser = SimpleNodeParser()
nodes = parser.get_nodes_from_documents(documents)

產生索引

現在我們已經創建了節點,可以在其上建立索引。我們將使用 VectorStoreIndex,它會從節點中的所有文本創建嵌入,並將其存儲在向量數據庫中。

from llama_index import LLMPredictor, VectorStoreIndex
from langchain import OpenAI
os.environ["OPENAI_API_KEY"] = "api-key"

index = VectorStoreIndex(nodes)

建立檢索器

我們將使用 VectorIndexRetriever,它會根據相似度檢索出前 k 個匹配的文件。在這個例子中,我們將 k 設為 2。

from llama_index.retrievers import VectorIndexRetriever

retriever = VectorIndexRetriever(
    index=index,
    similarity_top_k=2,
)   

建立查詢引擎

現在我們可以在檢索器之上構建一個查詢引擎來開始進行查詢。

from llama_index.query_engine import RetrieverQueryEngine

query_engine = RetrieverQueryEngine(
    retriever=retriever
)

詢問問題

現在我們可以在檢索器上建立一個查詢引擎來開始進行查詢。

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

Jupyter Notebook完整範例下載

https://github.com/SamurAIGPT/LlamaIndex-course/blob/main/fundamentals/Fundamentals.ipynb

Posted on

LlamaIndex介紹

主要功能

LlamaIndex 專注於將非結構化數據(如文本文件、PDF、網頁內容等)轉換為可以用於查詢和分析的結構化索引。它為用戶提供了一種簡單的方法來構建和查詢這些索引,從而更好地利用大型語言模型進行數據處理和檢索。

LlamaIndex 提供了以下功能來幫忙構建上下文增強 LLM 應用程式:

  • 數據索引和向量化:LlamaIndex 可以將非結構化數據轉換為向量表示,這對於 LLM 來說更易於處理。可以輕鬆地將自己的數據添加到 LlamaIndex 中,並讓 LLM 從中學習。
  • 數據檢索:LlamaIndex 可以根據用戶查詢快速準確地檢索相關數據。這意味著 LLM 應用程式將能夠快速找到其所需的信息,以提供準確的響應。
  • LLM 集成:LlamaIndex 可以與各種 LLM 集成,例如 GPT-3 和 Jurassic-1 Jumbo。這意味著可以選擇最適合的應用程式的 LLM。

使用教學(使用OpenAI的功能)

官方教學: https://docs.llamaindex.ai/en/latest/getting_started/starter_example/

LlamaIndex預設會使用OpenAI的Indexing功能去做文字的索引,以下為一個官方的範例,使用之前需要先安裝llama-index套件

pip install llama-index
pip install python-dotenv

接著下載數據並且放到data資料夾內,然後設定環境變數

設定環境變數的方法為到專案內新增.env檔案,並在其中設定OPENAI_API_KEY(可以到這邊申請)

OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxx

接著新增一個檔案名為starter.py,內容如下:

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
import logging
import sys
import os.path
from llama_index.core import (
    VectorStoreIndex,
    SimpleDirectoryReader,
    StorageContext,
    load_index_from_storage,
)
# 載入環境變數
from dotenv import load_dotenv 
load_dotenv()

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

# 假如已經有索引了,就不用再重新建立索引
PERSIST_DIR = "./storage"
if not os.path.exists(PERSIST_DIR):
    # 載入文件並建立索引
    documents = SimpleDirectoryReader("data").load_data()
    index = VectorStoreIndex.from_documents(documents)
    # 儲存索引
    index.storage_context.persist(persist_dir=PERSIST_DIR)
else:
    # 載入已存在的索引
    storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    index = load_index_from_storage(storage_context)

# 使用索引的資料詢問問題
query_engine = index.as_query_engine()
response = query_engine.query("What did the author do growing up?")
print(response)

此時文件結構應該像下面這樣子

執行之後,可以看到程式載入了data內的資料,呼叫https://api.openai.com/v1/embeddings來做詞嵌入的動作

以下是訊息中的一些重要部分:

  • connect_tcp.startedconnect_tcp.complete:表示開始和完成 TCP 連接。在這裡,連接成功建立到了 api.openai.com 的 443 端口。
  • start_tls.startedstart_tls.complete:表示開始和完成 TLS 握手過程,確保通信的安全性。
  • send_request_headers.startedsend_request_headers.complete:表示開始和完成發送請求頭的過程。
  • send_request_body.startedsend_request_body.complete:表示開始和完成發送請求主體的過程。
  • receive_response_headers.startedreceive_response_headers.complete:表示開始和完成接收響應頭的過程。響應頭中包含了一些重要的信息,如響應的 HTTP 狀態碼、內容類型、限速等。
  • INFO:httpx:HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK":表示成功發送了 HTTP POST 請求到 https://api.openai.com/v1/embeddings 並收到了 200 OK 的響應。

上面這些訊息則代表已經生成了storage資料夾,儲存詞嵌入的結果

使用索引的資料詢問問題

下面這樣簡短的程式碼可自動載入"./storage"內的嵌入檔案,並且將嵌入的檔案和詢問的問題傳送給OpenAI API的https://api.openai.com/v1/chat/completions文字生成機器人

# 載入已存在的索引
storage_context = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
index = load_index_from_storage(storage_context)

# 使用索引的資料詢問問題
query_engine = index.as_query_engine()
response = query_engine.query("What did the author do growing up?")
print(response)

則可看到得到的回應如下:

The author worked on writing short stories and programming, starting with the IBM 1401 in 9th grade, using an early version of Fortran. Later, the author transitioned to microcomputers, particularly a TRS-80, where they wrote simple games, a rocket prediction program, and a word processor.

檢索增強生成 (RAG)

RAG(檢索增強生成)是一種用於構建大型語言模型 (LLM) 應用程式的架構。它由以下五個關鍵階段組成:

  1. 載入:此階段涉及將數據從其原始位置導入到您的管道中。數據可以來自各種來源,包括文檔、數據庫、API 等。Node 是 LlamaIndex 中數據的原子單位,表示文件中的“chunk”。節點具有將它們與它們所在的文件以及其他節點相關聯的元數據。連接器:資料連接器(通常稱為讀取器),可以從各種數據源和格式,例如資料庫、檔案、網路 API 等,將資料讀取到 LlamaIndex 的文件 (Documents) 和節點 (Nodes) 中。
  2. 索引:取得資料後,LlamaIndex 可以協助您將資料建立索引,變成易於檢索的結構。這通常會包含生成向量嵌入 (vector embeddings),並將它們儲存在稱為向量儲存庫 (vector store) 的特殊數據庫中。索引也可以儲存各種關於資料的元數據(metadata)。
    大型語言模型 (LLMs) 會產生稱為嵌入的資料數值表示。當您根據相關性過濾資料時,LlamaIndex 會將查詢轉換成嵌入,您的向量儲存庫會找到與查詢嵌入數值上相似的資料。
  3. 儲存:此階段涉及將索引數據存儲在持久存儲器中。這使您可以稍後查詢數據,而無需再次重新索引。LlamaIndex 提供了各種存儲選項,可幫助您選擇最適合您的需求的選項。
  4. 查詢:此階段涉及使用 LLM 對索引數據進行查詢。LlamaIndex 提供了各種查詢方法,包括子查詢、多步驟查詢和混合策略。常使用的術語包括RetrieversRoutersNode PostprocessorsResponse Synthesizers
  5. 評估:此階段涉及評估您的管道的性能。這包括測量查詢的準確性、相關性和速度。LlamaIndex 提供了各種評估工具,可幫助您微調您的管道以獲得最佳結果。

官方釋出的範例專案

https://github.com/run-llama/chat-llamaindex

Posted on

機器學習的效能衡量指標

混淆矩陣

混淆矩陣(Confusion Matrix)是一種評估分類模型性能的工具,特別適用於監督學習中的分類問題。它能夠幫助你了解模型在不同類別上的預測結果,並提供更多信息來評估模型的準確性。

混淆矩陣是一個方陣,其中每一行代表實際的類別,每一列代表模型預測的類別。以下是一個二元分類問題的混淆矩陣範例:

預測為正類 (Positive)預測為負類 (Negative)
實際為正類 (Positive)真正類 (TP)偽負類 (FN)
實際為負類 (Negative)偽正類 (FP)真負類 (TN)
  • TP(True Positive)是模型將正例正確預測為正例的樣本數量。
  • TN(True Negative)是模型將負例正確預測為負例的樣本數量。
  • FP(False Positive)是模型將負例錯誤預測為正例的樣本數量。
  • FN(False Negative)是模型將正例錯誤預測為負例的樣本數量。

準確率(Accuracy)

預測正確的樣本數量與總樣本數量之比

Accuracy= (tp+tn)/(tp+fp+fn+tn)

精確率(Precision)

指的是在所有被模型預測為正類的樣本中,實際上是正類的比例。換句話說,它衡量了模型正確預測正例的能力,並且避免錯誤地將負例分類為正例

Precision= tp/(tp+fp)

召回率(Recall)

實際上被正確預測為正例的樣本數量除以所有實際正類樣本的數量

 Recall = tp/(tp+fn)

F1-score

是一個綜合了精確度(Precision)和召回率(Recall)的指標,使用精確度和召回率的值計算 F1-score

Precision-Recall 曲線

用於評估二元分類器性能的一種圖表。它描述了在不同閾值下模型的精確度(Precision)和召回率(Recall)之間的折衷關係。

在 Precision-Recall 曲線上,x 軸通常表示召回率,y 軸表示精確度。理想情況下,我們希望模型能夠同時實現高精確度和高召回率,即圖表右上角的位置。但是,通常情況下,提高精確度可能會降低召回率,反之亦然。這種權衡關係取決於分類器的閾值設置,可以通過調整閾值來改變精確度和召回率之間的平衡。

ISO-F1 曲線

ISO-F1 曲線是一種評估多類別分類器性能的方法,特別用於不平衡類別數據集。ISO-F1 曲線通過在 F1-score 和類別別不平衡程度之間繪製關係圖來評估分類器的性能。

ISO-F1 曲線以不同的 F1-score 為橫軸,以類別別不平衡程度(通常以每個類別的正例數量比例或類別的預測概率分佈)為縱軸。它通過改變分類器的閾值或類別別的權重來繪製曲線,從而呈現出不同 F1-score 和類別別不平衡程度之間的平衡關係。

ISO-F1 曲線的一個常見應用是用於調整分類器的閾值,從而使得在不同類別別的不平衡情況下都能達到相對均衡的性能。透過該曲線,可以找到一個合適的閾值,以平衡不同類別別之間的性能,從而提高整體的分類器性能。

Posted on

LangChain的基礎鏈介紹

甚麼是LangChain

LangChain是根據大型語言模型(LLM) 打造應用程式的框架。LangChain使用基礎鏈來建立由 LLM(大型語言模型)支援的應用程式。這些基本鍊是模組化構建塊,用於在應用程式中執行特定任務。

LangChain 是用於開發由語言模型驅動的應用程式的框架。

  • 具有上下文採集能力:將語言模型連接到上下文來源(提示指令,少量的範例,需要回應的內容等)
  • 具有推理能力:依賴語言模型進行推理(根據提供的上下文如何回答,採取什麼行動等)

教學資源

鏈結構介紹

鏈( Chains )是一個非常通用的概念,它指的是將一系列模組化組件(或其他鏈)以特定方式組合起來,以實現共同的用例。

LLMChain(單鏈)

類別說明: https://api.python.langchain.com/en/latest/chains/langchain.chains.llm.LLMChain.html

最常用的鏈類型,它結合了PromptTemplate(input)、Model(LLM)和Guardrails(output)來接收用戶輸入,進行相應的格式化,將其傳遞給模型並獲取回應,然後驗證和修正(如果需要)模型的輸出。

SequentialChain(循序鏈)

類別說明: https://api.python.langchain.com/en/latest/chains/langchain.chains.sequential.SequentialChain.html


同一次的詢問,至少兩次的與LLM交互,把複雜的問題拆解成小的問題,然後再輸出回應

這邊是一篇說明文章:https://blog.csdn.net/wangjiansui/article/details/137509565

總之就是讓輸入到輸出之間串聯多個LLM系統並依序執行

以下是如何使用 SequentialChain 的一些範例:

  • 機器翻譯: SequentialChain 可用於透過使用專門針對不同語言對的 LLM 呼叫鏈將文字從一種語言翻譯為另一種語言。
  • 文字摘要: SequentialChain 可用於透過使用一系列 LLM 呼叫來摘要文本,這些呼叫從文本中提取關鍵訊息,然後產生摘要。
  • Q&A: SequentialChain 可用於透過使用一系列 LLM 調用來回答問題,這些調用從文本文檔中提取信息,然後生成問題的答案。

TransformChain(轉換鏈)

類別說明: https://api.python.langchain.com/en/latest/chains/langchain.chains.transform.TransformChain.html

這些轉換可以是簡單的文字操作(例如,文字清理)或更複雜的模型。

以下是 TransformChain 工作原理的詳細說明:

  1. 輸入: TransformChain 接收 LLM 的輸出作為輸入。此輸出可以是文字、程式碼或任何其他資料格式。
  2. 轉換:然後 TransformChain 對輸入資料套用一系列轉換。這些轉換由使用者提供的函數或預先定義的 LangChain 轉換定義。
  3. 輸出: TransformChain 的最終輸出是將所有轉換應用於輸入資料的結果。此輸出可以用作另一個鏈的輸入或作為應用程式的最終輸出。

以下是如何使用 TransformChain 的一些範例:

  • 文字清理: TransformChain 可用於透過刪除標點符號、將文字轉換為小寫以及刪除停用詞來清理文字。
  • 特徵提取: TransformChain 可用於從文本中提取特徵,例如詞頻或情緒分數。
  • 數據標準化: TransformChain 可用於標準化數據,例如縮放數值數據或將分類數據轉換為數值表示。
Posted on

QLoRA – Efficient Finetuning of Quantized LLMs

QLoRA 擴展了 LoRA,透過量化原始網路的權重值來提高效率,從高解析度資料類型(如 Float32)到較低解析度資料類型(如 int4)。這會減少記憶體需求並加快計算速度。

什麼是QLoRA

QLORA(Quantized LoRA)方法是一種用於大型語言模型(LLMs)的微調的新方法。傳統上,微調大型模型需要龐大的計算資源,而QLORA則提出了一種可以在GPU上進行低成本微調的方法。QLORA的關鍵創新在於使用了4位量化技術,並引入了可訓練的低秩適配器權重,從而大幅降低了微調過程中所需的記憶體,並且在不影響模型性能的情況下實現了相當於16位完全微調基準的預測性能。

QLoRA 技術所做的三個面向改進

  • 4-bit 常態浮點(NormalFloat):這是一種資訊理論上最優的量化資料類型,適用於服徠常態分佈的資料。與4-bit 整數和4-bit 浮點相比,它在實踐中能取得更好的效果。量化是指用更少的位數來表示數據,從而降低記憶體佔用。
  • 雙量化(Double Quantization):這種方法會量化量化常數本身,可以節省大約每個參數0.37 位(例如對於一個65B 參數的模型,可以節省大約3GB 內存)。量化常數是量化過程中產生的一些中間值。
  • 分頁優化器(Paged Optimizers):這利用了NVIDIA 統一記憶體的功能,避免在處理包含長序列的迷你批次資料時梯度檢查點(gradient checkpointing) 造成的記憶體激增。梯度檢查點是一種訓練技巧,可以節省內存,但可能會降低精度。

由上圖可知,QLoRA 利用了nVidia 統一記憶體功能,當GPU 記憶體不足時,該功能允許GPU->CPU 無縫頁面傳輸,從而管理GPU 中突然出現的記憶體峰值,並協助解決記憶體溢出/超限問題。

利用QLoRA所做的研究

由於 QLORA 的高效性,可以進行深入的指令微調和聊天機器人效能研究,所涉及的模型規模是常規微調因記憶體開銷而無法企及的。 因此,提出論文的團隊針對多個指令微調資料集、模型架構以及參數規模介於 80M 到 65B 的模型訓練了超過 1000 個模型。 除了證明 QLORA 能恢復 16 位元精度效能(§4)以及訓練出最先進的聊天機器人 Guanaco(§5)之外,還分析了訓練模型的趨勢。

首先,他們發現資料品質比資料集大小重要得多,例如,一個包含9k 個樣本的資料集(OASST1) 在聊天機器人效能方面優於一個包含45 萬個樣本的資料集(子集化的FLAN v2 ),即使兩者都旨在支持遵循指令泛化。

其次,他們展示了強大的大規模多任務語言理解(MMLU) 基準測試性能並不意味著強大的Vicuna 聊天機器人基準測試性能,反之亦然- 換句話說,對於給定任務而言,數據集的適用性比大小更重要

相關資源:

Posted on

LoRA (Low-Rank Adaptation)

LoRA(Low-Rank Adaptation)是什麼

LoRA是一種有效的參數微調技術,可幫助改善大型語言模型在特定任務上的效能表現,並且具有較低的運算和儲存成本。它是一種用於在大型語言模型(LLM)上進行參數微調的技術。 它旨在透過降低模型參數的秩(rank)來減少模型的複雜度,從而提高模型的泛化能力和適應性。

在傳統的參數微調過程中,常常會遇到過擬合的問題,特別是當訓練資料較少或訓練資料與目標任務不符時。 LoRA透過引入一個低秩的參數矩陣,將原始的高維參數矩陣分解成兩個低秩矩陣的乘積,從而降低模型的複雜度。 這種降維的方式可以有效地減少模型的參數量,減緩過度擬合的情況,並提高模型的泛化能力。

LoRA的主要優點

  • 更快的訓練速度 :將原始的高維度參數矩陣分解成低秩矩陣,可以大幅減少模型的參數數量。
  • 更低的計算成本 : 將原始的高維度參數矩陣分解成低秩矩陣,進而降低模型的計算和儲存成本。它不是添加層,而是為參數添加值,不會導致推理延遲。
  • 更少的泛化損失: LoRA能夠提高模型的泛化能力,使其更能適應不同的任務和領域。

LoRA流程說明

  • 使用預訓練的 LLM 權重初始化 A 和 B 矩陣。
  • 將 LLM 應用於特定任務的訓練數據集。
  • 在訓練過程中,只有 A 矩陣會針對訓練數據集(輸入資料(X))進行微調。
  • 訓練完成後,獲得了針對特定任務適應的 LLM,也就是H(輸出)。

運作原理

在LoRA中,一組新參數同時加入了網路WA和中WB。這些網路利用低秩權重向量,其向量的維度表示為dxr和rxd。在這裡,「d」代表原始凍結網路參數向量的維度,而「r」表示所選的低秩或更低維度。值得注意的是,「r」的值越小,模型訓練過程就越加速和簡化。確定適當的「r」值是LoRA中的關鍵決策。選擇較低的值會導致更快且更具成本效益的模型訓練,但可能不會產生最佳結果。相反,選擇較高的「r」值會增加訓練時間和成本,但會增強模型處理更複雜任務的能力。

LoRA的運作方式是,首先需要一個預先訓練的LLM,並凍結其大部分參數。然後,將這些凍結的預訓練模型權重與可訓練的秩分解矩陣一起注入到變壓器的每一層中。這樣做有助於精細化模型,特別是在低資源硬體上調整模型。

從上表可以看出,LoRA 方法的結果與經典的微調方法相當,可以用更少的時間和資源獲得或多或少相同的結果,並且有更快的執行時間和更短的訓練時間,真是太棒了!

結論

  • LoRA 是一種模型適應技術,可減少 LLM 中的參數數量,同時保持其效能。
  • 它透過將LLM的權重分解為低秩矩陣(共同特徵)和隨機矩陣(特定於任務的變體)來實現這一點。
  • 低秩矩陣和隨機矩陣相結合產生一個特定於任務的適配器,該適配器可以根據特定任務自訂 LLM。
  • LoRA 在訓練速度、運算效率和模型大小方面具有優勢,使其適合資源受限的環境。
  • LoRA 多數的成果比 Fine-tuning 的成果還要好,並且訓練的參數量遠小於 Fine-tuning。

更多資訊請見

LoRA: Low-Rank Adaptation of Large Language Models:

Posted on

Retrieval-Augmented LLMs

檢索增強生成(RAG)的工作流程

從使用者查詢開始,透過向量資料庫檢索,到填入提示,最終形成回答的整個過程。

RETA-LLM框架可以看作是實現RAG目標的一種具體實現方式,它提供了一套模組化的工具和方法來將外部知識整合到語言模型中,以提升其產生答案的能力。

RETA-LLM Framework

研究論文: https://arxiv.org/pdf/2306.05212v1

過去通用的LLM增強工具包(如LangChain)與RETA-LLM有所不同,RETA-LLM專注於檢索增強LLMs,並提供更多的插件模組。

檢索增強LLMs使用兩個模組的檢索和生成策略:

  • 根據用戶的請求檢索文件或段落(文件檢索模組)
  • 利用這些相關文件作為參考生成答案(答案生成模組)。

除了這兩個基本模組外,RETA-LLM還提供了三個可選模組:

  • 請求重寫模組,以使用戶當前的請求更完整和清晰
  • 萃取模組,從檢索到的整個文件內容中提取相關段落或片段
  • 事實檢查模組,以驗證生成答案中是否存在事實錯誤

這些可選模組可以使IR系統和LLMs之間的交互更加有效和順暢。RETA-LLM中LLMs和IR系統之間的解綁更加徹底,這使得搜索引擎和LLMs的定制更加方便。

RETA-LLM的框架圖

RETA-LLM的工作流程如下:

  • 使用請求重寫模組修改目前使用者請求,使其完整且清晰。 由於使用者可能向RETA-LLM提出一系列問題,目前使用者請求的語意可能不完整。 例如,使用者可能會問「經濟學院怎麼樣?」而歷史請求是「介紹資訊學院的專業」。 在這種情況下,使用者的準確意思是「介紹經濟學院的專業」。 由於LLMs在對話式密集檢索中顯示出出色的重寫查詢能力,RETA-LLM將當前使用者請求和先前的對話歷史提供給LLMs進行重寫。
  • 然後,RETA-LLM使用文件檢索模組根據修訂後的使用者請求從外部語料庫中檢索相關文件。 文檔檢索模組是與IR系統連接的模組。 它從外部知識語料庫中檢索相關文件並傳回前K個。 。
  • 接下來,RETA-LLM使用段萃取模組從檢索到的文件中提取與使用者請求相關的片段,以形成參考文獻。 由於LLMs的輸入長度限制(通常為2048或4096個標記),因此不可能直接將所有前K個相關文件內容連接起來作為它們產生答案的參考文獻。 透過截斷文件內容的瑣碎方法可能會遺失其中的重要資訊。 因此,RETA-LLM重複使用LLMs自身從修訂後的請求中提取相關片段。 由於一個文件的長度也可能超出限制,RETA-LLM採用滑動視窗策略逐步擷取片段。 在我們的預設配置中,滑動視窗大小和步長設定為512和256。 然後,這些片段被連接在一起作為參考文獻。
  • 此外,RETA-LLM使用答案產生模組為使用者請求產生答案。 如同先前的研究所建議的,透過提供來自外部語料庫檢索到的參考文獻,LLMs可以產生更準確的答案。
  • 最後,RETA-LLM使用事實檢查模組驗證產生的答案是否包含事實錯誤,並為使用者要求輸出最終回應。 儘管提供了產生的額外證據,LLMs也可能出現幻覺。 有必要設計一個模組進行進一步的事實驗證。 由於LLMs具有強大的自然語言理解能力,我們將參考文獻和生成的答案提供給它們進行判斷。 因此,RETA-LLM可以決定是否輸出產生的答案,或只是說「我無法回答這個問題」。

請注意,LLMs的所有輸入都包含在指示或提示中。 如圖1所示,在RETA-LLM中完全解開了IR系統和LLMs之間的連結。 我們RETA-LLM中的這種分離設計使用戶可以自訂自己的個人搜尋引擎和LLMs。

知識檢索的過程

  • 內建工具增強助手功能: 內建的工具可以將上傳的文件中的外部知識與助手功能結合起來,使助手能夠存取並利用這些外部知識來回答使用者的問題。
  • 內容分塊、索引和嵌入儲存: 上傳的檔案內容將被分成區塊,然後進行索引和嵌入儲存。 這意味著文件內容將被切割成較小的片段,每個片段都會被賦予一個特定的標識,並且會轉換成向量表示,以便更有效地處理和檢索。
  • 檢索嵌入以回答輸入查詢: 當使用者提出查詢時,系統會將檢索嵌入的向量表示以尋找與查詢相關的內容區塊。 這些內容區塊中包含的知識將被用來回答使用者的查詢,以提供更準確和全面的答案。

RAG的挑戰

  • 檢索模型: 選擇合適的檢索模型是一項挑戰。 不同的檢索模型可能適用於不同的場景,因此需要仔細選擇以確保檢索的效果和效率。
  • 稠密或稀疏表示: 在RAG中,可以使用稠密或稀疏的表示來表示檢索到的內容。 稠密表示通常具有更高的維度和更多的信息,但也可能更加計算密集。 稀疏表示則可能更加高效,但可能會遺失某些細節資訊。
  • 內容區塊的單位: 將內容分成適當的區塊是一個挑戰。 區塊的大小和粒度會影響到檢索和處理的效率,因此需要找到一個合適的單位來平衡資訊的完整性和處理的複雜性。
  • 類似的參考引入噪音: 當有多個相似的參考資料時,可能會引入噪音,使系統難以確定哪個參考是最相關的。 這可能會影響答案的準確性和一致性。
  • 有些問題需要跨文件引用來回答: 某些問題可能需要引用多個文件中的資訊才能進行回答。 這增加了檢索和整合資訊的複雜性,需要係統能夠有效地處理跨文件的引用和關聯資訊。
Posted on

提示工程框架的概念

明確具體的提問

  • 請求模型採用一個人物角色
  • 使用分隔符清楚地指示輸入的不同部分
  • 指定完成任務所需的步驟
  • 提供示例
  • 指定輸出的期望長度

以下為一個範例

In-Context Learning和Chain-of-Thought

  • In-Context Learning(上下文學習): 這是指模型在學習和處理文字時能夠考慮上下文資訊的能力。 在上下文學習中,模型不僅僅關注單字或短語的訊息,而是根據前後文的內容來理解當前文本的含義。 這種能力使得模型能夠更好地理解文本的語境,從而產生更準確和連貫的輸出。
  • Chain-of-Thought(思維鏈): 這指的是模型在生成文本時能夠保持連貫性和邏輯性的能力。 在思維鏈中,模型可以根據前面產生的內容來決定後續產生的內容,並保持文字的一致性和邏輯性。 這種能力使得模型能夠產生更連貫和有意義的文字輸出。
圖片來源: https://arxiv.org/pdf/2205.11916.pdf

Tree-of-Thoughts思維樹

思考樹(ToT)是一種透過將複雜問題分解為更易於解決的小問題,為LLM推理提供了更結構化的提示框架。

與在鏈中推理的CoT不同,ToT以樹的形式組織其解決問題的策略。每個節點都被稱為“思維”,是一個連貫的語言序列,是通往最終答案的一步。

透過將問題劃分為離散的「思想」單元——從填字遊戲中的一系列簡短單字到數學方程式的一個組成部分——ToT確保問題的每個階段都得到系統的解決。

圖片來源: https://arxiv.org/pdf/2305.10601.pdf

在「oracle模式」下,ToT的表現比CoT還要好