Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,10 @@ switchyard/
│ │ ├── openai_llm_backend.py # OpenAiPassthroughBackend
│ │ ├── openai_native_backend.py # OpenAiNativeBackend
│ │ ├── anthropic_native_llm_backend.py # AnthropicNativeBackend
│ │ ├── latency_service_llm_backend.py # LatencyServiceLLMBackend
│ │ ├── llm_target.py # LlmTarget, BackendFormat
│ │ ├── multi_llm_backend.py # MultiLlmBackend helpers
│ │ ├── stats_llm_backend.py # StatsLlmBackend
│ │ ├── backend_format_resolver.py # BackendFormatResolver
│ │ └── health_poller.py # HealthPoller, EndpointHealthStatus
│ │ └── backend_format_resolver.py # BackendFormatResolver
│ ├── processors/ # Request-side / response-side component implementations
│ │ ├── format_translate.py
│ │ ├── random_routing_request_processor.py
Expand All @@ -205,8 +203,7 @@ switchyard/
│ │ ├── sse_helpers.py
│ │ └── base.py
│ └── config/
│ ├── intake_sink_config.py
│ └── latency_service_backend_config.py
│ └── intake_sink_config.py
├── cli/ # CLI (requires `nemo-switchyard[cli]`)
│ ├── switchyard_cli.py # `switchyard` entry point
│ ├── launch_command.py # `switchyard launch claude/codex`
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ All notable changes to Switchyard are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Removed

- **Latency-aware router** — the `latency_service` route type and its
`LatencyServiceLLMBackend`, `LatencyServiceBackendConfig`,
`LatencyServiceEndpoint`, and `LatencyServiceProfileConfig` public API are
removed. It depended on NVIDIA Inference Hub's latency endpoint and schema.
Deployments that need multi-endpoint, load- or latency-aware routing should
migrate to [Dynamo](https://github.com/ai-dynamo/dynamo) (backend-load /
KV-cache-aware routing with request failover) or an external load balancer
such as [Traefik](https://doc.traefik.io/traefik/reference/routing-configuration/http/load-balancing/service/)
or HAProxy.

## [0.1.0] — Initial release

First public release of Switchyard — a typed, composable control plane for LLM
Expand Down
6 changes: 3 additions & 3 deletions crates/switchyard-components/tests/stats_accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ fn routing_decision_counts_are_grouped_by_profile_type() -> Result<()> {
accumulator.record_routing_decision("stage_router", "dimensions")?;
accumulator.record_routing_decision("stage_router", "dimensions")?;
accumulator.record_routing_decision("stage_router", "llm-classifier")?;
accumulator.record_routing_decision("latency-service", "health")?;
accumulator.record_routing_decision("escalation_router", "judge")?;

let snapshot = accumulator.snapshot()?;
assert_eq!(
Expand All @@ -771,8 +771,8 @@ fn routing_decision_counts_are_grouped_by_profile_type() -> Result<()> {
assert_eq!(
snapshot
.routing_decisions
.get("latency-service")
.and_then(|sources| sources.get("health")),
.get("escalation_router")
.and_then(|sources| sources.get("judge")),
Some(&1)
);

Expand Down
9 changes: 4 additions & 5 deletions crates/switchyard-py/src/core_bindings/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,11 +614,10 @@ impl PyProxyContext {
/// Records the measured backend-call latency in ms.
///
/// The Rust ``StatsLlmBackend`` wraps native backends and writes this
/// slot automatically. Python-only backends (e.g. ``LatencyServiceLLMBackend``)
/// that can't be wrapped record their measurement here so the
/// downstream ``StatsResponseProcessor`` can compute
/// ``routing_overhead_ms = total_latency - backend_latency`` and emit
/// it on ``/metrics``. Setting ``None`` clears the slot.
/// slot automatically. Python-only backends that can't be wrapped record
/// their measurement here so the downstream ``StatsResponseProcessor`` can
/// compute ``routing_overhead_ms = total_latency - backend_latency`` and
/// emit it on ``/metrics``. Setting ``None`` clears the slot.
#[setter]
fn set_backend_call_latency_ms(&self, value: Option<f64>) -> PyResult<()> {
let mut inner = self.lock()?;
Expand Down
6 changes: 3 additions & 3 deletions crates/switchyard-py/src/core_bindings/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,9 @@ impl PyResponseStream {
/// ``Switchyard.call`` round trip (``source`` is ``None``): the source was
/// moved onto the core stream by ``take_core_stream`` as a
/// ``SourceClosingStream``; dropping the inner adapter here drops that
/// wrapper, which closes the source on drop. This is the latency-router
/// production path, where response processors re-wrap the core stream and
/// ``source`` cannot be recovered on this object.
/// wrapper, which closes the source on drop. This is the production path
/// where response processors re-wrap the core stream and ``source``
/// cannot be recovered on this object.
fn aclose<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
self.consumed.store(true, Ordering::Release);
let stream = Arc::clone(&self.stream);
Expand Down
Loading
Loading