← 回 knowledge index

Knowledge Mirror

RAG 大量文件的多層次儲存與檢索設計

來源筆記:RAG 大量文件的多層次儲存與檢索設計.md

這份文件說明當 RAG 系統面對大量文件時,如何設計多層次儲存、有效率寫入、有效率讀取,以及如何把檢索結果組成可靠回答。 核心目標不是「把所有文件切 chunk 丟進 vector DB」而已,而是建立一套能支援: 大量文件持續寫入 文件更新與增量索引 快速檢索 精準召回 可引用來源 權限過濾 回答品質穩定 的 RAG 架構。 大量文件 RAG 不應只做單層 chunk emb…

RAG 大量文件的多層次儲存與檢索設計

#rag #retrieval #vector-database #system-design #ai-engineering #knowledge-base

這是什麼

這份文件說明當 RAG 系統面對大量文件時,如何設計多層次儲存、有效率寫入、有效率讀取,以及如何把檢索結果組成可靠回答。

核心目標不是「把所有文件切 chunk 丟進 vector DB」而已,而是建立一套能支援:

的 RAG 架構。

核心結論

大量文件 RAG 不應只做單層 chunk embedding。比較穩定的做法是:

Document layer
→ Section layer
→ Chunk layer
→ Fact / Entity layer(選配)

讀取時也不要一開始全庫搜尋 chunk,而應該:

Query 分析
→ 先找相關文件 / 章節
→ 再找精準 chunks
→ rerank
→ context packing
→ LLM 回答
→ citation / verification

有效率的 RAG 系統,本質上是:

寫入時多存索引與摘要,讀取時先粗後細,回答時只餵最有價值的上下文。

一、系統目標

1. 有效率存入

文件進來後,系統應該能:

2. 有效率讀取

使用者查詢時,系統應該能:

3. 有效率回應

回答時,系統應該能:

二、資料分層設計

1. Document Layer:文件層

文件層是整份文件的索引。

適合用來回答:

建議欄位:

{
  "doc_id": "doc_001",
  "source_type": "pdf | markdown | web | notion | google_drive",
  "source_uri": "https://...",
  "title": "退款政策文件",
  "summary": "這份文件說明退款條件、期限與例外情境。",
  "tags": ["policy", "refund", "customer-service"],
  "language": "zh-TW",
  "version": "2026-05-01",
  "content_hash": "sha256...",
  "permission_scope": ["support_team"],
  "created_at": "2026-05-07T10:00:00Z",
  "updated_at": "2026-05-07T10:00:00Z",
  "embedding": "embedding(summary + title)"
}

文件層用途:

2. Section Layer:章節層

章節層代表文件中的自然結構,例如:

1. 退款政策
1.1 可退款條件
1.2 不可退款條件
2. 退貨流程
3. 特殊案例

建議欄位:

{
  "section_id": "sec_001",
  "doc_id": "doc_001",
  "heading_path": ["退款政策", "可退款條件"],
  "section_title": "可退款條件",
  "section_summary": "說明哪些訂單符合退款資格。",
  "start_page": 3,
  "end_page": 5,
  "content_hash": "sha256...",
  "embedding": "embedding(section_summary + heading_path)"
}

章節層用途:

3. Chunk Layer:片段層

chunk 是實際餵給 LLM 的主要內容。

建議欄位:

{
  "chunk_id": "chunk_001",
  "doc_id": "doc_001",
  "section_id": "sec_001",
  "heading_path": ["退款政策", "可退款條件"],
  "text": "使用者在付款後 7 天內,且商品未出貨時,可以申請退款...",
  "token_count": 420,
  "chunk_index": 3,
  "page_start": 4,
  "page_end": 4,
  "prev_chunk_id": "chunk_000",
  "next_chunk_id": "chunk_002",
  "content_hash": "sha256...",
  "embedding": "embedding(text)"
}

Chunk 設計建議:

chunk size:300–800 tokens
overlap:10–20%

實際數字要依文件類型調整:

| 文件類型 | chunk 建議 |

|---|---|

| FAQ | 小 chunk,問題答案成對保留 |

| 法規 / 政策 | 中等 chunk,保留條文完整性 |

| 技術文件 | 按 heading / code block 切 |

| 長篇報告 | 章節摘要 + chunk 混合 |

| 表格 | 優先轉成結構化 records |

4. Fact / Entity Layer:事實層,選配

如果文件中有大量規則、產品規格、政策條件,可以抽成結構化 facts。

例如:

{
  "fact_id": "fact_001",
  "doc_id": "doc_001",
  "section_id": "sec_001",
  "subject": "退款期限",
  "predicate": "是",
  "object": "付款後 7 天內",
  "condition": "商品尚未出貨",
  "source_chunk_id": "chunk_001",
  "confidence": 0.92
}

Fact Layer 適合:

