新聞中心
隨著開源大型語言模型的性能不斷提高,編寫和分析代碼、推薦、文本摘要和問答(QA)對的性能都有了很大的提高。但是當涉及到QA時,LLM通常會在未訓練數(shù)據(jù)的相關(guān)的問題上有所欠缺,很多內(nèi)部文件都保存在公司內(nèi)部,以確保合規(guī)性、商業(yè)秘密或隱私。當查詢這些文件時,會使得LLM產(chǎn)生幻覺,產(chǎn)生不相關(guān)、捏造或不一致的內(nèi)容。

創(chuàng)新互聯(lián)基于成都重慶香港及美國等地區(qū)分布式IDC機房數(shù)據(jù)中心構(gòu)建的電信大帶寬,聯(lián)通大帶寬,移動大帶寬,多線BGP大帶寬租用,是為眾多客戶提供專業(yè)服務(wù)器托管報價,主機托管價格性價比高,為金融證券行業(yè)托管服務(wù)器,ai人工智能服務(wù)器托管提供bgp線路100M獨享,G口帶寬及機柜租用的專業(yè)成都idc公司。
為了處理這一挑戰(zhàn)的一種可用技術(shù)是檢索增強生成(retrieve - augmented Generation, RAG)。它涉及通過在響應(yīng)生成之前引用其訓練數(shù)據(jù)源之外的權(quán)威知識庫來增強響應(yīng)的過程。RAG應(yīng)用程序包括一個檢索系統(tǒng),用于從語料庫中獲取相關(guān)文檔片段,以及一個LLM,用于使用檢索到的片段作為上下文生成響應(yīng),所以語料庫的質(zhì)量及其在向量空間中的表示(稱為嵌入)在RAG的準確性中發(fā)揮重要作用。
在本文中,我們將使用可視化庫renumics-spotlight在2-D中可視化FAISS向量空間的多維嵌入,并通過改變某些關(guān)鍵的矢量化參數(shù)來尋找提高RAG響應(yīng)精度的可能性。對于我們選擇的LLM,將采用TinyLlama 1.1B Chat,這是一個緊湊的模型,與Llama 2相同的架構(gòu)。它的優(yōu)點是具有更小的資源占用和更快的運行時間,但其準確性沒有成比例的下降,這使它成為快速實驗的理想選擇。
系統(tǒng)設(shè)計
QA系統(tǒng)有兩個模塊,如圖所示。
LoadFVectorize模塊加載pdf或web文檔。對于最初的測試和可視化。第二個模塊加載LLM并實例化FAISS檢索,然后創(chuàng)建包含LLM、檢索器和自定義查詢提示的檢索鏈。最后我們對它的向量空間進行可視化。
代碼實現(xiàn)
1、安裝必要的庫
renumics-spotlight庫使用類似umap的可視化,將高維嵌入減少到更易于管理的2D可視化,同時保留關(guān)鍵屬性。我們在以前的文章中也介紹過umap的使用,但是只是功能性的簡單介紹,這次我們作為完整的系統(tǒng)設(shè)計,將他整合到一個真正可用的實際項目中。首先是安裝必要的庫:
pip install langchain faiss-cpu sentence-transformers flask-sqlalchemy psutil unstructured pdf2image unstructured_inference pillow_heif opencv-python pikepdf pypdf
pip install renumics-spotlight
CMAKE_ARGS="-DLLAMA_METAL=on" FORCE_CMAKE=1 pip install --upgrade --force-reinstall llama-cpp-python --no-cache-dir上面的最后一行是安裝帶有Metal支持的llama- pcp -python庫,該庫將用于在M1處理器上加載帶有硬件加速的TinyLlama。
2、LoadFVectorize模塊
模塊包括3個功能:
load_doc處理在線pdf文檔的加載,每個塊分割512個字符,重疊100個字符,返回文檔列表。
vectorize調(diào)用上面的函數(shù)load_doc來獲取文檔的塊列表,創(chuàng)建嵌入并保存到本地目錄opdf_index,同時返回FAISS實例。
load_db檢查FAISS庫是否在目錄opdf_index中的磁盤上并嘗試加載,最終返回一個FAISS對象。
該模塊代碼的完整代碼如下:
# LoadFVectorize.py
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.document_loaders import OnlinePDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
# access an online pdf
def load_doc() -> 'List[Document]':
loader = OnlinePDFLoader("https://support.riverbed.com/bin/support/download?did=7q6behe7hotvnpqd9a03h1dji&versinotallow=9.15.0")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=100)
docs = text_splitter.split_documents(documents)
return docs
# vectorize and commit to disk
def vectorize(embeddings_model) -> 'FAISS':
docs = load_doc()
db = FAISS.from_documents(docs, embeddings_model)
db.save_local("./opdf_index")
return db
# attempts to load vectorstore from disk
def load_db() -> 'FAISS':
embeddings_model = HuggingFaceEmbeddings()
try:
db = FAISS.load_local("./opdf_index", embeddings_model)
except Exception as e:
print(f'Exception: {e}\nNo index on disk, creating new...')
db = vectorize(embeddings_model)
return db3、主模塊
主模塊最初定義了以下模板的TinyLlama提示符模板:
<|system|>{context}<|user|>{question}<|assistant|>另外采用來自TheBloke的量化版本的TinyLlama可以極大的減少內(nèi)存,我們選擇以GGUF格式加載量化LLM。
然后使用LoadFVectorize模塊返回的FAISS對象,創(chuàng)建一個FAISS檢索器,實例化RetrievalQA,并將其用于查詢。
# main.py
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_community.llms import LlamaCpp
from langchain_community.embeddings import HuggingFaceEmbeddings
import LoadFVectorize
from renumics import spotlight
import pandas as pd
import numpy as np
# Prompt template
qa_template = """<|system|>
You are a friendly chatbot who always responds in a precise manner. If answer is
unknown to you, you will politely say so.
Use the following context to answer the question below:
{context}
<|user|>
{question}
<|assistant|>
"""
# Create a prompt instance
QA_PROMPT = PromptTemplate.from_template(qa_template)
# load LLM
llm = LlamaCpp(
model_path="./models/tinyllama_gguf/tinyllama-1.1b-chat-v1.0.Q5_K_M.gguf",
temperature=0.01,
max_tokens=2000,
top_p=1,
verbose=False,
n_ctx=2048
)
# vectorize and create a retriever
db = LoadFVectorize.load_db()
faiss_retriever = db.as_retriever(search_type="mmr", search_kwargs={'fetch_k': 3}, max_tokens_limit=1000)
# Define a QA chain
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=faiss_retriever,
chain_type_kwargs={"prompt": QA_PROMPT}
)
query = 'What versions of TLS supported by Client Accelerator 6.3.0?'
result = qa_chain({"query": query})
print(f'--------------\nQ: {query}\nA: {result["result"]}')
visualize_distance(db,query,result["result"])向量空間可視化本身是由上面代碼中的最后一行visualize_distance處理的:
visualize_distance訪問FAISS對象的屬性__dict__,index_to_docstore_id本身是值docstore-ids的關(guān)鍵索引字典,用于向量化的總文檔計數(shù)由索引對象的屬性ntotal表示。
vs = db.__dict__.get("docstore")
index_list = db.__dict__.get("index_to_docstore_id").values()
doc_cnt = db.index.ntotal調(diào)用對象索引的方法reconstruct_n,可以實現(xiàn)向量空間的近似重建
embeddings_vec = db.index.reconstruct_n()有了docstore-id列表作為index_list,就可以找到相關(guān)的文檔對象,并使用它來創(chuàng)建一個包括docstore-id、文檔元數(shù)據(jù)、文檔內(nèi)容以及它在所有id的向量空間中的嵌入的列表:
doc_list = list()
for i,doc-id in enumerate(index_list):
a_doc = vs.search(doc-id)
doc_list.append([doc-id,a_doc.metadata.get("source"),a_doc.page_content,embeddings_vec[i]])然后使用列表創(chuàng)建一個包含列標題的DF,我們最后使用這個DF進行可視化
df = pd.DataFrame(doc_list,columns=['id','metadata','document','embedding'])在繼續(xù)進行可視化之前,還需要將問題和答案結(jié)合起來,我們創(chuàng)建一個單獨的問題以及答案的DF,然后與上面的df進行合并,這樣能夠顯示問題和答案出現(xiàn)的地方,在可視化時我們可以高亮顯示:
# add rows for question and answer
embeddings_model = HuggingFaceEmbeddings()
question_df = pd.DataFrame(
{
"id": "question",
"question": question,
"embedding": [embeddings_model.embed_query(question)],
})
answer_df = pd.DataFrame(
{
"id": "answer",
"answer": answer,
"embedding": [embeddings_model.embed_query(answer)],
})
df = pd.concat([question_df, answer_df, df])這里使用使用np.linalg.norm在文件和問題嵌入上的進行距離大小的計算:
question_embedding = embeddings_model.embed_query(question)
# add column for vector distance
df["dist"] = df.apply(
lambda row: np.linalg.norm(
np.array(row["embedding"]) - question_embedding
),axis=1,)因為spotlight可以對df進行可視化,所有我們直接調(diào)用即可
spotlight.show(df)這一步將在瀏覽器窗口中啟動spotlight。
運行測試
1、基本測試
下面是我們選擇的樣本問題:
What versions of TLS supported by Client Accelerator 6.3.0?
正確答案是:
Client Accelerator 6.3.0 supports TLS 1.1 or 1.2.
以下額外信息可能包含在響應(yīng)中。
You must enable this capability using the following CLI command on the Client Accelerator:(config) # policy id?
?ssl backend client-tls-1.2Even though TLS 1.1 is not mentioned in the syntax of this command, using ?this command automatically enables support for both TLS 1.1 and 1.2.
然后我們看看TinyLlama對上述問題的回答:
Client Accelerator 6.3.0 supports TLS 1.1 or 1.2 as the default ?supported TLS versions with Client Accelerator. You must enable this ?capability using the following CLI command on the Client Accelerator:```(config) # policy id?
?ssl backend client-tlss1.2```Note that this command only applies to TLS 1.1 or TLS?1.2. If you need to ?support older TLS versions, you can use the?ssl backend?command with ?the?client-tlss1.0?or?client-tlss1.1?option?instead.
看起來與實際答案非常相似,但它并不完全正確,因為這些TLS版本不是其默認值。
那么我們來看看他是從哪些段落中找到的答案呢?
在可以spotlight中使用visible 按鈕來控制顯示的列。按“dist”對表格進行排序,在頂部顯示問題、答案和最相關(guān)的文檔片段。查看我們文檔的嵌入,它將幾乎所有文檔塊描述為單個簇。這是合理的,因為我們原始pdf是針對特定產(chǎn)品的部署指南,所以被認為是一個簇是沒有問題的。
單擊Similarity Map選項卡中的過濾器圖標,它只突出顯示所選的文檔列表,該列表是緊密聚集的,其余的顯示為灰色,如圖下所示。
2、測試塊大小和重疊參數(shù)
由于檢索器是影響RAG性能的關(guān)鍵因素,讓我們來看看影響嵌入空間的幾個參數(shù)。TextSplitter的塊大小chunk size(1000,2000)和/或重疊overlap (100,200)參數(shù)在文檔分割期間是不同的。
對所有組合的對于輸出似乎相似,但是如果我們仔細比較正確答案和每個回答,準確答案是(1000,200)。其他回答中不正確的細節(jié)已經(jīng)用紅色突出顯示。我們來嘗試使用可視化嵌入來解釋這一行為:
從左到右觀察,隨著塊大小的增加,我們可以觀察到向量空間變得稀疏且塊更小。從底部到頂部,重疊逐漸增多,向量空間特征沒有明顯變化。在所有這些映射中整個集合仍然或多或少地呈現(xiàn)為一個單一的簇,并只有幾個異常值存在。這種情況在生成的響應(yīng)中是可以看到的因為生成的響應(yīng)都非常相似。
如果查詢位于簇中心等位置時由于最近鄰可能不同,在這些參數(shù)發(fā)生變化時響應(yīng)很可能會發(fā)生顯著變化。如果RAG應(yīng)用程序無法提供預(yù)期答案給某些問題,則可以通過生成類似上述可視化圖表并結(jié)合這些問題進行分析,可能找到最佳劃分語料庫以提高整體性能方面優(yōu)化方法。
為了進一步說明,我們將兩個來自不相關(guān)領(lǐng)域(Grammy Awards和JWST telescope)的維基百科文檔的向量空間進行可視化展示。
def load_doc():
loader = WebBaseLoader(['https://en.wikipedia.org/wiki/66th_Annual_Grammy_Awards','https://en.wikipedia.org/wiki/James_Webb_Space_Telescope'])
documents = loader.load()
...只修改了上面代碼其余的代碼保持不變。運行修改后的代碼,我們得到下圖所示的向量空間可視化。
這里有兩個不同的不重疊的簇。如果我們要在任何一個簇之外提出一個問題,那么從檢索器獲得上下文不僅不會對LLM有幫助,而且還很可能是有害的。提出之前提出的同樣的問題,看看我們LLM產(chǎn)生什么樣的“幻覺”
Client Accelerator 6.3.0 supports the following versions of Transport Layer Security (TLS):
- TLS 1.2\2. TLS 1.3\3. TLS 1.2 with Extended Validation (EV) certificates\4. TLS 1.3 with EV certificates\5. TLS 1.3 with SHA-256 and SHA-384 hash algorithms
這里我們使用FAISS用于向量存儲。如果你正在使用ChromaDB并想知道如何執(zhí)行類似的可視化,renumics-spotlight也是支持的。
總結(jié)
檢索增強生成(RAG)允許我們利用大型語言模型的能力,即使LLM沒有對內(nèi)部文檔進行訓練也能得到很好的結(jié)果。RAG涉及從矢量庫中檢索許多相關(guān)文檔塊,然后LLM將其用作生成的上下文。因此嵌入的質(zhì)量將在RAG性能中發(fā)揮重要作用。
在本文中,我們演示并可視化了幾個關(guān)鍵矢量化參數(shù)對LLM整體性能的影響。并使用renumics-spotlight,展示了如何表示整個FAISS向量空間,然后將嵌入可視化。Spotlight直觀的用戶界面可以幫助我們根據(jù)問題探索向量空間,從而更好地理解LLM的反應(yīng)。通過調(diào)整某些矢量化參數(shù),我們能夠影響其生成行為以提高精度。
新聞名稱:可視化FAISS矢量空間并調(diào)整RAG參數(shù)提高結(jié)果精度
網(wǎng)站URL:http://m.5511xx.com/article/dhihidp.html


咨詢
建站咨詢
