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