1use crate::{AgentContext, AgentResult};
7use car_inference::{GenerateParams, GenerateRequest};
8
9#[derive(Debug, Clone)]
11pub struct VerifyConfig {
12 pub max_tokens: usize,
13 pub temperature: f64,
14 pub model: Option<String>,
15}
16
17impl Default for VerifyConfig {
18 fn default() -> Self {
19 Self {
20 max_tokens: 2048,
21 temperature: 0.1, model: None,
23 }
24 }
25}
26
27pub struct Verifier {
29 ctx: AgentContext,
30 config: VerifyConfig,
31}
32
33impl Verifier {
34 pub fn new(ctx: AgentContext) -> Self {
35 Self {
36 ctx,
37 config: VerifyConfig::default(),
38 }
39 }
40
41 pub fn with_config(ctx: AgentContext, config: VerifyConfig) -> Self {
42 Self { ctx, config }
43 }
44
45 pub async fn verify(&self, output: &str, criteria: &str) -> AgentResult {
47 let prompt = format!(
48 "You are a verification agent. Your job is to determine if the output meets the criteria.\n\n\
49 ## Acceptance Criteria\n{criteria}\n\n\
50 ## Output to Verify\n{output}\n\n\
51 Respond with:\n\
52 VERDICT: PASS or FAIL\n\
53 REASONS:\n\
54 - (specific reasons for your verdict)\n\
55 ISSUES:\n\
56 - (specific issues found, or 'None' if passing)"
57 );
58
59 let start = std::time::Instant::now();
60 let req = GenerateRequest {
61 prompt,
62 model: self.config.model.clone(),
63 params: GenerateParams {
64 temperature: self.config.temperature,
65 max_tokens: self.config.max_tokens,
66 ..Default::default()
67 },
68 context: None,
69 tools: None,
70 images: None,
71 messages: None,
72 cache_control: false,
73 response_format: None,
74 intent: None,
75 };
76
77 match self.ctx.inference.generate_tracked(req).await {
78 Ok(result) => {
79 let passed = result.text.contains("VERDICT: PASS");
80 AgentResult {
81 agent: "verifier".into(),
82 output: result.text,
83 confidence: if passed { 0.9 } else { 0.8 },
84 model_used: result.model_used,
85 latency_ms: start.elapsed().as_millis() as u64,
86 }
87 }
88 Err(e) => AgentResult {
89 agent: "verifier".into(),
90 output: format!("Verification failed: {}", e),
91 confidence: 0.0,
92 model_used: String::new(),
93 latency_ms: start.elapsed().as_millis() as u64,
94 },
95 }
96 }
97}