Skip to content

refactor(libsy): classifier::score returns the response alongside the score - #203

Merged
linj-glitch merged 4 commits into
mainfrom
linj/switch-1054-classifier-changes
Jul 30, 2026
Merged

refactor(libsy): classifier::score returns the response alongside the score#203
linj-glitch merged 4 commits into
mainfrom
linj/switch-1054-classifier-changes

Conversation

@linj-glitch

@linj-glitch linj-glitch commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Extends the Classifier trait so score() returns (Classification, Option) instead of just Classification. The Option lets a classifier that already called a model hand back that response directly, so fall_through skips the outbound call and the turn is not paid for twice. All implementors updated. Part 2 of breaking up PR #172.

Summary by CodeRabbit

  • New Features

    • Classifiers can now provide an immediate response during routing, avoiding unnecessary model calls.
    • Added support for selecting the highest-confidence classification.
    • Existing routing, affinity, staging, and delegation behavior remains intact.
  • Bug Fixes

    • Prevented duplicate model calls when a classifier has already produced a response.
    • Improved propagation of classifier decisions through routing pipelines.

@linj-glitch
linj-glitch requested a review from a team as a code owner July 30, 2026 17:43
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

The classifier scoring contract now returns (Classification, Option<Response>). Implementations and tests adopt the tuple shape, while FallThrough returns classifier-served responses directly and otherwise preserves model fallback behavior.

Classifier response routing

Layer / File(s) Summary
Classifier scoring contract
crates/libsy/src/core/classifier.rs
The public Classifier::score API returns a classification with an optional response, and Classification gains max_classification().
Classifier implementation propagation
crates/libsy/src/algorithms/{llm_class.rs,rand.rs,stage.rs,subagent_affinity_tests.rs}, crates/libsy/src/algorithms/util/*, crates/libsy/tests/prompts.rs
Classifier wrappers, utilities, and test stubs adopt the tuple return shape while preserving their existing classification behavior.
FallThrough served-response execution
crates/libsy/src/algorithms/fall_through.rs
Routing captures optional served responses and execute returns them directly; absent responses continue through model fallback handling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Poem

I’m a rabbit with routes in a neat little line,
A response may hop out before models opine.
Scores wear a tuple, classifiers agree,
FallThrough skips calls when the answer is free.
Hop, hop—clean contracts for all to see!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main API change: classifier::score now returns the response alongside the score.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/libsy/src/core/classifier.rs (1)

97-102: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the served-response contract.

The public docs do not explain when Some(Response) is valid or that it bypasses the target call. Document that it must accompany a deciding classification and becomes the final turn response.

As per coding guidelines, add documentation for public Rust items.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libsy/src/core/classifier.rs` around lines 97 - 102, Document the
public async score method’s served-response contract: explain that
Some(Response) is valid only with a deciding Classification, becomes the final
turn response, and bypasses the target call. Add this Rust documentation
directly to score while preserving its existing signature and behavior.

Source: Coding guidelines

🧹 Nitpick comments (1)
crates/libsy/src/algorithms/fall_through.rs (1)

198-209: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a served-response short-circuit test.

No test returns Some(Response) and proves the selected target is not invoked. Cover this path with a classifier-provided response and a target client that records or rejects calls, preventing regressions that reintroduce the duplicate paid turn.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libsy/src/algorithms/fall_through.rs` around lines 198 - 209, Add a
test for the served-response branch in the fall-through algorithm, supplying a
classifier-provided Some(Response) and a target client that records or rejects
invocation. Assert the response is returned unchanged and the selected target is
never called, while preserving existing coverage for the None path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/libsy/src/core/classifier.rs`:
- Around line 97-102: Document the public async score method’s served-response
contract: explain that Some(Response) is valid only with a deciding
Classification, becomes the final turn response, and bypasses the target call.
Add this Rust documentation directly to score while preserving its existing
signature and behavior.

---

Nitpick comments:
In `@crates/libsy/src/algorithms/fall_through.rs`:
- Around line 198-209: Add a test for the served-response branch in the
fall-through algorithm, supplying a classifier-provided Some(Response) and a
target client that records or rejects invocation. Assert the response is
returned unchanged and the selected target is never called, while preserving
existing coverage for the None path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e7cb54c7-e16d-4b50-afe7-852d351afc4b

📥 Commits

Reviewing files that changed from the base of the PR and between f3ff7ff and ac10587.

📒 Files selected for processing (11)
  • crates/libsy/src/algorithms/fall_through.rs
  • crates/libsy/src/algorithms/llm_class.rs
  • crates/libsy/src/algorithms/rand.rs
  • crates/libsy/src/algorithms/stage.rs
  • crates/libsy/src/algorithms/subagent_affinity_tests.rs
  • crates/libsy/src/algorithms/util/affinity.rs
  • crates/libsy/src/algorithms/util/llm_judge.rs
  • crates/libsy/src/algorithms/util/stage.rs
  • crates/libsy/src/algorithms/util/subagent.rs
  • crates/libsy/src/core/classifier.rs
  • crates/libsy/tests/prompts.rs

Comment thread crates/libsy/src/algorithms/util/subagent.rs
Comment thread crates/libsy/src/algorithms/util/affinity.rs
Comment thread crates/libsy/src/algorithms/fall_through.rs
Comment thread crates/libsy/src/core/classifier.rs Outdated
@sabhatinas

Copy link
Copy Markdown
Contributor

Escalation feature should be a configuration knob in LLM classifier to optionally latch to a strong tier.

Consider this trajectory: wwww(l)sssss

  1. for turns < latch point marked as w, return resolved decision with score to route to weak model
  2. for turns > latch point marked as s, return resolved decision with score to route to strong model
  3. Use session affinity helper to latch future turns by adding a processor post decision.

@sabhatinas

Copy link
Copy Markdown
Contributor

can you add escalation as a flag/composable config inside llm classifier config?

  1. branch out in base implementation of llm classifier for classifier output
  2. llm classifier gives scores / decisions etc
  3. escalation router gives direct responses (with in-built latching)

… score

Signed-off-by: Lin Jia <linj@nvidia.com>
… PR 4

Signed-off-by: Lin Jia <linj@nvidia.com>
@linj-glitch
linj-glitch force-pushed the linj/switch-1054-classifier-changes branch from 45caf7a to 15e3dd8 Compare July 30, 2026 20:34
@linj-glitch
linj-glitch merged commit 6c3f265 into main Jul 30, 2026
15 checks passed
@linj-glitch
linj-glitch deleted the linj/switch-1054-classifier-changes branch July 30, 2026 21:05
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.

4 participants