Skip to content

metrics: extract_llm and extract_llm_sweep measure saved tokens against different baselines, so their per-arm savings are not comparable #195

Description

@amiddavid

The inconsistency

After #188, the two extraction components measure "saved tokens" against different baselines:

Component Measures Site
extract_llm_sweep content − the message as spliced extract_sweep.go, phase 3
extract_llm content − the projection extract_llm.go, out[k].saved

In marker_mode: full — the default — the text actually written is replacement + "\n" + marker + recovery hint. So the projection-based figure omits the marker and the hint, and overstates by that much per candidate. Measured on the sweep's stocked fixture before it was corrected: 86,458 claimed against 86,201 actually sent, i.e. ~23 tokens per candidate.

Both feed metrics.RecordExtractionSaving / RecordExtractionValue, and both surface in /stats under by_component, so the two arms of a comparison are no longer measuring the same thing.

Why the gap matters more than its size

It is systematic, not noise: a fixed per-candidate overhead in one component and not the other, so it scales with the number of removals rather than averaging out. A configuration that removes more looks disproportionately better under the projection-based figure.

That matters specifically because extract_llm's savings figure is what iteration 024's re-run will be judged on. Anyone reading the two arms side by side needs to know one is wire-measured and the other is not.

The sweep is the correct one

content − MessageText(req.Input[i]) after the splice is the number an operator can check against their bill: it is what the request actually shrank by. extract_llm should move to the same basis.

Why it was not fixed in #188

Deliberate, and the reasoning is worth keeping: #188's subject is reserve durability, and moving a published savings figure inside it would make the iteration-024 comparison unreadable for a reason unrelated to what that PR changed. A savings number should move in a change whose subject is the savings number — otherwise the re-run cannot separate "the mechanism got better" from "we started counting differently". The sweep's figure moved there only because a comment added in the same commit asserted it was the wire figure, which made it wrong rather than merely inconsistent.

Suggested fix

Mirror the sweep: compute saved in phase 3 from the spliced message rather than carrying the projection-only delta out of runCall. out[k].saved already exists for that purpose, so it is a one-line change plus its test.

Note the same question applies to the replay paths, which credit content − cached.Projected at the repeat rate — also projection-only.

Sequencing

Worth landing after the iteration-024 re-run, or as an explicit note beside its results, so the re-run's numbers stay comparable to the ones already published. Otherwise a savings change lands in the middle of the comparison it would invalidate.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions