use serde::{Deserialize, Serialize};
use agent_sdk_core::{AgentError, ProviderUsage};
use crate::{
ComparisonDesign, EvaluationId, EvaluationMetricDelta, EvaluationScope, EvaluationSubject,
ExpectedOutcome,
};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct EvaluationBudget {
pub max_provider_calls: u32,
pub max_prompt_chars: usize,
pub max_support_refs: usize,
}
impl Default for EvaluationBudget {
fn default() -> Self {
Self {
max_provider_calls: 1,
max_prompt_chars: 4_096,
max_support_refs: 8,
}
}
}
impl EvaluationBudget {
pub fn require_provider_call(&self) -> Result<(), AgentError> {
if self.max_provider_calls == 0 {
return Err(AgentError::contract_violation(
"evaluation budget allows zero provider calls",
));
}
Ok(())
}
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct EvaluationUsage {
pub provider_calls: u32,
pub provider_usage: Option<ProviderUsage>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct EvaluationRequest {
pub evaluation_id: EvaluationId,
pub scope: EvaluationScope,
pub subjects: Vec<EvaluationSubject>,
pub expected_outcome: ExpectedOutcome,
pub comparison: ComparisonDesign,
pub metric_deltas: Vec<EvaluationMetricDelta>,
pub budget: EvaluationBudget,
pub redacted_summary: String,
}
impl EvaluationRequest {
pub fn new(
evaluation_id: EvaluationId,
scope: EvaluationScope,
expected_outcome: ExpectedOutcome,
) -> Self {
Self {
evaluation_id,
scope,
subjects: Vec::new(),
redacted_summary: expected_outcome.redacted_summary.clone(),
expected_outcome,
comparison: ComparisonDesign::ObservedOnly,
metric_deltas: Vec::new(),
budget: EvaluationBudget::default(),
}
}
pub fn with_subject(mut self, subject: EvaluationSubject) -> Self {
self.subjects.push(subject);
self
}
pub fn with_comparison(mut self, comparison: ComparisonDesign) -> Self {
self.comparison = comparison;
self
}
pub fn with_metric_delta(mut self, metric_delta: EvaluationMetricDelta) -> Self {
self.metric_deltas.push(metric_delta);
self
}
pub fn with_metric_deltas(
mut self,
metric_deltas: impl IntoIterator<Item = EvaluationMetricDelta>,
) -> Self {
self.metric_deltas.extend(metric_deltas);
self
}
pub fn with_budget(mut self, budget: EvaluationBudget) -> Self {
self.budget = budget;
self
}
}