scouter-evaluate 0.25.0

LLM Evaluation logic for Scouter
Documentation
use crate::evaluate::agent::AgentContextBuilder;
use crate::tasks::evaluator::AssertionEvaluator;
use crate::{error::EvaluationError, tasks::traits::EvaluationTask};
use pyo3::prelude::*;
use pyo3::pyfunction;
use pythonize::depythonize;
use scouter_types::genai::{AgentAssertionTask, AssertionResult, AssertionResults};
use serde_json::Value;
use std::collections::HashMap;
use tracing::error;

impl EvaluationTask for AgentAssertionTask {
    fn execute(&self, context: &Value) -> Result<AssertionResult, EvaluationError> {
        AssertionEvaluator::evaluate_assertion(context, self)
    }
}

#[pyfunction]
#[pyo3(signature = (tasks, context))]
pub fn execute_agent_assertion_tasks(
    tasks: Vec<AgentAssertionTask>,
    context: &Bound<'_, PyAny>,
) -> Result<AssertionResults, EvaluationError> {
    let context: serde_json::Value = depythonize(context).map_err(|e| {
        EvaluationError::GenAIEvaluatorError(format!("Failed to deserialize context: {}", e))
    })?;
    let results: HashMap<String, AssertionResult> = tasks
        .iter()
        .map(|task| {
            let context_builder =
                AgentContextBuilder::from_context(&context, task.provider.as_ref())?;
            let resolved = context_builder.build_context(&task.assertion)?;
            task.execute(&resolved)
                .map(|result| (task.id.clone(), result))
        })
        .collect::<Result<HashMap<String, AssertionResult>, EvaluationError>>()?;

    Ok(AssertionResults { results })
}

pub(crate) fn execute_agent_assertions(
    context: &AgentContextBuilder,
    tasks: &[AgentAssertionTask],
) -> Result<AssertionResults, EvaluationError> {
    if tasks.is_empty() {
        return Ok(AssertionResults {
            results: HashMap::new(),
        });
    }

    let results: HashMap<String, AssertionResult> = tasks
        .iter()
        .map(|task| {
            let resolved = context.build_context(&task.assertion)?;
            task.execute(&resolved)
                .map(|result| (task.id.clone(), result))
        })
        .collect::<Result<HashMap<String, AssertionResult>, EvaluationError>>()
        .inspect_err(|e| {
            error!("Error executing agent assertions: {:?}", e);
        })?;

    Ok(AssertionResults { results })
}