1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use crate::client::Client;
5use crate::error::Result;
6
7#[derive(Debug, Clone, Serialize, Default)]
13pub struct VisionRequest {
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub image_base64: Option<String>,
17
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub image_url: Option<String>,
21
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub model: Option<String>,
25
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub profile: Option<String>,
29
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub context: Option<VisionContext>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, Default)]
37pub struct VisionContext {
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub installation_type: Option<String>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub phase: Option<String>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub expected_items: Option<Vec<String>>,
49}
50
51#[derive(Debug, Clone, Deserialize, Default)]
57pub struct VisionResponse {
58 #[serde(default)]
60 pub caption: Option<String>,
61
62 #[serde(default)]
64 pub tags: Vec<String>,
65
66 #[serde(default)]
68 pub objects: Vec<DetectedObject>,
69
70 #[serde(default)]
72 pub quality: Option<QualityAssessment>,
73
74 #[serde(default)]
76 pub relevance: Option<RelevanceCheck>,
77
78 #[serde(default)]
80 pub ocr: Option<OcrResult>,
81
82 #[serde(default)]
84 pub model: String,
85
86 #[serde(default)]
88 pub cost_ticks: i64,
89
90 #[serde(default)]
92 pub request_id: String,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize, Default)]
97pub struct DetectedObject {
98 pub label: String,
100
101 #[serde(default)]
103 pub confidence: f64,
104
105 #[serde(default)]
107 pub bounding_box: [i32; 4],
108}
109
110#[derive(Debug, Clone, Deserialize, Default)]
112pub struct QualityAssessment {
113 #[serde(default)]
115 pub overall: String,
116
117 #[serde(default)]
119 pub score: f64,
120
121 #[serde(default)]
123 pub blur: String,
124
125 #[serde(default)]
127 pub darkness: String,
128
129 #[serde(default)]
131 pub resolution: String,
132
133 #[serde(default)]
135 pub exposure: String,
136
137 #[serde(default)]
139 pub issues: Vec<String>,
140}
141
142#[derive(Debug, Clone, Deserialize, Default)]
144pub struct RelevanceCheck {
145 #[serde(default)]
147 pub relevant: bool,
148
149 #[serde(default)]
151 pub score: f64,
152
153 #[serde(default)]
155 pub expected_items: Vec<String>,
156
157 #[serde(default)]
159 pub found_items: Vec<String>,
160
161 #[serde(default)]
163 pub missing_items: Vec<String>,
164
165 #[serde(default)]
167 pub unexpected_items: Vec<String>,
168
169 #[serde(default)]
171 pub notes: Option<String>,
172}
173
174#[derive(Debug, Clone, Deserialize, Default)]
176pub struct OcrResult {
177 #[serde(default)]
179 pub text: Option<String>,
180
181 #[serde(default)]
183 pub metadata: HashMap<String, String>,
184
185 #[serde(default)]
187 pub overlays: Vec<TextOverlay>,
188}
189
190#[derive(Debug, Clone, Deserialize, Default)]
192pub struct TextOverlay {
193 #[serde(default)]
195 pub text: String,
196
197 #[serde(default)]
199 pub bounding_box: Option<[i32; 4]>,
200
201 #[serde(rename = "type", default)]
203 pub overlay_type: Option<String>,
204}
205
206impl Client {
211 pub async fn vision_analyze(&self, req: &VisionRequest) -> Result<VisionResponse> {
213 let (resp, _meta) = self
214 .post_json::<VisionRequest, VisionResponse>("/qai/v1/vision/analyze", req)
215 .await?;
216 Ok(resp)
217 }
218
219 pub async fn vision_detect(&self, req: &VisionRequest) -> Result<VisionResponse> {
221 let (resp, _meta) = self
222 .post_json::<VisionRequest, VisionResponse>("/qai/v1/vision/detect", req)
223 .await?;
224 Ok(resp)
225 }
226
227 pub async fn vision_describe(&self, req: &VisionRequest) -> Result<VisionResponse> {
229 let (resp, _meta) = self
230 .post_json::<VisionRequest, VisionResponse>("/qai/v1/vision/describe", req)
231 .await?;
232 Ok(resp)
233 }
234
235 pub async fn vision_ocr(&self, req: &VisionRequest) -> Result<VisionResponse> {
237 let (resp, _meta) = self
238 .post_json::<VisionRequest, VisionResponse>("/qai/v1/vision/ocr", req)
239 .await?;
240 Ok(resp)
241 }
242
243 pub async fn vision_quality(&self, req: &VisionRequest) -> Result<VisionResponse> {
245 let (resp, _meta) = self
246 .post_json::<VisionRequest, VisionResponse>("/qai/v1/vision/quality", req)
247 .await?;
248 Ok(resp)
249 }
250}