引言
檢索增強(qiáng)生成(Retrieval Augmented Generation,簡稱RAG)為大型語言模型(LLMs)提供了從某些數(shù)據(jù)源檢索到的信息,以此作為生成答案的基礎(chǔ)。簡而言之,RAG是搜索+LLM提示的結(jié)合,即在有搜索算法找到的信息作為上下文的情況下,讓模型回答提出的查詢。查詢和檢索到的上下文都被注入到發(fā)送給LLM的提示中。
目前,RAG是基于LLM系統(tǒng)中最受歡迎的架構(gòu)。許多產(chǎn)品幾乎完全基于RAG構(gòu)建,包括將網(wǎng)絡(luò)搜索引擎與LLMs相結(jié)合的問答服務(wù),以及數(shù)百種與數(shù)據(jù)聊天的應(yīng)用程序。
即使是向量搜索領(lǐng)域也因這種熱潮而興起,盡管基于嵌入的搜索引擎自2019年就已使用faiss開發(fā)。像chroma、weavaite.io和pinecone這樣的向量數(shù)據(jù)庫初創(chuàng)公司建立在現(xiàn)有的開源搜索索引之上--主要是faiss和nmslib,并且最近增加了對(duì)輸入文本的額外存儲(chǔ)和一些其他工具。
有兩個(gè)最突出的開源庫用于基于LLM的管道和應(yīng)用程序——LangChain和LlamaIndex,它們分別于2022年10月和11月成立,并在2023年獲得了大量的應(yīng)用。
本文的目的是系統(tǒng)化地介紹高級(jí)RAG技術(shù)的關(guān)鍵點(diǎn),并參考它們?cè)贚lamaIndex中的實(shí)現(xiàn)——以便幫助其他開發(fā)者深入了解這項(xiàng)技術(shù)。
如果您已經(jīng)熟悉RAG概念,請(qǐng)直接跳到高級(jí)RAG部分。
基礎(chǔ)的RAG技術(shù)
本文中,我們用一組文本文檔的語料庫來代表RAG的起點(diǎn)——我們跳過了在此之前的步驟,留給那些開源數(shù)據(jù)加載器去處理,這些加載器可以連接到任何可想象的來源,從YouTube到Notion。
簡單RAG案例大致如下:
將文本分割成塊,然后使用基于Transformer decoder的模型將這些塊嵌入到向量中,將所有這些向量放入一個(gè)索引中,最后為LLM創(chuàng)建一個(gè)提示,告訴模型在我們?cè)谒阉鞑襟E中找到的上下文中回答用戶的查詢。
在運(yùn)行時(shí),我們使用相同的編碼器模型將用戶的查詢向量化,然后對(duì)索引執(zhí)行這個(gè)查詢向量的搜索,找到前k個(gè)結(jié)果,從我們的數(shù)據(jù)庫中檢索相應(yīng)的文本塊,并將它們作為上下文輸入到LLM的提示中。
提示可能看起來是這樣的:
defquestion_answering(context,query): prompt=f""" Givetheanswertotheuserquerydelimitedbytriplebackticks```{query}``` usingtheinformationgivenincontextdelimitedbytriplebackticks```{context}```. Ifthereisnorelevantinformationintheprovidedcontext,trytoansweryourself, buttelluserthatyoudidnothaveanyrelevantcontexttobaseyouransweron. Beconciseandoutputtheanswerofsizelessthan80tokens. """ response=get_completion(instruction,prompt,model="gpt-3.5-turbo") answer=response.choices[0].message["content"] returnanswer
提示工程是提升RAG管道性能最經(jīng)濟(jì)的嘗試之一。確保您已經(jīng)查看了OpenAI提供的提示工程指南[2]。
盡管OpenAI作為LLM領(lǐng)域領(lǐng)導(dǎo)公司,但還有一些替代品,如Anthropic的Claude,最近流行的小型但非常強(qiáng)大的模型,如Mistral的Mixtral,Microsoft的Phi-2,以及許多開源選項(xiàng),如Llama2、OpenLLaMA、Falcon等,所以您可以為您的RAG管道選擇一個(gè)“大腦”。
高級(jí)RAG技術(shù)
現(xiàn)在我們將深入了解高級(jí)RAG技術(shù)的概述。下面是一個(gè)展示核心步驟的示意圖。為了保持圖表的可讀性,省略了一些邏輯循環(huán)和復(fù)雜的多步驟代理行為。
圖中的綠色元素是接下來討論的核心RAG技術(shù),藍(lán)色元素代表文本。并非所有高級(jí)RAG理念都能輕易在單一圖表上可視化,例如,省略了各種擴(kuò)大上下文的方法——我們將在后面深入探討這些。
切分和向量化
首先,我們想創(chuàng)建一個(gè)向量索引,代表我們文檔的內(nèi)容,然后在運(yùn)行時(shí)搜索這些向量與查詢向量之間最小的余弦距離,對(duì)應(yīng)于最接近的語義含義。
切分:Transformer模型有固定的輸入序列長度,即使輸入上下文窗口很大,一個(gè)句子或幾個(gè)句子的向量也比幾頁文本的平均向量更好地代表它們的語義含義(也取決于模型,但通常如此),所以要切分你的數(shù)據(jù)——將初始文檔切分為某個(gè)大小的塊,不會(huì)丟失它們的含義(將文本切分為句子或段落,而不是將單個(gè)句子切成兩部分)。有各種文本分割器實(shí)現(xiàn)能夠完成這項(xiàng)任務(wù)。
塊的大小是一個(gè)需要考慮的參數(shù)——它取決于你使用的嵌入模型及其在令牌上的容量,標(biāo)準(zhǔn)的Transformer編碼器模型如基于BERT的句子轉(zhuǎn)換器最多接受512個(gè)令牌,OpenAI ada-002能夠處理更長的序列,如8191個(gè)令牌,但這里的折中是為LLM提供足夠的上下文進(jìn)行推理與執(zhí)行搜索的足夠具體的文本嵌入。最近的一項(xiàng)研究[3]說明了塊大小選擇的考慮因素。在LlamaIndex中,這是通過NodeParser類來覆蓋的,它提供了一些高級(jí)選項(xiàng),如定義自己的文本分割器、元數(shù)據(jù)、節(jié)點(diǎn)/塊關(guān)系等。
向量化:下一步是選擇一個(gè)模型來嵌入切割后的塊——有很多選擇,例如像bge-large或E5嵌入系列這樣的搜索優(yōu)化模型——只需查看MTEB排行榜上[4]的最新更新。
要了解切分和向量化步驟的端到端實(shí)現(xiàn),請(qǐng)查看LlamaIndex中的一個(gè)完整的示例。
搜索索引
向量存儲(chǔ)索引:RAG管道的關(guān)鍵部分是搜索索引,它存儲(chǔ)了我們?cè)谏弦徊街蝎@得的向量化內(nèi)容。最簡單的實(shí)現(xiàn)使用平面索引——在查詢向量和所有塊向量之間進(jìn)行暴力距離計(jì)算。
一個(gè)為10000+元素規(guī)模上的高效檢索優(yōu)化的索引是一個(gè)向量索引,如faiss、nmslib或annoy,使用某種近似最近鄰實(shí)現(xiàn),如聚類、樹或HNSW算法。
還有一些托管解決方案,如OpenSearch或ElasticSearch,以及向量數(shù)據(jù)庫,它們?cè)诤笈_(tái)處理第1步中描述的數(shù)據(jù)攝取管道,如Pinecone、Weaviate或Chroma。根據(jù)選擇的索引、數(shù)據(jù)和搜索需求,可以將元數(shù)據(jù)與向量一起存儲(chǔ),然后使用元數(shù)據(jù)過濾器來搜索某些日期或來源內(nèi)的信息。
LlamaIndex支持許多向量存儲(chǔ)索引,但還支持其他更簡單的索引實(shí)現(xiàn),如列表索引、樹索引和關(guān)鍵詞表索引——我們將在融合檢索部分討論后者。
分層索引: 如果您需要從許多文檔中檢索信息,您需要能夠有效地在其中搜索,找到相關(guān)信息,并將其綜合為帶有來源引用的單一答案。在大型數(shù)據(jù)庫中做到這一點(diǎn)的有效方法是創(chuàng)建兩個(gè)索引——一個(gè)由摘要組成,另一個(gè)由文檔塊組成,并分兩步進(jìn)行搜索,首先通過摘要篩選出相關(guān)文檔,然后僅在這個(gè)相關(guān)組內(nèi)搜索。
假設(shè)性問題和HyDE:另一種方法是讓LLM為每個(gè)塊生成一個(gè)問題,并將這些問題嵌入向量中,在運(yùn)行時(shí)針對(duì)這個(gè)問題向量索引進(jìn)行查詢搜索(在我們的索引中用問題向量替換塊向量),然后在檢索后路由到原始文本塊,并將它們作為上下文發(fā)送給LLM以獲得答案。這種方法通過查詢與假設(shè)性問題之間更高的語義相似性,提高了搜索質(zhì)量。
還有一種逆向邏輯方法稱為HyDE——讓LLM給定查詢生成一個(gè)假設(shè)性回應(yīng),然后使用其向量和查詢向量來提高搜索質(zhì)量。
上下文豐富化:上下文豐富化是檢索更小的塊以提高搜索質(zhì)量,但添加周圍上下文讓LLM進(jìn)行推理。通常有兩種做法——通過在檢索到的較小塊周圍的句子擴(kuò)展上下文,或者將文檔遞歸地分割成包含較小子塊的多個(gè)較大的父塊。
句子窗口檢索: 在這個(gè)方案中,文檔中的每個(gè)句子都分別嵌入,這提供了極高的查詢與上下文余弦距離搜索的準(zhǔn)確性。為了在找到最相關(guān)的單個(gè)句子后更好地推理所發(fā)現(xiàn)的上下文,我們通過在檢索到的句子前后擴(kuò)展k個(gè)句子的上下文窗口,然后將這個(gè)擴(kuò)展的上下文發(fā)送給LLM。
自動(dòng)合并檢索器(又稱父文檔檢索器):這里的想法與句子窗口檢索非常相似——搜索更精細(xì)的信息片段,然后在將這些上下文提供給LLM進(jìn)行推理之前擴(kuò)展上下文窗口。文檔被分割成較小的子塊,這些子塊引用較大的父塊。
在這種方法中,首先在更細(xì)粒度的子塊上進(jìn)行搜索,找到與查詢最相關(guān)的塊。然后,系統(tǒng)會(huì)自動(dòng)將這些子塊與它們所屬的更大的父塊結(jié)合起來。這樣做的目的是在回答查詢時(shí)為LLM提供更豐富的上下文。例如,如果一個(gè)子塊是一段或一小節(jié),父塊可能是整個(gè)章節(jié)或文檔的一大部分。這種方法既保留了檢索精度(因?yàn)槭窃诟〉膲K上搜索),同時(shí)也通過提供更廣泛的上下文來增強(qiáng)LLM的推理能力。
在檢索過程中首先獲取較小的塊,然后如果在檢索到的前k個(gè)塊中有超過n個(gè)塊與同一個(gè)父節(jié)點(diǎn)(較大的塊)相關(guān)聯(lián),我們就用這個(gè)父節(jié)點(diǎn)替換提供給LLM的上下文——這就像自動(dòng)將幾個(gè)檢索到的塊合并成一個(gè)較大的父塊,因此得名。需要注意的是——搜索僅在子節(jié)點(diǎn)索引中進(jìn)行。想要更深入地了解,請(qǐng)查看LlamaIndex關(guān)于遞歸檢索器+節(jié)點(diǎn)引用的教程[5]。
融合檢索或混合搜索:這是一個(gè)相對(duì)較老的想法,即從兩個(gè)世界中各取所長——基于關(guān)鍵字的傳統(tǒng)搜索(稀疏檢索算法,如tf-idf或搜索行業(yè)標(biāo)準(zhǔn)BM25)和現(xiàn)代語義或向量搜索,并將它們結(jié)合在一個(gè)檢索結(jié)果中。這里唯一的技巧是正確組合具有不同相似性得分的檢索結(jié)果——這個(gè)問題通常通過使用倒數(shù)排名融合算法來解決,重新排列檢索結(jié)果以獲得最終輸出。
在LangChain[6]中,這是通過Ensemble Retriever類實(shí)現(xiàn)的,它結(jié)合了你定義的一系列檢索器,例如faiss向量索引和基于BM25的檢索器,并使用RRF進(jìn)行重排。在LlamaIndex[7]中這種做法也非常類似。
混合或融合搜索通常會(huì)提供更好的檢索結(jié)果,因?yàn)樗Y(jié)合了兩種互補(bǔ)的搜索算法,同時(shí)考慮了查詢和存儲(chǔ)文檔之間的語義相似性和關(guān)鍵詞匹配。
重排和過濾
使用上述任何算法得到檢索結(jié)果后,現(xiàn)在是時(shí)候通過過濾、重排或一些轉(zhuǎn)換來精煉這些結(jié)果了。在LlamaIndex中,有多種可用的后處理器,可以根據(jù)相似性分?jǐn)?shù)、關(guān)鍵詞、元數(shù)據(jù)過濾結(jié)果,或者使用其他模型進(jìn)行重排,比如LLM、句子轉(zhuǎn)換器交叉編碼器、Cohere重排端點(diǎn),或者基于日期的最新性等元數(shù)據(jù)——基本上,你能想到的都可以。
重排和過濾是在將檢索到的上下文提供給LLM以獲取最終答案之前的最后一步。現(xiàn)在是時(shí)候進(jìn)入更復(fù)雜的RAG技術(shù),如查詢轉(zhuǎn)換和路由,這兩者都涉及到LLM,因此代表了主動(dòng)性行為——在我們的RAG流程中涉及到一些復(fù)雜的邏輯,包括LLM的推理。
查詢轉(zhuǎn)換
查詢轉(zhuǎn)換是一系列技術(shù),利用LLM作為推理引擎來修改用戶輸入,以提高檢索質(zhì)量。
有幾種不同的方式可以做到這一點(diǎn)。如果查詢很復(fù)雜,LLM可以將其分解成幾個(gè)子查詢。例如,如果你問:
“在Github上,Langchain和LlamaIndex哪個(gè)框架的星星更多?”由于我們不太可能在語料庫中找到直接的比較,所以將這個(gè)問題分解成兩個(gè)預(yù)設(shè)簡單和具體信息檢索的子查詢是有意義的:
“Langchain在Github上有多少星星?”
“LlamaIndex在Github上有多少星星?”這兩個(gè)查詢將并行執(zhí)行,然后將檢索到的上下文合并成一個(gè)提示,供LLM合成最初查詢的最終答案。Langchain和LlamaIndex都實(shí)現(xiàn)了這一功能——在Langchain中作為多查詢檢索器,在LlamaIndex中作為子問題查詢引擎。
回溯提示使用LLM生成更一般的查詢,我們?yōu)榇藱z索獲得更一般或高層次的上下文,有助于支撐我們對(duì)原始查詢的回答。也會(huì)對(duì)原始查詢進(jìn)行檢索,兩種上下文都在最終生成答案的步驟中輸入給LLM。這是LangChain的實(shí)現(xiàn)方法。
查詢重寫使用LLM重構(gòu)初始查詢以改善檢索。LangChain和LlamaIndex都有實(shí)現(xiàn),雖然有些不同,但我認(rèn)為在這里L(fēng)lamaIndex的解決方案更為強(qiáng)大。
此外, 還有一個(gè)概念是參考引用。這一部分不作為單獨(dú)的一章來介紹,因?yàn)樗袷且环N工具而不是檢索改進(jìn)技術(shù),盡管它非常重要。如果我們?yōu)榱嘶卮鹨粋€(gè)問題而使用了多個(gè)來源,可能是因?yàn)槌跏疾樵兊膹?fù)雜性(我們需要執(zhí)行多個(gè)子查詢,然后將檢索到的上下文合并成一個(gè)答案),或者是因?yàn)槲覀冊(cè)诓煌奈臋n中找到了與單個(gè)查詢相關(guān)的上下文,那么就會(huì)出現(xiàn)一個(gè)問題:我們能否準(zhǔn)確地回溯引用我們的來源。
有幾種方法可以做到這一點(diǎn):
將引用任務(wù)插入我們的提示中,并要求LLM提及使用的來源的ID。
將生成的響應(yīng)部分與我們索引中的原始文本塊匹配——llamaindex為這種情況提供了一個(gè)基于模糊匹配的高效解決方案。如果你還沒有聽說過模糊匹配,這是一種非常強(qiáng)大的字符串匹配技術(shù)。
聊天引擎
在構(gòu)建一個(gè)能夠針對(duì)單個(gè)查詢多次運(yùn)行的優(yōu)秀RAG系統(tǒng)中,下一個(gè)重要的環(huán)節(jié)是聊天邏輯,這與前LLM時(shí)代的經(jīng)典聊天機(jī)器人一樣,需要考慮對(duì)話上下文。這對(duì)于支持后續(xù)問題、指代消解或與先前對(duì)話上下文相關(guān)的任意用戶命令是必要的。這可以通過查詢壓縮技術(shù)來解決,同時(shí)考慮聊天上下文和用戶查詢。
如同往常,有幾種處理上述上下文壓縮的方法 —一種流行且相對(duì)簡單的方法是ContextChatEngine,它首先檢索與用戶查詢相關(guān)的上下文,然后將其連同聊天歷史記錄從內(nèi)存緩沖區(qū)發(fā)送給LLM,以便LLM在生成下一個(gè)回答時(shí)能夠了解之前的上下文。
更復(fù)雜的一個(gè)例子是CondensePlusContextMode — 在這種模式中,每次交互時(shí)都會(huì)將聊天歷史和最后一條消息壓縮成一個(gè)新的查詢,然后這個(gè)查詢會(huì)進(jìn)入索引,檢索到的上下文連同原始用戶消息一起傳遞給LLM,以生成答案。
值得注意的是,LlamaIndex還支持基于OpenAI代理的聊天引擎,提供更靈活的聊天模式,Langchain也支持OpenAI功能性API。還有其他類型的聊天引擎,如ReAct Agent,但我們?cè)诤竺嬖儆懻摯肀旧怼?/p>
查詢路由
查詢路由是一個(gè)以LLM為驅(qū)動(dòng)的決策步驟,決定針對(duì)用戶查詢接下來要做什么——通常的選項(xiàng)包括概括總結(jié)、針對(duì)某些數(shù)據(jù)索引執(zhí)行搜索,或嘗試多種不同的路徑,然后將它們的輸出合成一個(gè)答案。
查詢路由器還用于選擇索引,或更廣泛地說,數(shù)據(jù)存儲(chǔ)位置,以發(fā)送用戶查詢——無論你擁有多個(gè)數(shù)據(jù)來源,例如經(jīng)典的向量存儲(chǔ)、圖形數(shù)據(jù)庫或關(guān)系型數(shù)據(jù)庫,還是擁有一個(gè)索引層次結(jié)構(gòu)——對(duì)于多文檔存儲(chǔ),一個(gè)相當(dāng)?shù)湫偷那闆r可能是一個(gè)概要索引和另一個(gè)文檔塊向量的索引。
定義查詢路由器包括設(shè)置它可以做出的選擇。路由選項(xiàng)的選擇是通過LLM調(diào)用進(jìn)行的,返回預(yù)定義格式的結(jié)果,用于將查詢路由到給定的索引,或者,如果我們談?wù)撝鲃?dòng)性行為,路由到子鏈或甚至其他代理,如下面的多文檔代理方案所示。
LlamaIndex和LangChain都支持查詢路由器。
RAG中的代理
Langchain和LlamaIndex都支持的代理(Agents),自從第一個(gè)LLM API發(fā)布以來就已經(jīng)存在——這個(gè)想法是為一個(gè)能夠進(jìn)行推理的LLM提供一套工具和一個(gè)要完成的任務(wù)。這些工具可能包括一些確定性函數(shù),如任何代碼函數(shù)、外部API甚至其他代理——LLM鏈?zhǔn)秸{(diào)用的這個(gè)想法是LangChain名字的由來。
代理本身是一個(gè)巨大的領(lǐng)域,要在RAG概覽中深入探討是不可能的,所以我將繼續(xù)討論基于代理的多文檔檢索案例,并在OpenAI助手這個(gè)相對(duì)較新的領(lǐng)域短暫停留,因?yàn)樗亲罱麿penAI開發(fā)者大會(huì)上作為GPTs介紹的,并在下面描述的RAG系統(tǒng)的底層工作。
OpenAI助手基本上實(shí)現(xiàn)了圍繞LLM所需的許多工具,我們之前在開源中擁有這些工具——聊天歷史記錄、知識(shí)存儲(chǔ)、文檔上傳界面,以及或許最重要的,函數(shù)調(diào)用API。后者提供了將自然語言轉(zhuǎn)換為對(duì)外部工具或數(shù)據(jù)庫查詢的API調(diào)用的能力。
在LlamaIndex中,OpenAIAgent類將這種高級(jí)邏輯與ChatEngine和QueryEngine類結(jié)合起來,提供基于知識(shí)和上下文的聊天,以及在一次對(duì)話中調(diào)用多個(gè)OpenAI函數(shù)的能力,這確實(shí)帶來了智能的代理行為。
讓我們來看一下多文檔代理方案——一個(gè)相當(dāng)復(fù)雜的設(shè)置,涉及對(duì)每個(gè)文檔初始化一個(gè)代理(OpenAIAgent),能夠進(jìn)行文檔概要和經(jīng)典的問答機(jī)制,并有一個(gè)頂級(jí)代理,負(fù)責(zé)將查詢路由到文檔代理,并進(jìn)行最終答案的合成。
每個(gè)文檔代理都有兩個(gè)工具——一個(gè)向量存儲(chǔ)索引和一個(gè)概要索引,并根據(jù)路由查詢決定使用哪一個(gè)。而對(duì)于頂級(jí)代理來說,所有文檔代理都分別是工具。
這個(gè)方案展示了一個(gè)高級(jí)的RAG架構(gòu),其中每個(gè)參與的代理都做出了許多路由決策。這種方法的好處是能夠比較不同的解決方案或?qū)嶓w,這些解決方案或?qū)嶓w描述在不同的文檔及其概要中,同時(shí)包括經(jīng)典的單文檔概要和問答機(jī)制——這基本上涵蓋了最常見的與文檔集合聊天的用例。這種復(fù)雜方案的缺點(diǎn)可以從圖中猜測——由于涉及代理中LLM的多次來回迭代,它有些慢。順便說一下,LLM調(diào)用總是RAG流程中最長的操作——搜索本身就是為速度優(yōu)化的設(shè)計(jì)。所以對(duì)于大型多文檔存儲(chǔ),我建議考慮對(duì)這個(gè)方案進(jìn)行一些簡化,使其可擴(kuò)展。
響應(yīng)合成器
這是任何RAG流程的最后一步——基于我們仔細(xì)檢索的所有上下文和初始用戶查詢生成答案。最簡單的方法可能是將所有獲取到的上下文(超過某個(gè)相關(guān)性閾值的)連同查詢一起一次性輸入給LLM。但是,像往常一樣,還有其他更復(fù)雜的選項(xiàng),涉及多次LLM調(diào)用以優(yōu)化檢索到的上下文并生成更好的答案。
響應(yīng)合成的主要方法包括:
通過逐塊將檢索到的上下文發(fā)送給LLM來迭代地完善答案。
概括檢索到的上下文以適應(yīng)提示。
基于不同的上下文塊生成多個(gè)答案,然后將它們連接或概括起來。有關(guān)更多細(xì)節(jié),請(qǐng)查閱響應(yīng)合成器模塊文檔[8]。
編碼器和LLM微調(diào)
這種方法涉及對(duì)RAG流程中的兩個(gè)深度學(xué)習(xí)模型之一進(jìn)行微調(diào)——要么是負(fù)責(zé)嵌入質(zhì)量和上下文檢索質(zhì)量的Transformer編碼器,要么是負(fù)責(zé)最佳利用提供的上下文來回答用戶查詢的LLM,幸運(yùn)的是,后者是一個(gè)很好的少量樣本學(xué)習(xí)器。
如今一個(gè)很大的優(yōu)勢是能夠使用像GPT-4這樣的高端LLM來生成高質(zhì)量的合成數(shù)據(jù)集。但使用由專業(yè)研究團(tuán)隊(duì)在精心收集、清洗和驗(yàn)證的大型數(shù)據(jù)集上訓(xùn)練的開源模型,并使用小型合成數(shù)據(jù)集進(jìn)行快速調(diào)整,可能會(huì)降低模型的整體能力。
編碼器微調(diào):我對(duì)編碼器微調(diào)方法也有些懷疑,因?yàn)樽钚碌臑樗阉鲀?yōu)化的Transformer編碼器相當(dāng)高效。所以我在LlamaIndex筆記本設(shè)置中測試了對(duì)bge-large-en-v1.5(在撰寫本文時(shí)為MTEB排行榜前4)進(jìn)行微調(diào)的性能提升,結(jié)果顯示檢索質(zhì)量提高了2%。雖然不是很驚人,但了解這個(gè)選項(xiàng)還是不錯(cuò)的,尤其是如果你有一個(gè)你正在為之構(gòu)建RAG的狹窄領(lǐng)域數(shù)據(jù)集。
排名器微調(diào):另一個(gè)老方法是,如果你不完全信任你的基礎(chǔ)編碼器,就使用交叉編碼器對(duì)檢索結(jié)果進(jìn)行重排。其工作方式如下——你將查詢和前k個(gè)檢索到的文本塊傳遞給交叉編碼器,以SEP令牌分隔,并對(duì)其進(jìn)行微調(diào),以輸出1表示相關(guān)塊,0表示不相關(guān)。這里有一個(gè)這種調(diào)整過程的例子[9],結(jié)果顯示交叉編碼器微調(diào)提高了4%的成對(duì)分?jǐn)?shù)。
LLM微調(diào):最近OpenAI開始提供LLM微調(diào)API,LlamaIndex有關(guān)于在RAG設(shè)置中微調(diào)GPT-3.5-turbo的教程[10],以“提煉”一些GPT-4的知識(shí)。這里的想法是拿一個(gè)文檔,用GPT-3.5-turbo生成一些問題,然后使用GPT-4根據(jù)文檔內(nèi)容生成這些問題的答案(構(gòu)建一個(gè)由GPT4驅(qū)動(dòng)的RAG流程),然后對(duì)GPT-3.5-turbo進(jìn)行微調(diào),使其在問題-答案對(duì)的數(shù)據(jù)集上進(jìn)行訓(xùn)練。用于RAG流程評(píng)估的ragas框架顯示,忠實(shí)度指標(biāo)提高了5%,意味著微調(diào)后的GPT 3.5-turbo模型比原始模型更好地利用了提供的上下文來生成其答案。
一種更復(fù)雜的方法在最近的RA-DIT論文[11]中展示:由Meta AI研究提出的檢索增強(qiáng)雙指導(dǎo)調(diào)整技術(shù),建議對(duì)LLM和檢索器(原論文中的雙編碼器)進(jìn)行調(diào)整,針對(duì)查詢、上下文和答案的三元組。有關(guān)實(shí)現(xiàn)細(xì)節(jié),請(qǐng)參考這個(gè)指南[12]。這種技術(shù)用于通過微調(diào)API對(duì)OpenAI LLM進(jìn)行微調(diào),以及對(duì)Llama2開源模型進(jìn)行微調(diào)(在原論文中),結(jié)果顯示在知識(shí)密集型任務(wù)指標(biāo)上提高了約5%(與Llama2 65B with RAG相比),以及在常識(shí)推理任務(wù)上提高了幾個(gè)百分點(diǎn)。
評(píng)估
RAG系統(tǒng)性能評(píng)估有幾個(gè)框架,它們共享一個(gè)理念,即擁有幾個(gè)獨(dú)立的指標(biāo),如整體答案相關(guān)性、答案的根據(jù)性、忠實(shí)度和檢索到的上下文相關(guān)性。
前一節(jié)提到的Ragas使用忠實(shí)度和答案相關(guān)性作為生成答案質(zhì)量的指標(biāo),以及經(jīng)典的上下文精確度和召回率用于RAG方案的檢索部分。
在Andrew NG最近發(fā)布的精彩短課程《構(gòu)建和評(píng)估高級(jí)RAG》中,LlamaIndex和評(píng)估框架Truelens建議使用RAG三元組——檢索到的上下文與查詢的相關(guān)性、根據(jù)性(LLM答案受提供的上下文支持的程度)以及答案與查詢的相關(guān)性。
最關(guān)鍵且最可控的指標(biāo)是檢索到的上下文相關(guān)性——基本上上面描述的高級(jí)RAG流程的第1-7部分以及編碼器和排名器微調(diào)部分旨在改善這一指標(biāo),而第8部分和LLM微調(diào)則專注于答案相關(guān)性和根據(jù)性。
一個(gè)相當(dāng)簡單的檢索器評(píng)估流程的例子可以在這里[13]找到,并且已應(yīng)用于編碼器微調(diào)部分。一種更高級(jí)的方法不僅考慮命中率,還考慮了平均倒數(shù)排名(一個(gè)常見的搜索引擎指標(biāo))以及生成答案的指標(biāo),如忠實(shí)度和相關(guān)性,這在OpenAI cookbook[14]中有所展示。
LangChain有一個(gè)相當(dāng)先進(jìn)的評(píng)估框架LangSmith[15],可以實(shí)現(xiàn)自定義評(píng)估器,它還監(jiān)控RAG流程中的運(yùn)行軌跡,以使你的系統(tǒng)更透明。
如果你在使用LlamaIndex構(gòu)建,那么有一個(gè)rag_evaluator llama包[16],提供了一個(gè)快速工具,用公共數(shù)據(jù)集評(píng)估你的流程。
結(jié)論
我試圖概述RAG的核心算法方法,并且用一些示例來說明它們,希望這能激發(fā)一些在你的RAG流程中嘗試的新想法,或者為今年發(fā)明的眾多技術(shù)帶來一些系統(tǒng)化——對(duì)我來說,2023年到目前為止是ML領(lǐng)域最激動(dòng)人心的一年。
還有許多其他需要考慮的事情,如基于網(wǎng)絡(luò)搜索的RAG(LlamaIndex的RAGs、webLangChain等),更深入地探討主動(dòng)架構(gòu)(以及最近OpenAI在這個(gè)游戲中的份額)以及一些關(guān)于LLM長期記憶的想法。
RAG系統(tǒng)的主要生產(chǎn)挑戰(zhàn)除了答案相關(guān)性和忠實(shí)度之外,還有速度,尤其是如果你傾向于更靈活的基于代理的方案。ChatGPT和大多數(shù)其他助手使用的這種流媒體功能不是隨機(jī)的賽博朋克風(fēng)格,而只是一種縮短感知答案生成時(shí)間的方式。這就是為什么我看到小型LLM和最近的Mixtral和Phi-2發(fā)布在這個(gè)方向上有一個(gè)非常光明的未來。
審核編輯:黃飛
-
編碼器
+關(guān)注
關(guān)注
45文章
3652瀏覽量
134847 -
大模型
+關(guān)注
關(guān)注
2文章
2499瀏覽量
2909 -
LLM
+關(guān)注
關(guān)注
0文章
295瀏覽量
356
原文標(biāo)題:精彩手繪全解:RAG技術(shù),從入門到精通
文章出處:【微信號(hào):zenRRan,微信公眾號(hào):深度學(xué)習(xí)自然語言處理】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論