use std::collections::HashMap;
use std::sync::Arc;
use bitrouter_sdk::BitrouterError;
use bitrouter_sdk::caller::CallerContext;
use bitrouter_sdk::config::{AdequacyConfig, PolicyTableConfig};
use bitrouter_sdk::language_model::types::{
Content, GenerationParams, Message, PipelineRequest, Prompt, ProviderMetadata, Role,
};
use bitrouter_sdk::language_model::{ObserveHook, PipelineContext, RequestOutcome};
use crate::adequacy::AdequacyLedger;
use crate::adequacy::observer::AdequacyObserveHook;
use crate::policy_table_router::{PolicyTable, PolicyTableRouter};
const CHEAP: &str = "vendor/cheap";
const CAPABLE: &str = "vendor/capable";
fn workload_table() -> Arc<PolicyTable> {
let cfg = PolicyTableConfig {
key_strategy: Default::default(),
tiers: HashMap::from([
("cheap".to_string(), CHEAP.to_string()),
("capable".to_string(), CAPABLE.to_string()),
]),
fingerprints: HashMap::from([("after_routine".to_string(), "cheap".to_string())]),
default_tier: Some("capable".to_string()),
tool_use_tier: None,
tool_safe_tiers: Vec::new(),
adequacy: AdequacyConfig {
enabled: true,
explore_enabled: true,
explore_tier: Some("cheap".to_string()),
..Default::default()
},
};
PolicyTable::from_config(&cfg).expect("configured")
}
fn cheap_is_adequate(fingerprint: &str) -> bool {
match fingerprint {
"after_safe" => true,
"after_risky" | "after_routine" => false,
_ => true,
}
}
fn prompt_after(tool: &str) -> Prompt {
Prompt {
model: "inbound".to_string(),
system: None,
system_provider_metadata: ProviderMetadata::new(),
messages: vec![
Message::text(Role::User, "go"),
Message {
role: Role::Assistant,
content: vec![Content::ToolCall {
id: format!("call_{tool}"),
name: tool.to_string(),
arguments: "{}".to_string(),
provider_executed: false,
dynamic: false,
provider_metadata: ProviderMetadata::new(),
}],
},
],
tools: Vec::new(),
params: GenerationParams::default(),
response_format: None,
tool_choice: None,
stream: false,
}
}
fn context(served_model: &str, prompt: Prompt) -> PipelineContext {
PipelineContext::new(PipelineRequest::new(
served_model.to_string(),
CallerContext::new("k", "u"),
prompt,
))
}
#[tokio::test]
async fn the_loop_converges_to_a_safe_cheaper_policy() {
let table = workload_table();
let ledger = Arc::new(AdequacyLedger::in_memory_explore(1, 0, 1, 2));
let router = PolicyTableRouter::new(table.clone(), Some(ledger.clone()));
let observer = AdequacyObserveHook::new(table.clone(), ledger.clone());
let price = |model: &str| if model == CHEAP { 1u64 } else { 10u64 };
let mut spend = 0u64;
let mut flagship_only_spend = 0u64;
for _round in 0..30 {
for tool in ["safe", "risky", "routine"] {
let fingerprint = format!("after_{tool}");
let mut prompt = prompt_after(tool);
router.apply(&mut prompt);
let served = prompt.model.clone();
spend += price(&served);
flagship_only_spend += price(CAPABLE);
let served_cheap = served == CHEAP;
let inadequate = served_cheap && !cheap_is_adequate(&fingerprint);
let outcome = if inadequate {
RequestOutcome::Failed(BitrouterError::internal("cheap inadequate"))
} else {
RequestOutcome::Completed
};
observer
.on_request_end(&context(&served, prompt_after(tool)), &outcome)
.await;
}
}
assert!(
ledger.is_locked("after_safe"),
"exploration must discover and lock the safe downgrade"
);
assert!(
!ledger.is_locked("after_risky"),
"the unsafe downgrade must not be locked"
);
assert!(
ledger.is_pinned("after_risky"),
"the unsafe exploration candidate must be escalated"
);
assert!(
ledger.is_pinned("after_routine"),
"the unsafe operator downgrade must self-correct"
);
let route = |tool: &str| {
let mut p = prompt_after(tool);
router.apply(&mut p);
p.model
};
assert_eq!(route("safe"), CHEAP, "safe step settled on the cheap tier");
assert_eq!(route("risky"), CAPABLE, "risky step escalated to capable");
assert_eq!(
route("routine"),
CAPABLE,
"routine (operator) downgrade escalated to capable"
);
assert!(
spend < flagship_only_spend,
"the converged policy must cost less than capable-only: {spend} vs {flagship_only_spend}"
);
}