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