Skip to content

fix(extract): compact prompt for small models, junk mention scoring (#59, #57) - #135

Open
JordanCoin wants to merge 3 commits into
mainfrom
fix/57-59-extraction-quality
Open

JordanCoin wants to merge 3 commits into
mainfrom
fix/57-59-extraction-quality

Conversation

@JordanCoin

@JordanCoin JordanCoin commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

Closes #59
Closes #57

#59: compact prompt for small models, thinking-model output

  • _is_compact_model(model, setting) reads the parameter count from the tag. Models under 8B (mistral:7b, qwen2.5:1.5b, gemma3:270m) and the qwen3 family get the compact prompt; llama3.1:8b keeps the full prompt. MoE tags like 8x7b are skipped, a few known small tags (llama3.2, tinyllama, phi3) count as small, and unknown models get the full prompt. ai.compact_prompt: auto|true|false (env OPENFOIA_AI_COMPACT_PROMPT) overrides the rule. qwen3:8b on the full prompt returned truncated JSON even with think: false at 4000 and 8000 tokens.
  • _build_extraction_prompt(..., compact=False) builds the compact form when asked: core types plus custom types, one line each, no relationship section, one short JSON example. The docstring now describes what the code does.
  • _call_ollama and _call_openai strip <think>...</think> before returning. format: json is unchanged.

Local A/B, FOIA letter fixture, 14 expected entities:

model full prompt compact prompt
qwen3:8b 123s, truncated JSON, 0/14 27s, valid JSON, 12-13/14
llama3.1:8b 76s, 12/14 24-28s, 9-10/14

#57: junk mention scoring

These scores are now 0: anything over 80 characters, NER mentions under 3 characters, sentences (two sentence-ending periods, or a terminal period with 6+ words; U.S. and Dr. don't count), and NER mentions with 2+ garbled tokens.
These lower the score without dropping the mention: one garbled token (-0.30), a non-alphanumeric ratio above 0.25 (-0.50), PERSON over 5 tokens (-0.40).
The name-token check accepts any script, so José Müller passes.

Tests

tests/test_extraction_quality.py:

  • the junk examples from the issue score 0 on every backend
  • legitimate names score above 0.3, including U.S. Department of Justice and AT&T
  • a table of model names and their size class
  • the compact prompt has no relationship section and is under half the full prompt's length
  • <think> stripping leaves parseable JSON

Full suite: 619 passed, 28 skipped. The 2 TestLLMExtraction failures are pre-existing: the default model llama3.2 is not pulled locally, so the LLM call fails before extraction.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce

JordanCoin and others added 3 commits November 6, 2026 11:54
, #57)

#59: _build_extraction_prompt claimed a compact prompt for models of 8B
or fewer but built one prompt for all. _is_compact_model parses the
parameter count from the model tag (qwen3:8b, llama3.1:8b, qwen2.5:1.5b;
8x7b MoE tags are skipped) and falls back to a short list of known small
tags; unknown sizes keep the full prompt. The compact prompt lists core
types plus custom types and drops the relationship section. _call_ollama
and _call_openai strip <think>...</think> before returning.

Local A/B on the FOIA letter fixture: qwen3:8b full prompt ran 123s and
returned truncated JSON (0/14); compact returned valid JSON with 12-13/14
in 27s. llama3.1:8b went 12/14 full to 9-10/14 compact in a third of
the time.

#57: _mention_score now drops mentions over 80 characters, NER mentions
under 3, sentences (two sentence-ending periods, or a terminal one with
6+ words; "U.S." and "Dr." do not count), and NER mentions with two or
more garbled tokens. One garbled token, a non-alphanumeric ratio above
0.25, and PERSON over 5 tokens are penalties, not drops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce
…der 8B

Review fixes for #135:
- A standalone "&" no longer counts as a garbled token, so "Kirkland &
  Ellis LLP" and "Wells Fargo & Co." keep their score.
- The sentence check ignores periods after abbreviations (org suffixes,
  Dr., Rev., Jr., Dept., Div., ...). The PERSON over-5-tokens penalty
  counts name tokens only, so titles don't push a name over the limit.
- The punctuation-ratio penalty applies to PERSON, ORGANIZATION and
  LOCATION only; MONEY like "$1,250,000.00" keeps its score.
- Model sizes in "m" (gemma3:270m) are compact.
- Auto cutoff is now under 8B plus the qwen3 family, so llama3.1:8b keeps
  the full prompt. qwen3:8b on the full prompt with think disabled still
  returned truncated JSON at 4000 and 8000 tokens. New ai.compact_prompt
  (auto|true|false, env OPENFOIA_AI_COMPACT_PROMPT) overrides the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce
…breviation; match qwen3 anywhere in model name

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQw8DDrDZ2tFzswSSEtce
@JordanCoin

Copy link
Copy Markdown
Owner Author

Review (Claude opus reviewer, read-only, 2026-11-06), two passes: MERGE. Pass 1 found the new junk scoring dropped 'X & Y' orgs (Kirkland & Ellis to 0.48) and six-word names ending in Inc. (hard zero), and penalized MONEY for punctuation; all fixed in the second commit and re-measured across a 35-name battery on regex and spaCy. Compact-prompt cutoff settled by A/B: qwen3:8b emits broken JSON on the full prompt at 4000 and 8000 tokens with thinking on or off, llama3.1:8b scores 12/14 on full, so auto = under 8B or the qwen3 family, overridable via ai.compact_prompt. Third commit (coordinator): six-plus-word mostly-lowercase mentions score 0 so a sentence ending in 'Inc.' no longer passes, and qwen3 is matched anywhere in the model name (hf.co/unsloth/Qwen3-8B-GGUF). Pre-existing and tracked separately: non-Latin names (東京都) and 2-letter names (Ng, 3M) score 0 because the letter count is ASCII-only.

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.

LLM extraction: model-specific prompt templates + Qwen3 support Entity extraction: filter junk entities from regex fallback

1 participant