<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RAGFlow on YennJ12 Engineering Blog</title><link>https://yennj12.js.org/yennj12_blog_V4/tags/ragflow/</link><description>Recent content in RAGFlow on YennJ12 Engineering Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 10 Sep 2026 13:00:00 +0800</lastBuildDate><atom:link href="https://yennj12.js.org/yennj12_blog_V4/tags/ragflow/feed.xml" rel="self" type="application/rss+xml"/><item><title>RAGFlow Intro Part 1 — 全景架構 — 從一份 PDF 到一句帶引用的答案</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part1-overview-architecture-zh/</link><pubDate>Thu, 10 Sep 2026 09:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part1-overview-architecture-zh/</guid><description>大多數人讀 RAG 開源專案的方式，是打開 README，跑 docker compose up，上傳一份 PDF，看到答案出來就說「我懂了」。 真正的答案是：一個生產級 RAG 引擎有 80% 的複雜度不在「呼叫 LLM」那一行，而在資料怎麼被解析、怎麼被切、怎麼被編碼、怎麼被存、怎麼被取回、以及取回之後怎麼證明它沒有胡說。 Demo 只需要 200 行。引擎需要一整套子系統。 這個系列拆解的是後者。
前言：這個系列要做什麼 RAGFlow （InfiniFlow，Apache-2.0，2023-12-12 開源）是目前最受關注的開源 RAG 引擎之一：GitHub 上約 9.0 萬顆星、1.06 萬 fork，官方定位是「a leading open-source RAG engine that fuses cutting-edge RAG with Agent capabilities to create a superior context layer for LLMs」。
它值得逐層讀完，理由不是星星數，而是：它把 RAG 每一個環節都實作成可替換的元件，而且每個選擇背後都有明確的理由。 讀它等於讀一份「RAG 系統設計的參考答案」。
這個系列分成五篇：
Part 主題 對應原始碼 Part 1（本篇） 全景架構、資料的兩條路徑、部署形態 docker/、conf/、整體 Part 2 資料進場：DeepDoc 解析與 Chunking 策略 deepdoc/、rag/app/、rag/nlp/ Part 3 Encode 與 Save：向量化、索引 Schema、雙引擎抽象 conf/mapping.</description></item><item><title>RAGFlow Intro Part 2 — 資料進場 — DeepDoc 解析、Chunking 策略與 14 種模板</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part2-deepdoc-chunking-zh/</link><pubDate>Thu, 10 Sep 2026 10:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part2-deepdoc-chunking-zh/</guid><description>大多數人處理 RAG 的文件解析，是 PyPDF2.extract_text() 加一個 RecursiveCharacterTextSplitter(512, 50)，然後把精力全部投在 prompt 上。 真正的答案是：如果 chunk 是壞的，prompt 再怎麼調都是在補救；而 chunk 的品質，在解析那一步就已經決定了 80%。 「Quality in, quality out」不是口號，它是一個工程順序的宣告。 這篇文章拆的就是 RAGFlow 的「in」。
前言 Part 1 畫完了 RAGFlow 的全景圖。本篇下鑽到 ingestion 路徑的前半段——從一個二進位檔案，到一組準備好被編碼的 chunk。
這一段對應兩個目錄：
deepdoc/ 「這份文件長什麼樣子」 ← 視覺與格式理解 ├── vision/ OCR / 版面辨識 / 表格結構辨識（ONNX 模型） └── parser/ 19 個格式解析器 + 外部解析後端接入 rag/app/ 「這份文件該怎麼切」 ← 14 種切分模板 rag/nlp/ 切分契約與分詞（__init__.py 68 KB，delim.py，rag_tokenizer.py） 順序很重要：先理解版面，再決定切法。 反過來就是 naive RAG。
一、核心問題：為什麼「抽文字」不等於「解析」 先看一個具體的失敗案例。一份雙欄排版的論文 PDF，用純文字抽取會得到：
Abstract 1. Introduction ← 兩欄的標題被讀成同一行 We propose a novel Recent work ← 左欄句子 + 右欄句子黏在一起 method for in retrieval-augment document ed generation has understanding.</description></item><item><title>RAGFlow Intro Part 3 — Encode 與 Save — 向量化、索引 Schema 與雙引擎抽象</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part3-embedding-indexing-zh/</link><pubDate>Thu, 10 Sep 2026 11:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part3-embedding-indexing-zh/</guid><description>大多數人處理 RAG 的儲存，是 collection.add(documents=chunks, embeddings=vecs)，然後就不再想這件事。 真正的答案是：索引的 schema 決定了你三個月後能做什麼查詢；相似度函式決定了你的關鍵字檢索是有效還是裝飾；欄位命名決定了你換 embedding 模型要不要重建整個索引。 這些決定在寫入的那一刻就凍結了。 這篇文章拆的是 RAGFlow 在那一刻做的每一個選擇。
前言 Part 2 結束時，我們手上有一組 chunk：純文字、可能帶版面座標、可能帶人工或 LLM 產生的關鍵字與問句。
本篇處理接下來兩步：
chunks ──▶ ① Encode（向量化） ──▶ ② Save（寫進 doc engine + 物件儲存） rag/svr/task_executor.py conf/mapping.json rag/llm/embedding_model.py rag/utils/*_conn.py 這兩步看起來機械，實際上藏了 RAGFlow 最有辨識度的幾個設計。我們從最反直覺的一個開始。
一、Encode：為什麼向量是「檔名 × 0.1 + 內容 × 0.9」 task_executor.py 的 embedding() 函式，核心只有幾行：
1async def embedding(docs, mdl, parser_config=None, callback=None): 2 tts, cnts = [], [] 3 for d in docs: 4 tts.</description></item><item><title>RAGFlow Intro Part 4 — Decode 與檢索 — 混合搜尋、Rerank、GraphRAG/RAPTOR 與引用</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part4-retrieval-rerank-zh/</link><pubDate>Thu, 10 Sep 2026 12:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part4-retrieval-rerank-zh/</guid><description>大多數人談 RAG 的檢索，是「向量搜尋 top-5，然後塞進 prompt」。 真正的答案是：檢索是一條有六個階段的管線——問句改寫、查詢編譯、雙路召回、融合、重排、上下文擴展——而每個階段都有自己的失敗模式和自己的權重。 向量相似度只是其中一個訊號，而且通常不是最重要的那個。 這篇文章把 RAGFlow 的每一個權重、每一個閾值、每一個退避策略都攤開來。
前言 Part 3 把資料放進了索引。本篇是反向操作：一句人話進來，一組帶引用的答案出去。
主戰場是兩個檔案：
rag/nlp/query.py （9.5 KB） 查詢編譯器：人話 → 加權布林查詢 rag/nlp/search.py （45 KB） 召回、融合、重排、引用對齊 加上兩個進階模組：
rag/graphrag/ GraphRAG（general / light / ner 三種抽取策略 + 社群報告） rag/svr/task_executor_refactor/raptor_service.py RAPTOR 摘要樹 以及生成端：
api/db/services/dialog_service.py 對話編排（2200+ 行） rag/prompts/generator.py prompt 組裝與 token 預算 完整管線長這樣：
問句 │ ├─① 問句改寫（3 種，都是 LLM 呼叫，都可關） │ ├─② 查詢編譯（純規則，零 LLM） │ ├─③ 雙路召回（一次請求）─────────┐ │ │ ├─④ 融合（引擎相關） │ 這三步在 │ │ doc engine ├─⑤ 本地重排（應用層） │ 和應用層 │ │ 之間反覆 ├─⑥ Cross-encoder rerank（可選）─┘ │ ├─⑦ 上下文擴展（TOC / children / 表格圖片上下文） │ ├─⑧ 進階召回（GraphRAG / RAPTOR / web search） │ ├─⑨ Prompt 組裝（token 預算） │ └─⑩ 生成 + 事後引用對齊 一、問句改寫：三個可選的 LLM 前置步驟 dialog_service.</description></item><item><title>RAGFlow Intro Part 5 — 系統與程式碼結構 — 服務分層、Task Executor 與 Go 遷移</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part5-system-code-structure-zh/</link><pubDate>Thu, 10 Sep 2026 13:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/ragflow-intro-part5-system-code-structure-zh/</guid><description>大多數人讀開源專案的原始碼，是從 README 跳到 main()，看幾個函式，然後說「架構我懂了」。 真正的答案是：一個系統的架構不在程式碼裡，在進程拓撲、佇列語意、失敗處理與擴充邊界裡。 哪些東西是無狀態的？任務失敗會怎樣？要加一倍吞吐要改什麼？這三個問題答得出來，才算讀懂。 這篇文章回答的就是這三個問題。
前言 Part 1 到 Part 4 拆完了資料的完整生命週期。本篇回到工程層：這些邏輯是怎麼被組織成一個能跑、能擴、能維護的系統的。
要處理的問題：
① 有幾個進程？誰是無狀態的？擴充要改哪個參數？ ② 一個 HTTP 請求從 nginx 到資料庫，經過幾層？ ③ 非同步任務系統的語意：投遞、消費、確認、取消、重試、超時 ④ 兩套 DAG 引擎（Agent Canvas / Ingestion Pipeline）為什麼要兩套？ ⑤ 為什麼一個 Python 專案的 GitHub 主要語言標成 Go？ 一、程式碼地圖 先給一張完整的目錄職責表。這張表的來源是 repo 自帶的 AGENTS.md（專案給 AI coding agent 的操作指引），它比 docs/ 更貼近當前程式碼。
ragflow/ │ ├── api/ Python API server（Quart + Peewee） │ ├── ragflow_server.py 進程入口（6.5 KB） │ ├── apps/ │ │ ├── restful_apis/ 29 個 API 藍圖（dataset / document / chunk / chat …） │ │ ├── services/ API 層的服務（薄，做參數轉換與編排） │ │ └── auth/ 認證 │ ├── db/ │ │ ├── db_models.</description></item></channel></rss>