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