成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Dify+RAGFLow:基于占位符的圖片問答升級方案

人工智能
占位符方案能否完全解決 LLM 幻覺?答案是不能完全保證,但是測試下來能極 大降低特定錯誤的概率。

4/2 號時寫了一篇 RAGFlow 實現圖片問答的原理解析,后續在知識星球內有星友陸續反饋在使用我提供的源碼復現時,會出現知識庫中能渲染圖片,但回答中圖片無法正常加載的問題。

圖片

知識庫預覽和引用文件部分是直接展示原始數據或進行簡單渲染,它們能正確顯示圖片,證明原始上傳的增強文本中的 URL 是正確的,并且圖片服務器和網絡配置是通的,問題出在聊天內容生成這個環節。

圖片

我當時提供了三種選擇選擇,分別是:更強的 prompt 指令、更強的 LLM 和”占位符+后處理“的方案,鑒于后續大家反饋前兩種效果依然不夠穩定,這篇我來系統的分享下如何實現第三種更符合實際生產場景的 RAG 富文本處理方案。

圖片

這篇試圖說清楚:

占位符方案如何將圖片 URL 幻覺問題,從一個難以控制的“語義幻覺”轉變為一個相對更容易處理的“格式遵循”問題,從而極大降低圖片顯示錯誤的概率。它不是銀彈,但通常是處理富文本(圖文混排)RAG 中最實用的工程方法之一。

以下,enjoy:

1、占位符方案的好處

LLM 的核心行為是生成文本,而非精確復制特定格式的字符串,尤其是當這些字符串看起來像可解釋內容時。

原始問題:

LLM 看到的是`<img src="http://{server_ip}:8000/images/..." alt="..." width="...">`這樣的標簽,它看起來像是有意義的 HTML 和 URL。LLM 嘗試"理解"上下文,并可能基于文本內容(比如“燃油噴射器泄漏圖”)重新生成一個它認為更合適的 src(例如改成 .../fuel_injector_leak.png),導致 URL 失效。 

占位符方案:

LLM 看到的是 [IMG::page1_img1_uuid.png] 這樣的特殊標記。這種格式更像是一個代碼片段或元數據標簽,而不是自然語言或標準 HTML。LLM 被明確指示(通過 Prompt)要將其視為特殊標記,如果需要引用就原樣復制。它"創造性地"修改這種標記的動機和可能性都大大降低了。它不太可能去"理解" page1_img1_uuid.png 并把它改成 fuel_injector_leak.png。 

1.1降低 LLM 修改風險

占位符通常是簡單的、非描述性的文本字符串(如 [IMG::page1_img1_eef46633] 或類似的格式)。LLM 在生成回答時,更有可能將這些占位符視為需要原樣保留的特殊標記或代碼片段,而不是像 HTML <img> 標簽那樣容易被“理解”和“重構”的內容。

1.2解耦內容與表示

將圖片的存在(通過占位符表示)與其具體的網絡位置(URL)分離。LLM 專注于基于文本內容(包括占位符)生成連貫的回答,而圖片渲染的細節則由后續步驟處理。

1.3更強的控制力

通過后處理步驟,我們可以精確地控制最終呈現給用戶的 <img> 標簽的格式,確保 URL 和其他屬性(如 alt, width)的準確性。

2、后處理步驟是關鍵

這個方案的核心在于,在 LLM 從 RAGFlow 獲得包含占位符的回答后,必須有一個后處理步驟。這個步驟負責查找回答中的所有占位符,并使用之前存儲的映射關系將其替換回完整的 HTML <img> 標簽。大致有以下兩種實現方式:

2.1直接使用 ragflow_sdk (不推薦)

優點是,我們可以完全控制整個流程,集成度高。在獲取到 chat.answer() 的結果(包含占位符的文本)后,可以立即執行 Python 代碼進行替換,然后再將最終結果呈現給用戶或傳遞給下游系統。 

缺點也很明顯,這種方式通常意味著我們需要自行構建用戶界面 (UI) 或者將 RAG 邏輯嵌入到一個更大的后端應用中。標準的 RAGFlow Web UI 是與其自身后端緊密集成的,不太可能直接支持你在調用鏈中插入自定義的 Python 后處理步驟。而修改 RAGFlow UI 來支持這一點會非常復雜。

2.2使用 Dify 工作流(推薦)

Dify 提供了強大的可視化工作流編排能力,我們可以清晰地看到數據流轉。將 RAGFlow 作為知識庫(通過其 API)接入,LLM 調用作為另一個節點,而后處理邏輯則封裝在 Dify 的 "Code" 節點中,職責清晰。

