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