不適合:

三、有效率的寫入設計

寫入流程總覽

Input document
→ Normalize
→ Hash / deduplicate
→ Parse structure
→ Generate document summary
→ Split sections
→ Generate section summaries
→ Split chunks
→ Generate embeddings
→ Store metadata + vectors
→ Build indexes

1. Normalize:格式標準化

所有來源先轉成統一格式。

PDF / HTML / Markdown / Word / Notion
→ canonical markdown / plain text

標準化時要處理:

2. Hash:避免重複寫入

每份文件都算 hash:

doc_hash = sha256(normalized_content)

每個 section / chunk 也算 hash:

section_hash = sha256(section_text)
chunk_hash = sha256(chunk_text)

寫入時先比較:

如果 doc_hash 沒變 → 不重建
如果 section_hash 沒變 → 不重建該章節
如果 chunk_hash 沒變 → 不重算 embedding

這是大量文件系統省成本的關鍵。

3. Parse Structure:保留文件結構

不要只按 token 數硬切。

優先用文件自然結構:

H1 / H2 / H3
PDF outline
章節標題
條文編號
FAQ Q/A
表格 row

如果文件沒有結構,再 fallback 成 token-based chunking。

4. Summary:寫入時預先摘要

寫入時可以先產生:

document_summary
section_summary

這些摘要不是最終回答,而是 retrieval index。

好處:

5. Embedding:分層建立向量

不要只 embedding chunk。

建議至少建立三種 embedding:

document embedding:title + document_summary
section embedding:heading_path + section_summary
chunk embedding:chunk text

選配:

fact embedding:subject + predicate + object + condition

6. Batch 寫入

大量文件寫入時不要一筆一筆寫。

建議:

parse jobs
→ embedding batch jobs
→ vector upsert batch
→ metadata DB transaction

寫入批次設計:

embedding batch size:依模型 API / 本機模型吞吐量調整
vector upsert batch:100–1000 records
metadata insert:transaction

7. 寫入資料庫分工

建議分開:

Metadata DB:Postgres / MySQL / TiDB
Vector DB:pgvector / Milvus / Qdrant / Weaviate / TiDB Vector
Object Storage:原始文件 / normalized markdown

儲存分工:

| 類型 | 存哪裡 |

|---|---|

| 原始文件 | object storage / filesystem |

| normalized text | object storage / DB |

| metadata | relational DB |

| vector | vector DB |

| chunk text | DB 或 object storage |

| access control | metadata DB |

| processing state | job table |

四、有效率的讀取設計

讀取流程總覽

User query
→ Query understanding
→ Permission filter
→ Document / section retrieval
→ Chunk retrieval
→ Rerank
→ Context packing
→ Answer generation
→ Citation

1. Query Understanding

先判斷問題類型:

fact lookup:查明確事實
policy reasoning:查政策並判斷
summary:總結某文件
comparison:比較多文件
troubleshooting:找解法
exploratory:探索式問題

不同問題走不同 retrieval 策略。

| 問題類型 | Retrieval 策略 |

|---|---|

| 明確事實 | fact / chunk 優先 |

| 政策判斷 | section + chunk + fact |

| 文件摘要 | document + section |

| 比較問題 | 多 document retrieval |

| debug / 排錯 | chunk + rerank |

2. Permission Filter

權限一定要在 retrieval 前做,不要等 LLM 看到後再要求它不要說。

WHERE permission_scope includes current_user

這是安全底線。

3. 粗到細檢索

不要直接全庫 chunk search。

建議:

Step 1:document / section search 找候選範圍
Step 2:只在候選範圍內做 chunk search
Step 3:rerank chunks

範例:

query → 找 top 10 sections
→ 在這 10 個 sections 的 chunks 裡找 top 30 chunks
→ rerank 成 top 6 chunks
→ 組 context

4. Hybrid Search

純 vector search 容易漏掉精確詞,例如:

所以建議 hybrid:

vector search + keyword / BM25 search

再合併結果。

5. Rerank

初步 retrieval 找到的是候選,不一定是最好。

Rerank 可以用:

排序因素:

semantic similarity
keyword match
document freshness
source authority
section relevance
user permission
query intent match

6. Context Packing

不要把 top chunks 直接全部塞進 prompt。

要做:

Context 格式建議:

[Source 1]
doc: 退款政策 v2026
section: 退款政策 > 可退款條件
page: 4
text: ...

[Source 2]
doc: 退款政策 v2026
section: 退款政策 > 不可退款條件
page: 5
text: ...

五、有效率的回應設計

回答 prompt 原則

System prompt 要明確限制:

你只能根據提供的 sources 回答。
如果 sources 沒有答案,請說不知道。
回答時要引用來源。
不要補充 sources 以外的資訊。
若來源互相衝突,請指出衝突。

回答格式

建議根據問題類型輸出。

