Skip to content

perf(ingest): send every TOC batch at once (HAL-1545) - #70

Open
hallelx2 wants to merge 1 commit into
halleluyaholudele/hal-1708-engine-llmgate-guard-fixfrom
halleluyaholudele/hal-1545-engine-the-toc-stage-batches-at-24k-and-loops-sequentially
Open

hallelx2 wants to merge 1 commit into
halleluyaholudele/hal-1708-engine-llmgate-guard-fixfrom
halleluyaholudele/hal-1545-engine-the-toc-stage-batches-at-24k-and-loops-sequentially

Conversation

@hallelx2

@hallelx2 hallelx2 commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Why

Six Judge loops in the TOC stage built a batch, sent it, waited, then built the next. The batches were independent, so each phase took the sum of its requests where it could have taken the longest.

What

  • sendJudgeBatches: builds every batch first, sends them together, and lets the adaptive limiter set concurrency. The first failure cancels the rest and fails the phase, never returning a partial set (the contract every caller already had).
  • Applied to detection fan-out, detection, verification, contents confirmation, page resolution and heading split.
  • The leaf splitter processes every leaf of a generation at once, each with its own Usage, folded back in tree order so the ledger and Degraded list are deterministic.
  • The resolver breaks ties in sorted key order, not map order.
  • The 24k budget is unchanged. The issue's 6k proposal rested on a probe that was later retracted.

Evidence

21 FinanceBench filings, one at a time, Judge-only (docs/evaluations/2026-09-28-latency-was-our-cpu.md §2):

build median/filing max total cost coverage
original 66.1 s 456.5 s 1,673 s $0.1331 47/47
+ #69 8.8 s 49.4 s 234 s $0.1316 47/47
+ this 4.1 s 15.9 s 105 s $0.1330 47/47

Title recall against the original build is 0.944. The tokenizer fix alone, which asks identical questions, reaches 0.949, so that's Jev's run-to-run floor and this sits inside it. The issue's "≥ 0.96" bar can't be met by re-running unchanged code.

Tests: concurrency, order, and cancel-on-first-failure for sendJudgeBatches; the existing ingest suite. go test -race green locally. CI blocked (HAL-1712).

Stacked on #69.

Closes HAL-1545

Summary by Sourcery

Reduce TOC ingest latency by concurrently executing independent Judge work while preserving deterministic accounting, ordering, and failure behavior.

Enhancements:

  • Parallelize independent TOC Judge batches across detection, verification, confirmation, page resolution, and heading splitting to reduce ingest latency while preserving ordered results and fail-fast phase semantics.
  • Process leaves concurrently within each split generation and merge usage deterministically.
  • Make page-resolution tie breaking deterministic by sorting candidate keys.

Tests:

  • Add coverage for concurrent Judge dispatch, ordered results, cancellation on first failure, and empty input.

Each Judge phase of the TOC stage — detection fan-out, detection,
verification, contents confirmation, page resolution and heading
splitting — built one batch, sent it, waited for the answer and only
then built the next. The batches never depended on each other, so a
phase's wall clock was the sum of its requests where it could have
been the longest of them. They now build every batch and hand the set
to sendJudgeBatches, which sends them together and lets llmgate's
adaptive limiter decide how many are in flight. The first failure
cancels the rest and fails the phase, never a partial set, which is
the contract every caller already had.

The leaf splitter walks one generation at a time and splits every
leaf of a generation at once; each leaf accounts into its own Usage,
folded back in tree order so the ledger and its Degraded list read
the same on every run. The resolver now chooses between tied pages in
sorted key order instead of map order.

The request budget stays at 24k. The 6k this issue first proposed
rested on a probe the 2026-09-25 evaluation retracted.
Copilot AI lite review requested due to automatic review settings September 28, 2026 03:26
@sourcery-ai

sourcery-ai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR reduces TOC Judge-stage latency by batching all independent requests concurrently through a shared cancel-on-failure helper and parallelizing leaf splits generation by generation, while preserving phase-level failure behavior, request/result ordering, deterministic usage accounting, and deterministic page-resolution ties.

Sequence diagram for concurrent TOC Judge batches

sequenceDiagram
    participant Phase as TOCPhase
    participant Helper as sendJudgeBatches
    participant Judge as llmgateJudge

    Phase->>Helper: sendJudgeBatches(ctx, Judge, reqs)
    par Independent request 1
        Helper->>Judge: Judge(ctx, reqs[0])
        Judge-->>Helper: Judgment[0]
    and Independent request 2
        Helper->>Judge: Judge(ctx, reqs[1])
        Judge-->>Helper: Judgment[1]
    and Additional requests
        Helper->>Judge: Judge(ctx, reqs[i])
        Judge-->>Helper: Judgment[i]
    end
    Helper-->>Phase: results in request order

    alt First request fails
        Judge-->>Helper: error
        Helper->>Helper: cancel()
        Helper-->>Phase: firstErr, no partial results
    end
Loading

Flow diagram for generation-by-generation leaf splitting

flowchart TD
    Start["Collect splittable leaves"] --> Generation["Process one generation"]
    Generation --> Parallel["splitLeaf for every leaf concurrently"]
    Parallel --> Fold["merge Usage and results in tree order"]
    Fold --> Children{Children created?}
    Children -->|Yes| Generation
    Children -->|No| Done["Return deterministic ledger and tree"]
Loading

File-Level Changes

Change Details Files
Parallelize independent Judge batches while preserving ordered results and all-or-nothing phase semantics.
  • Added a shared concurrent sender that launches all requests, returns results by request index, and cancels outstanding work after the first error.
  • Converted TOC detection, fan-out, title verification, entry confirmation, page resolution, and heading-splitting flows to build requests before sending them.
  • Kept usage accounting and downstream processing in deterministic request order.
pkg/ingest/judge_send.go
pkg/ingest/judge_send_test.go
pkg/ingest/toc_extract_judge.go
pkg/ingest/toc_judge.go
pkg/ingest/toc_judge_fanout.go
pkg/ingest/toc_resolve.go
pkg/ingest/toc_split.go
Parallelize leaf splitting within each generation without introducing races or nondeterministic accounting.
  • Collects all eligible leaves for a generation and processes them concurrently.
  • Uses per-leaf Usage values, then merges results in tree order.
  • Processes newly created child leaves in subsequent generations.
pkg/ingest/toc_split.go
pkg/ingest/toc_builder.go
Make page-resolution tie handling deterministic.
  • Sorts question keys before applying strict-improvement selection so equal scores do not depend on map iteration order.
pkg/ingest/toc_resolve.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f3327de3-dc28-4f99-a734-35e1fc3258da

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

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.

2 participants