previews · research · ingestion model benchmark

Which model should write ingestion’s summaries?

Benchmarking the deprecated prod model against the GPT-5.6 family on 39 real documents, through the exact production code path.

Final 2026-07-12 Author: Adolfo Tamayo Harness: ingestion#697 OpenAI deprecations

Set summarisation to gpt-5.6-luna @ medium. It is a pure parameter change (no code, no deploy beyond a restart), roughly 3× faster than prod today, and nearly halves judge-flagged hallucinations. gpt-5.6-terra @ medium is the quality-first alternative at 2.4× the cost. The current model, gpt-5-mini, shuts down on December 11, 2026 and lost on every metric except raw price — and that price retires with it. OpenAI’s suggested drop-in, gpt-5.4-mini, was the weakest candidate head-to-head, so don’t take the default migration path.

2.9×
faster summaries (p50 13.1s → 4.6s)
22 → 12
hallucination-flagged docs (of 39)
$19.6
per 1k docs (prod: $5.6)
1,732
LLM calls, 0 errors, ~$22 spend

Why now

Ingestion generates two summaries for every document it processes (a structured ≤500-word summary and a 1–3 sentence concise one), plus a vision description for images. All three run on OpenAI models. The summarisation model in production is gpt-5-mini at reasoning effort low, and its snapshot is shut down on December 11, 2026. We have to move; the question is where to.

Two findings from scoping worth keeping: ingestion’s models are not defined in Langfuse prompt configs (both prompts have empty config objects) — they come from WORKER__TEXT_SUMMARISATION_* env vars via Parameter Store, so a model switch is a parameter change plus restart. The image path is different: analyze_image.py hardcodes gpt-5.4-mini in code, and that model is not in the December shutdown, so vision has no deadline.

Methodology

1 · Corpus 39 text docs + 4 images 2 · Matrix run 718 generations, prod code path 3 · Judge 1,014 judgements, gpt-5.5 4 · Report quality · latency · cost

Corpus. 50 text documents: 31 real production PDFs (leases, affidavits, court filings, USPTO correspondence) plus S3 edge cases from the existing eval corpus — Urdu, Polish and Welsh forms, filled forms, DOCX and TXT. 39 had usable extracted text (the rest are corrupted or image-only PDFs, recorded as skipped). 4 scanned images (150dpi form scans, a screenshot) feed the vision task.

Execution. Every config ran through the real pipeline code: the two prompts fetched live from Langfuse at the production label, executed by the same split_and_aggregate library prod uses (litellm underneath), with per-call token usage and latency captured. Latency is total call time; ingestion is batch and non-streaming, so time-to-first-token is deliberately not measured.

Held constant to isolate the model variable: context window pinned to 250k for every config (prod’s value), identical text extraction, identical prompts, temperature 1.0.

Scoring. Deterministic checks (word-limit and sentence-count compliance, structure present) plus an LLM judge — gpt-5.5, outside the candidate family to reduce self-preference. Each output gets rubric scores 1–10 for coverage, faithfulness and structure with hallucination flags; each main summary is also judged head-to-head against the prod baseline, twice with positions swapped to cancel order bias.

Judge robustness. The three decision-relevant configs were re-judged with a cross-provider judge (Anthropic’s claude-opus-4-8, no stake in an all-OpenAI field). The ranking held and sharpened: hallucination-flagged docs 12/39 for the baseline vs 2/39 for luna@medium, faithfulness 8.92 vs 9.41. The only judge-sensitive axis was pairwise preference — the same verbosity effect already discounted below — so the recommendation does not rest on gpt-5.5’s opinion.

ConfigRole$ in / out per 1M tokens
gpt-5-mini@lowProd baseline — deprecated 2026-12-110.25 / 2.00
gpt-5.4-mini@lowOpenAI’s recommended replacement0.75 / 4.50
gpt-5.6-luna @ none / low / mediumCandidate — fast tier1.00 / 6.00
gpt-5.6-terra @ none / low / mediumCandidate — balanced tier2.50 / 15.00
gpt-5.6-sol@lowQuality-ceiling reference5.00 / 30.00

Results — main summary (≤500 words)

Latency per document, p50 (bar) · p95 in the right column — lower is better
gpt-5-mini@low
13.10s · p95 29.07s
gpt-5.6-sol@low
9.85s · p95 15.83s
gpt-5.6-terra@low
5.95s · p95 8.55s
gpt-5.6-terra@medium
5.83s · p95 9.55s
gpt-5.6-terra@none
5.53s · p95 8.25s
gpt-5.6-luna@medium
4.59s · p95 6.86s
gpt-5.4-mini@low
4.41s · p95 7.00s
gpt-5.6-luna@low
4.10s · p95 6.07s
gpt-5.6-luna@none
3.73s · p95 6.36s
prod baselinerecommendedother configs
ConfigCoverageFaithfulnessStructureHalluc. docs≤500w compliant$ / 1k docs
gpt-5-mini@low (prod)8.548.419.2122 / 3959%5.63
gpt-5.4-mini@low8.549.009.3113 / 3992%14.25
gpt-5.6-luna@none8.779.159.5113 / 3982%18.72
gpt-5.6-luna@low8.648.909.3114 / 3985%19.07
gpt-5.6-luna@medium ← recommended8.779.039.3112 / 3985%19.63
gpt-5.6-terra@none8.649.009.4613 / 3987%46.26
gpt-5.6-terra@low8.829.009.5414 / 3990%46.67
gpt-5.6-terra@medium8.859.009.6214 / 3987%46.80
gpt-5.6-sol@low8.909.109.4610 / 3997%94.94
Docs with judge-flagged hallucinations, of 39 — lower is better
gpt-5-mini@low
22 / 39
gpt-5.6-terra@medium
14 / 39
gpt-5.6-luna@low
14 / 39
gpt-5.4-mini@low
13 / 39
gpt-5.6-luna@medium
12 / 39
gpt-5.6-sol@low
10 / 39