事實查詢

答案:
...

來源:
- 文件 A,第 3 頁

政策判斷

判斷:
可以 / 不可以 / 需要更多資訊

理由:
1. ...
2. ...

來源:
- ...

比較問題

比較結果:
- A:...
- B:...

差異:
...

來源:
...

回答後驗證

重要場景可以多一步 verification:

Answer
→ Check whether every claim is supported by sources
→ Remove unsupported claims
→ Add missing citation

尤其適合:

六、整體架構草圖

                 ┌─────────────────────┐
                 │   Document Sources   │
                 │ PDF / Web / MD / DB  │
                 └──────────┬──────────┘
                            │
                            ▼
                 ┌─────────────────────┐
                 │ Normalize / Parse    │
                 │ clean + structure    │
                 └──────────┬──────────┘
                            │
                            ▼
                 ┌─────────────────────┐
                 │ Hash / Deduplicate   │
                 │ doc/section/chunk    │
                 └──────────┬──────────┘
                            │
                            ▼
       ┌────────────────────────────────────────┐
       │ Multi-level Index Builder              │
       │ doc summary / section summary / chunks │
       └──────────┬───────────────┬─────────────┘
                  │               │
                  ▼               ▼
       ┌────────────────┐  ┌──────────────────┐
       │ Metadata DB    │  │ Vector DB         │
       │ docs/sections  │  │ embeddings        │
       │ chunks/facts   │  │ doc/sec/chunk vec │
       └────────────────┘  └──────────────────┘


Query Flow

User Query
   │
   ▼
Query Understanding
   │
   ▼
Permission Filter
   │
   ▼
Document / Section Retrieval
   │
   ▼
Chunk Retrieval + Hybrid Search
   │
   ▼
Rerank
   │
   ▼
Context Packing
   │
   ▼
LLM Answer with Citation
   │
   ▼
Verification / Final Response

七、實作優先順序

MVP

先做:

documents
sections
chunks
metadata
chunk embeddings
section summary embeddings
basic hybrid search
citation

不要一開始就做太複雜。

第二階段

再加:

document summary embedding
reranker
incremental indexing
permission filter
query classification
context packing optimizer

第三階段

最後才加:

fact extraction
knowledge graph
multi-hop retrieval
answer verification
eval dataset
online feedback loop

八、常見錯誤

1. 只做 chunk embedding

結果:

2. chunk 太大

結果:

3. chunk 太小

結果:

4. 沒有 metadata

結果:

5. 權限過濾放太晚

錯誤做法:

先 retrieve,再叫 LLM 不要說

正確做法:

先 permission filter,再 retrieve

6. 沒有 eval

RAG 看起來能答,不代表答得準。

至少要測:

retrieval precision
retrieval recall
answer faithfulness
citation correctness
latency

九、可以落地的資料表草案

documents

CREATE TABLE documents (
  doc_id TEXT PRIMARY KEY,
  source_type TEXT,
  source_uri TEXT,
  title TEXT,
  summary TEXT,
  language TEXT,
  version TEXT,
  content_hash TEXT,
  permission_scope JSON,
  created_at TIMESTAMP,
  updated_at TIMESTAMP
);

sections

CREATE TABLE sections (
  section_id TEXT PRIMARY KEY,
  doc_id TEXT REFERENCES documents(doc_id),
  heading_path JSON,
  section_title TEXT,
  section_summary TEXT,
  start_page INT,
  end_page INT,
  content_hash TEXT,
  created_at TIMESTAMP,
  updated_at TIMESTAMP
);

chunks

CREATE TABLE chunks (
  chunk_id TEXT PRIMARY KEY,
  doc_id TEXT REFERENCES documents(doc_id),
  section_id TEXT REFERENCES sections(section_id),
  heading_path JSON,
  text TEXT,
  token_count INT,
  chunk_index INT,
  page_start INT,
  page_end INT,
  prev_chunk_id TEXT,
  next_chunk_id TEXT,
  content_hash TEXT,
  created_at TIMESTAMP,
  updated_at TIMESTAMP
);

embeddings

CREATE TABLE embeddings (
  embedding_id TEXT PRIMARY KEY,
  owner_type TEXT, -- document | section | chunk | fact
  owner_id TEXT,
  embedding_model TEXT,
  embedding VECTOR,
  created_at TIMESTAMP
);

十、總結

大量文件 RAG 的關鍵不是「切 chunk + embedding」而已,而是:

寫入時:
保留結構、建立摘要、分層 embedding、支援增量更新

讀取時:
先粗後細、權限前置、hybrid search、rerank、context packing

回應時:
來源約束、citation、必要時 verification

一句話:

好的 RAG 系統,是把文件整理成可檢索、可追溯、可更新、可控權限的多層知識索引,再用先粗後細的方式把最有用的上下文交給 LLM。