GrooveSeek

Semantic search over a Markdown knowledge base, served over MCP.

View the Project on GitHub alphabet-h/grooveseek

25. embedding endpoint が断った入力は skip し、一時的な失敗は再試行する

背景と課題

provider = "openai-compatible" (ADR-0022) では、rebuild_index (grooveseek/src/indexer.rs) が embedding し直すファイルは 1 本ごとに 1 回以上の HTTP リクエストになる。この記録までは、リクエストが 1 つでも 失敗すると failed to embed chunks for <file> で run 全体が止まっていた。walk は毎回 同じ順でファイルを回るので、次の run も同じファイルで止まり、その後ろのファイルは いつまでも索引されなかった。ループの後に続く段階も走らなかった: 消えたファイルの row を 消す sweep と、宣言フィールドの集合の記録である。

これを起こす失敗は 2 種類あり、性質が違う:

問いは、groove index・MCP rebuild_index・watcher がそれぞれをどう扱うか、それも 設定の誤りを成功に見える run の陰に隠さずに、である。

判断の軸

検討した選択肢

  1. どの失敗でファイルを skip するか。
    • どの失敗でも skip する。退けた: 401 や次元違いで全ファイルが skip になり、run は 成功を報告してしまう。
    • 入力が原因の失敗 (HTTP 400・413・422) だけ skip する。 採用。
    • 従来どおりどの失敗でも止まる。退けた: 上の問題そのもの。
  2. 長い入力を送る前にどう抑えるか。
    • token 数で。退けた: groove は alias の背後にある model の tokenizer を持たず、 endpoint がどれを使うかも知り得ない。
    • バイト数で。退けた: マルチバイト文字の途中で切れ、文字体系ごとに残る量が変わる。
    • 文字数 (Unicode scalar value) で。 採用。単位はサーバの token 上限と一致しないが、 それでも長すぎる入力は上の skip に落ちる。
  3. 再試行について何を設定として出すか。
    • 待ち時間もキーにする。退けた: 凍結されるキーが増え、調整を求める声も無い。
    • max_retries だけ。待ち時間は定数。 採用。
    • キーを出さない。退けた: 低遅延が要る daemon には再試行を切る手段が要る (結果と代償を参照)。
  4. 拒否のあった run が何を報告するか。
    • 常に exit 0。退けた: endpoint が 400 で答える設定の誤りが、skip の多い正常な run に 見えてしまう。
    • 拒否が 1 件でもあれば exit 非 0。退けた: 大きく健全な知識ベースに長すぎるチャンクが 1 つあるだけで、毎回の run が失敗になる。
    • 拒否があり、かつ endpoint が何も受け付けなかったときだけ exit 非 0。 採用。 この形はファイルではなく model / document_model か endpoint を指している。 endpoint が前のバッチを受け付けた後で断ったファイルは、この拒否ではなく受け付けた 側に数える: 受け付けたバッチが設定の正しさを示している。

決定

断られた入力はそのファイルを skip し、一時的な失敗は再試行し、拒否しか起きなかった run は最後まで済ませてから失敗にする。

結果と代償

参考