Reading the head-to-head numbers honestly. In pairwise judging the old baseline “wins” against most candidates — but that is verbosity bias, not quality. It averages 484 words per summary against 379–409 for everything else, and only 59% of its summaries respect the 500-word limit the prompt itself declares (overflow is truncated in production). The judge rewards the extra detail in a side-by-side read; the rubric, which scores each summary against its source, tells the opposite story: worst faithfulness, most hallucination flags. We weight the rubric, compliance and latency — the metrics that reflect what production actually ships.

Pairwise vs prod baseline, per 39 docs (positions swapped, aggregated) — win / tie / loss
gpt-5.6-terra@medium
20
5
14
best head-to-head
gpt-5.6-terra@low
19
4
16
gpt-5.6-terra@none
17
3
19
gpt-5.6-sol@low
16
6
17
gpt-5.6-luna@medium
13
5
21
recommended
gpt-5.6-luna@none
12
7
20
gpt-5.6-luna@low
11
7
21
gpt-5.4-mini@low
7
2
30
weakest candidate
wintieloss

Results — concise summary (1–3 sentences)

Same shape, compressed. The baseline again over-writes (72% sentence-count compliance); gpt-5.6-luna@medium has the fewest hallucination flags (5/39) at p50 1.2s vs the baseline’s 3.2s. gpt-5.4-mini posts the lowest coverage score anywhere in the run (6.67) — its concise summaries drop material facts.

ConfigCoverageFaithfulnessHalluc. docs1–3 sent. compliantp50 latency$ / 1k docs
gpt-5-mini@low (prod)7.599.007 / 3972%3.22s3.95
gpt-5.4-mini@low6.679.137 / 3997%1.36s11.21
gpt-5.6-luna@medium ← recommended7.219.215 / 3992%1.17s15.03
gpt-5.6-terra@medium7.339.216 / 3995%1.57s38.10
gpt-5.6-sol@low7.109.105 / 3992%2.34s74.15

Results — image analysis n=4, indicative only

gpt-5.6-luna@low beats the hardcoded gpt-5.4-mini on speed (p50 4.3s vs 6.1s) at similar cost, but four images is a signal, not evidence. Since gpt-5.4-mini is not deprecated, there is no deadline here: either expand the image corpus and re-run before deciding, or switch to luna@low for family consistency whenever analyze_image.py is next touched (it needs a code change either way).

ConfigMean wordsp50 latencyp95 latency$ / 1k images
gpt-5.4-mini (current, hardcoded)5676.05s7.48s5.34
gpt-5.6-luna@low4744.32s5.78s6.90
gpt-5.6-luna@none5104.69s11.01s6.75
gpt-5.6-terra@low5247.07s8.43s17.48

Cost at production volume

Production runs roughly 190k documents a month through summarisation (Axiom, trailing 30 days: ~178k per-file runs plus ~15k batch runs), each generating both summaries. At the measured per-document costs:

Option$ / 1k docs (both prompts)~$ / month at 190k docsvs today
gpt-5-mini@low — today, retired Dec 119.61,850
gpt-5.4-mini@low — cheapest migration25.54,900+3.0k
gpt-5.6-luna@medium ← recommended34.76,700+4.8k
gpt-5.6-terra@medium84.916,400+14.5k

Three things this table settles:

A model-independent lever if the delta matters: the pipeline currently sends the full document text twice, once per prompt. A single call producing both summaries would pay for input once — roughly 40% off any option above (luna lands near ~$4k/month). That is a small processing-task change, separate from the model decision.

Outcome

Set now: gpt-5.6-luna@medium

  • Ties for best hallucination rate among realistic options (12/39 vs prod’s 22/39)
  • p50 4.6s main / 1.2s concise — ~3× faster than prod
  • $19.6 per 1k docs; 2.4× cheaper than terra
  • medium fits the existing effort config type: parameter change onlyWORKER__TEXT_SUMMARISATION_LLM_MODEL + _REASONING_EFFORT for the three worker services, context window stays 250k
  • litellm already accepts gpt-5.6 — this whole run went through the prod code path

Quality-first alternative: gpt-5.6-terra@medium

  • Only config that beats the old baseline head-to-head (20W / 5T / 14L)
  • Best structure score (9.62); still 2.3× faster than prod
  • $46.8 per 1k docs — worth it only if summary quality is a product priority at current volumes

Explicitly not recommended

Follow-ups. If a future config wants effort none, xhigh or max, the Literal["low","medium","high"] type on the worker config needs widening first. Separately, the 5.6 family’s 1M-token window could reduce chunking for very large documents; that was deliberately pinned to 250k here and deserves its own experiment.

Caveats.