use super::traits::{LearningBackend, LearningSignal, Trajectory};
pub struct NoopLearner;
impl NoopLearner {
pub fn new() -> Self {
Self
}
}
impl Default for NoopLearner {
fn default() -> Self {
Self::new()
}
}
impl LearningBackend for NoopLearner {
fn record(&self, _trajectory: &Trajectory) {
}
fn adapt(&self, _signal: &LearningSignal) {
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pipeline::traits::{ChatRequest, LlmMessage, QualityScore, RoutingDecision};
use clawft_types::provider::{ContentBlock, LlmResponse, StopReason, Usage};
use std::collections::HashMap;
fn make_trajectory() -> Trajectory {
Trajectory {
request: ChatRequest {
messages: vec![LlmMessage {
role: "user".into(),
content: "hello".into(),
tool_call_id: None,
tool_calls: None,
}],
tools: vec![],
model: None,
max_tokens: None,
temperature: None,
auth_context: None,
complexity_boost: 0.0,
},
routing: RoutingDecision {
provider: "openai".into(),
model: "gpt-4o".into(),
reason: "test".into(),
..Default::default()
},
response: LlmResponse {
id: "resp-1".into(),
content: vec![ContentBlock::Text { text: "Hi!".into() }],
stop_reason: StopReason::EndTurn,
usage: Usage {
input_tokens: 5,
output_tokens: 2,
total_tokens: 0,
},
metadata: HashMap::new(),
},
quality: QualityScore {
overall: 0.9,
relevance: 0.95,
coherence: 0.85,
},
}
}
#[test]
fn record_does_not_panic() {
let learner = NoopLearner::new();
learner.record(&make_trajectory());
}
#[test]
fn adapt_does_not_panic() {
let learner = NoopLearner::new();
learner.adapt(&LearningSignal {
feedback_type: "thumbs_up".into(),
value: 1.0,
});
}
#[test]
fn adapt_negative_signal_does_not_panic() {
let learner = NoopLearner::new();
learner.adapt(&LearningSignal {
feedback_type: "thumbs_down".into(),
value: -1.0,
});
}
#[test]
fn multiple_records_do_not_panic() {
let learner = NoopLearner::new();
for _ in 0..100 {
learner.record(&make_trajectory());
}
}
#[test]
fn multiple_adapts_do_not_panic() {
let learner = NoopLearner::new();
for i in 0..50 {
learner.adapt(&LearningSignal {
feedback_type: format!("signal_{i}"),
value: i as f32 / 50.0,
});
}
}
#[test]
fn default_trait_impl() {
let learner = NoopLearner;
learner.record(&make_trajectory());
learner.adapt(&LearningSignal {
feedback_type: "test".into(),
value: 0.0,
});
}
}