Skip to content

Add semantic deduplication for ranked crawl chunks - #51

Merged
MarcellM01 merged 1 commit into
TinySuiteHQ:mainfrom
benmaster82:feat/semantic-dedupe
Aug 22, 2026
Merged

Add semantic deduplication for ranked crawl chunks#51
MarcellM01 merged 1 commit into
TinySuiteHQ:mainfrom
benmaster82:feat/semantic-dedupe

Conversation

@benmaster82

Copy link
Copy Markdown
Contributor

What

Adds an optional embedding-based semantic deduplication stage to research
chunk selection, layered after the existing lexical Jaccard filter. It removes
syndicated, paraphrased, or reworded chunks that share the same meaning but have
low literal token overlap, which the Jaccard filter cannot catch.

How

  • chunk_pool_selection_service: cosine-similarity dedup against already-accepted
    chunks in ranked order, so the highest-ranked member of a duplicate group is
    kept. Cooperates with per-source quotas and the fill pass, and records one
    rejection diagnostic per dropped chunk (chunk_id, reason, similarity,
    matched_chunk_id).
  • hybrid_embed_search_service: attaches the dense document embedding already
    computed during ranking to each ranked chunk, so semantic dedup reuses it with
    no extra embedding calls. The embedding is dropped again after selection so it
    never bloats trace files or public payloads.
  • config: adds chunk_semantic_dedupe_enabled (default true) and
    chunk_semantic_dedupe_threshold (default 0.92, conservative) with coercion and
    annotated config comments. SearchResult and existing shapes are unchanged.
  • research pipeline: wires the new settings through selection.

Design notes

Lexical Jaccard stays as a cheap first pass; semantic dedup ru
already-bounded oversampled pool, comparing each candidate to the running
selected output. A conservative default threshold avoids mergi
that happen to be phrased similarly, and the stage can be disabled entirely.

Acceptance criteria

  • Identifies semantically similar chunks despite low Jaccard o
  • Retains the highest-ranked duplicate: done
  • Works across varied source URLs including syndicated/paraphr
  • Cooperates with per-source quotas and fill: done
  • Reuses existing embeddings, no redundant computation: done
  • Config in JSON settings: done
  • Targeted tests for paraphrases, related-but-distinct chunks,
    variation, disabled state, embedding reuse: done
  • README settings and design tradeoffs: done

Testing

python -m unittest discover tests -> 293 passed (1 skipped).
Also drove the real research pipeline end-to-end with the ONNX
a paraphrase pair measured cosine 0.57 with Jaccard token overlap 0.18; with
semantic dedup enabled the lower-ranked paraphrase was dropped
both were kept.

Implements issue TinySuiteHQ#12. Adds an optional embedding-based semantic
deduplication stage to research chunk selection, layered after the
existing lexical Jaccard filter, so syndicated or paraphrased chunks
with low literal token overlap are removed. It reuses the dense
embeddings already computed during ranking, so no extra embedding
calls are made.

- chunk_pool_selection_service: cosine-similarity dedup against
  already-accepted chunks in ranked order, keeping the highest-ranked
  member of a duplicate group; cooperates with per-source quotas and
  the fill pass; records single per-chunk rejection diagnostics.
- hybrid_embed_search_service: attach the dense document embedding to
  each ranked chunk so downstream selection can reuse it.
- config: add chunk_semantic_dedupe_enabled (default true) and
  chunk_semantic_dedupe_threshold (default 0.92), with coercion and
  annotated JSON config comments.
- research pipeline: wire the new settings through selection and drop
  the reused embeddings once selection is done.
- tests and README for the new behavior.
@MarcellM01

Copy link
Copy Markdown
Collaborator

Thank you so much for the implementation, sorry for the delay, I will merge this in today 😄 !

@MarcellM01 MarcellM01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against issue #12 and current main. The implementation reuses ranked chunk embeddings, preserves ranked-order and quota/fill behavior, adds focused coverage and documentation, merges cleanly, and passes the full local suite (293 tests, 1 skipped). Thank you, Ben!

@MarcellM01
MarcellM01 merged commit 7f7ca9a into TinySuiteHQ:main Aug 22, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants