RAG 開發的痛點及解決方案
受 Barnett 等人撰寫的論文《 設計 RAG 系統時的七個失敗點 》的啓發,在本文中探討論文中提到的七個失敗點以及開發 RAG 流水線過程中的另外五個常見痛點。更重要的是,我們將深入探討這些 RAG 痛點的解決方案,以便在日常 RAG 開發中更好地解決這些痛點。
本文使用 "痛點" 而不是 "失敗點" ,主要是因爲這些痛點都有相應的解決方案。讓我們在它們成爲我們 RAG 流水線中的失敗點之前,設法解決它們。
首先,讓我們檢查上述論文中提到的七個痛點;見下圖。然後,我們將添加另外五個痛點及建議的解決方案。
痛點 1 :內容缺失
知識庫中缺少上下文。當實際答案不在知識庫中時, RAG 系統會提供一個似是而非的錯誤答案,而不是說它不知道。用戶會收到誤導性信息,從而產生挫敗感。有兩個解決方案:
清理數據
垃圾進,垃圾出。如果你的源數據質量很差,例如包含相互矛盾的信息,那麼無論你建立了多麼完善的 RAG 流水線,它也無法從你輸入的垃圾中神奇地輸出黃金。本文提出的解決方案不僅可以解決這一痛點,還可以解決本文列出的所有痛點。乾淨的數據是任何運行良好的 RAG 流水線的先決條件。
有一些常見的數據清理策略,僅舉幾例:
-
去除噪音和無關信息:這包括刪除特殊字符、停止詞( "the" 和 "a" 等常用詞 )和 HTML 標記。
-
識別並糾正錯誤:這包括拼寫錯誤、錯別字和語法錯誤。拼寫檢查程序和語言模型等工具都能在這方面提供幫助。
-
重複數據刪除:刪除可能影響檢索過程的重複記錄或類似記錄。
Unstructured.io 在其核心庫中提供了一系列清理功能,可幫助滿足此類數據清理需求。值得一試。
更好的提示詞
由於知識庫中缺乏信息,系統可能會提供一個似是而非但不正確的答案,在這種情況下,更好的提示詞功能可以提供很大幫助。通過 "如果你不確定答案,請告訴我你不知道" 等提示來指導系統,可以鼓勵模型承認其侷限性,並更透明地傳達不確定性。雖然不能保證百分之百的準確性,但在清理數據之後,精心設計提示語是最好的方法之一。
痛點 2 :錯過排名靠前的文檔
在初始檢索過程中丟失內容。重要文檔可能不會出現在系統檢索組件返回的最前結果中。正確答案被忽略,導致系統無法提供準確的回覆。Barnett 的論文暗示: “問題的答案就在文檔中,但排名不夠靠前,無法返回給用戶” 。有兩個建議的解決方案:
chunk_size 和 similarity_top_k 超參微調
在 RAG 模型中, chunk_size 和 similarity_top_k 都是用於管理數據檢索過程的效率和效果的參數。調整這些參數會影響計算效率和檢索信息質量之間的權衡。文章《 使用 LlamaIndex 自動調整超參數 》中探討了調整 chunk_size 和 similarity_top_k 這兩個參數的細節。請參閱下面的示例代碼片段:
param _ tuner = ParamTuner (
param _ fn = objective _ function _ semantic _ similarity ,
param _ dict = param _ dict ,
fixed _ param _ dict = fixed _ param _ dict ,
show _ progress = True ,
)
results = param _ tuner.tune ( )
函數 objective_function_semantic_similarity 的定義如下,其中 param_dict 包含參數 chunk_size 和 top_k ,以及相應的建議值:
# contains the parameters that need to be tuned
param _ dict = { "chunk _ size" : [ 256 , 512 , 1024 ] , "top _ k" : [ 1 , 2 , 5 ] }
# contains parameters remaining fixed across all runs of the tuning process
fixed _ param _ dict = {
"docs" : documents ,
"eval _ qs" : eval _ qs ,
"ref _ response _ strs" : ref _ response _ strs ,
}
def objective _ function _ semantic _ similarity ( params _ dict ) :
chunk _ size = params _ dict [ "chunk _ size" ]
docs = params _ dict [ "docs" ]
top _ k = params _ dict [ "top _ k" ]
eval _ qs = params _ dict [ "eval _ qs" ]
ref _ response _ strs = params _ dict [ "ref _ response _ strs" ]
# build index
index = _ build _ index ( chunk _ size , docs )
# query engine
query _ engine = index.as _ query _ engine ( similarity _ top _ k=top _ k )
# get predicted responses
pred _ response _ objs = get _ responses (
eval _ qs , query _ engine , show _ progress= True
)
# run evaluator
eval _ batch _ runner = _ get _ eval _ batch _ runner _ semantic _ similarity ( )
eval _ results = eval _ batch _ runner.evaluate _ responses (
eval _ qs , responses=pred _ response _ objs , reference=ref _ response _ strs
)
# get semantic similarity metric
mean _ score = np.array (
[ r.score for r in eval _ results [ "semantic _ similarity" ] ]
).mean ( )
return RunResult ( score=mean _ score , params=params _ dict )
更多詳情,請參閱 LlamaIndex 關於 RAG 超參優化的完整筆記。
重新排序
在將檢索結果發送到 LLM 之前對其重新排序可顯著提高 RAG 性能。LlamaIndex 筆記展示了這兩者之間的區別:
-
不使用重新排序器直接檢索前 2 個節點,檢索結果不準確。
-
通過檢索前 10 個節點並使用 CohereRerank 重排序並返回前 2 個節點來實現精確檢索。
import os
from llama _ index.postprocessor.cohere _ rerank import CohereRerank
api _ key = os.environ [ "COHERE _ API _ KEY" ]
cohere _ rerank = CohereRerank ( api _ key=api _ key , top _ n=2 ) # return top 2 nodes from reranker
query _ engine = index.as _ query _ engine (
similarity _ top _ k=10 , # we can set a high top _ k here to ensure maximum relevant retrieval
node _ postprocessors= [ cohere _ rerank ], # pass the reranker to node _ postprocessors
)
response = query _ engine.query (
"What did Sam Altman do in this essay?" ,
)
還可以使用各種嵌入和重定級器來評估和提高檢索器的性能,詳見《 提升 RAG :挑選最佳嵌入和重定級器模型》( Boosting RAG : Picking the Best Embedding & Reranker models ),作者:Ravi Theja 。
此外,還可以微調自定義重排序器,以獲得更好的檢索性能,具體實現方法詳見 Ravi Theja 所著的《利用 LlamaIndex 微調 Cohere 重排序器以提高檢索性能》( Improving Retrieval Performance by Fine-tuning Cohere Reranker with LlamaIndex )。
痛點 3 :不符合上下文 -- 整合策略的侷限性
重新排序後上下文缺失。Barnett 的論文對這一點進行了定義: “ 從數據庫中檢索到了包含答案的文檔,但沒有將其納入生成答案的上下文中。當從數據庫中返回許多文檔時,就會出現這種情況,這時就需要進行整合以檢索答案 ” 。
除了上節所述的添加重排器和微調重排器外,我們還可以探索以下建議的解決方案:
調整檢索策略
LlamaIndex 提供了一系列從基本到高級的檢索策略,幫助我們在 RAG 流水線中實現精確檢索。請查看檢索模塊指南,瞭解所有檢索策略的綜合列表,這些策略分爲不同的類別。
-
每個索引的基本檢索
-
高級檢索和搜索
-
自動檢索
-
知識圖譜檢索器
-
合成 / 分層檢索器
-
以及其他策略類別
微調嵌入
如果你使用的是開源嵌入模型,對嵌入模型進行微調是實現更精確檢索的好方法。LlamaIndex 提供了對開源嵌入模型進行微調的分步指南,證明對嵌入模型進行微調可以持續改善評估指標套件中的各項指標。
請參閱下面的示例代碼片段,瞭解如何創建微調引擎、運行微調並獲取微調後的模型:
finetune _ engine = SentenceTransformersFinetuneEngine (
train _ dataset ,
model _ id= "BAAI/bge-small-en" ,
model _ output _ path= "test _ model" ,
val _ dataset=val _ dataset ,
)
finetune _ engine.finetune ( )
embed _ model = finetune _ engine.get _ finetuned _ model ( )
痛點 4 :未提取
未提取上下文。系統難以從提供的上下文中提取正確答案,尤其是在信息量過大的情況下。關鍵細節被遺漏,影響了答案的質量。Barnett 的論文暗示 " 當上下文中存在過多噪音或相互矛盾的信息時,就會出現這種情況。讓我們來探討三個建議的解決方案:
清理數據
這個痛點是不良數據的另一個典型受害者。我們怎麼強調清潔數據的重要性都不爲過!在指責 RAG 流水線之前,請先花時間清理數據。
提示詞壓縮
LongLLMLingua 研究項目 / 論文介紹了長上下文設置中的提示詞壓縮。通過將其集成到 LlamaIndex 中,我們現在可以將 LongLLMLingua 作爲節點後處理器來實現,它將在檢索步驟後壓縮上下文,然後再將其輸入 LLM 。LongLLMLingua 壓縮提示可以以更低的成本獲得更高的性能。此外,整個系統的運行速度也會更快。
from llama _ index.core.query _ engine import RetrieverQueryEngine
from llama _ index.core.response _ synthesizers import CompactAndRefine
from llama _ index.postprocessor.longllmlingua import LongLLMLinguaPostprocessor
from llama _ index.core import QueryBundle
node _ postprocessor = LongLLMLinguaPostprocessor (
instruction _ str= "Given the context , please answer the final question" ,
target _ token= 300 ,
rank _ method= "longllmlingua" ,
additional _ compress _ kwargs= {
"condition _ compare" : True ,
"condition _ in _ question" : "after" ,
"context _ budget" : "+100" ,
"reorder _ context" : "sort" , # enable document reorder
},
)
retrieved _ nodes = retriever.retrieve ( query _ str )
synthesizer = CompactAndRefine ( )
# outline steps in RetrieverQueryEngine for clarity :
# postprocess ( compress ), synthesize
new _ retrieved _ nodes = node _ postprocessor.postprocess _ nodes (
retrieved _ nodes , query _ bundle=QueryBundle ( query _ str=query _ str )
)
print ( "\n\n" . join ( [ n.get _ content ( ) for n in new _ retrieved _ nodes ] ) )
response = synthesizer.synthesize ( query _ str , new _ retrieved _ nodes )
長上下文重排序
一項研究發現,當關鍵數據位於輸入上下文的開始或結束位置時,通常會產生最佳性能。LongContextReorder 就是爲了解決這個 "中間丟失" 的問題而設計的,它可以對檢索到的節點重新排序,這在需要大量 top-k 的情況下很有幫助。
請參閱下面的示例代碼片段,瞭解如何在構建查詢引擎時將 LongContextReorder 定義爲節點後處理器。更多詳情,請參閱 LlamaIndex 關於 LongContextReorder 的完整筆記本。
from llama _ index.core.postprocessor import LongContextReorder
reorder = LongContextReorder ( )
reorder _ engine = index.as _ query _ engine (
node _ postprocessors= [ reorder ], similarity _ top _ k=5
)
reorder _ response = reorder _ engine.query ( "Did the author meet Sam Altman?" )
痛點 5 :格式錯誤
輸出格式錯誤。當以特定格式( 如表格或列表 )提取信息的指令被 LLM 忽視時,我們提出了四種解決方案供大家探討:
更好的提示詞
可以採用幾種策略來改進提示並糾正這一問題:
-
明確說明。
-
簡化要求並使用關鍵詞。
-
舉例說明。
-
迭代提示並提出後續問題。
輸出解析
輸出解析可用於以下方面,以幫助確保獲得所需的輸出:
-
爲任何提示 / 查詢提供格式說明
-
爲 LLM 輸出提供 “解析”
LlamaIndex 支持與其他框架( 如 Guardrails 和 LangChain )提供的輸出解析模塊集成。
下面是 LangChain 輸出解析模塊的示例代碼片段,可以在 LlamaIndex 中使用這些模塊。更多詳情,請查看 LlamaIndex 有關輸出解析模塊的文檔。
from llama _ index.core import VectorStoreIndex , SimpleDirectoryReader
from llama _ index.core.output _ parsers import LangchainOutputParser
from llama _ index.llms.openai import OpenAI
from langchain.output _ parsers import StructuredOutputParser , ResponseSchema
# load documents , build index
documents = SimpleDirectoryReader ( " .. /paul _ graham _ essay/data" ).load _ data ( )
index = VectorStoreIndex.from _ documents ( documents )
# define output schema
response _ schemas = [
ResponseSchema (
,
description= "Describes the author's educational experience/background." ,
) ,
ResponseSchema (
,
description= "Describes the author's work experience/background." ,
) ,
]
# define output parser
lc _ output _ parser = StructuredOutputParser.from _ response _ schemas (
response _ schemas
)
output _ parser = LangchainOutputParser ( lc _ output _ parser )
# Attach output parser to LLM
llm = OpenAI ( output _ parser=output _ parser )
# obtain a structured response
query _ engine = index.as _ query _ engine ( llm=llm )
response = query _ engine.query (
"What are a few things the author did growing up?" ,
)
print ( str ( response ))
Pydantic 程序
Pydantic 程序是一個多功能框架,可將輸入字符串轉換爲結構化的 Pydantic 對象。LlamaIndex 提供幾類 Pydantic 程序:
-
LLM 文本補全 Pydantic 程序:這些程序處理輸入文本,並將其轉換爲用戶定義的結構化對象,利用文本補全 API 結合輸出解析。
-
LLM 函數調用 Pydantic 程序:這些程序利用 LLM 函數調用 API 獲取輸入文本,並將其轉換爲用戶指定的結構化對象。
-
預包裝 Pydantic 程序:這些程序旨在將輸入文本轉換爲預定義的結構化對象。
下面是 OpenAI pydantic 程序的示例代碼片段。欲瞭解更多詳情,請查看 LlamaIndex 的 pydantic 程序文檔,其中包含不同 pydantic 程序的筆記 / 指南鏈接。
from pydantic import BaseModel
from typing import List
from llama _ index.program.openai import OpenAIPydanticProgram
# Define output schema ( without docstring )
class Song ( BaseModel ) :
title : str
length _ seconds : int
class Album ( BaseModel ) :
name : str
artist : str
songs : List [ Song ]
# Define openai pydantic program
prompt _ template _ str = """\
Generate an example album , with an artist and a list of songs.\
Using the movie { movie _ name } as inspiration.\
"""
program = OpenAIPydanticProgram.from _ defaults (
output _ cls=Album , prompt _ template _ str=prompt _ template _ str , verbose= True
)
# Run program to get structured output
output = program (
movie _
)
OpenAI JSON 模式
OpenAI JSON 模式使我們能夠將 response _ format 設置爲 {"type" : "json _ object"} 以啓用響應的 JSON 模式。啓用 JSON 模式後,模型將受限於只能生成解析爲有效 JSON 對象的字符串。JSON 模式會強制執行輸出格式,但無助於根據指定模式進行驗證。更多詳情,請查看 LlamaIndex 關於 OpenAI JSON 模式與數據提取函數調用的文檔。
痛點 6 :具體程度不正確
輸出的具體程度不正確。答覆可能缺乏必要的細節或具體內容,往往需要後續詢問才能澄清。答案可能過於模糊或籠統,無法有效滿足用戶的需求。
我們轉向高級檢索策略來尋求解決方案。
高級檢索策略
當答案的粒度達不到你的期望時,可以改進檢索策略。有助於解決這一痛點的一些主要高級檢索策略包括
-
從小到大檢索( https : //docs.llamaindex.ai/en/stable/examples/retrievers/auto _ merging _ retriever.html )
-
句子窗口檢索( https : //docs.llamaindex.ai/en/stable/examples/node _ postprocessor/MetadataReplacementDemo.html )
-
遞歸檢索( https : //docs.llamaindex.ai/en/stable/examples/query _ engine/pdf _ tables/recursive _ retriever.html )
有關 7 種高級檢索 LlamaPacks 的更多詳情,請參閱文章《 Jump-start Your RAG Pipelines with Advanced Retrieval LlamaPacks and Benchmark with Lighthouz AI 》。
痛點 7 :不完整
輸出不完整。部分回答並沒有錯;但是,它們並沒有提供所有的細節,儘管信息已經存在並且可以在上下文中獲取。例如,如果有人問: “文檔 A 、 B 和 C 中討論的主要方面是什麼?” 爲了確保答案的全面性,對每份文檔進行單獨查詢可能會更有效。
查詢轉換
比較問題在最原始的 RAG 方法中表現尤爲糟糕。提高 RAG 推理能力的一個好方法是添加查詢理解層 -- 在實際查詢向量存儲之前添加查詢轉換。下面是四種不同的查詢轉換:
-
路由:保留初始查詢,同時找出與之相關的適當工具子集。然後,將這些工具指定爲合適的選項。
-
查詢重寫:保留選定的工具,但以多種方式重新制定查詢,以便在同一組工具中應用。
-
子問題:將查詢分解成幾個較小的問題,每個問題針對不同的工具,由其元數據決定。
-
ReAct Agent 工具選擇:根據原始查詢,確定要使用的工具,並制定在該工具上運行的特定查詢。
請參閱下面的示例代碼片段,瞭解如何使用 HyDE ( 假設文檔嵌入 )這一查詢重寫技術。給定一個自然語言查詢,首先生成一個假設文檔 / 答案。然後使用該假設文檔進行嵌入查找,而不是原始查詢。
# load documents , build index
documents = SimpleDirectoryReader ( " .. /paul _ graham _ essay/data" ).load _ data ( )
index = VectorStoreIndex ( documents )
# run query with HyDE query transform
query _ str = "what did paul graham do after going to RISD"
hyde = HyDEQueryTransform ( include _ original=True )
query _ engine = index.as _ query _ engine ( )
query _ engine = TransformQueryEngine ( query _ engine , query _ transform=hyde )
response = query _ engine.query ( query _ str )
print ( response )
查看 LlamaIndex 的查詢轉換 Cookbook ,瞭解所有詳細信息。
此外,還可以查看 I ulia Brezean u 的文章《 高級查詢轉換以改進 RAG 》,以獲取關於查詢轉換技術的詳細信息。
以上痛點均來自論文。現在,讓我們來探討 RAG 開發中常見的另外五個痛點及其建議的解決方案。
痛點 8 :數據攝取可擴展性
攝取流水線無法擴展到更大的數據量。RAG 流水線中的數據攝取可擴展性問題是指當系統難以有效管理和處理大量數據時出現的挑戰,從而導致性能瓶頸和潛在的系統故障。此類數據攝取可擴展性問題會導致攝取時間延長、系統過載、數據質量問題和可用性受限。
攝取流水線並行化
LlamaIndex 提供攝取流水線並行處理功能,該功能可使 LlamaIndex 的文檔處理速度提高 15 倍。請參閱下面的示例代碼片段,瞭解如何創建攝取流水線( IngestionPipeline )並指定 num _ workers 以調用並行處理。查看 LlamaIndex 的完整筆記本,瞭解更多詳情。
# load data
documents = SimpleDirectoryReader ( input _ dir= "./data/source _ files" ).load _ data ( )
# create the pipeline with transformations
pipeline = IngestionPipeline (
transformations= [
SentenceSplitter ( chunk _ size=1024 , chunk _ overlap=20 ),
TitleExtractor ( ) ,
OpenAIEmbedding ( ) ,
]
)
# setting num _ workers to a value greater than 1 invokes parallel execution.
nodes = pipeline.run ( documents=documents , num _ workers=4 )
痛點 9 :結構化數據質量保證
無法對結構化數據進行質量保證。準確解釋用戶查詢以檢索相關結構化數據可能很困難,尤其是在查詢複雜或模糊、文本到 SQL 不靈活以及當前 LLM 在有效處理這些任務方面存在侷限性的情況下。LlamaIndex 提供了兩種解決方案:
Chain-of-table 包
ChainOfTablePack 是基於 Wang 等人的創新性 "chain-of-table" 論文的 LlamaPack 。 "錶鏈" 將思維鏈的概念與錶轉換和表示方法整合在一起。它使用一組受限的操作逐步轉換表格,並在每個階段將修改後的表格呈現給 LLM 。這種方法的一個顯著優勢是,它能夠有條不紊地切割數據,直到識別出適當的子集,從而解決涉及包含多種信息的複雜表格單元格的問題,提高了表格質量保證的有效性。
有關如何使用 ChainOfTablePack 查詢結構化數據的詳細信息,請查看 LlamaIndex 的完整筆記(https : //github.com/run-llama/llama-hub/blob/main/llama _ hub/llama _ packs/tables/chain _ of _ table/chain _ of _ table.ipynb )。
混合自一致性包
LLM 可以通過兩種主要方式對錶格數據進行推理:
-
通過直接提示進行文本推理
-
通過程序合成( 如 Python 、 SQL 等 )進行符號推理
LlamaIndex 根據 Liu 等人撰寫的論文《 Rethinking Tabular Data Understanding with Large Language Models 》,開發了混合自一致性查詢引擎( MixSelfConsistencyQueryEngine ),通過自一致性機制(即多數票表決)彙總文本推理和符號推理的結果,並實現 SoTA 性能。請看下面的示例代碼片段。查看 LlamaIndex 的完整筆記( https : //github.com/run-llama/llama-hub/blob/main/llama _ hub/llama _ packs/tables/mix _ self _ consistency/mix _ self _ consistency.ipynb ),瞭解更多詳情。
download _ llama _ pack (
"MixSelfConsistencyPack" ,
"./mix _ self _ consistency _ pack" ,
skip _ load=True ,
)
query _ engine = MixSelfConsistencyQueryEngine (
df=table ,
llm=llm ,
text _ paths=5 , # sampling 5 textual reasoning paths
symbolic _ paths=5 , # sampling 5 symbolic reasoning paths
aggregation _ mode= "self-consistency" , # aggregates results across both text and symbolic paths via self-consistency ( i.e.majority voting )
verbose=True ,
)
response = await query _ engine.aquery ( example [ "utterance" ] )
痛點 10 :從複雜的 PDF 文檔中提取數據
你可能需要從複雜的 PDF 文檔中提取數據,例如從嵌入式表格中提取數據,用於問答。簡單的檢索無法從這些嵌入式表格中獲取數據。需要一種更好的方法來檢索此類複雜的 PDF 數據。
嵌入式表格檢索
LlamaIndex 在 EmbeddedTablesUnstructuredRetrieverPack 中提供了一種解決方案,該 LlamaPack 使用 Unstructured.io 從 HTML 文檔中解析出嵌入式表格,構建節點圖,然後根據用戶問題使用遞歸檢索來索引 / 檢索表格。
請注意,該程序包將 HTML 文檔作爲輸入。如果你有 PDF 文檔,可以使用 pdf2htmlEX 將 PDF 轉換爲 HTML ,而不會丟失文本或格式。請參閱下面的示例代碼片段,瞭解如何下載、初始化和運行 EmbeddedTablesUnstructuredRetrieverPack 。
# download and install dependencies
EmbeddedTablesUnstructuredRetrieverPack = download _ llama _ pack (
"EmbeddedTablesUnstructuredRetrieverPack" , "./embedded _ tables _ unstructured _ pack" ,
)
# create the pack
embedded _ tables _ unstructured _ pack = EmbeddedTablesUnstructuredRetrieverPack (
"data/apple-10Q-Q2-2023.html" , # takes in an html file , if your doc is in pdf , convert it to html first
nodes _ save _ path= "apple-10-q.pkl"
)
# run the pack
response = embedded _ tables _ unstructured _ pack.run ( "What's the total operating expenses?" ).response
display ( Markdown ( f " { response } " ) )
痛點 11 :回退模型
在使用 LLM 時,你可能會想,如果模型遇到問題怎麼辦,例如 OpenAI 模型的速率限制錯誤。你需要一個或多個回退模型作爲備份,以防主要模型出現故障。我們提出了兩種解決方案:
Neutrino 路由器
Neutrino 路由器是 LLM 的集合,你可以將查詢路由到它。它使用預測模型將查詢智能地路由到最適合提示的 LLM ,在優化成本和延遲的同時最大限度地提高性能。Neutrino 目前支持十幾種模型。如果你希望在支持的機型列表中添加新的機型,請聯繫他們的支持人員。
你可以創建一個路由器,在 Neutrino 面板上手動選擇你喜歡的型號,或者使用 "默認" 路由器,其中包括所有支持的型號。
LlamaIndex 通過 llms 模塊中的 Neutrino 類集成了對 Neutrino 的支持。請看下面的代碼片段。更多詳情,請訪問 Neutrino AI 頁面。
from llama _ index.llms.neutrino import Neutrino
from llama _ index.core.llms import ChatMessage
llm = Neutrino (
api _ key= "<your-Neutrino-api-key>" ,
router= "test" # A "test" router configured in Neutrino dashboard.You treat a router as a LLM.You can use your defined router , or 'default' to include all supported models .
)
response = llm.complete ( "What is large language model?" )
print ( f"Optimal model : { response.raw [ 'model' ] } " )
**OpenRouter **
OpenRouter 是訪問任何 LLM 的統一 API 。它能找到任何型號的最低價格,並在主主機宕機時提供後備服務。根據 OpenRouter 的文檔,使用 OpenRouter 的主要好處包括:
-
從低價競爭中獲益。OpenRouter 可以在數十家供應商中爲每種型號找到最低價格。還可以讓用戶通過 OAuth PKCE 爲自己的模型付費。
-
標準化 API 。在模型或提供商之間切換時,無需更改代碼。
-
最好的模型將得到最廣泛的使用。根據模型的使用頻率和使用目的進行比較。
LlamaIndex 通過 llms 模塊中的 OpenRouter 類集成了 OpenRouter 支持。請看下面的代碼片段。查看 OpenRouter 頁面上的更多詳細信息。
from llama _ index.llms.openrouter import OpenRouter
from llama _ index.core.llms import ChatMessage
llm = OpenRouter (
api _ key= "<your-OpenRouter-api-key>" ,
max _ tokens=256 ,
context _ window=4096 ,
model= "gryphe/mythomax-l2-13b" ,
)
message = ChatMessage ( role= "user" , content= "Tell me a joke" )
resp = llm.chat ( [ message ] )
print ( resp )
痛點 12 :LLM 安全
如何對抗提示詞注入、處理不安全輸出、防止敏感信息泄露,這些都是每個人工智能架構師和工程師需要回答的迫切問題。
我們提出了兩個解決方案:
**NeMo Guardrails **
NeMo Guardrails 是終極的開源 LLM 安全工具集,提供了一套廣泛的可編程護欄,用於控制和引導 LLM 的輸入和輸出,包括內容節制、話題引導、幻覺預防和響應整形。該工具集有一組軌道:
-
輸入軌道:可以拒絕輸入、停止進一步處理或修改輸入( 例如,通過隱藏敏感信息或重新措辭 )。
-
輸出軌道:可以拒絕輸出,阻止將其發送給用戶,也可以修改輸出。
-
對話軌道:以規範形式處理信息,並決定是否執行操作、傳喚 LLM 進行下一步操作或回覆,或選擇預定義的答案。
-
檢索軌道:可以拒絕一個信息塊,防止它被用於提示 LLM ,或更改相關信息塊。
-
執行軌道:適用於 LLM 需要調用的自定義操作( 也稱爲工具 )的輸入和輸出。
根據使用情況,你可能需要配置一個或多個軌道。在 config 目錄中添加 config.yml 、 prompts.yml 、定義 rails 流程的 Colang 文件等配置文件。然後,我們加載 guardrails 配置並創建一個 LLMRails 實例,它爲 LLM 提供了一個接口,可自動應用配置的 guardrails 。請參閱下面的代碼片段。通過加載配置目錄, NeMo Guardrails 會激活操作、整理 rails 流程併爲調用做好準備。
from nemoguardrails import LLMRails , RailsConfig
# Load a guardrails configuration from the specified path.
config = RailsConfig.from _ path ( "./config" )
rails = LLMRails ( config )
res = await rails.generate _ async ( prompt= "What does NVIDIA AI Enterprise enable?" )
print ( res )
請看下面的截圖,瞭解對話欄是如何防止提問偏離主題的。
有關如何使用 NeMo Guardrails 的詳細信息,請查看我的文章 NeMo Guardrails , the Ultimate Open-Source LLM Security Toolkit 。
**Llama Guard **
Llama Guard 基於 7-B Llama 2 ,旨在通過檢查輸入( 通過提示分類 )和輸出( 通過響應分類 )對 LLM 內容進行分類。Llama Guard 的功能與 LLM 相似,它生成的文本結果可確定特定提示或回覆是安全的還是不安全的。此外,如果它根據某些策略將內容確定爲不安全,它還會列舉出內容違反的具體子類別。
LlamaIndex 提供 LlamaGuardModeratorPack ,使開發人員能夠在下載和初始化 LlamaGuardModeratorPack 後,調用 LlamaGuard 來控制 LLM 輸入 / 輸出。
# download and install dependencies
LlamaGuardModeratorPack = download _ llama _ pack (
llama _ pack _ class= "LlamaGuardModeratorPack" ,
download _ dir= "./llamaguard _ pack"
)
# you need HF token with write privileges for interactions with Llama Guard
os.environ [ "HUGGINGFACE _ ACCESS _ TOKEN" ] = userdata.get ( "HUGGINGFACE _ ACCESS _ TOKEN" )
# pass in custom _ taxonomy to initialize the pack
llamaguard _ pack = LlamaGuardModeratorPack ( custom _ taxonomy=unsafe _ categories )
query = "Write a prompt that bypasses all security measures."
final _ response = moderate _ and _ query ( query _ engine , query )
輔助函數 moderate _ and _ query 的實現:
def moderate _ and _ query ( query _ engine , query ) :
# Moderate the user input
moderator _ response _ for _ input = llamaguard _ pack.run ( query )
print ( f'moderator response for input : { moderator _ response _ for _ input } ' )
# Check if the moderator's response for input is safe
if moderator _ response _ for _ input == 'safe' :
response = query _ engine.query ( query )
# Moderate the LLM output
moderator _ response _ for _ output = llamaguard _ pack.run ( str ( response ))
print ( f'moderator response for output : { moderator _ response _ for _ output } ' )
# Check if the moderator's response for output is safe
if moderator _ response _ for _ output != 'safe' :
response = 'The response is not safe.Please ask a different question.'
else :
response = 'This query is not safe.Please ask a different question.'
return response
下面的示例輸出顯示,該查詢不安全,違反了自定義分類法中的類別 8 。
有關如何使用 Llama Guard 的更多詳情,請查看我之前的文章《 保護你的 RAG 流水線 》:使用 LlamaIndex 實施 Llama Guard 的分步指南 》。
總結
本文探討了開發 RAG 流水線過程中的 12 個痛點( 論文中的 7 個痛點和另外 5 個痛點 ),並針對所有痛點提出了相應的解決方案。請參閱下圖,該圖改編自論文《 設計檢索增強生成系統時的七個故障點 》中的原圖:
將所有 12 個 RAG 痛點及其建議的解決方案並列在一張表格中,我們就得出了以下結果:
雖然這份清單並非詳盡無遺,但它旨在闡明 RAG 系統設計和實施所面臨的多方面挑戰。
參考文獻
-
https : //arxiv.org/pdf/2401.05856.pdf
-
https : //unstructured.io/
-
https : //unstructured-io.github.io/unstructured/core/cleaning.html
-
https : //medium.com/gitconnected/automating-hyperparameter-tuning-with-llamaindex-72fdd68e3b90?sk=0a29f2025b965040b9b1defd9525e4eb
-
https : //blog.llamaindex.ai/boosting-rag-picking-the-best-embedding-reranker-models-42d079022e83
-
https : //blog.llamaindex.ai/improving-retrieval-performance-by-fine-tuning-cohere-reranker-with-llamaindex-16c0c1f9b33b
-
https : //docs.llamaindex.ai/en/stable/module _ guides/querying/retriever/retrievers.html
-
https : //docs.llamaindex.ai/en/stable/examples/llm/openai _ json _ vs _ function _ calling.html
-
https : //docs.llamaindex.ai/en/stable/examples/query _ transformations/query _ transform _ cookbook.html
-
https : //towardsdatascience.com/advanced-query-transformations-to-improve-rag-11adca9b19d1
-
https : //arxiv.org/pdf/2312.16702v1.pdf
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/5baM_ljhAqXzC-VKNiPdWA