圖片

Dify+RAGFlow:1+1>2的混合架構,詳細教程+實施案例

總結來說,通過 Dify 工作流中的 Code 節點實現后處理邏輯是完全可行的,并且可能是更靈活、更易于管理的方案,特別是如果你希望利用現成的或 Dify 提供的 UI 時。

3、映射關系的存儲和訪問

我們需要一種方便且穩定的方式來存儲和檢索占位符 -> URL 的映射。 存儲環節,在處理 PDF 時,將生成的映射關系與增強文本一起保存,例如存為一個 JSON 文件,其名稱與知識庫或文檔相關聯。 檢索環節,在進行聊天并需要進行后處理時,需要能夠加載與當前知識庫/助手相關的映射文件。具體實現上我試過如下三種方式,推薦最后一種。

3.1映射關系作為知識庫

這個做法是我最先想到的一種。就是將映射關系保存為 TXT 文件并上傳到 RAGFlow 單獨知識庫,利用 RAGFlow 的 "One" 分塊策略來確保整個映射文件作為一個單元被檢索,避免了映射關系被分割的問題。

但仔細想了下意識到,實際測試在本地預處理腳本(如 process_pdf.py)運行時,我們無法知道 RAGFlow 將為即將上傳的原始文檔(例如,從 PDF 生成的增強文本文件)分配的 document_id。 document_id 是在調用 dataset.upload_documents() 之后由 RAGFlow 系統生成的。本地腳本在調用此 API 之前運行,因此無法預先獲取這個 ID。

3.2共享文件系統方案

這里需要先解釋一個 Docker 卷掛載的概念,這是一種將宿主機(運行 Docker 的機器)上的目錄或文件鏈接到 Docker 容器內部指定路徑的機制。它允許容器訪問宿主機上的文件,并且宿主機和容器之間的數據是實時同步的(在掛載的目錄內)。

圖片

當我們運行 process_pdf.py 腳本會生成映射文件 (.json) 并保存在宿主機的一個特定目錄下(例如 ~/ragflow_project/mappings)。 Dify 應用在其工作流的 Code 節點里需要讀取這些 .json 文件。 通過卷掛載,我們可以把宿主機上的 ~/ragflow_project/mappings 目錄映射到 Dify 容器內部的一個路徑(例如 /data/mappings)。 這樣,Dify 容器內的 Code 節點就可以像訪問本地文件一樣,通過路徑 /data/mappings/{unique_id}.json 來讀取映射文件了。

但是這個方案我測試下來沒有成功,docker exec 一直顯示 "No such file or directory",這意味著在 docker-compose.yaml 中為 api 服務定義的 volume 掛載沒有成功。可能是因為 Docker Desktop 正在使用 WSL 2 后端,WSL 2 有更原生的方式訪問 Windows 文件系統(通常通過 /mnt/c, /mnt/d 等路徑),不再依賴舊的 Hyper-V 文件共享設置。一時半會沒研究明白,再加上這并不是一個適合在生產場景使用的方案,就果斷棄了。

3.3阿里云 OSS(或其他云對象存儲)

在考慮技術方案時,必須充分考慮實際生產場景,尤其是多用戶并發訪問和部署架構帶來的影響。OSS 方案更適合生產環境,原因有以下幾點:

  • 解耦存儲: 將映射文件存儲在獨立、高可用的云存儲中,而不是依賴本地文件系統。
  • 避免本地環境問題: 不再受 Windows 路徑、WSL 2 掛載、Docker Desktop 配置等本地復雜性的影響。 
  • 可擴展性好: OSS 可以輕松處理大量文件和高并發訪問。 
  • 部署更簡單: Dify 容器不再需要特殊的文件系統掛載,只需要配置好訪問 OSS 的網絡和憑證即可。
    阿里云OSS訪問地址:https://oss.console.aliyun.com/overview

4、OSS 配置流程

4.1獲取 OSS 訪問憑證

Access Key ID、Access Key Secret、Endpoint、Bucket Name (你用于存儲映射文件的存儲桶名稱) ,以及一個用于存放映射文件的目錄前綴 (例如 mappings/)

4.2交互方式選擇

關于 Dify 中 code 節點和 OSS 的交互方式,最初我是默認選擇使用 OSS SDK 的方式,結果發現報錯:ModuleNotFoundError: No module named 'oss2' ,這說明 Dify 為 Code 節點提供的沙箱環境沒有包含阿里云 OSS 的 SDK。這和 Coze 一樣是一個常見的限制,沙箱環境通常只包含一組有限的基礎庫。 

