自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

手搓RAG新增功能:遞歸檢索與迭代查詢+重回成熟框架API

人工智能
在上那篇提到的我手搓的那個(gè) RAG 項(xiàng)目新增功能中,漏掉了遞歸檢索與迭代查詢,這篇補(bǔ)上。

在上那篇提到的我手搓的那個(gè) RAG 項(xiàng)目新增功能中,漏掉了遞歸檢索與迭代查詢,這篇補(bǔ)上(源碼見知識(shí)星球)。經(jīng)過初步調(diào)試對(duì)召回效果有明顯提升,這種方法解決了傳統(tǒng) RAG 的幾個(gè)關(guān)鍵問題:

  • 處理復(fù)雜多步驟問題:通過多次迭代,分解復(fù)雜問題
  • 信息不足的補(bǔ)充:當(dāng)初始檢索結(jié)果不足以回答問題時(shí),自動(dòng)生成補(bǔ)充查詢
  • 多角度信息收集:能夠從不同角度收集相關(guān)信息

1、遞歸檢索具體實(shí)現(xiàn)

遞歸檢索函數(shù)(recursive_retrieval)

(支持最多三次迭代查詢)

每次迭代使用混合檢索(向量檢索+BM25)獲取信息

使用 LLM 分析當(dāng)前檢索結(jié)果,判斷是否需要進(jìn)一步查詢

如果需要,LLM 會(huì)生成新的查詢問題,用于下一輪檢索

換句話說,遞歸檢索的工作原理可以理解為"先檢索-后思考-再檢索"的過程,模擬了人解決問題的方式:先獲取一些信息,思考下是否足夠,如果不夠則繼續(xù)查找更多相關(guān)信息??傊玫慕Y(jié)果不是一蹴而就的。

為了更直觀的讓大家了解這個(gè)遞歸檢索的過程,貼幾張本地測(cè)試圖片,供參考。需要說明的是,目前這個(gè)版本中還沒做多模態(tài)的預(yù)處理和圖片的召回,后續(xù)結(jié)合具體案例更新在知識(shí)星球中。

圖片

圖片

圖片

圖片

2、核心組件全解析

下面再對(duì)整個(gè)代碼的核心組件做進(jìn)一步的解析,大家可以在這個(gè)基礎(chǔ)上按照業(yè)務(wù)需求進(jìn)一步優(yōu)化:

圖片

2.1文檔處理和向量化

文本提?。菏褂?pdfminer.high_level.extract_text_to_fp 從 PDF 提取文本內(nèi)容

文本分塊:使用 RecursiveCharacterTextSplitter 將長(zhǎng)文本分割成更小的塊(在代碼中塊大小設(shè)為 400 字符,重疊為 40 字符)

向量化:使用 all-MiniLM-L6-v2 模型為每個(gè)文本塊生成嵌入向量

存儲(chǔ):將文本塊、向量和元數(shù)據(jù)存儲(chǔ)到 ChromaDB 向量數(shù)據(jù)庫(kù)

輔助索引:同時(shí)構(gòu)建 BM25Okapi 索引用于基于關(guān)鍵詞的檢索

分塊粒度和嵌入質(zhì)量直接影響檢索性能,這部分大家需要結(jié)合自己的文檔結(jié)構(gòu)特點(diǎn)自行調(diào)整,上述列出的做法僅供參考。

2.2混合檢索機(jī)制

結(jié)合了兩種不同的檢索方法:

語(yǔ)義向量檢索:基于嵌入向量的相似度搜索,能夠捕捉語(yǔ)義關(guān)系

BM25 關(guān)鍵詞檢索:基于詞頻的經(jīng)典檢索算法,專注于關(guān)鍵詞匹配

混合策略:通過 hybrid_merge 函數(shù)融合兩種檢索結(jié)果,使用α參數(shù)(0.7)控制兩種方法的權(quán)重

這種混合策略結(jié)合了語(yǔ)義理解和關(guān)鍵詞匹配的優(yōu)勢(shì),提高了檢索的綜合表現(xiàn)。

2.3重排序機(jī)制

檢索到初步結(jié)果后,使用更精確的模型進(jìn)行重排序:

交叉編碼器重排序:使用 CrossEncoder 模型,能夠同時(shí)考慮查詢和文檔內(nèi)容進(jìn)行更精確的相關(guān)性評(píng)分

LLM 重排序:可選使用 LLM 對(duì)查詢和文檔的相關(guān)性進(jìn)行評(píng)分,利用大模型的理解能力

緩存機(jī)制:使用@lru_cache 減少重復(fù)計(jì)算,提高效率

重排序步驟使檢索結(jié)果更符合用戶的實(shí)際需求,大幅提升了檢索質(zhì)量。

2.4遞歸檢索與迭代查詢

這是新增的一個(gè)功能,也是實(shí)測(cè)下來對(duì)最終效果有明顯提升的一點(diǎn),由 recursive_retrieval 函數(shù)實(shí)現(xiàn):

初始檢索:使用原始查詢進(jìn)行首輪檢索

結(jié)果分析:使用 LLM 分析當(dāng)前檢索結(jié)果是否充分回答問題

查詢改寫:如果信息不足,LLM 會(huì)生成一個(gè)新的、更具體或從不同角度的查詢

迭代過程:使用新查詢繼續(xù)檢索,直到獲取足夠信息或達(dá)到最大迭代次數(shù)

這個(gè)機(jī)制解決了單次檢索的局限性,能夠處理復(fù)雜問題、多步驟推理,以及需要從多個(gè)角度收集信息的場(chǎng)景。

2.5生成回答

系統(tǒng)支持兩種回答生成方式:

本地 Ollama 模型:使用 deepseek-r1:1.5b 或 deepseek-r1:7b 模型在本地生成回答

SiliconFlow API:調(diào)用云端 API 使用更強(qiáng)大的模型生成回答

圖片

https://cloud.siliconflow.cn/i/cmXGS5IJ

思維鏈處理:支持分離思考過程,以可折疊的形式展示給用戶

之所以選擇新增一個(gè)商業(yè)api選項(xiàng),也是因?yàn)槲易约旱碾娔X跑本地模型是在太卡,問了一些復(fù)雜問題容易觸發(fā)超時(shí)機(jī)制。當(dāng)然另外還有個(gè)重要原因是,在針對(duì)不同核心組件做調(diào)優(yōu)時(shí),保持 chat 模型的水準(zhǔn)個(gè)人實(shí)踐下來也很重要,否則就變成了過度雕花。

3、優(yōu)化方向參考

因?yàn)橹皇欠奖愦蠹揖毷?,大家感興趣的可以在目前代碼基礎(chǔ)上做如下優(yōu)化:

3.1文檔格式支持?jǐn)U展

當(dāng)前系統(tǒng)僅支持 PDF 文件,可擴(kuò)展支持:

