async_openai/types/
impls.rs

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