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