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