fix(chunking): stable content-defined chunking with hash-based reuse planning - #1650
Open
MauryaQbit wants to merge 2 commits into
Open
fix(chunking): stable content-defined chunking with hash-based reuse planning#1650MauryaQbit wants to merge 2 commits into
MauryaQbit wants to merge 2 commits into
Conversation
…planning Mid-file edits to upserted documents re-embed nearly all chunks because fixed-position boundaries shift every downstream chunk, defeating the per-chunk content-hash reuse check (appends diff fine since nothing shifts). Add @repo/chunking: structural (heading/fence) resync points plus FastCDC-style content-hash anchored cuts within sections, and planChunkReuse() which matches old/new chunks by content hash instead of position. A mid-file sentence edit on a 45KB doc now re-embeds 1 chunk instead of ~half the document. Fixes supermemoryai#1649
- bun.lock: add packages/chunking workspace so bun install --frozen-lockfile stays green - ci.yml: run chunking unit tests + type checking when packages/chunking changes (same pattern as tools/ai-sdk)
Author
|
Update: pushed lockfile + CI wiring so this is merge-ready pending review. Second commit (\9d22f5e)
Verified locally with the exact CI toolchain (bun 1.3.6)
Note: the Actions runs for this fork PR show \�ction_required, so CI needs a maintainer to approve the workflow runs. Ready for review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1649.
Problem
On the self-hosted server, updating an existing document via the /v3/documents\ customId upsert path re-embeds nearly all chunks when the edit is anywhere but the tail: a one-paragraph mid-file edit to a 105 KB doc re-embedded 1007 of 1102 chunks (~21 min CPU on 2 vCPU with local embeddings). Append-only documents diff perfectly, which points at position-sensitive chunk boundaries defeating the per-chunk reuse check for mid-file edits: an early insertion/deletion shifts every downstream boundary, so every downstream chunk hash changes and reuse never hits.
Fix
New zero-dependency shared package @repo/chunking\ (\packages/chunking) implementing exactly the two mitigations suggested in the issue:
Intended adoption on the upsert path: \chunks = stableChunkText(content)\ then \plan = planChunkReuse(storedChunks, chunks)\ and embed only \plan.embedIndices. Pure TS, no
ode:crypto, runs in Node/Bun/Workers.
Verification
14 new vitest tests (\packages/chunking/src/stable-chunking.test.ts, \�un run test\ in the package after install; verified here with vitest 3.2.4 — 14/14 pass). On a generated 45 KB / 90-chunk markdown doc:
Also covered: determinism, sequential positions + hash identity, sentence-boundary cuts, intact code-fence lines, duplicate-chunk FIFO pairing, position-independent matching, empty-input edge cases. \ sc --noEmit --strict\ (incl.
oUncheckedIndexedAccess\ + \exactOptionalPropertyTypes) and \�iome check\ are clean.
Note: the ingestion/embedding pipeline itself lives outside this monorepo, so this PR provides the algorithm + tested reference implementation for the pipeline to adopt; no existing behavior in this repo changes.