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