clia_async_openai/types/
impls.rs

1use std::{
2    fmt::Display,
3    path::{Path, PathBuf},
4};
5
6use crate::{
7    download::{download_url, save_b64},
8    error::OpenAIError,
9    traits::AsyncTryFrom,
10    types::InputSource,
11    util::{create_all_dir, create_file_part},
12};
13
14use bytes::Bytes;
15
16use super::{
17    AddUploadPartRequest, AudioInput, AudioResponseFormat, ChatCompletionFunctionCall,
18    ChatCompletionFunctions, ChatCompletionNamedToolChoice, ChatCompletionRequestAssistantMessage,
19    ChatCompletionRequestAssistantMessageContent, ChatCompletionRequestDeveloperMessage,
20    ChatCompletionRequestDeveloperMessageContent, ChatCompletionRequestFunctionMessage,
21    ChatCompletionRequestMessage, ChatCompletionRequestMessageContentPartAudio,
22    ChatCompletionRequestMessageContentPartImage, ChatCompletionRequestMessageContentPartText,
23    ChatCompletionRequestSystemMessage, ChatCompletionRequestSystemMessageContent,
24    ChatCompletionRequestToolMessage, ChatCompletionRequestToolMessageContent,
25    ChatCompletionRequestUserMessage, ChatCompletionRequestUserMessageContent,
26    ChatCompletionRequestUserMessageContentPart, ChatCompletionToolChoiceOption, CreateFileRequest,
27    CreateImageEditRequest, CreateImageVariationRequest, CreateMessageRequestContent,
28    CreateSpeechResponse, CreateTranscriptionRequest, CreateTranslationRequest, DallE2ImageSize,
29    EmbeddingInput, FileInput, FilePurpose, FunctionName, Image, ImageInput, ImageModel,
30    ImageResponseFormat, ImageSize, ImageUrl, ImagesResponse, ModerationInput, Prompt, Role, Stop,
31    TimestampGranularity,
32};
33
34/// for `impl_from!(T, Enum)`, implements
35/// - `From<T>`
36/// - `From<Vec<T>>`
37/// - `From<&Vec<T>>`
38/// - `From<[T; N]>`
39/// - `From<&[T; N]>`
40///
41/// for `T: Into<String>` and `Enum` having variants `String(String)` and `StringArray(Vec<String>)`
42macro_rules! impl_from {
43    ($from_typ:ty, $to_typ:ty) => {
44        // From<T> -> String variant
45        impl From<$from_typ> for $to_typ {
46            fn from(value: $from_typ) -> Self {
47                <$to_typ>::String(value.into())
48            }
49        }
50
51        // From<Vec<T>> -> StringArray variant
52        impl From<Vec<$from_typ>> for $to_typ {
53            fn from(value: Vec<$from_typ>) -> Self {
54                <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
55            }
56        }
57
58        // From<&Vec<T>> -> StringArray variant
59        impl From<&Vec<$from_typ>> for $to_typ {
60            fn from(value: &Vec<$from_typ>) -> Self {
61                <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
62            }
63        }
64
65        // From<[T; N]> -> StringArray variant
66        impl<const N: usize> From<[$from_typ; N]> for $to_typ {
67            fn from(value: [$from_typ; N]) -> Self {
68                <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
69            }
70        }
71
72        // From<&[T; N]> -> StringArray variatn
73        impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
74            fn from(value: &[$from_typ; N]) -> Self {
75                <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
76            }
77        }
78    };
79}
80
81// From String "family" to Prompt
82impl_from!(&str, Prompt);
83impl_from!(String, Prompt);
84impl_from!(&String, Prompt);
85
86// From String "family" to Stop
87impl_from!(&str, Stop);
88impl_from!(String, Stop);
89impl_from!(&String, Stop);
90
91// From String "family" to ModerationInput
92impl_from!(&str, ModerationInput);
93impl_from!(String, ModerationInput);
94impl_from!(&String, ModerationInput);
95
96// From String "family" to EmbeddingInput
97impl_from!(&str, EmbeddingInput);
98impl_from!(String, EmbeddingInput);
99impl_from!(&String, EmbeddingInput);
100
101/// for `impl_default!(Enum)`, implements `Default` for `Enum` as `Enum::String("")` where `Enum` has `String` variant
102macro_rules! impl_default {
103    ($for_typ:ty) => {
104        impl Default for $for_typ {
105            fn default() -> Self {
106                Self::String("".into())
107            }
108        }
109    };
110}
111
112impl_default!(Prompt);
113impl_default!(ModerationInput);
114impl_default!(EmbeddingInput);
115
116impl Default for InputSource {
117    fn default() -> Self {
118        InputSource::Path {
119            path: PathBuf::new(),
120        }
121    }
122}
123
124/// for `impl_input!(Struct)` where
125/// ```text
126/// Struct {
127///     source: InputSource
128/// }
129/// ```
130/// implements methods `from_bytes` and `from_vec_u8`,
131/// and `From<P>` for `P: AsRef<Path>`
132macro_rules! impl_input {
133    ($for_typ:ty) => {
134        impl $for_typ {
135            pub fn from_bytes(filename: String, bytes: Bytes) -> Self {
136                Self {
137                    source: InputSource::Bytes { filename, bytes },
138                }
139            }
140
141            pub fn from_vec_u8(filename: String, vec: Vec<u8>) -> Self {
142                Self {
143                    source: InputSource::VecU8 { filename, vec },
144                }
145            }
146        }
147
148        impl<P: AsRef<Path>> From<P> for $for_typ {
149            fn from(path: P) -> Self {
150                let path_buf = path.as_ref().to_path_buf();
151                Self {
152                    source: InputSource::Path { path: path_buf },
153                }
154            }
155        }
156    };
157}
158
159impl_input!(AudioInput);
160impl_input!(FileInput);
161impl_input!(ImageInput);
162
163impl Display for ImageSize {
164    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165        write!(
166            f,
167            "{}",
168            match self {
169                Self::S256x256 => "256x256",
170                Self::S512x512 => "512x512",
171                Self::S1024x1024 => "1024x1024",
172                Self::S1792x1024 => "1792x1024",
173                Self::S1024x1792 => "1024x1792",
174            }
175        )
176    }
177}
178
179impl Display for DallE2ImageSize {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        write!(
182            f,
183            "{}",
184            match self {
185                Self::S256x256 => "256x256",
186                Self::S512x512 => "512x512",
187                Self::S1024x1024 => "1024x1024",
188            }
189        )
190    }
191}
192
193impl Display for ImageModel {
194    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195        write!(
196            f,
197            "{}",
198            match self {
199                Self::DallE2 => "dall-e-2",
200                Self::DallE3 => "dall-e-3",
201                Self::Other(other) => other,
202            }
203        )
204    }
205}
206
207impl Display for ImageResponseFormat {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        write!(
210            f,
211            "{}",
212            match self {
213                Self::Url => "url",
214                Self::B64Json => "b64_json",
215            }
216        )
217    }
218}
219
220impl Display for AudioResponseFormat {
221    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222        write!(
223            f,
224            "{}",
225            match self {
226                AudioResponseFormat::Json => "json",
227                AudioResponseFormat::Srt => "srt",
228                AudioResponseFormat::Text => "text",
229                AudioResponseFormat::VerboseJson => "verbose_json",
230                AudioResponseFormat::Vtt => "vtt",
231            }
232        )
233    }
234}
235
236impl Display for TimestampGranularity {
237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238        write!(
239            f,
240            "{}",
241            match self {
242                TimestampGranularity::Word => "word",
243                TimestampGranularity::Segment => "segment",
244            }
245        )
246    }
247}
248
249impl Display for Role {
250    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251        write!(
252            f,
253            "{}",
254            match self {
255                Role::User => "user",
256                Role::System => "system",
257                Role::Assistant => "assistant",
258                Role::Function => "function",
259                Role::Tool => "tool",
260            }
261        )
262    }
263}
264
265impl Display for FilePurpose {
266    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267        write!(
268            f,
269            "{}",
270            match self {
271                Self::Assistants => "assistants",
272                Self::Batch => "batch",
273                Self::FineTune => "fine-tune",
274                Self::Vision => "vision",
275            }
276        )
277    }
278}
279
280impl ImagesResponse {
281    /// Save each image in a dedicated Tokio task and return paths to saved files.
282    /// For [ResponseFormat::Url] each file is downloaded in dedicated Tokio task.
283    pub async fn save<P: AsRef<Path>>(&self, dir: P) -> Result<Vec<PathBuf>, OpenAIError> {
284        create_all_dir(dir.as_ref())?;
285
286        let mut handles = vec![];
287        for id in self.data.clone() {
288            let dir_buf = PathBuf::from(dir.as_ref());
289            handles.push(tokio::spawn(async move { id.save(dir_buf).await }));
290        }
291
292        let results = futures::future::join_all(handles).await;
293        let mut errors = vec![];
294        let mut paths = vec![];
295
296        for result in results {
297            match result {
298                Ok(inner) => match inner {
299                    Ok(path) => paths.push(path),
300                    Err(e) => errors.push(e),
301                },
302                Err(e) => errors.push(OpenAIError::FileSaveError(e.to_string())),
303            }
304        }
305
306        if errors.is_empty() {
307            Ok(paths)
308        } else {
309            Err(OpenAIError::FileSaveError(
310                errors
311                    .into_iter()
312                    .map(|e| e.to_string())
313                    .collect::<Vec<String>>()
314                    .join("; "),
315            ))
316        }
317    }
318}
319
320impl CreateSpeechResponse {
321    pub async fn save<P: AsRef<Path>>(&self, file_path: P) -> Result<(), OpenAIError> {
322        let dir = file_path.as_ref().parent();
323
324        if let Some(dir) = dir {
325            create_all_dir(dir)?;
326        }
327
328        tokio::fs::write(file_path, &self.bytes)
329            .await
330            .map_err(|e| OpenAIError::FileSaveError(e.to_string()))?;
331
332        Ok(())
333    }
334}
335
336impl Image {
337    async fn save<P: AsRef<Path>>(&self, dir: P) -> Result<PathBuf, OpenAIError> {
338        match self {
339            Image::Url { url, .. } => download_url(url, dir).await,
340            Image::B64Json { b64_json, .. } => save_b64(b64_json, dir).await,
341        }
342    }
343}
344
345macro_rules! impl_from_for_integer_array {
346    ($from_typ:ty, $to_typ:ty) => {
347        impl<const N: usize> From<[$from_typ; N]> for $to_typ {
348            fn from(value: [$from_typ; N]) -> Self {
349                Self::IntegerArray(value.to_vec())
350            }
351        }
352
353        impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
354            fn from(value: &[$from_typ; N]) -> Self {
355                Self::IntegerArray(value.to_vec())
356            }
357        }
358
359        impl From<Vec<$from_typ>> for $to_typ {
360            fn from(value: Vec<$from_typ>) -> Self {
361                Self::IntegerArray(value)
362            }
363        }
364
365        impl From<&Vec<$from_typ>> for $to_typ {
366            fn from(value: &Vec<$from_typ>) -> Self {
367                Self::IntegerArray(value.clone())
368            }
369        }
370    };
371}
372
373impl_from_for_integer_array!(u32, EmbeddingInput);
374impl_from_for_integer_array!(u16, Prompt);
375
376macro_rules! impl_from_for_array_of_integer_array {
377    ($from_typ:ty, $to_typ:ty) => {
378        impl From<Vec<Vec<$from_typ>>> for $to_typ {
379            fn from(value: Vec<Vec<$from_typ>>) -> Self {
380                Self::ArrayOfIntegerArray(value)
381            }
382        }
383
384        impl From<&Vec<Vec<$from_typ>>> for $to_typ {
385            fn from(value: &Vec<Vec<$from_typ>>) -> Self {
386                Self::ArrayOfIntegerArray(value.clone())
387            }
388        }
389
390        impl<const M: usize, const N: usize> From<[[$from_typ; N]; M]> for $to_typ {
391            fn from(value: [[$from_typ; N]; M]) -> Self {
392                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
393            }
394        }
395
396        impl<const M: usize, const N: usize> From<[&[$from_typ; N]; M]> for $to_typ {
397            fn from(value: [&[$from_typ; N]; M]) -> Self {
398                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
399            }
400        }
401
402        impl<const M: usize, const N: usize> From<&[[$from_typ; N]; M]> for $to_typ {
403            fn from(value: &[[$from_typ; N]; M]) -> Self {
404                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
405            }
406        }
407
408        impl<const M: usize, const N: usize> From<&[&[$from_typ; N]; M]> for $to_typ {
409            fn from(value: &[&[$from_typ; N]; M]) -> Self {
410                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
411            }
412        }
413
414        impl<const N: usize> From<[Vec<$from_typ>; N]> for $to_typ {
415            fn from(value: [Vec<$from_typ>; N]) -> Self {
416                Self::ArrayOfIntegerArray(value.to_vec())
417            }
418        }
419
420        impl<const N: usize> From<&[Vec<$from_typ>; N]> for $to_typ {
421            fn from(value: &[Vec<$from_typ>; N]) -> Self {
422                Self::ArrayOfIntegerArray(value.to_vec())
423            }
424        }
425
426        impl<const N: usize> From<[&Vec<$from_typ>; N]> for $to_typ {
427            fn from(value: [&Vec<$from_typ>; N]) -> Self {
428                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.clone()).collect())
429            }
430        }
431
432        impl<const N: usize> From<&[&Vec<$from_typ>; N]> for $to_typ {
433            fn from(value: &[&Vec<$from_typ>; N]) -> Self {
434                Self::ArrayOfIntegerArray(
435                    value
436                        .to_vec()
437                        .into_iter()
438                        .map(|inner| inner.clone())
439                        .collect(),
440                )
441            }
442        }
443
444        impl<const N: usize> From<Vec<[$from_typ; N]>> for $to_typ {
445            fn from(value: Vec<[$from_typ; N]>) -> Self {
446                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
447            }
448        }
449
450        impl<const N: usize> From<&Vec<[$from_typ; N]>> for $to_typ {
451            fn from(value: &Vec<[$from_typ; N]>) -> Self {
452                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
453            }
454        }
455
456        impl<const N: usize> From<Vec<&[$from_typ; N]>> for $to_typ {
457            fn from(value: Vec<&[$from_typ; N]>) -> Self {
458                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
459            }
460        }
461
462        impl<const N: usize> From<&Vec<&[$from_typ; N]>> for $to_typ {
463            fn from(value: &Vec<&[$from_typ; N]>) -> Self {
464                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
465            }
466        }
467    };
468}
469
470impl_from_for_array_of_integer_array!(u32, EmbeddingInput);
471impl_from_for_array_of_integer_array!(u16, Prompt);
472
473impl From<&str> for ChatCompletionFunctionCall {
474    fn from(value: &str) -> Self {
475        match value {
476            "auto" => Self::Auto,
477            "none" => Self::None,
478            _ => Self::Function { name: value.into() },
479        }
480    }
481}
482
483impl From<&str> for FunctionName {
484    fn from(value: &str) -> Self {
485        Self { name: value.into() }
486    }
487}
488
489impl From<String> for FunctionName {
490    fn from(value: String) -> Self {
491        Self { name: value }
492    }
493}
494
495impl From<&str> for ChatCompletionNamedToolChoice {
496    fn from(value: &str) -> Self {
497        Self {
498            r#type: super::ChatCompletionToolType::Function,
499            function: value.into(),
500        }
501    }
502}
503
504impl From<String> for ChatCompletionNamedToolChoice {
505    fn from(value: String) -> Self {
506        Self {
507            r#type: super::ChatCompletionToolType::Function,
508            function: value.into(),
509        }
510    }
511}
512
513impl From<&str> for ChatCompletionToolChoiceOption {
514    fn from(value: &str) -> Self {
515        match value {
516            "auto" => Self::Auto,
517            "none" => Self::None,
518            _ => Self::Named(value.into()),
519        }
520    }
521}
522
523impl From<String> for ChatCompletionToolChoiceOption {
524    fn from(value: String) -> Self {
525        match value.as_str() {
526            "auto" => Self::Auto,
527            "none" => Self::None,
528            _ => Self::Named(value.into()),
529        }
530    }
531}
532
533impl From<(String, serde_json::Value)> for ChatCompletionFunctions {
534    fn from(value: (String, serde_json::Value)) -> Self {
535        Self {
536            name: value.0,
537            description: None,
538            parameters: value.1,
539        }
540    }
541}
542
543// todo: write macro for bunch of same looking From trait implementations below
544
545impl From<ChatCompletionRequestUserMessage> for ChatCompletionRequestMessage {
546    fn from(value: ChatCompletionRequestUserMessage) -> Self {
547        Self::User(value)
548    }
549}
550
551impl From<ChatCompletionRequestSystemMessage> for ChatCompletionRequestMessage {
552    fn from(value: ChatCompletionRequestSystemMessage) -> Self {
553        Self::System(value)
554    }
555}
556
557impl From<ChatCompletionRequestDeveloperMessage> for ChatCompletionRequestMessage {
558    fn from(value: ChatCompletionRequestDeveloperMessage) -> Self {
559        Self::Developer(value)
560    }
561}
562
563impl From<ChatCompletionRequestAssistantMessage> for ChatCompletionRequestMessage {
564    fn from(value: ChatCompletionRequestAssistantMessage) -> Self {
565        Self::Assistant(value)
566    }
567}
568
569impl From<ChatCompletionRequestFunctionMessage> for ChatCompletionRequestMessage {
570    fn from(value: ChatCompletionRequestFunctionMessage) -> Self {
571        Self::Function(value)
572    }
573}
574
575impl From<ChatCompletionRequestToolMessage> for ChatCompletionRequestMessage {
576    fn from(value: ChatCompletionRequestToolMessage) -> Self {
577        Self::Tool(value)
578    }
579}
580
581impl From<ChatCompletionRequestUserMessageContent> for ChatCompletionRequestUserMessage {
582    fn from(value: ChatCompletionRequestUserMessageContent) -> Self {
583        Self {
584            content: value,
585            name: None,
586        }
587    }
588}
589
590impl From<ChatCompletionRequestSystemMessageContent> for ChatCompletionRequestSystemMessage {
591    fn from(value: ChatCompletionRequestSystemMessageContent) -> Self {
592        Self {
593            content: value,
594            name: None,
595        }
596    }
597}
598
599impl From<ChatCompletionRequestDeveloperMessageContent> for ChatCompletionRequestDeveloperMessage {
600    fn from(value: ChatCompletionRequestDeveloperMessageContent) -> Self {
601        Self {
602            content: value,
603            name: None,
604        }
605    }
606}
607
608impl From<ChatCompletionRequestAssistantMessageContent> for ChatCompletionRequestAssistantMessage {
609    fn from(value: ChatCompletionRequestAssistantMessageContent) -> Self {
610        Self {
611            content: Some(value),
612            ..Default::default()
613        }
614    }
615}
616
617impl From<&str> for ChatCompletionRequestUserMessageContent {
618    fn from(value: &str) -> Self {
619        ChatCompletionRequestUserMessageContent::Text(value.into())
620    }
621}
622
623impl From<String> for ChatCompletionRequestUserMessageContent {
624    fn from(value: String) -> Self {
625        ChatCompletionRequestUserMessageContent::Text(value)
626    }
627}
628
629impl From<&str> for ChatCompletionRequestSystemMessageContent {
630    fn from(value: &str) -> Self {
631        ChatCompletionRequestSystemMessageContent::Text(value.into())
632    }
633}
634
635impl From<String> for ChatCompletionRequestSystemMessageContent {
636    fn from(value: String) -> Self {
637        ChatCompletionRequestSystemMessageContent::Text(value)
638    }
639}
640
641impl From<&str> for ChatCompletionRequestDeveloperMessageContent {
642    fn from(value: &str) -> Self {
643        ChatCompletionRequestDeveloperMessageContent::Text(value.into())
644    }
645}
646
647impl From<String> for ChatCompletionRequestDeveloperMessageContent {
648    fn from(value: String) -> Self {
649        ChatCompletionRequestDeveloperMessageContent::Text(value)
650    }
651}
652
653impl From<&str> for ChatCompletionRequestAssistantMessageContent {
654    fn from(value: &str) -> Self {
655        ChatCompletionRequestAssistantMessageContent::Text(value.into())
656    }
657}
658
659impl From<String> for ChatCompletionRequestAssistantMessageContent {
660    fn from(value: String) -> Self {
661        ChatCompletionRequestAssistantMessageContent::Text(value)
662    }
663}
664
665impl From<&str> for ChatCompletionRequestToolMessageContent {
666    fn from(value: &str) -> Self {
667        ChatCompletionRequestToolMessageContent::Text(value.into())
668    }
669}
670
671impl From<String> for ChatCompletionRequestToolMessageContent {
672    fn from(value: String) -> Self {
673        ChatCompletionRequestToolMessageContent::Text(value)
674    }
675}
676
677impl From<&str> for ChatCompletionRequestUserMessage {
678    fn from(value: &str) -> Self {
679        ChatCompletionRequestUserMessageContent::Text(value.into()).into()
680    }
681}
682
683impl From<String> for ChatCompletionRequestUserMessage {
684    fn from(value: String) -> Self {
685        value.as_str().into()
686    }
687}
688
689impl From<&str> for ChatCompletionRequestSystemMessage {
690    fn from(value: &str) -> Self {
691        ChatCompletionRequestSystemMessageContent::Text(value.into()).into()
692    }
693}
694
695impl From<&str> for ChatCompletionRequestDeveloperMessage {
696    fn from(value: &str) -> Self {
697        ChatCompletionRequestDeveloperMessageContent::Text(value.into()).into()
698    }
699}
700
701impl From<String> for ChatCompletionRequestSystemMessage {
702    fn from(value: String) -> Self {
703        value.as_str().into()
704    }
705}
706
707impl From<String> for ChatCompletionRequestDeveloperMessage {
708    fn from(value: String) -> Self {
709        value.as_str().into()
710    }
711}
712
713impl From<&str> for ChatCompletionRequestAssistantMessage {
714    fn from(value: &str) -> Self {
715        ChatCompletionRequestAssistantMessageContent::Text(value.into()).into()
716    }
717}
718
719impl From<String> for ChatCompletionRequestAssistantMessage {
720    fn from(value: String) -> Self {
721        value.as_str().into()
722    }
723}
724
725impl From<Vec<ChatCompletionRequestUserMessageContentPart>>
726    for ChatCompletionRequestUserMessageContent
727{
728    fn from(value: Vec<ChatCompletionRequestUserMessageContentPart>) -> Self {
729        ChatCompletionRequestUserMessageContent::Array(value)
730    }
731}
732
733impl From<ChatCompletionRequestMessageContentPartText>
734    for ChatCompletionRequestUserMessageContentPart
735{
736    fn from(value: ChatCompletionRequestMessageContentPartText) -> Self {
737        ChatCompletionRequestUserMessageContentPart::Text(value)
738    }
739}
740
741impl From<ChatCompletionRequestMessageContentPartImage>
742    for ChatCompletionRequestUserMessageContentPart
743{
744    fn from(value: ChatCompletionRequestMessageContentPartImage) -> Self {
745        ChatCompletionRequestUserMessageContentPart::ImageUrl(value)
746    }
747}
748
749impl From<ChatCompletionRequestMessageContentPartAudio>
750    for ChatCompletionRequestUserMessageContentPart
751{
752    fn from(value: ChatCompletionRequestMessageContentPartAudio) -> Self {
753        ChatCompletionRequestUserMessageContentPart::InputAudio(value)
754    }
755}
756
757impl From<&str> for ChatCompletionRequestMessageContentPartText {
758    fn from(value: &str) -> Self {
759        ChatCompletionRequestMessageContentPartText { text: value.into() }
760    }
761}
762
763impl From<String> for ChatCompletionRequestMessageContentPartText {
764    fn from(value: String) -> Self {
765        ChatCompletionRequestMessageContentPartText { text: value }
766    }
767}
768
769impl From<&str> for ImageUrl {
770    fn from(value: &str) -> Self {
771        Self {
772            url: value.into(),
773            detail: Default::default(),
774        }
775    }
776}
777
778impl From<String> for ImageUrl {
779    fn from(value: String) -> Self {
780        Self {
781            url: value,
782            detail: Default::default(),
783        }
784    }
785}
786
787impl From<String> for CreateMessageRequestContent {
788    fn from(value: String) -> Self {
789        Self::Content(value)
790    }
791}
792
793impl From<&str> for CreateMessageRequestContent {
794    fn from(value: &str) -> Self {
795        Self::Content(value.to_string())
796    }
797}
798
799impl Default for ChatCompletionRequestUserMessageContent {
800    fn default() -> Self {
801        ChatCompletionRequestUserMessageContent::Text("".into())
802    }
803}
804
805impl Default for CreateMessageRequestContent {
806    fn default() -> Self {
807        Self::Content("".into())
808    }
809}
810
811impl Default for ChatCompletionRequestDeveloperMessageContent {
812    fn default() -> Self {
813        ChatCompletionRequestDeveloperMessageContent::Text("".into())
814    }
815}
816
817impl Default for ChatCompletionRequestSystemMessageContent {
818    fn default() -> Self {
819        ChatCompletionRequestSystemMessageContent::Text("".into())
820    }
821}
822
823impl Default for ChatCompletionRequestToolMessageContent {
824    fn default() -> Self {
825        ChatCompletionRequestToolMessageContent::Text("".into())
826    }
827}
828
829// start: types to multipart from
830
831impl AsyncTryFrom<CreateTranscriptionRequest> for reqwest::multipart::Form {
832    type Error = OpenAIError;
833
834    async fn try_from(request: CreateTranscriptionRequest) -> Result<Self, Self::Error> {
835        let audio_part = create_file_part(request.file.source).await?;
836
837        let mut form = reqwest::multipart::Form::new()
838            .part("file", audio_part)
839            .text("model", request.model);
840
841        if let Some(prompt) = request.prompt {
842            form = form.text("prompt", prompt);
843        }
844
845        if let Some(response_format) = request.response_format {
846            form = form.text("response_format", response_format.to_string())
847        }
848
849        if let Some(temperature) = request.temperature {
850            form = form.text("temperature", temperature.to_string())
851        }
852
853        if let Some(language) = request.language {
854            form = form.text("language", language);
855        }
856
857        if let Some(timestamp_granularities) = request.timestamp_granularities {
858            for tg in timestamp_granularities {
859                form = form.text("timestamp_granularities[]", tg.to_string());
860            }
861        }
862
863        Ok(form)
864    }
865}
866
867impl AsyncTryFrom<CreateTranslationRequest> for reqwest::multipart::Form {
868    type Error = OpenAIError;
869
870    async fn try_from(request: CreateTranslationRequest) -> Result<Self, Self::Error> {
871        let audio_part = create_file_part(request.file.source).await?;
872
873        let mut form = reqwest::multipart::Form::new()
874            .part("file", audio_part)
875            .text("model", request.model);
876
877        if let Some(prompt) = request.prompt {
878            form = form.text("prompt", prompt);
879        }
880
881        if let Some(response_format) = request.response_format {
882            form = form.text("response_format", response_format.to_string())
883        }
884
885        if let Some(temperature) = request.temperature {
886            form = form.text("temperature", temperature.to_string())
887        }
888        Ok(form)
889    }
890}
891
892impl AsyncTryFrom<CreateImageEditRequest> for reqwest::multipart::Form {
893    type Error = OpenAIError;
894
895    async fn try_from(request: CreateImageEditRequest) -> Result<Self, Self::Error> {
896        let image_part = create_file_part(request.image.source).await?;
897
898        let mut form = reqwest::multipart::Form::new()
899            .part("image", image_part)
900            .text("prompt", request.prompt);
901
902        if let Some(mask) = request.mask {
903            let mask_part = create_file_part(mask.source).await?;
904            form = form.part("mask", mask_part);
905        }
906
907        if let Some(model) = request.model {
908            form = form.text("model", model.to_string())
909        }
910
911        if request.n.is_some() {
912            form = form.text("n", request.n.unwrap().to_string())
913        }
914
915        if request.size.is_some() {
916            form = form.text("size", request.size.unwrap().to_string())
917        }
918
919        if request.response_format.is_some() {
920            form = form.text(
921                "response_format",
922                request.response_format.unwrap().to_string(),
923            )
924        }
925
926        if request.user.is_some() {
927            form = form.text("user", request.user.unwrap())
928        }
929        Ok(form)
930    }
931}
932
933impl AsyncTryFrom<CreateImageVariationRequest> for reqwest::multipart::Form {
934    type Error = OpenAIError;
935
936    async fn try_from(request: CreateImageVariationRequest) -> Result<Self, Self::Error> {
937        let image_part = create_file_part(request.image.source).await?;
938
939        let mut form = reqwest::multipart::Form::new().part("image", image_part);
940
941        if let Some(model) = request.model {
942            form = form.text("model", model.to_string())
943        }
944
945        if request.n.is_some() {
946            form = form.text("n", request.n.unwrap().to_string())
947        }
948
949        if request.size.is_some() {
950            form = form.text("size", request.size.unwrap().to_string())
951        }
952
953        if request.response_format.is_some() {
954            form = form.text(
955                "response_format",
956                request.response_format.unwrap().to_string(),
957            )
958        }
959
960        if request.user.is_some() {
961            form = form.text("user", request.user.unwrap())
962        }
963        Ok(form)
964    }
965}
966
967impl AsyncTryFrom<CreateFileRequest> for reqwest::multipart::Form {
968    type Error = OpenAIError;
969
970    async fn try_from(request: CreateFileRequest) -> Result<Self, Self::Error> {
971        let file_part = create_file_part(request.file.source).await?;
972        let form = reqwest::multipart::Form::new()
973            .part("file", file_part)
974            .text("purpose", request.purpose.to_string());
975        Ok(form)
976    }
977}
978
979impl AsyncTryFrom<AddUploadPartRequest> for reqwest::multipart::Form {
980    type Error = OpenAIError;
981
982    async fn try_from(request: AddUploadPartRequest) -> Result<Self, Self::Error> {
983        let file_part = create_file_part(request.data).await?;
984        let form = reqwest::multipart::Form::new().part("data", file_part);
985        Ok(form)
986    }
987}
988
989// end: types to multipart form