RAG 開發四大痛點及解決方案 原創
1、痛點1:知識缺失
知識庫缺乏必要的上下文信息,導致 RAG 系統在無法找到確切答案時,可能會提供模棱兩可的錯誤信息,而不是直接表明其無知。這種情況下,用戶可能會接收到誤導性的信息,從而感到沮喪。針對這一問題,有以下兩種解決方案:
解決方案一:優化數據質量
“垃圾輸入,垃圾輸出。” 若源數據質量不佳,比如:存在相互矛盾的信息,即便是再完美的 RAG 流程也無法從劣質數據中提煉出有價值的知識。以下提出的解決方案不僅能解決這一難題,還能應對本文中提到的其他問題。高質量的數據是確保 RAG 流程順暢運行的關鍵。
以下是一些常見的數據優化策略:
1. 清除噪音和無關信息:包括移除特殊字符、停用詞(比如:“the”和“a”等常見詞匯)以及 HTML 標簽。
2. 識別并修正錯誤:涉及拼寫錯誤、打字錯誤和語法錯誤。拼寫檢查工具和語言模型等資源對此很有幫助。
3. 去除重復數據:消除可能干擾檢索過程的重復或相似記錄。
解決方案二:優化提示詞設計
由于知識庫信息不足,系統可能會提供看似合理卻錯誤的答案。在這種情況下,優化提示詞可以顯著提升系統表現。通過使用“若你不確定答案,請表明你不知道”等提示詞,可以引導大模型承認其局限,并更清晰地表達不確定性。雖然這不能確保答案的絕對正確性,但在數據優化之后,設計恰當的提示詞是提高系統透明度的有效手段之一。
2、痛點2:更相關的知識沒有檢索出來
在初步檢索階段知識未能被檢索出來。關鍵的文檔可能沒有在檢索組件給出的初步結果中,導致正確答案被遺漏,大模型因此無法提供精確的響應。研究指出:“問題的答案其實就藏在文檔里,只是因為它排名不夠高,所以沒有被呈現給用戶。”針對這一問題,有以下兩種解決方案:
解決方案一:調整 chunk_size 和 similarity_top_k 超參數
在 RAG 模型中,chunk_size 和 similarity_top_k 是控制數據檢索效率和準確性的兩個關鍵參數。對這些參數的調整會影響到計算效率和信息檢索質量之間的平衡。
解決方案二:Rerank 重排序
在將檢索結果傳遞給大語言模型(LLM)之前對其進行重新排序,可以顯著增強 RAG 系統的性能。LlamaIndex 的筆記揭示了有無重新排序的差別:
- 未經重新排序直接獲取前兩個節點的檢索結果,導致結果不夠精確。
- 相比之下,檢索前 10 個節點并利用 CohereRerank 進行重排序,然后僅返回前兩個節點,可以實現更精確的檢索。
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?" ,
)
3、痛點3:格式錯誤
輸出格式不正確。當大語言模型(LLM)未能遵循以特定格式(比如:表格或列表)提取信息的指令時,我們提出了以下四種解決方案:
解決方案一:優化提示詞設計
為了改善提示詞并解決這一問題,可以采取以下幾種策略:
- 明確指出格式要求。
- 簡化指令并突出關鍵術語。
- 提供具體示例。
- 對提示詞進行迭代并追加相關問題。??
解決方案二:輸出解析方法
輸出解析可以用于以下目的,以確保獲得期望的輸出格式:
- 為每個提示/查詢提供格式化指南。
- 對LLM的輸出進行“解析”處理。??
以下是一個使用 LangChain 輸出解析模塊的示例代碼片段,該模塊可在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 (
name= "Education" ,
description= "Describes the author's educational experience/background." ,
) ,
ResponseSchema (
name= "Work" ,
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 程序的示例代碼片段:
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 _ name= "The Shining" , description= "Data model for an album."
)
解決方案四:OpenAI JSON 模式
通過OpenAI的 JSON 模式,我們可以將`response_format`設置為`{ "type": "json_object" }`,從而激活響應的 JSON 模式。當啟用 JSON 模式后,大模型將被限制僅生成可以解析為有效 JSON 對象的字符串。JSON 模式確保了輸出格式的強制性,但它并不支持根據特定模式進行驗證。
4、痛點4:輸出不完整
回答缺失完整性。雖然部分答復沒有錯誤,但它們并未包含所有必要的細節,即便這些信息在上下文中是可獲取的。比如:當有人提問:“文檔A、B和C中討論的主要議題是什么?”為了確保回答的完整性,單獨對每份文檔進行查詢可能更為有效。
解決方案一:查詢變換
在最初的 RAG 方法中,比較類型的問題表現尤為不佳。提升 RAG 推理能力的一個有效方法是引入查詢理解層——在實際將查詢向量存入存儲之前進行查詢變換。以下是四種不同的查詢變換方法:
1. 路由:保留原始查詢,并識別出與之相關的合適工具子集。隨后,將這些工具指定為合適的選項。
2. 查詢重寫:保留選定的工具,但以不同方式重新構建查詢,以便在同一工具集中應用。
3. 子問題分解:將查詢拆分為幾個更小的問題,每個問題針對不同的工具,由其元數據來決定。
4. 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 )
本文轉載自公眾號玄姐聊AGI 作者:玄姐
原文鏈接:??https://mp.weixin.qq.com/s/YQJ4CXKPNDM9XW1OpFrN8g??
