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