圖片

所以使用 HTTP Request 節點是快速驗證核心邏輯的好方法, 既然 Dify Code 節點無法直接與 OSS SDK 交互,我們可以讓 Dify 的 HTTP Request 節點來負責獲取映射文件的內容,然后將獲取到的內容傳遞給 Code 節點進行處理。

圖片

4.3配置 Bucket 自定義域名

在確定了使用 http 節點訪問映射文件后,我們還有個問題需要克服。就是阿里云 OSS 出于安全考慮,對于使用 OSS 默認域名 (如 xxx.oss-cn-shanghai.aliyuncs.com)或傳輸加速域名訪問時,會強制在返回頭中增加 x-oss-force-download: true 和 Content-Disposition: attachment。這會導致瀏覽器或 HTTP 客戶端(如 Dify 的 HTTP 節點)強制下載,即使你設置了對象的 Content-Disposition: inline 元數據。

圖片

因此 Dify HTTP 節點會將響應體識別為一個文件,因此 body 字段為空,而將文件信息放入了 files 數組中。它實際上已經成功下載了文件內容,只是沒有直接放在 body 里。官方推薦的方法是為你的 OSS Bucket 綁定一個你自己的、已備案的域名(正好有一個剛做好 ICP 備案)。

圖片

如果你沒有備案過的域名,為了完成測試可以使用template節點中直接填寫映射關系的內容,實測這樣和http節點效果是一致的。

然后要修改 Dify HTTP 節點中的請求 URL,使用這個自定義域名來訪問你的 JSON 文件,而不是使用 OSS 的默認域名。 訪問通過自定義域名的文件時,OSS 通常會尊重你在對象元數據中設置的 Content-Disposition: inline,從而允許預覽而不是強制下載。

圖片

在OSS點擊域名管理

圖片

在域名控制臺解析到OSS存儲位置

5、工作流解析

圖片

文檔預處理: 提取 PDF 中的圖片和文本。在生成的文本中,用唯一的占位符(例如 [IMG::page1_img1_uuid.png])標記圖片的位置,而不是直接插入 <img> 標簽。

映射關系存儲: 將"占位符"到"實際圖片訪問 URL"(指向獨立的圖片服務器)的映射關系保存為一個 JSON 文件,并將其上傳到阿里云 OSS 對象存儲中,以便后續訪問。

