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