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