獨立圖片服務: 運行一個獨立的 Docker 容器作為圖片服務器,負責托管從 PDF 中提取的圖片文件,并通過 HTTP 提供訪問(例如 http://<your-server-ip>:8000/images/...)。

RAG 流程: RAGFlow 知識庫僅存儲包含占位符的純文本。

圖片

后端處理 (Dify): 使用 Dify 工作流編排 RAG 查詢和 LLM 調用。在 LLM 生成包含占位符的回答后:

圖片

使用 Dify 的 HTTP Request 節點從 OSS 獲取對應的映射關系 JSON 文件(通過自定義域名訪問)。

使用 Dify 的 Code 節點解析 JSON,查找回答中的占位符,并將其替換回完整的 <img> HTML 標簽,其 src 指向圖片服務器的 URL。

6、QA/故障排除

Q: Dify Code 節點報錯 ModuleNotFoundError: No module named 'oss2 

A: Dify Code 節點的沙箱環境不包含 oss2 庫。解決方案是改用 Dify 的 HTTP Request 節點來獲取 OSS 上的映射文件內容(需要文件可公開訪問或使用預簽名 URL),然后將獲取到的字符串內容傳遞給 Code 節點進行 JSON 解析和處理。

Q: Dify HTTP Request 節點訪問 OSS URL 返回空 body,但在 files 數組中有內容

A: 這是因為 OSS 返回了 Content-Disposition: attachment 頭,Dify 將其視為文件下載。解決方案是在上傳映射文件到 OSS 時(在 process_pdf.py 中),明確設置 headers={'Content-Disposition': 'inline'}。

Q: 瀏覽器訪問圖片服務器 URL (http://:8000/images/...) 返回 "Not Found",但 curl http://localhost:8000 成功

A: 這通常是 Docker Volume 掛載問題 (尤其在 Windows/WSL2)。正在運行的 image-server 容器內的 /app/images 沒有同步宿主機 ./images 目錄的最新內容。解決方案:停止并刪除舊的 image-server 容器 (docker stop/rm),然后使用正確的 -v <宿主機絕對路徑>:/app/images 參數重新運行 docker run 命令啟動新容器。

圖片

7、寫在最后

7.1殘余風險

占位符方案能否完全解決 LLM 幻覺?答案是不能完全保證,但是測試下來能極 大降低特定錯誤的概率。 需了解的殘余風險包括:

  • 完全省略占位符: 如果它認為圖片不重要或與回答關系不大。 
  • 輕微修改占位符: 比如不小心加了空格、改變了括號 [ IMG:: ... ],或者截斷了文件名。這可能導致后續的 Code 節點正則匹配失敗。 
  • 在錯誤的位置插入占位符。 

7.2、圖片分頁問題

如何確保圖片鏈接與其所屬頁面的主要文本內容在同一個塊中,并且最好位于該塊的開頭或明確關聯的位置。這個問題我三天前在知識星球專門寫過一篇回復,大致有兩種方式:

圖片

1、改變圖片鏈接的插入時機和位置,圖片鏈接緊隨頁面開始標記,與該頁文本強關聯。即使默認分塊器在頁面中間分割,圖片鏈接也更有可能和頁面開頭的文本在一起。添加的 --- Page X Start/End --- 分隔符為后續更精細的分塊(方案二)打下基礎。

2、通過 paragraph_separator="\n--- Page ",強制分塊器在頁面邊界(或你定義的分隔符)處進行切割,最大程度保證頁面內容的完整性。

需要確保方案一中的分隔符 --- Page X Start/End --- 能夠被 \n--- Page 這個模式匹配到并作為切割點。

7.3正本清源

通過HTTP請求獲取并展示圖片(例如替換占位符)能夠顯著提高最終答案的可讀性和用戶體驗,但這屬于 RAG 流程末端(生成與呈現) 的優化。輸出格式的優化(如加入圖片)雖然重要,但屬于錦上添花,必須建立在核心檢索和生成能力達標的基礎上。

而從構建一個高質量、高效率 RAG 項目的基礎來看,數據預處理和分塊策略優化,絕對是更早期、更核心、也往往是決定 RAG 系統性能上限的關鍵工作。

后續幾篇我會回過頭來,從數據預處理(例如 MinerU、Mistral OCR等橫評)、動態分塊策略進一步寫些實踐經驗。

責任編輯:龐桂玉 來源: 韋東東
相關推薦

2025-04-25 01:30:00

RAGFlowDifyMiniO

2025-04-11 09:02:47

2025-04-07 07:00:00

2022-05-25 09:15:01

Swift 5.6占位符

2022-06-13 09:02:06

Swift類型占位符

2023-10-27 13:59:30

Mybatis占位符

2022-06-07 14:47:43

飛書智能問答模型

2025-05-28 01:00:00

大模型智能問答AI

2021-09-29 08:08:13

前端技術編程

2009-12-15 14:45:52

水星路由器升級

2009-07-22 07:41:00

Scala函數文本占位符語法

2024-06-20 11:52:44

C#占位符代碼

2025-05-22 06:39:08

2025-05-30 00:00:00

2025-06-20 08:52:58

2025-06-12 10:27:02

2025-05-30 03:00:00

RAGFlow

2025-04-14 00:40:00

2021-02-20 11:40:35

SpringBoot占位符開發技術

2011-09-19 14:16:22

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧美精品国产一级在线 | 午夜精品一区二区三区免费视频 | 日韩免费福利视频 | caoporn免费 | 97人人超碰 | 久久久久国产精品一区 | 91中文字幕在线 | 国产一区二区三区四区在线观看 | 国产精品精品视频一区二区三区 | 欧美嘿咻 | 亚洲一区二区av | www.蜜桃av | www.久草.com| 国产电影一区二区在线观看 | 欧美在线一二三 | 国产精品1区 | av色在线| 国产有码 | 亚洲精品乱码久久久久久按摩观 | 久久狼人天堂 | 午夜影院在线观看 | 韩日一区| 久久久久资源 | 在线观看视频亚洲 | 中文字幕高清 | 国精产品一区二区三区 | 国产精品久久久精品 | 国产精品综合 | 国产精品美女久久久久 | 亚洲欧美综合 | 久久久久久免费毛片精品 | 中文字幕精品视频 | 手机看片169 | 91在线观看| 久久亚洲欧美日韩精品专区 | 97人人澡人人爽91综合色 | avtt国产| 亚洲网址 | aaa精品| 成人黄色av网址 | 日韩精品一区二区三区视频播放 |