Skip to content

feat: Move LLM classifier algo#90

Open
grahamking wants to merge 4 commits into
mainfrom
gk-libsy-classifier-algo
Open

feat: Move LLM classifier algo#90
grahamking wants to merge 4 commits into
mainfrom
gk-libsy-classifier-algo

Conversation

@grahamking

@grahamking grahamking commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

From libsy-examples to libsy. Bring the three examples/ binaries
along.

Signed-off-by: Graham King grahamk@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added the LlmClassifierOrchAlgo and ClassifierDecision APIs for classifying requests and routing them to strong or weak models.
    • Added a streaming agent example that displays response tokens in real time.
  • Documentation
    • Updated crate documentation to describe classifier-based model routing.
  • Examples
    • Updated existing examples to use the newly available classifier API directly.

From `libsy-examples` to `libsy`. Bring the three `examples/` binaries
along.

Signed-off-by: Graham King <grahamk@nvidia.com>
@grahamking

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2cd64387-a977-4563-9c9b-44b8deee5ee3

📥 Commits

Reviewing files that changed from the base of the PR and between 93f0e3e and 2ab9154.

📒 Files selected for processing (7)
  • crates/libsy-examples/src/lib.rs
  • crates/libsy/examples/research_agent.rs
  • crates/libsy/examples/research_agent_core.rs
  • crates/libsy/examples/streaming_agent.rs
  • crates/libsy/src/algorithms.rs
  • crates/libsy/src/algorithms/llm_class.rs
  • crates/libsy/src/lib.rs
💤 Files with no reviewable changes (1)
  • crates/libsy-examples/src/lib.rs

Walkthrough

The LLM classifier is moved into libsy’s public API, example imports are updated, and a Tokio-based streaming agent example is added for streamed and aggregated responses.

Changes

LLM API and examples

Layer / File(s) Summary
Classifier module and public exports
crates/libsy/src/algorithms.rs, crates/libsy/src/algorithms/llm_class.rs, crates/libsy/src/lib.rs
Exports the classifier module, updates internal imports and prompt text, and re-exports ClassifierDecision and LlmClassifierOrchAlgo.
Example import migration
crates/libsy-examples/src/lib.rs, crates/libsy/examples/research_agent.rs, crates/libsy/examples/research_agent_core.rs
Moves classifier imports to libsy and removes the former examples-crate module export.
Streaming agent execution
crates/libsy/examples/streaming_agent.rs
Adds a Tokio example that handles run_stream, supplies token chunks, and prints streamed or aggregated responses.

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

Poem

I’m a rabbit with tokens to spare,
Streaming little words through the air.
The classifier found home,
New examples now roam,
And each chunk gets a whiskery flare!

🚥 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 matches the main change: moving the LLM classifier algorithm into libsy.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

Actionable comments posted: 4

🤖 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.

Inline comments:
In `@crates/libsy/examples/research_agent.rs`:
- Line 18: Update the import example in crates/libsy/README.md to use
libsy::LlmClassifierOrchAlgo instead of
libsy_examples::llm_class::LlmClassifierOrchAlgo, matching the migrated API and
the import shown in research_agent.rs.

In `@crates/libsy/examples/streaming_agent.rs`:
- Around line 11-13: Update the example command in the streaming_agent module
documentation to use the libsy package name instead of libsy-examples, while
keeping the streaming_agent example target unchanged.

In `@crates/libsy/src/algorithms/llm_class.rs`:
- Line 23: Update CLASSIFIER_PROMPT_PREAMBLE or the create_run_task
concatenation so the classifier prompt always includes a separator before
user_prompt, preserving readable text such as “...[0, 1]. prove it”. Add an
assertion verifying the exact assembled prompt shape.

In `@crates/libsy/src/lib.rs`:
- Around line 64-65: Re-export ClassifierTier alongside ClassifierDecision and
LlmClassifierOrchAlgo in the public exports of the crate root. Keep the
algorithms module private while making the ClassifierDecision::tier field’s type
nameable by downstream crates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2cd64387-a977-4563-9c9b-44b8deee5ee3

📥 Commits

