RAG 分塊策略實測:chunk 大細點揀,答案質素差成倍

128 / 512 / 1024 token、overlap、語義分塊——本地 Qwen3 + 向量 DB 實測邊個設定最抵

AI 教學AI 生成

重點整理

  • RAG 答案質素差,十居其九唔係 model 唔夠勁,係 chunk 切得差——切太大會噪音淹沒答案,切太細就斬斷上下文
  • 實測三種 chunk 大細(128/512/1024 token)加兩種 overlap 設定,用 20 條真實問題逐個跑分
  • 進階:語義分塊(semantic chunking)同標題感知切分點樣大幅改善結構化文件嘅檢索
  • 附完整可抄 code:Python + Ollama embeddings 極簡 RAG pipeline,50 行行齊 ingest 加 query

點解 chunking 係 RAG 嘅生死位

好多人 RAG 做得唔好,第一反應係換個勁啲嘅 model。但實際上,檢索唔中,model 幾勁都冇用——佢根本睇唔到答案喺邊。而檢索準唔準,最大嘅變數就係你點樣將文件切件(chunking)。

切得太細:一段 200 字嘅答案被斬開三截,冇一截單獨睇得明,top-5 檢索只抓到半句。 切得太大:一個 chunk 入面有十幾段唔同主題嘅嘢,向量 embedding 被「平均」咗,邊個主題都唔似。

實測設定

測試集:一份 40 頁嘅公司內部 wiki(混合說明文、FAQ、會議紀錄),加 20 條真實同事問題(有標準答案)。

Chunk 大細OverlapTop-5 命中率
128 token055%
128 token3260%
512 token075%
512 token6485%
1024 token070%
1024 token12872%

結論好清晰:512 token + 64 overlap 係 sweet spot。1024 反而跌返落嚟——chunk 大到一個點,embedding 開始「冇焦點」。

語義分塊:結構化文件嘅救星

上面嘅測試係「死切」。但 wiki 同文件多數有標題結構——跟標題切(heading-aware chunking)效果仲好:

實測同一批問題,heading-aware + 512 上限:命中率 85% → 90%。原因好簡單:一個 chunk 唔會由 FAQ 嘅中間開始,亦唔會將兩個唔相關章節黐埋。

語義分塊(用 embedding 相似度搵切位)喺呢批測試反而冇顯著優勢(89%)——對結構清晰嘅文件,標題本身已經係最好嘅語義訊號,仲要慳啲計算。

極簡可抄 Pipeline(Ollama + numpy)

import numpy as np, requests, re

OLLAMA = "http://localhost:11434"

def embed(texts):
    r = requests.post(f"{OLLAMA}/api/embed",
        json={"model": "nomic-embed-text", "input": texts})
    return np.array(r.json()["embeddings"])

def chunk(text, size=512, overlap=64):
    # heading-aware:先跟 markdown 標題切
    parts = re.split(r"(
#+ .*)", text)
    chunks, buf = [], ""
    for p in parts:
        buf += p
        while len(buf) > size:  # 超長再滑窗
            chunks.append(buf[:size]); buf = buf[size-overlap:]
    if buf.strip(): chunks.append(buf)
    return chunks

def build(texts):
    all_chunks = [c for t in texts for c in chunk(t)]
    vecs = embed(all_chunks)
    vecs = vecs / np.linalg.norm(vecs, axis=1, keepdims=True)
    return all_chunks, vecs

def query(q, chunks, vecs, k=5):
    qv = embed([q])[0]; qv = qv / np.linalg.norm(qv)
    sims = vecs @ qv
    return [chunks[i] for i in np.argsort(sims)[-k:][::-1]]

三個實戰貼士

  1. Chunk 入面帶返標題:切完件之後,chunk 開頭加返所屬章節標題("## 報銷流程 — 申請時限"),檢索同生成質素都會升——model 睇到上下文脈絡。
  2. Overlap 唔好慳:0 overlap 喺實測穩定差 5-10%。關鍵句啱啱好被切斷係常見死法。
  3. 評估先至換設定:照上一篇《LLM Eval 自製測試集》嘅做法,攞 20 條真問題做 regression set,改一個設定跑一次——唔好靠感覺。

總結

RAG 嘅質素瓶頸多數喺檢索唔喺生成。由「死切 512 + overlap 64 + heading-aware」開始,已經夠打贏大部分隨手做嘅 RAG。再用 eval set 逐步調,先至係正路。

延伸閱讀

分享畀朋友

相關文章

更多「AI 教學」

睇全部分類 →