purpose
commit diff の batch embed の分割軸を、file 件数から推定 token 予算へ変更する。
observation (2026-08-14, Cloudflare Observability)
毎 cron 以下が出力されている。
Failed to batch-embed diffs for Liplus-Project/neuron-graph-rag@1fb0f6b... chunk offset 0:
3030: Max context reached 60678 tokens but model supports only 60000
観測されたトークン数: 60,678 / 64,413 / 74,980 / 85,920。model 側の batch 集約上限は 60,000。
その結果、forward watermark が停止している。
| repo |
forward watermark |
boundary commit |
Liplus-Project/neuron-graph-rag |
2026-08-11T15:33:02Z |
1fb0f6b (failed) |
Liplus-Project/github-webhook-mcp |
2026-08-02T08:48:18Z |
add43f55 (failed) |
失敗は決定論的(同一 commit・同一分割で毎回同じ結果)。cron 再試行では回復しない。同居している Too many subrequests 系の一過性エラーとは性質が異なる。
premise
現状の src/pipeline/embed-diff.ts は MAX_EMBEDDING_BATCH_SIZE(20)による件数だけで chunk を切っている。1 input は MAX_EMBEDDING_INPUT_CHARS(8000 文字)まで truncate されるため、1 回の Workers AI 呼び出しに最大 20 × 8000 = 160,000 文字が載りうる。
「1 token あたりの文字数」は内容によって桁で変わる。ASCII のソースコードで約 3 文字/token、CJK の散文では約 1 文字/token。つまり件数上限は投入 token 量を全く縛れておらず、「どの patch も小さい」という暗黙の仮定の上でだけ成り立っている。
さらに src/pipeline/hash.ts の prepareDiffEmbeddingInput は commit message を file ごとに複製して先頭へ付ける。長い日本語 commit 本文 × 20 file で、patch 本体を数える前に上限へ到達する。
影響は「その commit だけが失敗する」で止まらない。batch call が失敗すると chunk 全体(最大 20 file)が failed に計上され、src/poller.ts の ingestCommitDiff はそれを未取り込み commit として扱う。#178 で入れた watermark 不変条件によりその commit を追い越さないので、恒久的に失敗する commit が 1 つあると diff surface 全体がそこで停止する。
これは不変条件が正しく効いた結果であり、不変条件側の欠陥ではない。修正対象は embed 側のみ。
constraints
- 分割は推定 token 予算で行う。件数軸は残さない(残せば同じ仮定が別の場所に残る)
- 単独で予算を超える input も必ず 1 件の batch として送る。欠落させない、無限ループさせない。さらに削るのは truncate 軸(
MAX_EMBEDDING_INPUT_CHARS)の責務
- input の順序を保持する。返却 vector と file の対応は位置で取っているので、分割時は input 配列と file 配列を同じ境界で切る
- chunk 単位の失敗隔離は現状維持(1 batch の失敗が後続 batch を止めない)
- 通常サイズの commit は従来どおり 1 call にまとめる。call 数を無用に増やさない。この worker では
Too many subrequests by single Worker invocation が現に発生しており、1 commit あたりの subrequest 数は逼迫している軸である
generateEmbeddingBatch の呼び出し元は src/pipeline/embed-diff.ts のみ(doc / issue / comment / release は単発 generateEmbedding 経路のため影響なし)
- 既存 vector の再 embed は不要。停止した watermark は修正後の通常 cron で前進すれば足りる
- 要件記述(
docs/0-requirements.md / docs/0-requirements.ja.md)を同一 PR で更新する
target files
src/pipeline/embedding.ts — token 推定と batch 分割の実装。MAX_EMBEDDING_BATCH_SIZE を退役させる
src/pipeline/embed-diff.ts — 呼び出し側を新しい分割へ差し替え
src/pipeline/embedding.test.ts(新規)— 推定関数と分割関数の契約
src/pipeline/embed-diff.test.ts(新規)— pipeline 経路での分割挙動
docs/0-requirements.md / docs/0-requirements.ja.md — Embedding Pipeline 節の該当記述(source ⇔ docs の対)
acceptance
- 1 batch の推定 token 数が上限(安全マージン込み)を超えない
- 上記 2 repo の forward watermark が boundary commit を越えて前進する
- 既存テストが通り、上限超過ケースの回帰テストが追加されている
purpose
commit diff の batch embed の分割軸を、file 件数から推定 token 予算へ変更する。
observation (2026-08-14, Cloudflare Observability)
毎 cron 以下が出力されている。
観測されたトークン数: 60,678 / 64,413 / 74,980 / 85,920。model 側の batch 集約上限は 60,000。
その結果、forward watermark が停止している。
Liplus-Project/neuron-graph-rag1fb0f6b(failed)Liplus-Project/github-webhook-mcpadd43f55(failed)失敗は決定論的(同一 commit・同一分割で毎回同じ結果)。cron 再試行では回復しない。同居している
Too many subrequests系の一過性エラーとは性質が異なる。premise
現状の
src/pipeline/embed-diff.tsはMAX_EMBEDDING_BATCH_SIZE(20)による件数だけで chunk を切っている。1 input はMAX_EMBEDDING_INPUT_CHARS(8000 文字)まで truncate されるため、1 回の Workers AI 呼び出しに最大 20 × 8000 = 160,000 文字が載りうる。「1 token あたりの文字数」は内容によって桁で変わる。ASCII のソースコードで約 3 文字/token、CJK の散文では約 1 文字/token。つまり件数上限は投入 token 量を全く縛れておらず、「どの patch も小さい」という暗黙の仮定の上でだけ成り立っている。
さらに
src/pipeline/hash.tsのprepareDiffEmbeddingInputは commit message を file ごとに複製して先頭へ付ける。長い日本語 commit 本文 × 20 file で、patch 本体を数える前に上限へ到達する。影響は「その commit だけが失敗する」で止まらない。batch call が失敗すると chunk 全体(最大 20 file)が
failedに計上され、src/poller.tsのingestCommitDiffはそれを未取り込み commit として扱う。#178 で入れた watermark 不変条件によりその commit を追い越さないので、恒久的に失敗する commit が 1 つあると diff surface 全体がそこで停止する。これは不変条件が正しく効いた結果であり、不変条件側の欠陥ではない。修正対象は embed 側のみ。
constraints
MAX_EMBEDDING_INPUT_CHARS)の責務Too many subrequests by single Worker invocationが現に発生しており、1 commit あたりの subrequest 数は逼迫している軸であるgenerateEmbeddingBatchの呼び出し元はsrc/pipeline/embed-diff.tsのみ(doc / issue / comment / release は単発generateEmbedding経路のため影響なし)docs/0-requirements.md/docs/0-requirements.ja.md)を同一 PR で更新するtarget files
src/pipeline/embedding.ts— token 推定と batch 分割の実装。MAX_EMBEDDING_BATCH_SIZEを退役させるsrc/pipeline/embed-diff.ts— 呼び出し側を新しい分割へ差し替えsrc/pipeline/embedding.test.ts(新規)— 推定関数と分割関数の契約src/pipeline/embed-diff.test.ts(新規)— pipeline 経路での分割挙動docs/0-requirements.md/docs/0-requirements.ja.md— Embedding Pipeline 節の該当記述(source ⇔ docs の対)acceptance