GGBrain效能架構報告

GBrain 0.42.67.0 · 架構與演算法報告

大量 Wiki,
如何依然查得快、改得穩?

GBrain 不在每次提問時翻遍所有 Markdown。它先把內容整理進 PostgreSQL, 再用語意、關鍵字與排名融合三種方法,快速縮小到少量高相關內容。

Executive summary

老闆先記住這四件事

01

Query 不掃檔案

日常搜尋直接查 PostgreSQL 已建好的索引,不逐一開啟 Wiki。

02

兩種搜尋互補

HNSW 找「意思」,GIN 找「原字詞」,避免只靠 embedding 的盲點。

03

修改只處理差異

Git delta 找變更檔案,content hash 再排除內容未改的頁面。

04

Markdown 仍要保留

核心知識以 Markdown + Git 保存;PostgreSQL 是可重建的加速層。

建議結論

超過約 1,000 個檔案,採 PostgreSQL + pgvector;但不要刪除核心 Markdown。

Query pipeline

一次問題,經過六個步驟

真正的加速不是「讓 LLM 讀得更快」,而是在 LLM 之前, 先用索引把上萬份內容縮小成最值得閱讀的一小批。

01

收到問題

例如:「我們之前怎麼處理 API 延遲?」

02

同時理解意思與字詞

產生 query embedding,也整理可用於精確搜尋的關鍵字。

03

兩條索引並行找候選

HNSW 找意思相近的內容;GIN 找名稱、代碼與原字詞。

04

RRF 合併排名

不硬加兩種不同分數,而是看各自名次,整合雙方共識。

05

選配精排與關係訊號

依模式加入 graph、context 或 reranker,修正最前面的順序。

06

回傳少量高相關內容

只把最有用的 chunks 交給 LLM,並保留來源資訊。

語意路線HNSW

找「意思相近」

將每個 chunk 變成向量座標,沿著多層近鄰捷徑快速走到相似內容, 不必比較資料庫裡的每個向量。

ABCD
適合:同義詞、換句話說、概念相近
字詞路線GIN

找「字真的出現」

建立「詞彙 → 哪些 chunks」的反向索引。人名、錯誤碼、函式名與精確片語, 可以直接定位。

PostgreSQL文件 1、2
ERR_502文件 4
cache文件 1、3、7
適合:專有名詞、代碼、精確文字
融合路線RRF

讓兩邊共同投票

只看每種搜尋中的名次,不硬加不同尺度的分數。 同時被語意與關鍵字選中的內容自然往前排。

  1. A語意 #1
  2. B語意 #2
  3. C語意 #3
  1. B字詞 #1
  2. D字詞 #2
  3. A字詞 #3
→ B、A 優先
優點:便宜、穩定、不需 LLM

非技術版理解

HNSW 像找「概念相近的書」;GIN 像查「書末索引」; RRF 則像把兩位圖書館員的推薦名單合併。

Update pipeline

Markdown 修改後,如何避免全部重做?

GBrain 以「檔案差異 → 內容差異 → chunk 差異」逐層縮小工作範圍。 HNSW 本身不會壞掉,PostgreSQL 會隨資料更新自動維護索引。

01

Git delta

只找新增、修改、刪除與改名檔案。

02

Content hash

內容完全相同就跳過,不重切、不重嵌入。

03

Parse

只解析有變化的 Markdown 與 frontmatter。

04

Re-chunk

重新切割該頁;清掉已不存在的舊 chunks。

05

Embedding

有變化的文字取得新向量;大量更新可延後處理。

06

Transaction

頁面與 chunks 在同一交易內更新,避免半套狀態。

07

Index maintenance

PostgreSQL 自動維護 GIN 與 HNSW。

正確性保護

不讓舊 chunk「幽靈般」留在搜尋裡

  • 新結果已沒有的 chunk index 會被刪除。
  • 文字改變但尚未有新 embedding 時,舊向量設為空值。
  • embed --stale 只補需要更新的向量。
  • 交易完成前,讀者不會看到只更新一半的頁面。

真正風險

小修改可能造成 chunk 邊界漂移

修改前A + BC + DE + F
前面插入文字後新增 + AB + CD + EF

結果仍正確,但多個 chunks 需要重新 embedding。這是成本問題,不是 HNSW 搜尋錯誤。

資料量放大後的效能風險
操作風險原因建議
日常 query走資料庫索引,不開啟全部 Markdown。監控 p95 latency 與連線池
少量 Markdown 修改低~中Git delta 與 content hash 限縮工作量。合併數十秒內的連續修改
大批量修改中~高重新切割、embedding 與索引寫入增加。先 ingest,再執行 embed --stale
首次/full ingest需要讀取、解析與索引全部內容。PostgreSQL、平行 worker、離峰執行
完整 lint目前會全量掃描,CLI 還會重跑一次統計。日常只 lint changed files
超大型單頁chunk 邊界漂移,且特定內容形狀可能非線性變慢。以主題拆成 10–100 KB 頁面

Storage model

本地檔案與 PostgreSQL,不是替代關係

原始資料層

Markdown + Private Git

人與 LLM 都能閱讀、編輯、review,也保留完整歷史。

  • 核心 Wiki 與決策紀錄
  • 版本歷史與多人合併
  • 資料庫損壞時可重建
sync只傳變更
高速服務層

PostgreSQL + pgvector

把 Markdown 轉成適合電腦快速查詢的結構與索引。

  • Pages、chunks、embeddings
  • GIN、HNSW 與 graph
  • 權限、工作佇列與 runtime state
db_tracked

核心知識

Markdown + Git 是 canonical;PostgreSQL 可由 repo 重建。

db_only

大量機器資料

Transcript、抓取內容等可主要存 DB;本地檔案只作 cache。

thin client

使用者端

員工電腦可只透過 MCP/API 查詢,不必各自保存完整 DB 或 Wiki。

Recommended decision

推薦採用「Git 原始資料 + PostgreSQL 查詢服務」

保留 Markdown 的可讀性與可恢復性,同時把高頻 query、向量、全文與權限交給 PostgreSQL。使用者端可以很輕,brain host 才負責重工作。

現在就做

  1. 1,000+ 檔案直接採 PostgreSQL + pgvector。
  2. Wiki 放 private Git,日常使用 incremental sync。
  3. 編輯停止 30–120 秒後再同步,不要每次按鍵觸發。
  4. 日常只 lint changed files;完整 lint 改成排程。
  5. 頁面以主題拆分,通常控制在 10–100 KB。

程式優化優先順序

  1. 設定在整次 ingest 中只載入一次。
  2. 同一 Markdown 只解析一次。
  3. 以 chunk hash/穩定 ID 只重嵌入真正變動的 chunk。
  4. 跨頁合併小型 embedding requests。
  5. Lint 改為單次掃描並加入 incremental cache。

名詞快速查

HNSW為什麼語意搜尋可以不用掃全部資料?

把向量組成多層近鄰網路,沿捷徑探索最相近區域;速度快但屬近似搜尋。

GIN全文索引在做什麼?

建立「詞彙 → 文件位置」的反向索引,專門處理精確字詞、名稱與代碼。

RRF如何合併兩種搜尋?

依各自名次給分,同時被多種搜尋選中的文件會自然上升,不必校準不同分數。

Chunk為什麼不能整份 Markdown 直接 embedding?

把長文件拆成可檢索的小段,才能只回傳真正相關的段落,減少 token 與雜訊。