文件

索引管線

追蹤檔案如何從監控 inbox,經過 parsing、SQLite persistence、OpenAI embedding,最後重建 vector cache。

Pipeline stage

inbox → watcher diff → parser → Upsert → pending rows → OpenAI → UpdateEmbedding → vector rebuild

每個已載入資料庫都會在 daemon 共用的 cancellation context 下執行一個 watcher goroutine 與一個 embedding-scheduler goroutine。

Watcher snapshot

每 10 秒,runWatcher 會對資料庫 inbox 呼叫 filesystem.WalkFiles。Walker 會遞迴建立包含下列資料的 snapshot:

Field 用途
Size 偵測檔案大小變更
ModTime 偵測內容或直接 entry 變更
IsDir 區分檔案與遞迴 directory node
Children 保留前次 subtree,供比較與移除偵測

成功掃描後,daemon 會非同步將 snapshot 寫入 {db}/record.json。下次啟動時會載入已儲存的 snapshot。

Watcher 依賴直接 directory entry 的 mtime 行為,只針對支援的本機 macOS 與 Linux filesystem 設計。

Parser dispatch

變更的非目錄 entry 會依 extension 或 text sniffing 選擇:

輸入 Parser path Chunking 行為
.pdf go_pkg_parser.PDF Document parser chunks
.docx go_pkg_parser.Docx Document parser chunks
.pptx go_pkg_parser.PPTX Presentation parser chunks
.csv, .tsv parseTabular 呼叫 go_pkg_parser.CSV 依 header,每五筆 data row 一組
.xlsx parseTabular 呼叫 go_pkg_parser.XLSX 依 header,每五筆 data row 一組
其他有效 UTF-8 文字 go_pkg_parser.Markdown Markdown/text chunks

Text sniffing 最多讀取 8,192 bytes,拒絕包含 NUL、無效 UTF-8 或空白的 sample。

略過的輸入

.DS_Store 會依名稱略過。已知的 image、video、audio、archive、executable、database、design、font 與其他 binary extension 會在 parsing 前略過,避免 image base64 與不支援的 binary data 進入文字 embedding pipeline。

Transactional upsert

databaseHandler.Upsert 是 filesystem layer 使用的唯一內容寫入入口。它會在同一 SQLite transaction 中:

  1. 將此 source 目前所有 active row 標記為 dismiss = TRUE
  2. 插入每個目前 chunk,或更新 (source, chunk) conflict。
  3. 將目前 chunk 恢復為 dismiss = FALSE
  4. 只有在 chunk content 未變時保留 embedding。
  5. 清除已變更的 embedding,並重設 is_embed = FALSE

此順序可處理縮短的檔案,不會回傳過期的尾端 chunk,也不會重新 embedding 未變更的 chunk。

已移除檔案

掃描目前 entry 後,walker 會比較先前 snapshot。缺少的 file node 會遞迴傳給 databaseHandler.Dismiss,透過設定 dismiss = TRUE 將 active row soft-delete。資料仍保留在 SQLite,但 indexing 與 query read 都會排除。

Embedding scheduler

每五秒,runEmbedder 會選取最多 64 筆符合下列條件的 row:

is_embed = FALSE AND dismiss = FALSE

Scheduler 將其 content 送至 EmbedBatch。過大的 input 會在 request 前截斷為 8,000 個 Unicode rune。Client 使用 text-embedding-3-small、512 dimensions 與一分鐘 HTTP timeout。

若 OpenAI 回傳錯誤數量的 vector,或任一 vector 維度錯誤,整個 batch 會被拒絕。

Race-safe 套用

UpdateEmbedding 只會在下列條件都仍相符時更新 row:

此設計可避免緩慢 OpenAI response 在檔案變更後附加過期 vector。Function 只回傳實際套用更新的 ID。

Vector cache 更新

對已套用的 ID,KuraDB 會將每個 vector 儲存至 database bucket、追蹤 source-to-chunk relation,並重建每個受影響的 source vector。Source vector 是有效且同維度 chunk vector 的 normalized sum。

Daemon 啟動時,cache 會從 SQLite 中 active 且已 embedding 的 row 重建,再重建所有 source vector。記憶體 cache 遺失時,SQLite 仍是權威來源。

操作時間

Pipeline 為非同步。正常狀況下,變更檔案可能等待最多一個 watcher interval 才開始 parsing,再等待最多一個 embedding interval 才被選取,另加 OpenAI request 時間。Keyword retrieval 可在 parsing 後、embedding 前使用 content;semantic retrieval 必須等待 vector 成功套用。

EN