feat(libsy): advisor review gate as a native algorithm and advisor route type - #371
feat(libsy): advisor review gate as a native algorithm and advisor route type#371eric-liu-nvidia wants to merge 4 commits into
Conversation
|
WalkthroughChangesAdvisor gate
Estimated code review effort: 4 (Complex) | ~60 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/switchyard-server/src/stats/algorithms.rs`:
- Line 31: Add concise Rust doc comments for the public advisor_gate field in
crates/switchyard-server/src/stats/algorithms.rs (lines 31-31), describing when
it appears in the serialized response. Also document every public field in
crates/switchyard-server/src/stats/algorithms/advisor_gate.rs (lines 42-53),
specifying each field’s count and grouping semantics.
In `@crates/switchyard-server/src/stats/algorithms/advisor_gate.rs`:
- Line 192: Update the stats binding in the test around StatsAccumulator::new to
be mutable, so the later StatsAccumulator::reset(&mut self) call compiles.
🪄 Autofix
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: 585f7428-96a2-4510-9e3b-71963e67e64e
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!Cargo.lock
📒 Files selected for processing (11)
Cargo.tomlcrates/libsy/Cargo.tomlcrates/libsy/src/algorithms.rscrates/libsy/src/algorithms/advisor_gate.rscrates/libsy/src/algorithms/util/llm_judge.rscrates/libsy/src/algorithms/util/prompts.rscrates/libsy/src/lib.rscrates/switchyard-server/src/config.rscrates/switchyard-server/src/stats/algorithms.rscrates/switchyard-server/src/stats/algorithms/advisor_gate.rscrates/switchyard-server/tests/server.rs
| #[derive(Clone, Debug, Default, PartialEq, Serialize)] | ||
| pub(crate) struct AlgorithmStatsSnapshot { | ||
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| pub advisor_gate: Option<AdvisorGateStatsSnapshot>, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document the new public statistics fields.
crates/switchyard-server/src/stats/algorithms.rs#L31-L31: document whenadvisor_gateis present in the serialized response.crates/switchyard-server/src/stats/algorithms/advisor_gate.rs#L42-L53: document the count and grouping semantics of each public field.
As per coding guidelines, add concise /// documentation for public Rust items.
📍 Affects 2 files
crates/switchyard-server/src/stats/algorithms.rs#L31-L31(this comment)crates/switchyard-server/src/stats/algorithms/advisor_gate.rs#L42-L53
🤖 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/switchyard-server/src/stats/algorithms.rs` at line 31, Add concise
Rust doc comments for the public advisor_gate field in
crates/switchyard-server/src/stats/algorithms.rs (lines 31-31), describing when
it appears in the serialized response. Also document every public field in
crates/switchyard-server/src/stats/algorithms/advisor_gate.rs (lines 42-53),
specifying each field’s count and grouping semantics.
Source: Coding guidelines
| .unwrap_or_else(|error| panic!("failed to build metrics exporter: {error}")); | ||
| let provider = SdkMeterProvider::builder().with_reader(exporter).build(); | ||
| let meter = provider.meter("switchyard"); | ||
| let stats = StatsAccumulator::new(registry, ["advisor_gate"]); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Make stats mutable.
Line 236 calls StatsAccumulator::reset(&mut self), but this binding is immutable. The test does not compile.
Proposed fix
- let stats = StatsAccumulator::new(registry, ["advisor_gate"]);
+ let mut stats = StatsAccumulator::new(registry, ["advisor_gate"]);📝 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.
| let stats = StatsAccumulator::new(registry, ["advisor_gate"]); | |
| let mut stats = StatsAccumulator::new(registry, ["advisor_gate"]); |
🤖 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/switchyard-server/src/stats/algorithms/advisor_gate.rs` at line 192,
Update the stats binding in the test around StatsAccumulator::new to be mutable,
so the later StatsAccumulator::reset(&mut self) call compiles.
315d4b0 to
136bc21
Compare
Signed-off-by: zengyuanl <zengyuanl@nvidia.com>
Signed-off-by: zengyuanl <zengyuanl@nvidia.com>
Signed-off-by: zengyuanl <zengyuanl@nvidia.com>
Signed-off-by: zengyuanl <zengyuanl@nvidia.com>
|
@eric-liu-nvidia can you address coderabbit first |
nachiketb-nvidia
left a comment
There was a problem hiding this comment.
Let's break this up into 2 or 3 MRs
- one for core logic
- one more for potential telemetry
- one more for server side config changes
also, if we have any prompts, let's make sure they're also knobs
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn advisor_route_approve_flow_and_stats() -> TestResult { |
There was a problem hiding this comment.
Can you wrap all of your tests in a #[cfg(test)] mod tests {? That will ensure they don't get compiled unless you are running tests. Grep for those strings in most other files for an example.
Adds the advisor review gate to the Rust server as a new route type:
type = "advisor".Benchmark results (Terminal-Bench 2.1)
With $64.76 ± $4.95 additional Opus 4.8 cost, the advisor review gate lifts Nemotron 3 Ultra accuracy by almost 25%.
How it works
There are two models: an executor (the model doing the work) and an advisor (a stronger model that checks the work).
REDO → the client never sees that reply. The proxy puts the advisor's feedback into the conversation ("not done yet — here is what is missing") and calls the executor again, so it keeps working.
max_reviews, default 1). After that, every call is a plain passthrough with zero overhead.If the advisor is down or replies with something unparseable, the gate fails open: the executor's reply goes to the client as if approved. Advisor problems never block the executor.
Why this shape: giving advice up front made the executor trust the plan and skip its own test-and-iterate loop. Checking only the final "I'm done" claim leaves the executor's normal behavior untouched and catches exactly one failure mode — stopping too early.
Example
Note for reviewers: this adds
regexas a production dependency of libsy (for the configurable review trigger pattern).🤖 Generated with Claude Code