use serde::{Deserialize, Serialize};
use crate::error::WyrdError;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct GenAiEvalResult {
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub score_label: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub score_value: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub explanation: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub response_id: Option<String>,
}
impl GenAiEvalResult {
pub fn validate(&self) -> Result<(), WyrdError> {
if self.name.is_empty() {
return Err(WyrdError::Validation {
message: "gen_ai_eval_result.name must be non-empty".to_string(),
details: serde_json::Value::Null,
});
}
if self.name.len() > 256 {
return Err(WyrdError::Validation {
message: format!(
"gen_ai_eval_result.name length must be <= 256, got {}",
self.name.len()
),
details: serde_json::Value::Null,
});
}
if let Some(value) = self.score_value
&& !value.is_finite()
{
return Err(WyrdError::Validation {
message: format!("gen_ai_eval_result.score_value must be finite, got {value}"),
details: serde_json::Value::Null,
});
}
if let Some(label) = &self.score_label
&& label.len() > 64
{
return Err(WyrdError::Validation {
message: format!(
"gen_ai_eval_result.score_label length must be <= 64, got {}",
label.len()
),
details: serde_json::Value::Null,
});
}
if let Some(explanation) = &self.explanation
&& explanation.len() > 4096
{
return Err(WyrdError::Validation {
message: format!(
"gen_ai_eval_result.explanation length must be <= 4096, got {}",
explanation.len()
),
details: serde_json::Value::Null,
});
}
if let Some(response_id) = &self.response_id
&& response_id.len() > 128
{
return Err(WyrdError::Validation {
message: format!(
"gen_ai_eval_result.response_id length must be <= 128, got {}",
response_id.len()
),
details: serde_json::Value::Null,
});
}
Ok(())
}
}