pub fn text_part(
content: impl Into<String>,
) -> ChatCompletionRequestUserMessageContentPartExpand description
Helper function to create a text content part.
Examples found in repository?
examples/vision_chat.rs (line 128)
114async fn demonstrate_multiple_images(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
115 println!(" Example 2: Multiple Image Analysis");
116 println!("---------------------------------------");
117
118 let question = "Compare these two images. What are the differences and similarities?";
119
120 println!("Question: {question}");
121 println!("Image 1: {}", SAMPLE_IMAGE_URLS[0]);
122 println!("Image 2: {}", SAMPLE_IMAGE_URLS[1]);
123 print!("Assistant: ");
124 io::stdout().flush()?;
125
126 // Create message parts manually for multiple images
127 let parts = vec![
128 text_part(question),
129 image_url_part_with_detail(SAMPLE_IMAGE_URLS[0], Detail::Auto),
130 image_url_part_with_detail(SAMPLE_IMAGE_URLS[1], Detail::Auto),
131 ];
132
133 let chat_builder = client
134 .chat()
135 .system("You are an expert at comparing and analyzing images. Provide thoughtful comparisons focusing on visual elements, composition, and content.")
136 .user_with_parts(parts)
137 .temperature(0.4);
138
139 let response = client.send_chat(chat_builder).await?;
140
141 if let Some(content) = response.content() {
142 println!("{content}");
143 } else {
144 println!("No response content received");
145 }
146
147 println!();
148 Ok(())
149}
150
151/// Demonstrate different detail levels for image analysis.
152async fn demonstrate_detail_levels(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
153 println!(" Example 3: Different Detail Levels");
154 println!("------------------------------------");
155
156 let image_url = SAMPLE_IMAGE_URLS[0];
157 let question = "Analyze this image";
158
159 // Test different detail levels
160 let detail_levels = vec![
161 (Detail::Low, "Low detail (faster, less detailed)"),
162 (Detail::High, "High detail (slower, more detailed)"),
163 (Detail::Auto, "Auto detail (balanced)"),
164 ];
165
166 for (detail, description) in detail_levels {
167 println!("\n{description}:");
168 print!("Assistant: ");
169 io::stdout().flush()?;
170
171 let chat_builder = client
172 .chat()
173 .system("Analyze the image and describe what you see. Adjust your response detail based on the image quality provided.")
174 .user_with_image_url_and_detail(question, image_url, detail)
175 .temperature(0.2)
176 .max_completion_tokens(100); // Limit response length for comparison
177
178 let response = client.send_chat(chat_builder).await?;
179
180 if let Some(content) = response.content() {
181 println!("{content}");
182 }
183 }
184
185 println!();
186 Ok(())
187}
188
189/// Demonstrate base64 image encoding and analysis.
190async fn demonstrate_base64_image(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
191 println!(" Example 4: Base64 Image Analysis");
192 println!("-----------------------------------");
193
194 let question = "What is this image? It's very small, what can you tell about it?";
195
196 println!("Question: {question}");
197 println!("Image: Small test image encoded as base64");
198 print!("Assistant: ");
199 io::stdout().flush()?;
200
201 // Create message parts with base64 image
202 let parts = vec![
203 text_part(question),
204 image_base64_part_with_detail(SAMPLE_BASE64_IMAGE, "image/png", Detail::High),
205 ];
206
207 let chat_builder = client
208 .chat()
209 .system("You are analyzing images provided in base64 format. Even if an image is very small or simple, try to provide what information you can.")
210 .user_with_parts(parts)
211 .temperature(0.3);
212
213 let response = client.send_chat(chat_builder).await?;
214
215 if let Some(content) = response.content() {
216 println!("{content}");
217 } else {
218 println!("No response content received");
219 }
220
221 println!();
222 Ok(())
223}
224
225/// Demonstrate conversation context with images.
226async fn demonstrate_conversation_with_images(
227 client: &Client,
228) -> Result<(), Box<dyn std::error::Error>> {
229 println!(" Example 5: Conversation Context with Images");
230 println!("----------------------------------------------");
231
232 let image_url = SAMPLE_IMAGE_URLS[0];
233
234 // First message: Analyze the image
235 println!("Step 1: Initial image analysis");
236 print!("Assistant: ");
237 io::stdout().flush()?;
238
239 let mut chat_builder = client
240 .chat()
241 .system("You are having a conversation about images. Remember details from previous messages to maintain context.")
242 .user_with_image_url("What's the main subject of this image?", image_url)
243 .temperature(0.3);
244
245 let response1 = client.send_chat(chat_builder).await?;
246 let first_response = response1.content().unwrap_or("No response").to_string();
247 println!("{first_response}");
248
249 // Second message: Follow-up question (without re-uploading the image)
250 println!("\nStep 2: Follow-up question");
251 print!("Assistant: ");
252 io::stdout().flush()?;
253
254 chat_builder = client
255 .chat()
256 .system("You are having a conversation about images. Remember details from previous messages to maintain context.")
257 .user_with_image_url("What's the main subject of this image?", image_url)
258 .assistant(&first_response)
259 .user("What colors are most prominent in the image we just discussed?")
260 .temperature(0.3);
261
262 let response2 = client.send_chat(chat_builder).await?;
263
264 if let Some(content) = response2.content() {
265 println!("{content}");
266 }
267
268 // Third message: Ask for creative interpretation
269 println!("\nStep 3: Creative interpretation");
270 print!("Assistant: ");
271 io::stdout().flush()?;
272
273 let second_response = response2.content().unwrap_or("No response").to_string();
274
275 chat_builder = client
276 .chat()
277 .system("You are having a conversation about images. Remember details from previous messages to maintain context.")
278 .user_with_image_url("What's the main subject of this image?", image_url)
279 .assistant(&first_response)
280 .user("What colors are most prominent in the image we just discussed?")
281 .assistant(second_response)
282 .user("Based on our discussion, write a short poem inspired by this image.")
283 .temperature(0.7);
284
285 let response3 = client.send_chat(chat_builder).await?;
286
287 if let Some(content) = response3.content() {
288 println!("{content}");
289 }
290
291 println!();
292 Ok(())
293}
294
295/// Demonstrate error handling patterns for vision requests.
296async fn demonstrate_error_handling(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
297 println!(" Example 6: Error Handling Patterns");
298 println!("------------------------------------");
299
300 println!("Testing various error scenarios...\n");
301
302 // Test 1: Invalid image URL
303 println!("Test 1: Invalid image URL");
304 let invalid_url = "https://this-domain-does-not-exist-12345.com/image.jpg";
305
306 let invalid_builder = client
307 .chat()
308 .user_with_image_url("What do you see?", invalid_url)
309 .temperature(0.3);
310
311 match client.send_chat(invalid_builder).await {
312 Ok(_) => println!(" Invalid URL request unexpectedly succeeded"),
313 Err(e) => match &e {
314 Error::Api {
315 status, message, ..
316 } => {
317 println!(" API properly rejected invalid URL ({status}): {message}");
318 }
319 Error::Http(reqwest_err) => {
320 println!(" HTTP error caught: {reqwest_err}");
321 }
322 Error::InvalidRequest(msg) => {
323 println!(" Validation caught invalid URL: {msg}");
324 }
325 _ => {
326 println!("ℹ Other error type: {e}");
327 }
328 },
329 }
330
331 // Test 2: Empty message with image
332 println!("\nTest 2: Empty text with image");
333 let empty_text_builder = client
334 .chat()
335 .user_with_image_url("", SAMPLE_IMAGE_URLS[0])
336 .temperature(0.3);
337
338 match client.send_chat(empty_text_builder).await {
339 Ok(response) => {
340 if let Some(content) = response.content() {
341 println!(
342 " API handled empty text gracefully: {}",
343 content.chars().take(50).collect::<String>()
344 );
345 }
346 }
347 Err(e) => {
348 println!("ℹ Empty text error: {e}");
349 }
350 }
351
352 // Test 3: Malformed base64 data
353 println!("\nTest 3: Malformed base64 image data");
354 let malformed_base64 = "this-is-not-valid-base64!@#$%";
355 let malformed_parts = vec![
356 text_part("What is this?"),
357 image_base64_part_with_detail(malformed_base64, "image/png", Detail::Auto),
358 ];
359
360 let malformed_builder = client.chat().user_with_parts(malformed_parts);
361
362 match client.send_chat(malformed_builder).await {
363 Ok(_) => println!(" Malformed base64 unexpectedly succeeded"),
364 Err(e) => match &e {
365 Error::Api {
366 status, message, ..
367 } => {
368 println!(" API properly rejected malformed base64 ({status}): {message}");
369 }
370 _ => {
371 println!("ℹ Other error for malformed base64: {e}");
372 }
373 },
374 }
375
376 println!("\n Error handling patterns demonstrated:");
377 println!(" • Invalid image URL handling");
378 println!(" • Empty text with image handling");
379 println!(" • Malformed base64 data validation");
380 println!(" • API error classification");
381 println!(" • Network error handling");
382
383 println!();
384 Ok(())
385}