
如何快速實(shí)現(xiàn)REST API集成以優(yōu)化業(yè)務(wù)流程
?索引過程是為檢索過程準(zhǔn)備數(shù)據(jù)。你應(yīng)該收集你想讓你的LLM知道的一切,例如,產(chǎn)品文檔、產(chǎn)品政策、公司網(wǎng)站等,這取決于你想讓聊天機(jī)器人做什么。然后你會(huì)把它分解成更小的文本塊(這樣你就可以很容易地把這些塊放進(jìn)LLM的上下文大?。?。然后,你將通過嵌入模型將塊轉(zhuǎn)換為矢量表示(這樣以后你就可以很容易地找到類似的塊)。最后,你可以將所有這些文本嵌入對(duì)保存在索引或矢量數(shù)據(jù)庫(kù)中,以供檢索使用。
? ? ? ?檢索過程發(fā)生在用戶查詢LLM時(shí)。在用戶提出問題后,你可以保留該查詢,而不是直接將其發(fā)送到LLM。相反,你將使用索引中文本塊中的一些附加信息來豐富查詢。你將使用相同的嵌入模型對(duì)用戶的原始查詢進(jìn)行編碼,然后執(zhí)行相似性搜索,在數(shù)據(jù)庫(kù)中找到最相似(大多數(shù)時(shí)候也是最相關(guān))的文本塊。
然后,為了生成,需要將文本塊插入到包括用戶原始查詢的提示中,LLM將使用檢索到的文本塊中提供的信息生成答案。
Answer the following question based on the given information only. If the given information is not enough to answer the question, simply reply "I don't know".
Question: "<user's original query>"
Given information: "<the text chunk you retrieved from the database>"
RAG是業(yè)界公認(rèn)的流程,LlamaIndex[1]和LangChain[2]兩個(gè)流行的庫(kù)支持上述這些步驟用于RAG流程。RAG需要矢量數(shù)據(jù)庫(kù)來創(chuàng)建索引和檢索,如Pinecone[3]和Chroma[4]。
這個(gè)過程簡(jiǎn)單有效,但在現(xiàn)實(shí)世界中,經(jīng)常會(huì)面臨以下問題:
在下一節(jié)中,我們將介紹一些克服這些問題并提高RAG性能的技術(shù)。
? ? ? ?經(jīng)過近一年的LLM使用,我學(xué)到了許多提高RAG性能的技術(shù),并總結(jié)了一些使用RAG的經(jīng)驗(yàn)教訓(xùn)。在本節(jié)中,我將介紹許多在檢索前、檢索中和檢索后提高RAG性能的技術(shù)。
預(yù)檢索技術(shù)包括可以在索引步驟中或在搜索數(shù)據(jù)庫(kù)中的塊之前使用的技術(shù)。
? ? ? ?第一種技術(shù)是提高索引數(shù)據(jù)的質(zhì)量。在機(jī)器學(xué)習(xí)領(lǐng)域,有一句話叫“垃圾進(jìn),垃圾出”,我認(rèn)為這也適用于RAG,但許多人只是忽略了這一步驟,并在這一非常關(guān)鍵的初始步驟之后專注于優(yōu)化步驟。您不應(yīng)該期望將每一個(gè)文檔(無論是否相關(guān))都放入您的矢量數(shù)據(jù)庫(kù),并抱著最好的希望。為了提高索引數(shù)據(jù)的質(zhì)量,您應(yīng)該:(1)刪除與特定任務(wù)無關(guān)的文本/文檔(2)將索引數(shù)據(jù)重新格式化為與最終用戶可能使用的格式類似的格式(3)向文檔中添加元數(shù)據(jù),以實(shí)現(xiàn)高效和有針對(duì)性的檢索。
這是我自己的一個(gè)例子。我需要檢索的文本是數(shù)學(xué)問題,但關(guān)于不同概念的兩個(gè)數(shù)學(xué)問題在語義上可能相似。例如,許多問題可能使用“湯姆第一天吃了8個(gè)蘋果……”,但它們可能測(cè)試加法、乘法和除法,這是非常不同的。在這種情況下,最好使用概念和級(jí)別的元數(shù)據(jù)對(duì)它們進(jìn)行標(biāo)記,并在檢索它們之前檢查正確的概念。
另一個(gè)非常典型的情況是,塊在拆分時(shí)可能會(huì)丟失信息??紤]一篇典型的文章,開頭的句子通過名字介紹實(shí)體,而后面的句子只依靠代詞來指代它們。不包含實(shí)際實(shí)體名稱的分割塊將失去語義,無法通過向量搜索進(jìn)行檢索。因此,在這種情況下,用實(shí)際名稱替換代詞可以提高分割塊的語義意義。
? ? ? ?第二種技術(shù)是分塊優(yōu)化。根據(jù)你的下游任務(wù)是什么,你需要確定塊的最佳長(zhǎng)度是多少,以及你希望每個(gè)塊有多少重疊。如果你的塊太小,它可能不包括LLM回答用戶查詢所需的所有信息;如果塊太大,它可能包含太多不相關(guān)的信息,從而混淆LLM,或者可能太大而無法適應(yīng)上下文大小。
根據(jù)我自己的經(jīng)驗(yàn),對(duì)于管道中的所有步驟,您不必拘泥于一種塊優(yōu)化方法。例如,如果您的管道同時(shí)涉及高級(jí)任務(wù)(如摘要)和低級(jí)任務(wù)(如基于函數(shù)定義的編碼),則可以嘗試使用較大的塊大小進(jìn)行摘要,然而使用較小的塊大小作為編碼參考。
? ? ? ?還有另一種技術(shù)是在嘗試在矢量數(shù)據(jù)庫(kù)中匹配用戶的查詢之前重寫該查詢。此步驟的本質(zhì)是將用戶的查詢轉(zhuǎn)換為與矢量數(shù)據(jù)庫(kù)中的查詢格式和內(nèi)容類似的格式和內(nèi)容。Query2Doc技術(shù)生成偽文檔,并用這些文檔擴(kuò)展查詢[5]。類似地,HyDE(假設(shè)文檔嵌入)生成與查詢相關(guān)的假設(shè)文檔[6]。
?以下是一些如何生成假設(shè)文檔的示例:
# if your reference documents are blog articles.
prompt = f"Please generate a paragraph from a blog article on {user_query}"
# if your reference documents are code documentations in markdown.
prompt = f"Please generate a code documentation for {user_query} in markdown format."
使用Query2Doc或HyDE技術(shù)時(shí)的一個(gè)陷阱是,假設(shè)文檔可能與實(shí)際文檔相矛盾或完全不一致,這可能導(dǎo)致不準(zhǔn)確的檢索。為了解決這個(gè)問題,您可以檢索包含和不包含假設(shè)文檔的文檔,這樣您就可以應(yīng)用我稍后將介紹的后期檢索技術(shù)來找到最佳參考文本。
? ? ? ?當(dāng)用戶的查詢很復(fù)雜,可能需要多個(gè)參考文本時(shí),可以使用LLM將其分解為多個(gè)子查詢,然后為每個(gè)查詢找到相關(guān)的文本塊。例如,如果用戶問兩個(gè)不同的問題“ChomaDB和Weaviate之間的區(qū)別是什么?”,可以分為“什么是ChromaDB?”和“什么是Weaviate?”。
? ? ? ? 下面是一個(gè)要求LLM分解查詢的示例:
Please rephrase the following query into three or fewer subqueries, so that each sub-query contains only one topic. Show each sub-query in each new line.
Query:"<original user query>"
?如果您的聊天機(jī)器人或代理可以處理多個(gè)下游任務(wù)和不同格式的用戶查詢,您可以考慮使用查詢路由,在該路由中,您可以將查詢動(dòng)態(tài)路由到不同的RAG進(jìn)程。例如,如果你的用戶正在詢問一個(gè)問題的特定答案,你可以將他們路由到查詢特定的塊;如果你的用戶要求一個(gè)整體的摘要,你可以將他們路由到一個(gè)遞歸創(chuàng)建的許多檢索到的文檔的摘要;如果您的用戶要求在兩個(gè)文檔之間進(jìn)行比較,您可能需要使用上面提到的子查詢技術(shù)。您可以使用LLM本身進(jìn)行路由,也可以使用關(guān)鍵字匹配/嵌入相似性進(jìn)行路由。
? ? ? ?準(zhǔn)備好查詢后,可以在RAG管道的第二步中進(jìn)一步改進(jìn)檢索結(jié)果。
第一種技術(shù)經(jīng)常被忽視,因?yàn)槿藗冎皇歉鴦e人做——一直堅(jiān)持向量相似性搜索。但是,您可以也應(yīng)該考慮使用其他搜索方法來取代向量相似性搜索,或者通過混合搜索來補(bǔ)充它。盡管矢量相似性搜索在大多數(shù)情況下可以找到相關(guān)文檔,但對(duì)于某些情況或數(shù)據(jù)結(jié)構(gòu),最好使用全文搜索、結(jié)構(gòu)化查詢、基于圖的搜索或混合搜索方法。
例如,如果您的文本數(shù)據(jù)包含許多語義非常相似的塊,但僅在某些關(guān)鍵字上有所不同,或者如果您的文字?jǐn)?shù)據(jù)包含太多通用文字,則最好使用精確的關(guān)鍵字匹配進(jìn)行搜索。例如,在電子商務(wù)中搜索僅按功能組不同的特定藥物名稱或數(shù)以萬計(jì)的類似產(chǎn)品名稱,可能會(huì)受益于全文匹配和過濾器。
另一個(gè)經(jīng)常被忽視的技術(shù)是針對(duì)特定任務(wù)測(cè)試和使用不同的嵌入。許多人甚至不會(huì)考慮這一點(diǎn),因?yàn)榭蚣?向量數(shù)據(jù)庫(kù)有一個(gè)默認(rèn)的嵌入選項(xiàng),他們只是隨波逐流。但不同的嵌入模型實(shí)際上可以捕獲不同的語義信息,并可能適用于不同的任務(wù)。一個(gè)有用的嵌入模型是指導(dǎo)嵌入,它允許您提供關(guān)于嵌入的數(shù)據(jù)類型和任務(wù)的具體說明[7][8]。您也可以參考MTEB排行榜,它是文本嵌入模型的基準(zhǔn)。一定要測(cè)試這些模型,因?yàn)樵谂判邪裆吓琶壳安⒉灰馕吨钸m合你的特定任務(wù)[9]。
除此之外,您還可以在檢索過程中進(jìn)行一些調(diào)整,使檢索更具相關(guān)性。Small2big、遞歸或上下文感知檢索是一種最初檢索較小的數(shù)據(jù)塊,由于更具體和更詳細(xì),這些數(shù)據(jù)塊更有可能與查詢匹配,然后繼續(xù)檢索父文檔或圍繞這些較小數(shù)據(jù)塊的較大文本塊,以包括更多上下文的技術(shù)。它們確保您檢索相關(guān)的塊以及所有重要的上下文。一些框架提供了對(duì)這種檢索的支持,如LangChain[2]中的ParentDocumentRetriever、句子窗口和LlamaIndex[1]中的節(jié)點(diǎn)引用。
如果您可以從小到大地檢索文檔,那么您也可以用另一種方式來檢索,分層檢索從更通用到更具體。例如,您可以創(chuàng)建兩層數(shù)據(jù),一層包含原始?jí)K,另一層包含塊的摘要。您首先在摘要索引中搜索最相關(guān)的文檔,然后在這些文檔中再次搜索特定的塊。這樣,你可以在第一關(guān)快速過濾掉不相關(guān)的文檔,然后在第二關(guān)找到實(shí)際的信息進(jìn)行問答。
? ? ? ?類似地,您可以將遞歸搜索與圖形搜索結(jié)合使用。該方法將相似性搜索與圖形數(shù)據(jù)結(jié)構(gòu)相結(jié)合。您首先通過向量相似性搜索找到最相關(guān)的塊,然后探索與這些塊相關(guān)的節(jié)點(diǎn),以探索更多潛在的有用信息。例如,如果您有一個(gè)包含Notion或Obsidian等互連文檔的數(shù)據(jù)庫(kù),則可以通過鏈接輕松找到LLM的相關(guān)文檔。LlamaIndex通過RecursiveRetriever模塊支持類似的搜索。
還有更多的代理方式來執(zhí)行檢索,方法是首先使用查詢文檔的工具/功能創(chuàng)建檢索器代理,并讓它決定是搜索更多信息還是僅將相關(guān)的檢索塊返回給原始代理以回答用戶的查詢。但這些技術(shù)通常需要更長(zhǎng)的響應(yīng)時(shí)間,而且可能不穩(wěn)定,因此可能不是很好的生產(chǎn)選擇。希望通過更強(qiáng)大的模型和更快的推理,我們可以在這個(gè)方向上獲得更好的結(jié)果。
在從數(shù)據(jù)庫(kù)中檢索到相關(guān)的塊之后,仍然有更多的技術(shù)可以提高生成質(zhì)量。根據(jù)任務(wù)的性質(zhì)和文本塊的格式,您可以使用以下一種或多種技術(shù)。
? ? ? ?如果你的任務(wù)與一個(gè)特定的塊更相關(guān),一種常用的技術(shù)是重新排序或評(píng)分。正如我前面提到的,向量相似性搜索中的高分并不意味著它總是具有最高的相關(guān)性。你應(yīng)該進(jìn)行第二輪重新排序或評(píng)分,找出對(duì)生成答案真正有用的文本塊。對(duì)于重新排序或評(píng)分,您可以要求LLM對(duì)文檔的相關(guān)性進(jìn)行排序,也可以使用一些其他方法,如關(guān)鍵字頻率或元數(shù)據(jù)匹配,在將這些文檔傳遞給LLM以生成最終答案之前,對(duì)選擇進(jìn)行細(xì)化。
? ? ? ?另一方面,如果你的任務(wù)與多個(gè)塊有關(guān)——比如摘要或比較。您可以在將信息傳遞給LLM之前進(jìn)行一些信息壓縮作為后處理,以減少噪聲或上下文長(zhǎng)度。例如,您可以首先從每個(gè)塊中總結(jié)、轉(zhuǎn)述或提取關(guān)鍵點(diǎn),然后將聚合的、濃縮的信息傳遞給LLM進(jìn)行生成。
? ? ? ?我發(fā)現(xiàn)還有一些其他技巧可以幫助改進(jìn)和平衡生成質(zhì)量和延遲。在實(shí)際生產(chǎn)中,您的用戶可能沒有時(shí)間等待多步驟RAG過程完成,尤其是當(dāng)存在LLM調(diào)用鏈時(shí)。如果您想提高RAG管道的延遲,以下選擇可能會(huì)有所幫助。
? ? ? ?第一種是在某些步驟中使用更小、更快的模型。對(duì)于RAG過程中的所有步驟,您不一定需要使用最強(qiáng)大的模型(通常是最慢的)。例如,對(duì)于一些簡(jiǎn)單的查詢重寫、假設(shè)文檔的生成或文本塊的匯總,您可能可以使用更快的模型(如7B或13B本地模型)。這些模型中的一些甚至能夠?yàn)橛脩羯筛哔|(zhì)量的最終輸出。
? ? ? 如果你感興趣,你可以閱讀更多關(guān)于如何運(yùn)行本地模型的信息[11],并在這個(gè)GitHub Repo[12]中查看我對(duì)一些小型LLM的評(píng)級(jí)。
? ? ? ?下一個(gè)技術(shù)是使一些中間步驟并行運(yùn)行。你不必總是等到一步完成后再進(jìn)入第二步。您可以進(jìn)行一些中間步驟,如并行混合搜索或多個(gè)塊并行的摘要。要做到這一點(diǎn),您可能需要大量修改RAG框架或自己創(chuàng)建RAG管道,但這可以大大減少最終輸出的時(shí)間。
? ? ??第三種技術(shù)是如果可能的話,讓LLM做出多項(xiàng)選擇,而不是生成長(zhǎng)文本。例如,在重新排序/評(píng)分時(shí),您可以要求LLM僅列出文本塊的分?jǐn)?shù)/排名,而不是將其生成或包括詳細(xì)解釋。
? ? ? ?另一個(gè)有用的提示是為常見問題或常見查詢實(shí)現(xiàn)緩存。如果新查詢與舊查詢非常相似或幾乎相同,則系統(tǒng)可以提供即時(shí)答案,而無需每次都經(jīng)過整個(gè)RAG過程。如果新查詢有點(diǎn)相似,但仍然相關(guān),您甚至可以將上一個(gè)查詢的答案包含到LLM中,作為生成新答案的參考。
? ? ? ?在本文中,我介紹了許多可以在LLM支持的應(yīng)用程序中改進(jìn)RAG管道的技術(shù),包括:
-RAG的基本過程:索引、檢索和生成
-預(yù)檢索技術(shù):
-檢索技術(shù)
-后期檢索技術(shù)
-平衡質(zhì)量和延遲
? ? ? 您可以在RAG管道中使用其中一種或多種技術(shù),使其更加準(zhǔn)確和高效。我希望這些技術(shù)可以幫助你為你的應(yīng)用程序構(gòu)建一個(gè)更好的RAG管道。
[1] http://www.llamaindex.ai/
[2] http://www.langchain.com/
[3] http://www.pinecone.io/
[4] http://www.trychroma.com/
[5] https://browse.arxiv.org/abs/2303.07678
[6] https://browse.arxiv.org/abs/2212.10496
[7] https://browse.arxiv.org/abs/2212.09741
[8] https://github.com/xlang-ai/instructor-embedding
[9] https://huggingface.co/spaces/mteb/leaderboard
[10] https://doi.org/10.48550/arXiv.2312.10997
[11] https://medium.com/design-bootcamp/a-complete-guide-to-running-local-llm-models-3225e4913620
[12] https://github.com/Troyanovsky/Local-LLM-Comparison-Colab-UI
[13]?https://bootcamp.uxdesign.cc/how-to-improve-rag-results-in-your-llm-apps-from-basics-to-advanced-822818014144
本文章轉(zhuǎn)載微信公眾號(hào)@ArronAI
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)