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::{
11 audio::{TranscriptionChunkingStrategy, TranslationResponseFormat},
12 images::{ImageBackground, ImageEditInput, ImageOutputFormat, ImageQuality, InputFidelity},
13 InputSource, VideoSize,
14 },
15 util::{create_all_dir, create_file_part},
16};
17
18use bytes::Bytes;
19
20use super::{
21 audio::{
22 AudioInput, AudioResponseFormat, CreateSpeechResponse, CreateTranscriptionRequest,
23 CreateTranslationRequest, TimestampGranularity, TranscriptionInclude,
24 },
25 images::{
26 CreateImageEditRequest, CreateImageVariationRequest, DallE2ImageSize, Image, ImageInput,
27 ImageModel, ImageResponseFormat, ImageSize, ImagesResponse,
28 },
29 responses::{EasyInputContent, Role as ResponsesRole},
30 AddUploadPartRequest, ChatCompletionFunctionCall, ChatCompletionFunctions,
31 ChatCompletionNamedToolChoice, ChatCompletionRequestAssistantMessage,
32 ChatCompletionRequestAssistantMessageContent, ChatCompletionRequestDeveloperMessage,
33 ChatCompletionRequestDeveloperMessageContent, ChatCompletionRequestFunctionMessage,
34 ChatCompletionRequestMessage, ChatCompletionRequestMessageContentPartAudio,
35 ChatCompletionRequestMessageContentPartImage, ChatCompletionRequestMessageContentPartText,
36 ChatCompletionRequestSystemMessage, ChatCompletionRequestSystemMessageContent,
37 ChatCompletionRequestToolMessage, ChatCompletionRequestToolMessageContent,
38 ChatCompletionRequestUserMessage, ChatCompletionRequestUserMessageContent,
39 ChatCompletionRequestUserMessageContentPart, ChatCompletionToolChoiceOption,
40 CreateContainerFileRequest, CreateFileRequest, CreateMessageRequestContent, CreateVideoRequest,
41 EmbeddingInput, FileExpiresAfterAnchor, FileInput, FilePurpose, FunctionName, ImageUrl,
42 ModerationInput, Prompt, Role, Stop,
43};
44
45macro_rules! impl_from {
54 ($from_typ:ty, $to_typ:ty) => {
55 impl From<$from_typ> for $to_typ {
57 fn from(value: $from_typ) -> Self {
58 <$to_typ>::String(value.into())
59 }
60 }
61
62 impl From<Vec<$from_typ>> for $to_typ {
64 fn from(value: Vec<$from_typ>) -> Self {
65 <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
66 }
67 }
68
69 impl From<&Vec<$from_typ>> for $to_typ {
71 fn from(value: &Vec<$from_typ>) -> Self {
72 <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
73 }
74 }
75
76 impl<const N: usize> From<[$from_typ; N]> for $to_typ {
78 fn from(value: [$from_typ; N]) -> Self {
79 <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
80 }
81 }
82
83 impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
85 fn from(value: &[$from_typ; N]) -> Self {
86 <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
87 }
88 }
89 };
90}
91
92impl_from!(&str, Prompt);
94impl_from!(String, Prompt);
95impl_from!(&String, Prompt);
96
97impl_from!(&str, Stop);
99impl_from!(String, Stop);
100impl_from!(&String, Stop);
101
102impl_from!(&str, ModerationInput);
104impl_from!(String, ModerationInput);
105impl_from!(&String, ModerationInput);
106
107impl_from!(&str, EmbeddingInput);
109impl_from!(String, EmbeddingInput);
110impl_from!(&String, EmbeddingInput);
111
112macro_rules! impl_default {
114 ($for_typ:ty) => {
115 impl Default for $for_typ {
116 fn default() -> Self {
117 Self::String("".into())
118 }
119 }
120 };
121}
122
123impl_default!(Prompt);
124impl_default!(ModerationInput);
125impl_default!(EmbeddingInput);
126
127impl Default for InputSource {
128 fn default() -> Self {
129 InputSource::Path {
130 path: PathBuf::new(),
131 }
132 }
133}
134
135macro_rules! impl_input {
144 ($for_typ:ty) => {
145 impl $for_typ {
146 pub fn from_bytes(filename: String, bytes: Bytes) -> Self {
147 Self {
148 source: InputSource::Bytes { filename, bytes },
149 }
150 }
151
152 pub fn from_vec_u8(filename: String, vec: Vec<u8>) -> Self {
153 Self {
154 source: InputSource::VecU8 { filename, vec },
155 }
156 }
157 }
158
159 impl<P: AsRef<Path>> From<P> for $for_typ {
160 fn from(path: P) -> Self {
161 let path_buf = path.as_ref().to_path_buf();
162 Self {
163 source: InputSource::Path { path: path_buf },
164 }
165 }
166 }
167 };
168}
169
170impl_input!(AudioInput);
171impl_input!(FileInput);
172impl_input!(ImageInput);
173
174impl Default for ImageEditInput {
175 fn default() -> Self {
176 Self::Image(ImageInput::default())
177 }
178}
179
180impl From<ImageInput> for ImageEditInput {
181 fn from(value: ImageInput) -> Self {
182 Self::Image(value)
183 }
184}
185
186impl From<Vec<ImageInput>> for ImageEditInput {
187 fn from(value: Vec<ImageInput>) -> Self {
188 Self::Images(value)
189 }
190}
191
192impl From<&str> for ImageEditInput {
194 fn from(value: &str) -> Self {
195 Self::Image(value.into())
196 }
197}
198
199impl From<String> for ImageEditInput {
200 fn from(value: String) -> Self {
201 Self::Image(value.into())
202 }
203}
204
205impl From<&Path> for ImageEditInput {
206 fn from(value: &Path) -> Self {
207 Self::Image(value.into())
208 }
209}
210
211impl From<PathBuf> for ImageEditInput {
212 fn from(value: PathBuf) -> Self {
213 Self::Image(value.into())
214 }
215}
216
217impl<const N: usize> From<[&str; N]> for ImageEditInput {
219 fn from(value: [&str; N]) -> Self {
220 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
221 }
222}
223
224impl<const N: usize> From<[String; N]> for ImageEditInput {
225 fn from(value: [String; N]) -> Self {
226 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
227 }
228}
229
230impl<const N: usize> From<[&Path; N]> for ImageEditInput {
231 fn from(value: [&Path; N]) -> Self {
232 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
233 }
234}
235
236impl<const N: usize> From<[PathBuf; N]> for ImageEditInput {
237 fn from(value: [PathBuf; N]) -> Self {
238 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
239 }
240}
241
242impl<'a> From<Vec<&'a str>> for ImageEditInput {
244 fn from(value: Vec<&'a str>) -> Self {
245 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
246 }
247}
248
249impl From<Vec<String>> for ImageEditInput {
250 fn from(value: Vec<String>) -> Self {
251 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
252 }
253}
254
255impl From<Vec<&Path>> for ImageEditInput {
256 fn from(value: Vec<&Path>) -> Self {
257 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
258 }
259}
260
261impl From<Vec<PathBuf>> for ImageEditInput {
262 fn from(value: Vec<PathBuf>) -> Self {
263 Self::Images(value.into_iter().map(|v| ImageInput::from(v)).collect())
264 }
265}
266
267impl Display for VideoSize {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 write!(
270 f,
271 "{}",
272 match self {
273 Self::S720x1280 => "720x1280",
274 Self::S1280x720 => "1280x720",
275 Self::S1024x1792 => "1024x1792",
276 Self::S1792x1024 => "1792x1024",
277 }
278 )
279 }
280}
281
282impl Display for ImageSize {
283 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284 write!(
285 f,
286 "{}",
287 match self {
288 Self::S256x256 => "256x256",
289 Self::S512x512 => "512x512",
290 Self::S1024x1024 => "1024x1024",
291 Self::S1792x1024 => "1792x1024",
292 Self::S1024x1792 => "1024x1792",
293 Self::S1536x1024 => "1536x1024",
294 Self::S1024x1536 => "1024x1536",
295 Self::Auto => "auto",
296 }
297 )
298 }
299}
300
301impl Display for DallE2ImageSize {
302 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
303 write!(
304 f,
305 "{}",
306 match self {
307 Self::S256x256 => "256x256",
308 Self::S512x512 => "512x512",
309 Self::S1024x1024 => "1024x1024",
310 }
311 )
312 }
313}
314
315impl Display for ImageModel {
316 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317 write!(
318 f,
319 "{}",
320 match self {
321 Self::DallE2 => "dall-e-2",
322 Self::DallE3 => "dall-e-3",
323 Self::GptImage1 => "gpt-image-1",
324 Self::GptImage1Mini => "gpt-image-1-mini",
325 Self::Other(other) => other,
326 }
327 )
328 }
329}
330
331impl Display for ImageBackground {
332 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
333 write!(
334 f,
335 "{}",
336 match self {
337 Self::Transparent => "transparent",
338 Self::Opaque => "opaque",
339 Self::Auto => "auto",
340 }
341 )
342 }
343}
344
345impl Display for ImageOutputFormat {
346 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
347 write!(
348 f,
349 "{}",
350 match self {
351 Self::Png => "png",
352 Self::Jpeg => "jpeg",
353 Self::Webp => "webp",
354 }
355 )
356 }
357}
358
359impl Display for InputFidelity {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 write!(
362 f,
363 "{}",
364 match self {
365 Self::High => "high",
366 Self::Low => "low",
367 }
368 )
369 }
370}
371
372impl Display for ImageQuality {
373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
374 write!(
375 f,
376 "{}",
377 match self {
378 Self::Low => "low",
379 Self::Medium => "medium",
380 Self::High => "high",
381 Self::Auto => "auto",
382 Self::Standard => "standard",
383 Self::HD => "hd",
384 }
385 )
386 }
387}
388
389impl Display for ImageResponseFormat {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 write!(
392 f,
393 "{}",
394 match self {
395 Self::Url => "url",
396 Self::B64Json => "b64_json",
397 }
398 )
399 }
400}
401
402impl Display for AudioResponseFormat {
403 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
404 write!(
405 f,
406 "{}",
407 match self {
408 AudioResponseFormat::Json => "json",
409 AudioResponseFormat::Srt => "srt",
410 AudioResponseFormat::Text => "text",
411 AudioResponseFormat::VerboseJson => "verbose_json",
412 AudioResponseFormat::Vtt => "vtt",
413 AudioResponseFormat::DiarizedJson => "diarized_json",
414 }
415 )
416 }
417}
418
419impl Display for TranslationResponseFormat {
420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421 write!(
422 f,
423 "{}",
424 match self {
425 TranslationResponseFormat::Json => "json",
426 TranslationResponseFormat::Srt => "srt",
427 TranslationResponseFormat::Text => "text",
428 TranslationResponseFormat::VerboseJson => "verbose_json",
429 TranslationResponseFormat::Vtt => "vtt",
430 }
431 )
432 }
433}
434
435impl Display for TimestampGranularity {
436 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437 write!(
438 f,
439 "{}",
440 match self {
441 TimestampGranularity::Word => "word",
442 TimestampGranularity::Segment => "segment",
443 }
444 )
445 }
446}
447
448impl Display for TranscriptionInclude {
449 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
450 write!(
451 f,
452 "{}",
453 match self {
454 TranscriptionInclude::Logprobs => "logprobs",
455 }
456 )
457 }
458}
459
460impl Display for Role {
461 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
462 write!(
463 f,
464 "{}",
465 match self {
466 Role::User => "user",
467 Role::System => "system",
468 Role::Assistant => "assistant",
469 Role::Function => "function",
470 Role::Tool => "tool",
471 }
472 )
473 }
474}
475
476impl Display for FilePurpose {
477 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
478 write!(
479 f,
480 "{}",
481 match self {
482 Self::Assistants => "assistants",
483 Self::Batch => "batch",
484 Self::FineTune => "fine-tune",
485 Self::Vision => "vision",
486 }
487 )
488 }
489}
490
491impl Display for FileExpiresAfterAnchor {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
493 write!(
494 f,
495 "{}",
496 match self {
497 Self::CreatedAt => "created_at",
498 }
499 )
500 }
501}
502
503impl ImagesResponse {
504 pub async fn save<P: AsRef<Path>>(&self, dir: P) -> Result<Vec<PathBuf>, OpenAIError> {
507 create_all_dir(dir.as_ref())?;
508
509 let mut handles = vec![];
510 for id in self.data.clone() {
511 let dir_buf = PathBuf::from(dir.as_ref());
512 handles.push(tokio::spawn(async move { id.save(dir_buf).await }));
513 }
514
515 let results = futures::future::join_all(handles).await;
516 let mut errors = vec![];
517 let mut paths = vec![];
518
519 for result in results {
520 match result {
521 Ok(inner) => match inner {
522 Ok(path) => paths.push(path),
523 Err(e) => errors.push(e),
524 },
525 Err(e) => errors.push(OpenAIError::FileSaveError(e.to_string())),
526 }
527 }
528
529 if errors.is_empty() {
530 Ok(paths)
531 } else {
532 Err(OpenAIError::FileSaveError(
533 errors
534 .into_iter()
535 .map(|e| e.to_string())
536 .collect::<Vec<String>>()
537 .join("; "),
538 ))
539 }
540 }
541}
542
543impl CreateSpeechResponse {
544 pub async fn save<P: AsRef<Path>>(&self, file_path: P) -> Result<(), OpenAIError> {
545 let dir = file_path.as_ref().parent();
546
547 if let Some(dir) = dir {
548 create_all_dir(dir)?;
549 }
550
551 tokio::fs::write(file_path, &self.bytes)
552 .await
553 .map_err(|e| OpenAIError::FileSaveError(e.to_string()))?;
554
555 Ok(())
556 }
557}
558
559impl Image {
560 async fn save<P: AsRef<Path>>(&self, dir: P) -> Result<PathBuf, OpenAIError> {
561 match self {
562 Image::Url { url, .. } => download_url(url, dir).await,
563 Image::B64Json { b64_json, .. } => save_b64(b64_json, dir).await,
564 }
565 }
566}
567
568macro_rules! impl_from_for_integer_array {
569 ($from_typ:ty, $to_typ:ty) => {
570 impl<const N: usize> From<[$from_typ; N]> for $to_typ {
571 fn from(value: [$from_typ; N]) -> Self {
572 Self::IntegerArray(value.to_vec())
573 }
574 }
575
576 impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
577 fn from(value: &[$from_typ; N]) -> Self {
578 Self::IntegerArray(value.to_vec())
579 }
580 }
581
582 impl From<Vec<$from_typ>> for $to_typ {
583 fn from(value: Vec<$from_typ>) -> Self {
584 Self::IntegerArray(value)
585 }
586 }
587
588 impl From<&Vec<$from_typ>> for $to_typ {
589 fn from(value: &Vec<$from_typ>) -> Self {
590 Self::IntegerArray(value.clone())
591 }
592 }
593 };
594}
595
596impl_from_for_integer_array!(u32, EmbeddingInput);
597impl_from_for_integer_array!(u32, Prompt);
598
599macro_rules! impl_from_for_array_of_integer_array {
600 ($from_typ:ty, $to_typ:ty) => {
601 impl From<Vec<Vec<$from_typ>>> for $to_typ {
602 fn from(value: Vec<Vec<$from_typ>>) -> Self {
603 Self::ArrayOfIntegerArray(value)
604 }
605 }
606
607 impl From<&Vec<Vec<$from_typ>>> for $to_typ {
608 fn from(value: &Vec<Vec<$from_typ>>) -> Self {
609 Self::ArrayOfIntegerArray(value.clone())
610 }
611 }
612
613 impl<const M: usize, const N: usize> From<[[$from_typ; N]; M]> for $to_typ {
614 fn from(value: [[$from_typ; N]; M]) -> Self {
615 Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
616 }
617 }
618
619 impl<const M: usize, const N: usize> From<[&[$from_typ; N]; M]> for $to_typ {
620 fn from(value: [&[$from_typ; N]; M]) -> Self {
621 Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
622 }
623 }
624
625 impl<const M: usize, const N: usize> From<&[[$from_typ; N]; M]> for $to_typ {
626 fn from(value: &[[$from_typ; N]; M]) -> Self {
627 Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
628 }
629 }
630
631 impl<const M: usize, const N: usize> From<&[&[$from_typ; N]; M]> for $to_typ {
632 fn from(value: &[&[$from_typ; N]; M]) -> Self {
633 Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
634 }
635 }
636
637 impl<const N: usize> From<[Vec<$from_typ>; N]> for $to_typ {
638 fn from(value: [Vec<$from_typ>; N]) -> Self {
639 Self::ArrayOfIntegerArray(value.to_vec())
640 }
641 }
642
643 impl<const N: usize> From<&[Vec<$from_typ>; N]> for $to_typ {
644 fn from(value: &[Vec<$from_typ>; N]) -> Self {
645 Self::ArrayOfIntegerArray(value.to_vec())
646 }
647 }
648
649 impl<const N: usize> From<[&Vec<$from_typ>; N]> for $to_typ {
650 fn from(value: [&Vec<$from_typ>; N]) -> Self {
651 Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.clone()).collect())
652 }
653 }
654
655 impl<const N: usize> From<&[&Vec<$from_typ>; N]> for $to_typ {
656 fn from(value: &[&Vec<$from_typ>; N]) -> Self {
657 Self::ArrayOfIntegerArray(
658 value
659 .to_vec()
660 .into_iter()
661 .map(|inner| inner.clone())
662 .collect(),
663 )
664 }
665 }
666
667 impl<const N: usize> From<Vec<[$from_typ; N]>> for $to_typ {
668 fn from(value: Vec<[$from_typ; N]>) -> Self {
669 Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
670 }
671 }
672
673 impl<const N: usize> From<&Vec<[$from_typ; N]>> for $to_typ {
674 fn from(value: &Vec<[$from_typ; N]>) -> Self {
675 Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
676 }
677 }
678
679 impl<const N: usize> From<Vec<&[$from_typ; N]>> for $to_typ {
680 fn from(value: Vec<&[$from_typ; N]>) -> Self {
681 Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
682 }
683 }
684
685 impl<const N: usize> From<&Vec<&[$from_typ; N]>> for $to_typ {
686 fn from(value: &Vec<&[$from_typ; N]>) -> Self {
687 Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
688 }
689 }
690 };
691}
692
693impl_from_for_array_of_integer_array!(u32, EmbeddingInput);
694impl_from_for_array_of_integer_array!(u32, Prompt);
695
696impl From<&str> for ChatCompletionFunctionCall {
697 fn from(value: &str) -> Self {
698 match value {
699 "auto" => Self::Auto,
700 "none" => Self::None,
701 _ => Self::Function { name: value.into() },
702 }
703 }
704}
705
706impl From<&str> for FunctionName {
707 fn from(value: &str) -> Self {
708 Self { name: value.into() }
709 }
710}
711
712impl From<String> for FunctionName {
713 fn from(value: String) -> Self {
714 Self { name: value }
715 }
716}
717
718impl From<&str> for ChatCompletionNamedToolChoice {
719 fn from(value: &str) -> Self {
720 Self {
721 r#type: super::ChatCompletionToolType::Function,
722 function: value.into(),
723 }
724 }
725}
726
727impl From<String> for ChatCompletionNamedToolChoice {
728 fn from(value: String) -> Self {
729 Self {
730 r#type: super::ChatCompletionToolType::Function,
731 function: value.into(),
732 }
733 }
734}
735
736impl From<&str> for ChatCompletionToolChoiceOption {
737 fn from(value: &str) -> Self {
738 match value {
739 "auto" => Self::Auto,
740 "none" => Self::None,
741 _ => Self::Named(value.into()),
742 }
743 }
744}
745
746impl From<String> for ChatCompletionToolChoiceOption {
747 fn from(value: String) -> Self {
748 match value.as_str() {
749 "auto" => Self::Auto,
750 "none" => Self::None,
751 _ => Self::Named(value.into()),
752 }
753 }
754}
755
756impl From<(String, serde_json::Value)> for ChatCompletionFunctions {
757 fn from(value: (String, serde_json::Value)) -> Self {
758 Self {
759 name: value.0,
760 description: None,
761 parameters: value.1,
762 }
763 }
764}
765
766impl From<ChatCompletionRequestUserMessage> for ChatCompletionRequestMessage {
769 fn from(value: ChatCompletionRequestUserMessage) -> Self {
770 Self::User(value)
771 }
772}
773
774impl From<ChatCompletionRequestSystemMessage> for ChatCompletionRequestMessage {
775 fn from(value: ChatCompletionRequestSystemMessage) -> Self {
776 Self::System(value)
777 }
778}
779
780impl From<ChatCompletionRequestDeveloperMessage> for ChatCompletionRequestMessage {
781 fn from(value: ChatCompletionRequestDeveloperMessage) -> Self {
782 Self::Developer(value)
783 }
784}
785
786impl From<ChatCompletionRequestAssistantMessage> for ChatCompletionRequestMessage {
787 fn from(value: ChatCompletionRequestAssistantMessage) -> Self {
788 Self::Assistant(value)
789 }
790}
791
792impl From<ChatCompletionRequestFunctionMessage> for ChatCompletionRequestMessage {
793 fn from(value: ChatCompletionRequestFunctionMessage) -> Self {
794 Self::Function(value)
795 }
796}
797
798impl From<ChatCompletionRequestToolMessage> for ChatCompletionRequestMessage {
799 fn from(value: ChatCompletionRequestToolMessage) -> Self {
800 Self::Tool(value)
801 }
802}
803
804impl From<ChatCompletionRequestUserMessageContent> for ChatCompletionRequestUserMessage {
805 fn from(value: ChatCompletionRequestUserMessageContent) -> Self {
806 Self {
807 content: value,
808 name: None,
809 }
810 }
811}
812
813impl From<ChatCompletionRequestSystemMessageContent> for ChatCompletionRequestSystemMessage {
814 fn from(value: ChatCompletionRequestSystemMessageContent) -> Self {
815 Self {
816 content: value,
817 name: None,
818 }
819 }
820}
821
822impl From<ChatCompletionRequestDeveloperMessageContent> for ChatCompletionRequestDeveloperMessage {
823 fn from(value: ChatCompletionRequestDeveloperMessageContent) -> Self {
824 Self {
825 content: value,
826 name: None,
827 }
828 }
829}
830
831impl From<ChatCompletionRequestAssistantMessageContent> for ChatCompletionRequestAssistantMessage {
832 fn from(value: ChatCompletionRequestAssistantMessageContent) -> Self {
833 Self {
834 content: Some(value),
835 ..Default::default()
836 }
837 }
838}
839
840impl From<&str> for ChatCompletionRequestUserMessageContent {
841 fn from(value: &str) -> Self {
842 ChatCompletionRequestUserMessageContent::Text(value.into())
843 }
844}
845
846impl From<String> for ChatCompletionRequestUserMessageContent {
847 fn from(value: String) -> Self {
848 ChatCompletionRequestUserMessageContent::Text(value)
849 }
850}
851
852impl From<&str> for ChatCompletionRequestSystemMessageContent {
853 fn from(value: &str) -> Self {
854 ChatCompletionRequestSystemMessageContent::Text(value.into())
855 }
856}
857
858impl From<String> for ChatCompletionRequestSystemMessageContent {
859 fn from(value: String) -> Self {
860 ChatCompletionRequestSystemMessageContent::Text(value)
861 }
862}
863
864impl From<&str> for ChatCompletionRequestDeveloperMessageContent {
865 fn from(value: &str) -> Self {
866 ChatCompletionRequestDeveloperMessageContent::Text(value.into())
867 }
868}
869
870impl From<String> for ChatCompletionRequestDeveloperMessageContent {
871 fn from(value: String) -> Self {
872 ChatCompletionRequestDeveloperMessageContent::Text(value)
873 }
874}
875
876impl From<&str> for ChatCompletionRequestAssistantMessageContent {
877 fn from(value: &str) -> Self {
878 ChatCompletionRequestAssistantMessageContent::Text(value.into())
879 }
880}
881
882impl From<String> for ChatCompletionRequestAssistantMessageContent {
883 fn from(value: String) -> Self {
884 ChatCompletionRequestAssistantMessageContent::Text(value)
885 }
886}
887
888impl From<&str> for ChatCompletionRequestToolMessageContent {
889 fn from(value: &str) -> Self {
890 ChatCompletionRequestToolMessageContent::Text(value.into())
891 }
892}
893
894impl From<String> for ChatCompletionRequestToolMessageContent {
895 fn from(value: String) -> Self {
896 ChatCompletionRequestToolMessageContent::Text(value)
897 }
898}
899
900impl From<&str> for ChatCompletionRequestUserMessage {
901 fn from(value: &str) -> Self {
902 ChatCompletionRequestUserMessageContent::Text(value.into()).into()
903 }
904}
905
906impl From<String> for ChatCompletionRequestUserMessage {
907 fn from(value: String) -> Self {
908 value.as_str().into()
909 }
910}
911
912impl From<&str> for ChatCompletionRequestSystemMessage {
913 fn from(value: &str) -> Self {
914 ChatCompletionRequestSystemMessageContent::Text(value.into()).into()
915 }
916}
917
918impl From<&str> for ChatCompletionRequestDeveloperMessage {
919 fn from(value: &str) -> Self {
920 ChatCompletionRequestDeveloperMessageContent::Text(value.into()).into()
921 }
922}
923
924impl From<String> for ChatCompletionRequestSystemMessage {
925 fn from(value: String) -> Self {
926 value.as_str().into()
927 }
928}
929
930impl From<String> for ChatCompletionRequestDeveloperMessage {
931 fn from(value: String) -> Self {
932 value.as_str().into()
933 }
934}
935
936impl From<&str> for ChatCompletionRequestAssistantMessage {
937 fn from(value: &str) -> Self {
938 ChatCompletionRequestAssistantMessageContent::Text(value.into()).into()
939 }
940}
941
942impl From<String> for ChatCompletionRequestAssistantMessage {
943 fn from(value: String) -> Self {
944 value.as_str().into()
945 }
946}
947
948impl From<Vec<ChatCompletionRequestUserMessageContentPart>>
949 for ChatCompletionRequestUserMessageContent
950{
951 fn from(value: Vec<ChatCompletionRequestUserMessageContentPart>) -> Self {
952 ChatCompletionRequestUserMessageContent::Array(value)
953 }
954}
955
956impl From<ChatCompletionRequestMessageContentPartText>
957 for ChatCompletionRequestUserMessageContentPart
958{
959 fn from(value: ChatCompletionRequestMessageContentPartText) -> Self {
960 ChatCompletionRequestUserMessageContentPart::Text(value)
961 }
962}
963
964impl From<ChatCompletionRequestMessageContentPartImage>
965 for ChatCompletionRequestUserMessageContentPart
966{
967 fn from(value: ChatCompletionRequestMessageContentPartImage) -> Self {
968 ChatCompletionRequestUserMessageContentPart::ImageUrl(value)
969 }
970}
971
972impl From<ChatCompletionRequestMessageContentPartAudio>
973 for ChatCompletionRequestUserMessageContentPart
974{
975 fn from(value: ChatCompletionRequestMessageContentPartAudio) -> Self {
976 ChatCompletionRequestUserMessageContentPart::InputAudio(value)
977 }
978}
979
980impl From<&str> for ChatCompletionRequestMessageContentPartText {
981 fn from(value: &str) -> Self {
982 ChatCompletionRequestMessageContentPartText { text: value.into() }
983 }
984}
985
986impl From<String> for ChatCompletionRequestMessageContentPartText {
987 fn from(value: String) -> Self {
988 ChatCompletionRequestMessageContentPartText { text: value }
989 }
990}
991
992impl From<&str> for ImageUrl {
993 fn from(value: &str) -> Self {
994 Self {
995 url: value.into(),
996 detail: Default::default(),
997 }
998 }
999}
1000
1001impl From<String> for ImageUrl {
1002 fn from(value: String) -> Self {
1003 Self {
1004 url: value,
1005 detail: Default::default(),
1006 }
1007 }
1008}
1009
1010impl From<String> for CreateMessageRequestContent {
1011 fn from(value: String) -> Self {
1012 Self::Content(value)
1013 }
1014}
1015
1016impl From<&str> for CreateMessageRequestContent {
1017 fn from(value: &str) -> Self {
1018 Self::Content(value.to_string())
1019 }
1020}
1021
1022impl Default for ChatCompletionRequestUserMessageContent {
1023 fn default() -> Self {
1024 ChatCompletionRequestUserMessageContent::Text("".into())
1025 }
1026}
1027
1028impl Default for CreateMessageRequestContent {
1029 fn default() -> Self {
1030 Self::Content("".into())
1031 }
1032}
1033
1034impl Default for ChatCompletionRequestDeveloperMessageContent {
1035 fn default() -> Self {
1036 ChatCompletionRequestDeveloperMessageContent::Text("".into())
1037 }
1038}
1039
1040impl Default for ChatCompletionRequestSystemMessageContent {
1041 fn default() -> Self {
1042 ChatCompletionRequestSystemMessageContent::Text("".into())
1043 }
1044}
1045
1046impl Default for ChatCompletionRequestToolMessageContent {
1047 fn default() -> Self {
1048 ChatCompletionRequestToolMessageContent::Text("".into())
1049 }
1050}
1051
1052impl AsyncTryFrom<CreateTranscriptionRequest> for reqwest::multipart::Form {
1055 type Error = OpenAIError;
1056
1057 async fn try_from(request: CreateTranscriptionRequest) -> Result<Self, Self::Error> {
1058 let audio_part = create_file_part(request.file.source).await?;
1059
1060 let mut form = reqwest::multipart::Form::new()
1061 .part("file", audio_part)
1062 .text("model", request.model);
1063
1064 if let Some(language) = request.language {
1065 form = form.text("language", language);
1066 }
1067
1068 if let Some(prompt) = request.prompt {
1069 form = form.text("prompt", prompt);
1070 }
1071
1072 if let Some(response_format) = request.response_format {
1073 form = form.text("response_format", response_format.to_string())
1074 }
1075
1076 if let Some(temperature) = request.temperature {
1077 form = form.text("temperature", temperature.to_string())
1078 }
1079
1080 if let Some(include) = request.include {
1081 for inc in include {
1082 form = form.text("include[]", inc.to_string());
1083 }
1084 }
1085
1086 if let Some(timestamp_granularities) = request.timestamp_granularities {
1087 for tg in timestamp_granularities {
1088 form = form.text("timestamp_granularities[]", tg.to_string());
1089 }
1090 }
1091
1092 if let Some(stream) = request.stream {
1093 form = form.text("stream", stream.to_string());
1094 }
1095
1096 if let Some(chunking_strategy) = request.chunking_strategy {
1097 match chunking_strategy {
1098 TranscriptionChunkingStrategy::Auto => {
1099 form = form.text("chunking_strategy", "auto");
1100 }
1101 TranscriptionChunkingStrategy::ServerVad(vad_config) => {
1102 form = form.text(
1103 "chunking_strategy",
1104 serde_json::to_string(&vad_config).unwrap().to_string(),
1105 );
1106 }
1107 }
1108 }
1109
1110 if let Some(known_speaker_names) = request.known_speaker_names {
1111 for kn in known_speaker_names {
1112 form = form.text("known_speaker_names[]", kn.to_string());
1113 }
1114 }
1115
1116 if let Some(known_speaker_references) = request.known_speaker_references {
1117 for kn in known_speaker_references {
1118 form = form.text("known_speaker_references[]", kn.to_string());
1119 }
1120 }
1121
1122 Ok(form)
1123 }
1124}
1125
1126impl AsyncTryFrom<CreateTranslationRequest> for reqwest::multipart::Form {
1127 type Error = OpenAIError;
1128
1129 async fn try_from(request: CreateTranslationRequest) -> Result<Self, Self::Error> {
1130 let audio_part = create_file_part(request.file.source).await?;
1131
1132 let mut form = reqwest::multipart::Form::new()
1133 .part("file", audio_part)
1134 .text("model", request.model);
1135
1136 if let Some(prompt) = request.prompt {
1137 form = form.text("prompt", prompt);
1138 }
1139
1140 if let Some(response_format) = request.response_format {
1141 form = form.text("response_format", response_format.to_string())
1142 }
1143
1144 if let Some(temperature) = request.temperature {
1145 form = form.text("temperature", temperature.to_string())
1146 }
1147 Ok(form)
1148 }
1149}
1150
1151impl AsyncTryFrom<CreateImageEditRequest> for reqwest::multipart::Form {
1152 type Error = OpenAIError;
1153
1154 async fn try_from(request: CreateImageEditRequest) -> Result<Self, Self::Error> {
1155 let mut form = reqwest::multipart::Form::new().text("prompt", request.prompt);
1156
1157 match request.image {
1158 ImageEditInput::Image(image) => {
1159 let image_part = create_file_part(image.source).await?;
1160 form = form.part("image", image_part);
1161 }
1162 ImageEditInput::Images(images) => {
1163 for image in images {
1164 let image_part = create_file_part(image.source).await?;
1165 form = form.part("image[]", image_part);
1166 }
1167 }
1168 }
1169
1170 if let Some(mask) = request.mask {
1171 let mask_part = create_file_part(mask.source).await?;
1172 form = form.part("mask", mask_part);
1173 }
1174
1175 if let Some(background) = request.background {
1176 form = form.text("background", background.to_string())
1177 }
1178
1179 if let Some(model) = request.model {
1180 form = form.text("model", model.to_string())
1181 }
1182
1183 if let Some(n) = request.n {
1184 form = form.text("n", n.to_string())
1185 }
1186
1187 if let Some(size) = request.size {
1188 form = form.text("size", size.to_string())
1189 }
1190
1191 if let Some(response_format) = request.response_format {
1192 form = form.text("response_format", response_format.to_string())
1193 }
1194
1195 if let Some(output_format) = request.output_format {
1196 form = form.text("output_format", output_format.to_string())
1197 }
1198
1199 if let Some(output_compression) = request.output_compression {
1200 form = form.text("output_compression", output_compression.to_string())
1201 }
1202
1203 if let Some(output_compression) = request.output_compression {
1204 form = form.text("output_compression", output_compression.to_string())
1205 }
1206
1207 if let Some(user) = request.user {
1208 form = form.text("user", user)
1209 }
1210
1211 if let Some(input_fidelity) = request.input_fidelity {
1212 form = form.text("input_fidelity", input_fidelity.to_string())
1213 }
1214
1215 if let Some(stream) = request.stream {
1216 form = form.text("stream", stream.to_string())
1217 }
1218
1219 if let Some(partial_images) = request.partial_images {
1220 form = form.text("partial_images", partial_images.to_string())
1221 }
1222
1223 if let Some(quality) = request.quality {
1224 form = form.text("quality", quality.to_string())
1225 }
1226
1227 Ok(form)
1228 }
1229}
1230
1231impl AsyncTryFrom<CreateImageVariationRequest> for reqwest::multipart::Form {
1232 type Error = OpenAIError;
1233
1234 async fn try_from(request: CreateImageVariationRequest) -> Result<Self, Self::Error> {
1235 let image_part = create_file_part(request.image.source).await?;
1236
1237 let mut form = reqwest::multipart::Form::new().part("image", image_part);
1238
1239 if let Some(model) = request.model {
1240 form = form.text("model", model.to_string())
1241 }
1242
1243 if request.n.is_some() {
1244 form = form.text("n", request.n.unwrap().to_string())
1245 }
1246
1247 if request.size.is_some() {
1248 form = form.text("size", request.size.unwrap().to_string())
1249 }
1250
1251 if request.response_format.is_some() {
1252 form = form.text(
1253 "response_format",
1254 request.response_format.unwrap().to_string(),
1255 )
1256 }
1257
1258 if request.user.is_some() {
1259 form = form.text("user", request.user.unwrap())
1260 }
1261 Ok(form)
1262 }
1263}
1264
1265impl AsyncTryFrom<CreateFileRequest> for reqwest::multipart::Form {
1266 type Error = OpenAIError;
1267
1268 async fn try_from(request: CreateFileRequest) -> Result<Self, Self::Error> {
1269 let file_part = create_file_part(request.file.source).await?;
1270 let mut form = reqwest::multipart::Form::new()
1271 .part("file", file_part)
1272 .text("purpose", request.purpose.to_string());
1273
1274 if let Some(expires_after) = request.expires_after {
1275 form = form
1276 .text("expires_after[anchor]", expires_after.anchor.to_string())
1277 .text("expires_after[seconds]", expires_after.seconds.to_string());
1278 }
1279 Ok(form)
1280 }
1281}
1282
1283impl AsyncTryFrom<AddUploadPartRequest> for reqwest::multipart::Form {
1284 type Error = OpenAIError;
1285
1286 async fn try_from(request: AddUploadPartRequest) -> Result<Self, Self::Error> {
1287 let file_part = create_file_part(request.data).await?;
1288 let form = reqwest::multipart::Form::new().part("data", file_part);
1289 Ok(form)
1290 }
1291}
1292
1293impl AsyncTryFrom<CreateContainerFileRequest> for reqwest::multipart::Form {
1294 type Error = OpenAIError;
1295
1296 async fn try_from(request: CreateContainerFileRequest) -> Result<Self, Self::Error> {
1297 let mut form = reqwest::multipart::Form::new();
1298
1299 if let Some(file_source) = request.file {
1301 let file_part = create_file_part(file_source).await?;
1302 form = form.part("file", file_part);
1303 } else if let Some(file_id) = request.file_id {
1304 form = form.text("file_id", file_id);
1305 }
1306
1307 Ok(form)
1308 }
1309}
1310
1311impl AsyncTryFrom<CreateVideoRequest> for reqwest::multipart::Form {
1312 type Error = OpenAIError;
1313
1314 async fn try_from(request: CreateVideoRequest) -> Result<Self, Self::Error> {
1315 let mut form = reqwest::multipart::Form::new().text("model", request.model);
1316
1317 form = form.text("prompt", request.prompt);
1318
1319 if request.size.is_some() {
1320 form = form.text("size", request.size.unwrap().to_string());
1321 }
1322
1323 if request.seconds.is_some() {
1324 form = form.text("seconds", request.seconds.unwrap());
1325 }
1326
1327 if request.input_reference.is_some() {
1328 let image_part = create_file_part(request.input_reference.unwrap().source).await?;
1329 form = form.part("input_reference", image_part);
1330 }
1331
1332 Ok(form)
1333 }
1334}
1335
1336impl Default for EasyInputContent {
1339 fn default() -> Self {
1340 Self::Text("".to_string())
1341 }
1342}
1343
1344impl Default for ResponsesRole {
1345 fn default() -> Self {
1346 Self::User
1347 }
1348}
1349
1350impl From<String> for EasyInputContent {
1351 fn from(value: String) -> Self {
1352 Self::Text(value)
1353 }
1354}
1355
1356impl From<&str> for EasyInputContent {
1357 fn from(value: &str) -> Self {
1358 Self::Text(value.to_owned())
1359 }
1360}