Reviewing files that changed from the base of the PR and between 93f0e3e and 2ab9154.

📒 Files selected for processing (7)
  • crates/libsy-examples/src/lib.rs
  • crates/libsy/examples/research_agent.rs
  • crates/libsy/examples/research_agent_core.rs
  • crates/libsy/examples/streaming_agent.rs
  • crates/libsy/src/algorithms.rs
  • crates/libsy/src/algorithms/llm_class.rs
  • crates/libsy/src/lib.rs
💤 Files with no reviewable changes (1)
  • crates/libsy-examples/src/lib.rs

@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

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 4

🤖 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.

Inline comments:
In `@crates/libsy/examples/research_agent.rs`:
- Line 18: Update the import example in crates/libsy/README.md to use
libsy::LlmClassifierOrchAlgo instead of
libsy_examples::llm_class::LlmClassifierOrchAlgo, matching the migrated API and
the import shown in research_agent.rs.

In `@crates/libsy/examples/streaming_agent.rs`:
- Around line 11-13: Update the example command in the streaming_agent module
documentation to use the libsy package name instead of libsy-examples, while
keeping the streaming_agent example target unchanged.

In `@crates/libsy/src/algorithms/llm_class.rs`:
- Line 23: Update CLASSIFIER_PROMPT_PREAMBLE or the create_run_task
concatenation so the classifier prompt always includes a separator before
user_prompt, preserving readable text such as “...[0, 1]. prove it”. Add an
assertion verifying the exact assembled prompt shape.

In `@crates/libsy/src/lib.rs`:
- Around line 64-65: Re-export ClassifierTier alongside ClassifierDecision and
LlmClassifierOrchAlgo in the public exports of the crate root. Keep the
algorithms module private while making the ClassifierDecision::tier field’s type
nameable by downstream crates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2cd64387-a977-4563-9c9b-44b8deee5ee3

📥 Commits

Reviewing files that changed from the base of the PR and between 93f0e3e and 2ab9154.

📒 Files selected for processing (7)
  • crates/libsy-examples/src/lib.rs
  • crates/libsy/examples/research_agent.rs
  • crates/libsy/examples/research_agent_core.rs
  • crates/libsy/examples/streaming_agent.rs
  • crates/libsy/src/algorithms.rs
  • crates/libsy/src/algorithms/llm_class.rs
  • crates/libsy/src/lib.rs
💤 Files with no reviewable changes (1)
  • crates/libsy-examples/src/lib.rs
🛑 Comments failed to post (4)
crates/libsy/examples/research_agent.rs (1)

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

Update the README import path in the same migration.

crates/libsy/README.md still documents libsy_examples::llm_class::LlmClassifierOrchAlgo; after this API move, users following that example will get a broken import. Change it to libsy::LlmClassifierOrchAlgo.

🤖 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/examples/research_agent.rs` at line 18, Update the import
example in crates/libsy/README.md to use libsy::LlmClassifierOrchAlgo instead of
libsy_examples::llm_class::LlmClassifierOrchAlgo, matching the migrated API and
the import shown in research_agent.rs.
crates/libsy/examples/streaming_agent.rs (1)

11-13: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
sed -n '/^\[package\]/,/^\[/p' crates/libsy/Cargo.toml

Repository: NVIDIA-NeMo/Switchyard

Length of output: 393


🏁 Script executed:

#!/bin/bash
set -eu

echo "== crates/libsy/examples/streaming_agent.rs =="
sed -n '1,120p' crates/libsy/examples/streaming_agent.rs

echo
echo "== Algorithm::run references =="
rg -n "Algorithm::run|LlmResponse::Stream|aggregate|stream" crates/libsy -g '*.rs'

Repository: NVIDIA-NeMo/Switchyard

Length of output: 23636


Use libsy in the example command.
crates/libsy/Cargo.toml names the package libsy, so cargo run -p libsy --example streaming_agent is the correct invocation.

🤖 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/examples/streaming_agent.rs` around lines 11 - 13, Update the
example command in the streaming_agent module documentation to use the libsy
package name instead of libsy-examples, while keeping the streaming_agent
example target unchanged.
crates/libsy/src/algorithms/llm_class.rs (1)

