Skip to content

An extraction reply cites sentences by number - #705

Closed
WaylandYang wants to merge 3 commits into
devfrom
fix/an-extraction-reply-cites-sentences
Closed

WaylandYang wants to merge 3 commits into
devfrom
fix/an-extraction-reply-cites-sentences

Conversation

@WaylandYang

@WaylandYang WaylandYang commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Related to #701, which has the measurement that started this.

Problem

An extraction reply spends most of its output restating what the server already has. One ai-timeline chunk (1,318 characters) came back as 13,620 characters, 2,965 tokens, for 13 entities and 19 facts:

  • Quotes: 24% of the JSON. Every fact copied its supporting sentence verbatim. 19 facts had 10 distinct sentences, and the quotes together were longer than the chunk.
  • Each side named three times: about 37%. subject, subject_ref and subject_span, and the same for the object. 24 of 38 spans equalled the name.

Output tokens are the slow part of a call.

Change

  • The Text block is numbered by sentence ([S1] …, UAX Fix GLIBC mismatch, and make the release prove the container boots #29 bounds). The text is otherwise untouched: line breaks and table rows are kept, and a table row is its own sentence.
  • A fact cites "sentence": 3, or a list for adjacent sentences. It names its sides by handle only, gives a span only when the sentence names the entity differently, and leaves out null fields. Names cite a sentence the same way.
  • utopia_extract::ground runs right after parsing. It fills quote from the cited sentences (min to max, always a substring of the chunk) and fills subject/object from the handles. Everything downstream still reads quote and the names, so span checks, same-sentence edges, the opening check, evidence rows and the queue agent's stale-quote check are unchanged. A reply that still writes quotes or names keeps them. A fact whose handle points nowhere is dropped and counted in skipped_facts.

Measured

Recall bench (NVIDIA filings, 52 items), measured together with #704 on the same run:

before after
recall 47/52 48/52 (1σ ≈ 2.7)
output per extraction call, same 76 chunks 1,157 684
total output tokens, same 76 chunks 87,896 51,987
seconds per chunk, 52-chunk earnings release 57 34

On google-deepmind.txt from ai-timeline (41 chunks, both PRs), output per call went 1,605 → 965 tokens and prompt 19,473 → 8,300.

Seconds depend on the provider's load at the time of day, so read them as direction only. 60 of 76 replies cited sentences, and the rest had no facts. None repeated names or quotes. All 566 evidence rows got a quote back, averaging 110 characters.

Tests

  • every_sentence_gets_a_number_and_the_text_is_otherwise_untouched
  • a_reply_by_sentence_and_handle_is_filled_in_from_the_text
  • a_sentence_number_outside_the_text_cites_nothing
  • existing pipeline tests with scripted replies in the old shape still pass
  • cargo test -p utopia-extract -p utopia-server, clippy and fmt clean

🤖 Generated with Claude Code

WaylandYang and others added 2 commits September 14, 2026 17:31
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: WaylandYang <wayland0916@gmail.com>
@WaylandYang
WaylandYang marked this pull request as draft September 14, 2026 15:04
@WaylandYang

Copy link
Copy Markdown
Contributor Author

Back to draft. The lease bench (Blackbaud HQ lease chain, 18 as-of questions) drops with this change. Every build below carries #696, #699 with its lock fix, #697 and #706; the only difference is this PR (the base's ontology is small and inlined, so #704 does not apply):

build run 1 run 2
without this PR 13/18 (1 partial) 17/18 (0 partial)
with this PR, opening numbered too 8/18 (6 partial) 7/18 (8 partial)
with this PR plus the gate fix in #696 7/18 (5 partial) 7/18 (6 partial)

The partials are old values left open next to new ones: the lease stays split across 4–5 entities with this PR against 2 without it. The recall bench (NVIDIA filings) did not show it (48/52). Next: find which half does it — sentence numbers in place of quotes, or facts that name their sides by handle only.

@WaylandYang

Copy link
Copy Markdown
Contributor Author

Closing. The two halves were measured apart on the lease bench, each as a build on top of the control (the same build as the table above without this PR):

build run 1 run 2 output tokens per call
control (quotes and names) 13/18 17/18 666
names dropped, quotes kept 8/18 8/18 437
sentence numbers, names kept 15/18 9/18 621
  • Names are load-bearing. When the model writes a handle that was never declared (e3) or collides with a known one (k3), the server binds the fact through its name. Without the name the fact is dropped: 24–32 malformed items per run against 17.
  • Sentence numbers are less exact than a copied quote on contract text. span_not_in_quote rose from 61–88 to 133–147 per run, because the cited sentence often is not the one that names the entity. On this corpus they saved only 7% of output tokens.

The per-chunk budget (#704) stays: it carries most of the saving on large ontologies (19.5k → 8.3k prompt tokens per call) without touching the output contract.

@WaylandYang
WaylandYang deleted the fix/an-extraction-reply-cites-sentences branch September 15, 2026 14:01
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.

1 participant