dspy_rs/evaluate/
evaluator.rs

1use crate::core::Module;
2use crate::data::{example::Example, prediction::Prediction};
3use futures::stream::{self, StreamExt};
4
5#[allow(async_fn_in_trait)]
6pub trait Evaluator: Module {
7    const MAX_CONCURRENCY: usize = 32;
8    const DISPLAY_PROGRESS: bool = true;
9
10    async fn metric(&self, example: &Example, prediction: &Prediction) -> f32;
11
12    async fn evaluate(&self, examples: Vec<Example>) -> f32 {
13        let predictions = self
14            .batch(
15                examples.clone(),
16                Self::MAX_CONCURRENCY,
17                Self::DISPLAY_PROGRESS,
18            )
19            .await
20            .unwrap();
21
22        let total = examples.len();
23
24        // Pair examples with predictions and evaluate with controlled concurrency
25        let metrics: Vec<f32> = stream::iter(examples.iter().zip(predictions.iter()).enumerate())
26            .map(|(_, (example, prediction))| {
27                let prediction = prediction.clone();
28                async move { self.metric(example, &prediction).await }
29            })
30            .buffer_unordered(Self::MAX_CONCURRENCY)
31            .collect()
32            .await;
33
34        metrics.iter().sum::<f32>() / total as f32
35    }
36}