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