# 支持更多文檔格式
def extract_text_from_file(file_path):
    """根據(jù)文件類型選擇適當(dāng)?shù)奶崛》椒?""
    ext = os.path.splitext(file_path)[1].lower()
   
    if ext == '.pdf':
        return extract_text_from_pdf(file_path)
    elif ext == '.docx':
        return extract_text_from_docx(file_path)
    elif ext == '.pptx':
        return extract_text_from_pptx(file_path)
    elif ext in ['.txt', '.md', '.py', '.java', '.js', '.html', '.css']:
        with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
            return f.read()
    elif ext in ['.csv', '.xlsx', '.xls']:
        return extract_text_from_spreadsheet(file_path)
    else:
        raise ValueError(f"不支持的文件類型: {ext}")

3.2高級(jí)分塊策略

可以實(shí)現(xiàn)更智能的分塊策略:

語(yǔ)義分塊:基于段落、章節(jié)或自然語(yǔ)義邊界進(jìn)行分塊

結(jié)構(gòu)感知分塊:識(shí)別文檔結(jié)構(gòu)(標(biāo)題、列表、表格等)

多粒度分塊:同時(shí)維護(hù)不同粒度的塊,靈活應(yīng)對(duì)不同類型的查詢 

# 多粒度分塊示例
def create_multi_granularity_chunks(text):
    """創(chuàng)建多粒度分塊"""
    # 大塊(1000字符):適合概述類問題
    large_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000, chunk_overlap=100
    )
    # 中塊(400字符):平衡粒度
    medium_splitter = RecursiveCharacterTextSplitter(
        chunk_size=400, chunk_overlap=40
    )
    # 小塊(150字符):適合精確問答
    small_splitter = RecursiveCharacterTextSplitter(
        chunk_size=150, chunk_overlap=20
    )
    
    large_chunks = large_splitter.split_text(text)
    medium_chunks = medium_splitter.split_text(text)
    small_chunks = small_splitter.split_text(text)
    
    return {
        "large": large_chunks,
        "medium": medium_chunks,
        "small": small_chunks
    }

3.3嵌入模型優(yōu)化

當(dāng)前系統(tǒng)使用 all-MiniLM-L6-v2,可以考慮:

更強(qiáng)大的多語(yǔ)言模型:如 multilingual-e5-large 提升中文理解能力

領(lǐng)域特定微調(diào):針對(duì)特定領(lǐng)域數(shù)據(jù)微調(diào)嵌入模型

多模型集成:使用多個(gè)嵌入模型并融合結(jié)果 

# 多模型嵌入示例
def generate_multi_model_embeddings(text):
    """使用多個(gè)模型生成嵌入并融合"""
    model1 = SentenceTransformer('all-MiniLM-L6-v2')
    model2 = SentenceTransformer('paraphrase-multilingual-mpnet-base-v2')
    
    # 生成嵌入
    emb1 = model1.encode(text)
    emb2 = model2.encode(text)
    
    # 簡(jiǎn)單融合策略:歸一化后拼接
    emb1_norm = emb1 / np.linalg.norm(emb1)
    emb2_norm = emb2 / np.linalg.norm(emb2)
    
    # 返回融合嵌入
    return np.concatenate([emb1_norm, emb2_norm])

3.4檢索與重排序改進(jìn)

可以考慮以下改進(jìn):

查詢擴(kuò)展:使用同義詞擴(kuò)展或關(guān)鍵詞擴(kuò)展增強(qiáng)原始查詢

密集檢索與稀疏檢索結(jié)合:更高級(jí)的混合檢索方法

上下文感知重排序:考慮已檢索文檔間的關(guān)系進(jìn)行重排序

多輪對(duì)話記憶:在多輪對(duì)話中利用歷史上下文改進(jìn)檢索

# 查詢擴(kuò)展示例
def expand_query(query):
    """使用LLM擴(kuò)展查詢,生成多個(gè)角度的查詢變體"""
    prompt = f"""
    為以下查詢生成3個(gè)不同角度的變體,以提高檢索召回率:
    
    原始查詢: {query}
    
    變體應(yīng)當(dāng)包含同義詞替換、關(guān)鍵詞擴(kuò)展或問題重構(gòu)。
    僅返回三個(gè)變體,每行一個(gè),不要有額外解釋。
    """
    
    response = call_llm_api(prompt)
    variants = [line.strip() for line in response.strip().split('\n')]
    return [query] + variants  # 返回原始查詢和變體

3.5其他可能的擴(kuò)展方向

結(jié)果驗(yàn)證機(jī)制:使用外部知識(shí)或規(guī)則驗(yàn)證生成結(jié)果的準(zhǔn)確性

用戶反饋學(xué)習(xí):根據(jù)用戶反饋調(diào)整檢索策略和參數(shù)

多模態(tài)支持:處理圖像、表格等非文本內(nèi)容

層次化索引:構(gòu)建文檔的層次化表示,從概覽到細(xì)節(jié)

個(gè)性化調(diào)整:根據(jù)用戶歷史查詢和偏好調(diào)整檢索策略

4、RAG 學(xué)習(xí)路線全梳理

最后回到學(xué)習(xí)路線上來,最開始手搓這個(gè) demo,也是自己為了更好的從底層理解 RAG 系統(tǒng),不曾想收到了很多正反饋。

圖片

https://github.com/weiwill88/Local_Pdf_Chat_RAG

另外正如上篇所說,直接使用封裝度高的框架容易讓人"知其然不知其所以然"。如果你已經(jīng)掌握了基礎(chǔ)原理,就可以考慮進(jìn)一步探索 RAGFlow 或者 LlamaIndex 等成熟框架的 Python API,充分利用成熟框架提供的生產(chǎn)力優(yōu)勢(shì)。按照個(gè)人近幾個(gè)月的學(xué)習(xí)和實(shí)踐經(jīng)驗(yàn),整體學(xué)習(xí)路線參考如下:

4.1從自建到框架的過渡期

對(duì)比學(xué)習(xí):將手搓實(shí)現(xiàn)的組件與成熟框架中對(duì)應(yīng)功能進(jìn)行比較

框架源碼閱讀:嘗試閱讀 LlamaIndex 或 RAGFlow 等框架的核心源碼,看看他們?nèi)绾螌?shí)現(xiàn)相同功能

增量替換:逐步用框架組件替換自建組件,對(duì)比性能和結(jié)果差異

4.2成熟框架深入學(xué)習(xí)

從示例入手:優(yōu)先研究官方提供的示例代碼和教程

構(gòu)建微型項(xiàng)目:使用框架 API 實(shí)現(xiàn)小型但完整的應(yīng)用

實(shí)驗(yàn)各種組件:測(cè)試不同的檢索器、嵌入模型、重排序策略等

4.3高級(jí)應(yīng)用與定制

探索高級(jí)功能:如多模態(tài) RAG、Agent 集成、自定義索引等

性能優(yōu)化:學(xué)習(xí)如何調(diào)整參數(shù)提高檢索質(zhì)量和速度

領(lǐng)域適配:根據(jù)特定行業(yè)或領(lǐng)域需求定制 RAG 系統(tǒng)

5、Python API vs Web 界面能做什么?

公眾號(hào)之前有篇文章詳細(xì)介紹了 RAGFlow 官方 Python API 各個(gè)模塊使用,后續(xù)有些盆友私信我問到,這些 api 除了可以批量的按照自定義方式處理文件外,還可以干啥?結(jié)合近期學(xué)習(xí)和實(shí)踐,提供以下五個(gè)方向供大家參考,具體參考示例代碼:

5.1系統(tǒng)集成能力

# 與現(xiàn)有系統(tǒng)集成示例
from ragflow import RAGPipeline
import your_company_database


# 從公司數(shù)據(jù)庫(kù)獲取文檔
documents = your_company_database.get_latest_documents()


# 使用RAGFlow處理
pipeline = RAGPipeline()
for doc in documents:
    pipeline.add_document(doc)
    
# 將結(jié)果同步回公司系統(tǒng)
processed_results = pipeline.get_indexed_status()
your_company_database.update_document_status(processed_results)

5.2定制化檢索策略

# 自定義混合檢索策略
from ragflow import RetrievalPipeline
from ragflow.retrievers import VectorRetriever, KeywordRetriever


# 創(chuàng)建自定義的檢索器組合
def custom_hybrid_retriever(query, top_k=10):
    # 使用向量檢索獲取語(yǔ)義相關(guān)結(jié)果
    semantic_results = vector_retriever.retrieve(query, top_k=top_k)
    
    # 使用關(guān)鍵詞檢索獲取精確匹配
    keyword_results = keyword_retriever.retrieve(query, top_k=top_k)
    
    # 自定義融合策略(比如考慮文檔及時(shí)性等)
    results = custom_merge_function(semantic_results, keyword_results, 
                                    recency_weight=0.2)
    return results

5.3高級(jí)處理流程自動(dòng)化

# 創(chuàng)建復(fù)雜的數(shù)據(jù)處理和RAG工作流
from ragflow import DocumentProcessor, Indexer, QueryEngine
import schedule
import time


def daily_knowledge_update():
    # 從多個(gè)來源獲取新文檔
    new_docs = fetch_documents_from_sources()
    
    # 文檔預(yù)處理(去重、格式轉(zhuǎn)換等)
    processed_docs = DocumentProcessor().process_batch(new_docs)
    
    # 增量更新索引
    indexer = Indexer()
    indexer.update_incrementally(processed_docs)
    
    # 生成日?qǐng)?bào)
    report = generate_daily_summary()
    send_email(report)


# 設(shè)置定時(shí)任務(wù)
schedule.every().day.at("01:00").do(daily_knowledge_update)


while True:
    schedule.run_pending()
    time.sleep(60)

5.4自定義評(píng)估和優(yōu)化

# 構(gòu)建RAG系統(tǒng)評(píng)估框架
from ragflow import RAGEvaluator
import matplotlib.pyplot as plt


# 準(zhǔn)備測(cè)試數(shù)據(jù)集
test_queries = load_test_queries()
ground_truth = load_ground_truth_answers()


# 測(cè)試不同的配置
configurations = [
    {"embeddings": "minilm", "chunk_size": 200, "retriever": "hybrid"},
    {"embeddings": "e5-large", "chunk_size": 500, "retriever": "vector"},
    {"embeddings": "bge-large", "chunk_size": 300, "retriever": "hybrid"}
]


results = {}
for config in configurations:
    # 構(gòu)建并測(cè)試每種配置
    rag_system = build_rag_with_config(config)
    eval_results = RAGEvaluator.evaluate(
        rag_system, test_queries, ground_truth
    )
    results[str(config)] = eval_results


# 可視化不同配置的性能比較
plot_evaluation_results(results)

5.5領(lǐng)域特定的增強(qiáng)

# 醫(yī)療領(lǐng)域RAG增強(qiáng)示例
from ragflow import RAGPipeline
from custom_medical_modules import MedicalTermNormalizer, DiseaseEntityExtractor


# 創(chuàng)建領(lǐng)域特定的文檔處理器
medical_processor = DocumentProcessor()
medical_processor.add_transformer(MedicalTermNormalizer())
medical_processor.add_transformer(DiseaseEntityExtractor())


# 構(gòu)建醫(yī)療特定的RAG系統(tǒng)
medical_rag = RAGPipeline(
    document_processor=medical_processor,
    retrieval_augmentors=[
        CitationRetriever(),  # 添加醫(yī)學(xué)文獻(xiàn)引用
        EvidenceLevelClassifier()  # 分類證據(jù)等級(jí)
    ],
    response_formatters=[
        MedicalDisclaimerFormatter(),  # 添加醫(yī)療免責(zé)聲明
        CitationFormatter()  # 格式化引用
    ]
)

當(dāng)然,還有結(jié)合多個(gè)框架使用的示例,我在Medium看到一個(gè)博主使用 LlamaIndex 整合多源數(shù)據(jù)并構(gòu)建索引,然后通過 RAGFlow 的深度解析和重排序優(yōu)化結(jié)果。最后利用 RAGFlow 的引用功能增強(qiáng)答案可信度,同時(shí)調(diào)用 LlamaIndex 的代理進(jìn)行動(dòng)態(tài)數(shù)據(jù)補(bǔ)充。不過,我還沒試過,感興趣的可以測(cè)試下看看。

RAGFlow 等框架的實(shí)際業(yè)務(wù)價(jià)值,不同實(shí)踐經(jīng)驗(yàn)的盆友可能有不同的體會(huì),個(gè)人總結(jié)其實(shí)就是一句話,使用這些框架的 Python API 可以讓我們快速構(gòu)建原型并迭代改進(jìn),比從 0-1 開發(fā)節(jié)省了大量時(shí)間。從而專注于解決業(yè)務(wù)問題,而非技術(shù)細(xì)節(jié)。

責(zé)任編輯:龐桂玉 來源: 韋東東
相關(guān)推薦

2025-03-04 11:01:00

2024-05-22 09:38:25

2025-04-01 09:25:09

2025-04-29 09:15:49

AI數(shù)據(jù)模型

2025-04-01 09:00:00

模型訓(xùn)練開源

2024-10-31 14:46:31

2024-11-19 13:05:40

2009-06-26 10:37:32

樹的匯總

2024-08-01 17:20:55

2023-10-14 17:46:17

RAG提示工程GPT-3

2023-12-18 10:45:31

2025-03-26 11:05:13

2009-09-08 11:26:35

Spring 3.0

2024-01-29 13:56:55

AI數(shù)據(jù)

2025-03-28 08:00:00

RAG文本檢索大模型

2025-04-27 00:30:00

RAG檢索增強(qiáng)生成AI

2024-10-17 09:09:04

2025-04-24 09:04:42

2025-03-10 08:00:00

RAG檢索Reranker

2024-04-19 13:55:36

python小迭代遞歸
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)