06_other_providers_batch/
06-other-providers-batch.rs

1/*
2Script to run a simple pipeline.
3
4Run with:
5```
6cargo run --example 01-simple
7```
8*/
9
10use anyhow::Result;
11use bon::Builder;
12use dspy_rs::{
13    ChatAdapter, Example, LM, Module, Predict, Prediction, Predictor, Signature, configure,
14    example, hashmap, prediction,
15};
16
17#[Signature(cot)]
18struct QASignature {
19    #[input]
20    pub question: String,
21
22    #[output]
23    pub answer: String,
24}
25
26#[Signature]
27struct RateSignature {
28    /// Rate the answer on a scale of 1(very bad) to 10(very good)
29
30    #[input]
31    pub question: String,
32
33    #[input]
34    pub answer: String,
35
36    #[output]
37    pub rating: i8,
38}
39
40#[derive(Builder)]
41pub struct QARater {
42    #[builder(default = Predict::new(QASignature::new()))]
43    pub answerer: Predict,
44    #[builder(default = Predict::new(RateSignature::new()))]
45    pub rater: Predict,
46}
47
48impl Module for QARater {
49    async fn forward(&self, inputs: Example) -> Result<Prediction> {
50        let answerer_prediction = self.answerer.forward(inputs.clone()).await?;
51
52        let question = inputs.data.get("question").unwrap().clone();
53        let answer = answerer_prediction.data.get("answer").unwrap().clone();
54        let answer_lm_usage = answerer_prediction.lm_usage;
55
56        let inputs = Example::new(
57            hashmap! {
58                "answer".to_string() => answer.clone(),
59                "question".to_string() => question.clone()
60            },
61            vec!["answer".to_string(), "question".to_string()],
62            vec![],
63        );
64        let rating_prediction = self.rater.forward(inputs).await?;
65        let rating_lm_usage = rating_prediction.lm_usage;
66
67        Ok(prediction! {
68            "answer"=> answer,
69            "question"=> question,
70            "rating"=> rating_prediction.data.get("rating").unwrap().clone(),
71        }
72        .set_lm_usage(answer_lm_usage + rating_lm_usage))
73    }
74}
75
76#[tokio::main]
77async fn main() {
78    // Anthropic
79    configure(
80        LM::builder()
81            .model("anthropic:claude-sonnet-4-5-20250929".to_string())
82            .build()
83            .await
84            .unwrap(),
85        ChatAdapter,
86    );
87
88    let example = vec![
89        example! {
90            "question": "input" => "What is the capital of France?",
91        },
92        example! {
93            "question": "input" => "What is the capital of Germany?",
94        },
95        example! {
96            "question": "input" => "What is the capital of Italy?",
97        },
98    ];
99
100    let qa_rater = QARater::builder().build();
101    let prediction = qa_rater.batch(example.clone(), 2, true).await.unwrap();
102    println!("Anthropic: {prediction:?}");
103
104    // Gemini
105    configure(
106        LM::builder()
107            .model("gemini:gemini-2.0-flash".to_string())
108            .build()
109            .await
110            .unwrap(),
111        ChatAdapter,
112    );
113
114    let prediction = qa_rater.batch(example, 2, true).await.unwrap();
115    println!("Gemini: {prediction:?}");
116}