Skip to content

fix(ml): sample the whole corpus and drop PROPN from distinctive_vocab (WO-18) - #114

Merged
sergi-torres merged 3 commits into
mainfrom
fix/wo-18-distinctive-vocab-corpus
Jul 28, 2026
Merged

fix(ml): sample the whole corpus and drop PROPN from distinctive_vocab (WO-18)#114
sergi-torres merged 3 commits into
mainfrom
fix/wo-18-distinctive-vocab-corpus

Conversation

@sergi-torres

@sergi-torres sergi-torres commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Base is fix/wo-08-comparison-corpora, not main. Stacked PR. When #113 merges, GitHub retargets this one to main and a conflict will appear in docs/decision_log.md — see the bottom.

What

Two fixes and their honest documentation:

  • (a) the corpus was truncated to 21%: a prefix was taken instead of sampling across the author's documents. A bisection-order sample now spends the 800k-character budget across all of them.
  • (b) PROPN tokens are filtered out. Character names are statistically distinctive but they are not style: havisham and pemberley say nothing about how someone writes.

Why

Closes #100

⚠️ This branch does NOT meet its own Definition of Done, deliberately

The DoD required a top-10 overlap ≤3. The measured result is 5, which is worse than what #89 left. This was accepted by the project owner on 2026-07-28 and recorded with its reasoning in docs/decision_log.md.

The reason is arithmetic, not implementation. With three documents, countenance (29 occurrences in Dickens) and say (1,866) both have df = 3/3 and therefore identical idf = 1.000. TF-IDF collapses into raw frequency and countenance can never win. Proper nouns were the only thing discriminating; removing them (correct) raises the overlap.

Rejected alternatives: re-scoring with log-odds or IDF against general English, because it changes an algorithm that docs/style_features.md §4.1 declares closed; and reverting the PROPN filter, which buys the metric at the price of the defect the issue exists to remove.

Accepted consequence: the distinctive vocabulary shows common words. All three authors share know, little, make, say, time.

How IBM Bob helped

  • Custom Mode used: none
  • Bob session export: n/a

Claude Code agents. This branch went through an independent verifier in a cold context that never saw the diff and received only the Definition of Done. It found two things the executor had not covered:

  1. The documentation asserted something false. style_features.md:305 still promised countenance/physiognomy/presently in the output, and :336 called that example "the standard the section sets for itself". None of the three appears even in the top-30. Both corrected, with a new Measured output block recording what the pipeline actually returns.
  2. Half (b) had no test at all. The verifier proved it by deleting the entire PROPN filter — the suite stayed green. test_lemmatize_corpus_drops_proper_nouns now covers it.

Screenshots / output

Real top-10, measured with the seed's own code path over the full corpus/:

austen : say know think make come time good great look little
dickens: say know look come make man time little think hand
poe    : say make great time long man know day eye little

Positive control for the new test, in a disposable copy outside the repo:

PASS A — filter present:  1 passed in 14.37s
PASS B — filter removed:  1 failed
  AssertionError: proper nouns reached the TF-IDF input: ['havisham', 'pemberley', 'wemmick']

Suite: 219 passed, 3 skipped. Cost: 211-231 s against #89's 216 s (between -2% and +7%; the threshold was +50%).

Checklist

  • Tests pass locally (make test)
  • Lint passes (make lint)
  • If schema changed (StyleProfile / Passport) → bumped version + updated docs/
  • If new env var → added to .env.example
  • If new/changed endpoint → updated docs/api_contract.yaml
  • Documentation in the relevant README.md updated
  • At least one teammate reviewed

Expected conflict in docs/decision_log.md. It is append-only and has four writers. Resolve by keeping all rows in chronological order — never by deleting someone else's.

Merging this requires a re-seed: every existing style_profiles row is invalidated.

sergi-torres and others added 2 commits July 28, 2026 01:45
Two defects reported in #100, applied and measured separately.

(a) The 800k-lemma-char cap in style_profile.py truncated by document
order, so "each author's full corpus is one document"
(docs/style_features.md 4.1) was really a prefix: 21% of Dickens'
chunks, 34% of Austen's, 89% of Poe's. Dickens' distinctive_vocab was
therefore the vocabulary of Great Expectations alone.

The cap stays -- it is the memory bound that keeps the seed at ~1.7 GB.
Chunks are now fed to spaCy in a deterministic bisection order
(_spread_order), so the chunks that fit inside the cap are drawn from
across the whole corpus. Cost is unchanged: the same number of chunks
goes through nlp.pipe, only the order differs.

(b) PROPN tokens are excluded, inside _lemmas_from_docs where spaCy's
POS tag is already computed -- not by a blacklist after the TF-IDF.
Decision 2026-07-28 (option A), recorded in docs/decision_log.md.
docs/style_features.md 4.1 "Preprocessing" updated to match, since the
code would otherwise contradict the spec.

Character names are gone from every author's top-30 (Dickens 9 -> 0,
Austen 10 -> 0). Re-seeding is required: every existing style_profiles
row is invalidated (#86).

Known, reported on the issue and NOT resolved here: (b) pushes the
three-way top-10 overlap from 3 to 5, because with N=3 documents the
IDF term is nearly constant and names were the only discriminating
tokens. The issue is left open for that decision.

Refs #100
… PROPN filter

Closes the documentation half of #100 (WO-18).

docs/style_features.md 4.1
- Remove two false claims: the section advertised "countenance",
  "physiognomy" and "presently" as the Dickens output and called that
  example "the standard the section sets for itself". Neither term
  reaches any author's top-10 or top-30.
- Add a "Measured output" block with the actual top-10 per author
  (measured 2026-07-28 over the full corpus/ through the seed code path)
  and state plainly that the feature returns ordinary high-frequency
  verbs and nouns, not signature vocabulary, with a three-way overlap
  of 5 terms.
- Explain why it cannot do better as specified: with three documents,
  any term present in all three is idf-tied, so TF-IDF collapses to raw
  frequency.

docs/decision_log.md
- Append the #100 DoD exception: the DoD requires a top-10 overlap <=3,
  measured is 5, which is worse than what #89 left. Records what was
  measured, the alternatives rejected, and who accepted it. Marked
  "pending 2/3 ratification" per the 2026-06-24 decision policy - no
  vote is claimed.

ai_pipeline/tests/test_style_profile_compute.py
- Add test_lemmatize_corpus_drops_proper_nouns. The PROPN filter had no
  test: removing it left the suite green. Verified to fail when the
  guard is removed from a disposable copy of the module.

219 passed, 3 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
author-ai Ready Ready Preview, Comment Jul 28, 2026 4:43pm

Base automatically changed from fix/wo-08-comparison-corpora to main July 28, 2026 16:42
@sergi-torres
sergi-torres merged commit 7b0af4f into main Jul 28, 2026
8 checks passed
@sergi-torres
sergi-torres deleted the fix/wo-18-distinctive-vocab-corpus branch July 28, 2026 16:46
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.

[ml] WO-18 — El vocabulario distintivo son nombres de personajes: el corpus se trunca al 21% y nadie filtra PROPN

1 participant