ACP(四):RAG工作流程及如何創建一個RAG應用

RAG的工作原理

你在考試的時候有可能會因為忘記某個概念或公式而失去分數,但考試如果是開卷形式,那么你只需要找到與考題最相關的知識點,并加上你的理解就可以進行回答了。

對于大模型來說也是如此,在訓練過程中由于沒有見過某個知識點(比如你們公司的制度文件),因此直接向它提問相關問題會得到不準確的答案;如果在大模型生成內容時,像開卷考試一樣將相關知識提供給它作為參考,那么大模型回答的質量也就會大幅提高了。
這引出了之前提到的一個核心理念:上下文工程(Context Engineering) ,專注于為大模型“上下文窗口”填充恰到好處的信息,以引導其完成特定任務。如果信息太少,模型會“不知道”;如果信息太多或無關,模型的性能會下降,成本也會增加。
而我們即將學習的RAG(Retrieval Augmented Generation,檢索增強生成),是上下文工程中最重要、最有效的技術這一,專門解決大模型“知識不足”的問題,RAG應用通常包含建立索引檢索生成兩部分。

建立索引

你可能會在考試前對參考資料做標記,來幫助你在考試時更容易地找到相關信息。類似的,RAG應用往往也會在回答前就已經做好了標記,這一過程叫做建立索引,建立索引包括四個步驟:

  1. 文檔解析
    就像你會將書上看到的視覺信息理解為文字信息一樣,RAG應用也需要首先將知識庫文檔進行加載并解析為大模型能夠理解的文字形式。
  2. 文本分段
    你通常不會在某道題時把整本書都翻閱一遍,而是去查找與問題最相關的幾個段落,因此你會先把參考資料做一個大致的分段。類似的,RAG應用也會在文檔解析后對文本進行分段,以便于在后續能夠快速找到與提問最相關的內容
  3. 文本向量化
    在開卷考試時,你通常會先在參考資料中尋找與問題最相關的段落,再去進行作答。在RAG應用,通常需要借助嵌入(embedding)模型分別對段落與問題進行數字化表示,在進行相似度比較后找出最相關的段落,數字化表示的過程就叫做文本向量化
  4. 存儲索引
    存儲索引將向量化后的段落存儲為向量數據庫,這樣RAG應用就無需在每次進行回復時都重復以上步驟,從而可以增加響應速度。
    在這里插入圖片描述

檢索生成

檢索、生成分別對應著RAG名字中的RetrievalGeneration兩階段。檢索就開卷考試時去查找資料的過程,生成則是在找到資料后,根據參考資料與問題進行作答的過程。

  1. 檢索生成
    檢索階段會召回與問題最相關的文本段。通過embedding模型對問題進行文本向量化,并與向量數據庫的段落進行語義相似度的比較,找出最相關的段落。檢索是RAG應用中最重要的環節,你可以想象如果考試的時候找到了錯誤的資料,那么回答一定是不準確的。這個步驟完美詮釋了上下文工程的精髓:從海量知識中“精準地選擇相關信息”來填充上下文。找到最匹配的內容,是保證后續生成質量的第一步。為了提高檢索準確性,除了使用性能強大的embedding模型,也可以做重排(Rerank)、句子窗口檢索等方法。

  2. 生成
    在檢索到相關的文本段后,RAG應用會將問題與文本段通過提示詞模板生成最終的提示詞,由大模型生成回復,這個階段更多是利用大模型的總結能力,而不是大模型本身具有的知識。這個提示詞模板的設計,是上下文工程的另一個關鍵環節。我們不僅要提供檢索到的“資料”,還要明確地“指導”模型如何使用這些資料來回答問題

一個典型的提示詞模板為:請根據以下信息回答用戶的問題:{召回文本段}。用戶的問題是:{question}。
在這里插入圖片描述
它的整體流程圖為:
在這里插入圖片描述

創建RAG應用

一個簡單的RAG應用

# 導入依賴
from llama_index.embeddings.dashscope import DashScopeEmbedding,DashScopeTextEmbeddingModels
from llama_index.core import SimpleDirectoryReader,VectorStoreIndex
from llama_index.llms.openai_like import OpenAILike# 這兩行代碼是用于消除 WARNING 警告信息,避免干擾閱讀學習,生產環境中建議根據需要來設置日志級別
import logging
logging.basicConfig(level=logging.ERROR)print("正在解析文件...")
# LlamaIndex提供了SimpleDirectoryReader方法,可以直接將指定文件夾中的文件加載為document對象,對應著解析過程
documents = SimpleDirectoryReader('./docs').load_data()print("正在創建索引...")
# from_documents方法包含切片與建立索引步驟
index = VectorStoreIndex.from_documents(documents,# 指定embedding 模型embed_model=DashScopeEmbedding(# 你也可以使用阿里云提供的其它embedding模型:https://help.aliyun.com/zh/model-studio/getting-started/models#3383780daf8hwmodel_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2))
print("正在創建提問引擎...")
query_engine = index.as_query_engine(# 設置為流式輸出streaming=True,# 此處使用qwen-plus模型,你也可以使用阿里云提供的其它qwen的文本生成模型:https://help.aliyun.com/zh/model-studio/getting-started/models#9f8890ce29g5ullm=OpenAILike(model="qwen-plus",api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",api_key=os.getenv("DASHSCOPE_API_KEY"),is_chat_model=True))
print("正在生成回復...")
streaming_response = query_engine.query('我們公司項目管理應該用什么工具')
print("回答是:")
# 采用流式輸出
streaming_response.print_response_stream()
正在解析文件...
正在創建索引...
正在創建提問引擎...
正在生成回復...
回答是:
項目管理應使用項目管理軟件,如Jira、Trello。這些工具可用于需求溝通、任務分配和進度跟蹤,配合協作工具如Slack或Microsoft Teams,能夠有效提升團隊協作效率。

保存與加載索引

你可能會發現,創建索引消耗的時間比較長。如果能夠將索引保存到本地,并在需要使用的時候直接加載,而不是重新建立索引,那就可以大幅提升回復的速度,LlamaIndex提供了簡單易實現的保存與加載索引的方法

# 將索引保存為本地文件
index.storage_context.persist("knowledge_base/test")
print("索引文件保存到了knowledge_base/test")

存在目錄列表會出現以下幾個文件:
在這里插入圖片描述

文件名作用說明
default__vector.json文本向量存儲存儲所有文本 chunk 的向量(embedding)及其對應的節點 ID。檢索時會用這些向量做相似度搜索。
image__vector.json圖片向量存儲如果你的文檔中有圖片,或者你用過圖片 embedding,這里會存儲圖片的向量。沒有圖片時可能為空或不存在。
docstore.json文檔存儲存儲原始的 Document 對象(包括文本內容、元數據等),用于在檢索到節點后還原原文。
graph_store.json圖結構存儲存儲索引的圖結構信息(節點之間的關系、父子節點等),主要用于分層索引(TreeIndex、GraphIndex)等。
index_store.json索引元信息存儲存儲索引的元數據(索引類型、版本、向量存儲的引用等),加載索引時會先讀取這個文件來恢復結構。
index_store.json├── 引用 → default__vector.json  (文本向量)├── 引用 → image__vector.json    (圖片向量)├── 引用 → docstore.json         (原始文檔)└── 引用 → graph_store.json      (節點關系)

🤔LlamaIndex 在 persist() 保存索引時,不同模型(Embedding 模型、LLM 模型)生成的文件會不會不一樣?

  1. 核心結論
    文件的種類和結構主要取決于 索引類型(VectorStoreIndex、TreeIndex、ListIndex 等)和數據類型(文本、圖片、音頻等),不是直接由模型決定的。
    文件的內容會因為你用的模型不同而不同(尤加粗樣式其是向量文件),但文件名和整體結構大體是一樣的。
  2. 為什么文件名大體固定
    LlamaIndex 的持久化是基于 StorageContext 的,它會把不同類型的數據存到不同的 Store 里:
    DocStore → docstore.json(原始文檔)
    VectorStore → default__vector.json / image__vector.json(向量數據)
    GraphStore → graph_store.json(節點關系)
    IndexStore → index_store.json(索引元信息)
    這些 Store 的名字是固定的,所以文件名也基本固定。
  3. 模型不同,變化在哪里?
    Embedding 模型不同 → default__vector.json(或 image__vector.json)里的向量值會不同,因為不同模型生成的向量維度、數值分布不一樣。
    例如:
    OpenAI: text-embedding-3-small → 1536 維向量
    阿里云: DashScope TEXT_EMBEDDING_V2 → 1024 維向量
    硅基流動: text-embedding-3-large → 3072 維向量
    維度不同會直接影響向量文件的內容和大小。
    是否有圖片/多模態數據 → 決定是否生成 image__vector.json。
    索引類型不同 → 決定是否生成 graph_store.json(比如 TreeIndex 會用到)。
    LLM 模型不同 → 不會直接影響這些持久化文件,因為 LLM 主要在查詢階段用,不會存到索引文件里(除非你把 LLM 生成的內容當作文檔再存)。
# 將本地索引文件加載為索引
from llama_index.core import StorageContext,load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="knowledge_base/test")
index = load_index_from_storage(storage_context,embed_model=DashScopeEmbedding(model_name=DashScopeTextEmbeddingModels.TEXT_EMBEDDING_V2))
print("成功從knowledge_base/test路徑加載索引")

LlamaIndex 會:
讀取 index_store.json → 確定索引類型和引用的文件。
加載 default__vector.json(或 image__vector.json)→ 獲取向量和元數據。
加載 docstore.json → 獲取原文。
如果有 graph_store.json → 加載節點關系。

從本地加載索引后,你可以再次進行提問測試是否可以正常工作。

print("正在創建提問引擎...")
query_engine = index.as_query_engine(# 設置為流式輸出streaming=True,# 此處使用qwen-plus模型,你也可以使用阿里云提供的其它qwen的文本生成模型:https://help.aliyun.com/zh/model-studio/getting-started/models#9f8890ce29g5ullm=OpenAILike(model="qwen-plus",api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",api_key=os.getenv("DASHSCOPE_API_KEY"),is_chat_model=True))
print("正在生成回復...")
streaming_response = query_engine.query('我們公司項目管理應該用什么工具')
print("回答是:")
streaming_response.print_response_stream()

你可以將上述代碼進行封裝,以便在后續持續迭代時快速使用。

from chatbot import rag# 引文在前面的步驟中已經建立了索引,因此這里可以直接加載索引。如果需要重建索引,可以增加一行代碼:rag.indexing()
index = rag.load_index(persist_path='./knowledge_base/test')
query_engine = rag.create_query_engine(index=index)rag.ask('我們公司項目管理應該用什么工具', query_engine=query_engine)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/98043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/98043.shtml
英文地址,請注明出處:http://en.pswp.cn/web/98043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

宇視設備視頻平臺EasyCVR視頻設備軌跡回放平臺監控攝像頭故障根因剖析

監控攝像頭的類型繁多,市場上提供了廣泛的選擇。然而,在使用監控攝像頭的過程中,用戶可能會遇到云臺在很短的時間內出現運轉不靈或完全無法轉動的問題。這里,我們將對這一常見問題進行深入分析。一、具體的原因: 1、距…

【Uni-App+SSM 寵物項目實戰】Day15:購物車添加

大家好!今天是學習路線的第15天,我們正式進入訂單與購物車核心模塊。昨天完成了商家服務列表的分頁加載,今天聚焦“購物車添加”功能——這是連接“商品瀏覽”與“訂單提交”的關鍵環節,用戶可將寵物用品(如糧食、玩具)加入購物車,后續統一結算。 為什么學這個? 購物車…

Java 黑馬程序員學習筆記(進階篇6)

常用的 API1. 正則表達式(1) 題目:貪婪爬取和非貪婪爬取① 貪婪爬取:爬取數據的時候盡可能的多獲取數據 ② 非貪婪爬取:爬取數據的時候盡可能的少獲取數據 ③ Java中默認的是貪婪爬取 ④ 后面加上 ? 可以轉變為非貪婪爬取(2) 捕獲分組捕獲分…

計算機網絡---數據鏈路層上

文章目錄1. 數據鏈路層的功能2. 組幀2.1 字符填充法2.2 字節填充法2.3 零比特填充法2.4 違規編碼2.5 總結3. 差錯控制3.1 檢錯編碼3.1.1 奇偶校驗3.1.2 循環冗余校驗碼(CRC)3.1.3 總結3.2 糾錯編碼(海明校驗碼)3.3 總結4. 流量控制…

機器學習實戰項目中,回歸與分類模型中該如何科學定義目標變量Y?

前言 在機器學習項目里,目標變量 (Y) 的定義決定了你能解答什么問題,以及模型能給業務帶來什么價值。選擇不當不僅可能導致模型誤差大、偏差嚴重,還可能讓業務決策方向偏離。 本文分兩大場景: 供應鏈項目中的 銷量預測&#xff08…

【 C/C++ 算法】入門動態規劃-----一維動態規劃基礎(以練代學式)

每日激勵:“不設限和自我肯定的心態:I can do all things。 — Stephen Curry” 緒論?: 本章是動態規劃算法的基礎入門篇,我將通過三道簡單題 一道中等難度的一維動態規劃題來帶你對動態規劃有個初認識,并基本了解動…

深入對比Tomcat與Netty:HTTP請求從網卡到Controller的全鏈路追蹤

我們日常用Spring Boot寫的RestController,感覺上就是一個簡單的方法,但它背后其實有一套復雜的網絡服務在支撐。一個HTTP請求到底是怎么從用戶的瀏覽器,穿過層層網絡,最終抵達我們代碼里的Controller方法的?理解這個過…

GO學習記錄十——發包

記錄下不同平臺的發包操作和期間遇到的問題 1.命令: $env:GOOSlinux $env:GOARCHamd64 go build -o release/HTTPServices-linux第一行,配置平臺,linux、windows 第二行,配置部署服務器的處理器架構 第三行,輸出目標文…

貪心算法與動態規劃

1. 什么是貪心算法? 貪心算法是一種在每一步選擇中都采取在當前狀態下最好或最優(即最有利)的選擇,從而希望導致結果是全局最好或最優的算法。 核心思想:“每步都貪心地選擇眼前最好的,不去考慮整個未來的長…

學會“讀網頁”:生成式 AI 在足球賽事信息整理中的實戰

逐步教程(Step-by-Step) — 適合初學者與教學類文章 背景(為什么要這樣做) 對于足球迷、資訊編輯與數據分析師來說,最快、最準確把握一場比賽的核心信息至關重要:比分、關鍵事件(進球、點球、紅…

BM3D 圖像降噪快速算法的 MATLAB 實現

BM3D 圖像降噪快速算法的 MATLAB 實現1. 快速 BM3D 算法流程(概述)步驟操作加速技巧① 分組塊匹配 堆疊FFT 互相關② 協同濾波3D 變換 硬閾值FFT 沿第三維③ 聚合加權平均稀疏矩陣累加 2. 核心函數(單文件版) 保存為 bm3d_fast.…

Go的schedt調度(runtime/proc.go)

1. 創建go的入口函數// Create a new g running fn. // Put it on the queue of gs waiting to run. // The compiler turns a go statement into a call to this. func newproc(fn *funcval) {gp : getg()pc : sys.GetCallerPC()systemstack(func() {newg : newproc1(fn, gp, …

Ubuntu 服務器配置轉發網絡訪問

配置文檔:Ubuntu 服務器轉發網絡訪問 一、網絡拓撲以以下網絡拓撲為示例Ubuntu 服務器(兩個網卡) eth1 10.66.71.222 (接入內網)eno1 192.168.2.100 (直連相機) 相機ip 192.168.2.1 Windows 客…

為什么企業需要高防IP

1. 抵御日益猖獗的DDoS攻擊 現代DDoS攻擊規模已突破Tbps級別 傳統防火墻無法應對大規模流量攻擊 高防IP采用分布式清洗中心,可輕松抵御300Gbps以上的攻擊流量 2. 保障業務連續性 網絡中斷1小時可能造成數百萬損失 高防IP確保服務99.99%可用性 智能切換機制實…

CSS基礎 - 選擇器備忘錄 --筆記5

目錄基礎選擇器組合器偽類選擇器屬性選擇器選擇器可以選中頁面上的特定元素并為其指定樣式。 CSS有多種選擇器。 基礎選擇器 標簽選擇器 – tagname:匹配目標元素的標簽名。優先級是0,0,1。如:p、h1、div類選擇器 – .class:匹配class屬性中…

自動駕駛中的傳感器技術46——Radar(7)

衛星雷達(又稱為分布式雷達)主要講當前雷達的雷達信號處理計算以及雷達目標相關的一些感知算法都遷移到中央域控進行,雷達端基本只負責數據采集,這樣做的影響如下: 雷達端成本與功耗降低; 雷達端采樣得到的…

【論文閱讀】Diff-Privacy: Diffusion-based Face Privacy Protection

基于擴散模型的人臉隱私保護方法——DiffPrivacy,解決了兩類人臉隱私任務:匿名化(anonymization)和視覺身份信息隱藏(visual identity information hiding)。1. 研究背景隨著人工智能和大數據技術的普及&am…

React 原理篇 - 深入理解虛擬 DOM

一、什么是虛擬 DOM? 在前端開發中,“虛擬 DOM” 是一個高頻出現的術語,尤其在 React 生態中被廣泛討論。但很多開發者對它的理解往往停留在 “JS 對象” 這個表層認知上。 實際上,虛擬 DOM 是一種編程概念—— 在這個概念里&…

對匯編的初理解

此處是一個簡單的函數,里面將調用了一個函數add()函數這里是函數的原型這里是調用lcd函數產生的匯編語言,翻譯過來就是r11,r0cnt(r4cnt,前文有提及),然后調用add函數,此處BL是指會回到指令的下一…

《Python 自動化實戰:從零構建一個文件同步工具》

《Python 自動化實戰:從零構建一個文件同步工具》 一、開篇引入:為什么我們需要文件同步? 你是否有過這樣的困擾: 公司電腦和家里電腦上都有工作項目,每次更新都要手動復制? U 盤頻繁傳輸文件,不僅麻煩還容易出錯? 項目文件夾動輒幾 G,每次同步都耗時長、效率低? 在…