Embedding
查看 pending chunk 如何透過 OpenAI 產生 embedding、無 race 地套用至 SQLite,並載入記憶體 vector cache。
Embedding scheduler
每五秒,runEmbedder 會依 ID 由小到大選取最多 64 筆符合下列條件的 row:
is_embed = FALSE AND dismiss = FALSE
Scheduler 將其 content 送至 EmbedBatch。超過 8,000 個 Unicode rune 的 input 會在 request 前截斷。Client 使用 text-embedding-3-small、512 dimensions 與一分鐘 HTTP timeout。
若 OpenAI 回傳錯誤數量的 vector,或任一 vector 維度錯誤,整個 batch 會被拒絕。被拒絕或失敗的 batch 只記錄 log,row 維持 pending,下一個 tick 會重試。
Race-safe 套用
UpdateEmbedding 在同一 transaction 中執行,只會在下列條件都仍相符時更新 row:
- Row ID 未變。
dismiss = FALSE。- 儲存的 content 與送去 embedding 的 content 相同。
此設計可避免緩慢 OpenAI response 在檔案變更後附加過期 vector。Function 只回傳實際套用更新的 ID。
Vector cache 更新
對已套用的 ID,KuraDB 會將每個 vector 儲存至 database bucket、追蹤 source-to-chunk relation,並重建每個受影響的 source vector。Source vector 是有效且同維度 chunk vector 的 normalized sum。
執行中的 cache 只會新增、不會淘汰。已 dismiss 的 row 的 vector 會留在記憶體直到重啟;content 已變更的 chunk 在新 vector 套用前仍保留舊 vector。Semantic 結果的內容仍正確,因為 hydration 以 dismiss = FALSE 讀取 SQLite,會丟棄已 dismiss 的 row 並回傳目前文字。
Daemon 啟動時,cache 會從 SQLite 中 active 且已 embedding 的 row 重建,再重建所有 source vector。記憶體 cache 遺失時,SQLite 仍是權威來源。