23-23: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve a separator before the user prompt.

create_run_task concatenates this constant directly with user_prompt, so the classifier receives text such as ...[0, 1].prove it. Add a trailing newline/space here or insert an explicit separator at the call site, and add an assertion covering the exact prompt shape.

🤖 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/llm_class.rs` at line 23, Update
CLASSIFIER_PROMPT_PREAMBLE or the create_run_task concatenation so the
classifier prompt always includes a separator before user_prompt, preserving
readable text such as “...[0, 1]. prove it”. Add an assertion verifying the
exact assembled prompt shape.
crates/libsy/src/lib.rs (1)

64-65: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
rg -n 'ClassifierTier|ClassifierDecision|pub use algorithms::llm_class' crates/libsy/src

Repository: NVIDIA-NeMo/Switchyard

Length of output: 2091


🏁 Script executed:

#!/bin/bash
set -eu

echo "== lib.rs =="
sed -n '1,120p' crates/libsy/src/lib.rs

echo
echo "== llm_class.rs (type definitions) =="
sed -n '1,90p' crates/libsy/src/algorithms/llm_class.rs

echo
echo "== any re-exports of ClassifierTier in repo =="
rg -n 'ClassifierTier' crates/libsy/src

Repository: NVIDIA-NeMo/Switchyard

Length of output: 10912


🏁 Script executed:

python3 - <<'PY'
from pathlib import Path
src = r'''
mod m {
    pub enum E { A }
}

pub struct S {
    pub x: Option<m::E>,
}

pub fn make() -> S {
    S { x: Some(m::E::A) }
}
'''
Path('/tmp/private_type_public_field.rs').write_text(src)
import subprocess, sys
p = subprocess.run(['rustc', '--crate-type=lib', '/tmp/private_type_public_field.rs', '-o', '/tmp/private_type_public_field.rlib'], capture_output=True, text=True)
print('exit', p.returncode)
print(p.stderr)
PY

Repository: NVIDIA-NeMo/Switchyard

Length of output: 715


Re-export ClassifierTier with ClassifierDecision. Downstream crates can’t name ClassifierTier from the public ClassifierDecision::tier field because algorithms is private. Re-export the tier type, or make tier private and expose an accessor.

Proposed fix
-pub use algorithms::llm_class::{ClassifierDecision, LlmClassifierOrchAlgo};
+pub use algorithms::llm_class::{
+    ClassifierDecision, ClassifierTier, LlmClassifierOrchAlgo,
+};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

mod algorithms;
pub use algorithms::llm_class::{
    ClassifierDecision, ClassifierTier, LlmClassifierOrchAlgo,
};
🤖 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/lib.rs` around lines 64 - 65, Re-export ClassifierTier
alongside ClassifierDecision and LlmClassifierOrchAlgo in the public exports of
the crate root. Keep the algorithms module private while making the
ClassifierDecision::tier field’s type nameable by downstream crates.

Thanks Code Rabbit!

Signed-off-by: Graham King <grahamk@nvidia.com>
Thanks GPT

Signed-off-by: Graham King <grahamk@nvidia.com>
@grahamking
grahamking marked this pull request as ready for review July 17, 2026 19:25
@grahamking
grahamking requested a review from a team as a code owner July 17, 2026 19:25
@ayushag-nv

Copy link
Copy Markdown
Contributor

@grahamking Does it work end to end with libsy example proxy ?

@grahamking

grahamking commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Does it work end to end with libsy example proxy ?

I don't know. For the example proxy I'd need to merge this #79 and the PR it builds on, into here wouldn't I?

The two examples/ binaries previously in libsy-examples/examples do run.

Signed-off-by: Graham King <grahamk@nvidia.com>
@messiaen

Copy link
Copy Markdown
Contributor

Does it work end to end with libsy example proxy ?

I don't know. For the example proxy I'd need to merge this #79 and the PR it builds on, into here wouldn't I?

The two examples/ binaries previously in libsy-examples/examples do run.

It's hardcoded in the demo. Currently you have to change the code in #86 to use LlmClassifier instead of Random.
But is should work after that

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.

3 participants