From 3e5286dad67343b93b88f7df5cb8520bae52d109 Mon Sep 17 00:00:00 2001 From: Dongri Jin Date: Tue, 9 Jul 2024 18:47:51 +0900 Subject: [PATCH] * use reqwest * support multipart form * fix audio apits --- Cargo.toml | 17 +- README.md | 11 +- examples/assistant.rs | 23 +- examples/audio_speech.rs | 22 + examples/audio_transcriptions.rs | 20 + examples/audio_translations.rs | 20 + examples/chat_completion.rs | 9 +- examples/completion.rs | 9 +- examples/data/problem.mp3 | Bin 0 -> 61440 bytes examples/data/problem_cn.mp3 | Bin 0 -> 45120 bytes examples/embedding.rs | 9 +- examples/function_call.rs | 13 +- examples/function_call_role.rs | 17 +- examples/text_to_speech.rs | 21 - examples/vision.rs | 9 +- src/v1/api.rs | 939 +++++++++++-------------------- src/v1/audio.rs | 8 +- src/v1/error.rs | 17 +- 18 files changed, 489 insertions(+), 675 deletions(-) create mode 100644 examples/audio_speech.rs create mode 100644 examples/audio_transcriptions.rs create mode 100644 examples/audio_translations.rs create mode 100644 examples/data/problem.mp3 create mode 100644 examples/data/problem_cn.mp3 delete mode 100644 examples/text_to_speech.rs diff --git a/Cargo.toml b/Cargo.toml index a9a13de..996b824 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openai-api-rs" -version = "4.1.1" +version = "5.0.0" edition = "2021" authors = ["Dongri Jin "] license = "MIT" @@ -9,16 +9,17 @@ repository = "https://github.com/dongri/openai-api-rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies.reqwest] +version = "0.12" +features = ["json", "multipart"] + +[dependencies.tokio] +version = "1" +features = ["full"] + [dependencies.serde] version = "1" features = ["derive"] -default-features = false [dependencies.serde_json] version = "1" -default-features = false - -[dependencies.minreq] -version = "2" -default-features = false -features = ["https-rustls", "json-using-serde", "proxy"] diff --git a/README.md b/README.md index c64b63c..7f28b04 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Check out the [docs.rs](https://docs.rs/openai-api-rs/). Cargo.toml ```toml [dependencies] -openai-api-rs = "4.1.1" +openai-api-rs = "5.0.0" ``` ## Usage @@ -48,13 +48,14 @@ $ export OPENAI_API_BASE=https://api.openai.com/v1 ## Example of chat completion ```rust -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest}; use openai_api_rs::v1::common::GPT4_O; use std::env; -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let req = ChatCompletionRequest::new( GPT4_O.to_string(), @@ -65,7 +66,7 @@ fn main() -> Result<(), Box> { }], ); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; println!("Content: {:?}", result.choices[0].message.content); println!("Response Headers: {:?}", result.headers); diff --git a/examples/assistant.rs b/examples/assistant.rs index c5acb83..133922e 100644 --- a/examples/assistant.rs +++ b/examples/assistant.rs @@ -1,4 +1,4 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::assistant::AssistantRequest; use openai_api_rs::v1::common::GPT4_O; use openai_api_rs::v1::message::{CreateMessageRequest, MessageRole}; @@ -7,8 +7,9 @@ use openai_api_rs::v1::thread::CreateThreadRequest; use std::collections::HashMap; use std::env; -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let mut tools = HashMap::new(); tools.insert("type".to_string(), "code_interpreter".to_string()); @@ -21,11 +22,11 @@ fn main() -> Result<(), Box> { let req = req.clone().tools(vec![tools]); println!("AssistantRequest: {:?}", req); - let result = client.create_assistant(req)?; + let result = client.create_assistant(req).await?; println!("Create Assistant Result ID: {:?}", result.id); let thread_req = CreateThreadRequest::new(); - let thread_result = client.create_thread(thread_req)?; + let thread_result = client.create_thread(thread_req).await?; println!("Create Thread Result ID: {:?}", thread_result.id.clone()); let message_req = CreateMessageRequest::new( @@ -33,16 +34,19 @@ fn main() -> Result<(), Box> { "`I need to solve the equation 3x + 11 = 14. Can you help me?".to_string(), ); - let message_result = client.create_message(thread_result.id.clone(), message_req)?; + let message_result = client + .create_message(thread_result.id.clone(), message_req) + .await?; println!("Create Message Result ID: {:?}", message_result.id.clone()); let run_req = CreateRunRequest::new(result.id); - let run_result = client.create_run(thread_result.id.clone(), run_req)?; + let run_result = client.create_run(thread_result.id.clone(), run_req).await?; println!("Create Run Result ID: {:?}", run_result.id.clone()); loop { let run_result = client .retrieve_run(thread_result.id.clone(), run_result.id.clone()) + .await .unwrap(); if run_result.status == "completed" { break; @@ -52,7 +56,10 @@ fn main() -> Result<(), Box> { } } - let list_message_result = client.list_messages(thread_result.id.clone()).unwrap(); + let list_message_result = client + .list_messages(thread_result.id.clone()) + .await + .unwrap(); for data in list_message_result.data { for content in data.content { println!( diff --git a/examples/audio_speech.rs b/examples/audio_speech.rs new file mode 100644 index 0000000..c6541d1 --- /dev/null +++ b/examples/audio_speech.rs @@ -0,0 +1,22 @@ +use openai_api_rs::v1::api::OpenAIClient; +use openai_api_rs::v1::audio::{self, AudioSpeechRequest, TTS_1}; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); + + let req = AudioSpeechRequest::new( + TTS_1.to_string(), + String::from("Money is not the problem, the problem is no money."), + audio::VOICE_ALLOY.to_string(), + String::from("examples/data/problem.mp3"), + ); + + let result = client.audio_speech(req).await?; + println!("{:?}", result); + + Ok(()) +} + +// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example audio_speech diff --git a/examples/audio_transcriptions.rs b/examples/audio_transcriptions.rs new file mode 100644 index 0000000..5a495c8 --- /dev/null +++ b/examples/audio_transcriptions.rs @@ -0,0 +1,20 @@ +use openai_api_rs::v1::api::OpenAIClient; +use openai_api_rs::v1::audio::{AudioTranscriptionRequest, WHISPER_1}; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); + + let req = AudioTranscriptionRequest::new( + "examples/data/problem.mp3".to_string(), + WHISPER_1.to_string(), + ); + + let result = client.audio_transcription(req).await?; + println!("{:?}", result); + + Ok(()) +} + +// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example audio_translations diff --git a/examples/audio_translations.rs b/examples/audio_translations.rs new file mode 100644 index 0000000..89bf87c --- /dev/null +++ b/examples/audio_translations.rs @@ -0,0 +1,20 @@ +use openai_api_rs::v1::api::OpenAIClient; +use openai_api_rs::v1::audio::{AudioTranslationRequest, WHISPER_1}; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); + + let req = AudioTranslationRequest::new( + "examples/data/problem_cn.mp3".to_string(), + WHISPER_1.to_string(), + ); + + let result = client.audio_translation(req).await?; + println!("{:?}", result); + + Ok(()) +} + +// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example audio_transcriptions diff --git a/examples/chat_completion.rs b/examples/chat_completion.rs index dfdabb4..d53134f 100644 --- a/examples/chat_completion.rs +++ b/examples/chat_completion.rs @@ -1,10 +1,11 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest}; use openai_api_rs::v1::common::GPT4_O; use std::env; -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let req = ChatCompletionRequest::new( GPT4_O.to_string(), @@ -15,7 +16,7 @@ fn main() -> Result<(), Box> { }], ); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; println!("Content: {:?}", result.choices[0].message.content); println!("Response Headers: {:?}", result.headers); diff --git a/examples/completion.rs b/examples/completion.rs index 362d9b7..e0fab80 100644 --- a/examples/completion.rs +++ b/examples/completion.rs @@ -1,9 +1,10 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::completion::{self, CompletionRequest}; use std::env; -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let req = CompletionRequest::new( completion::GPT3_TEXT_DAVINCI_003.to_string(), @@ -16,7 +17,7 @@ fn main() -> Result<(), Box> { .presence_penalty(0.6) .frequency_penalty(0.0); - let result = client.completion(req)?; + let result = client.completion(req).await?; println!("{:}", result.choices[0].text); Ok(()) diff --git a/examples/data/problem.mp3 b/examples/data/problem.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..9fce89ac0f99ce3ec148b002fcbc2a5adc23425a GIT binary patch literal 61440 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 YjG5b+nbT6r`Cr#m|5@hw|NY~?0OcFUAOHXW literal 0 HcmV?d00001 diff --git a/examples/data/problem_cn.mp3 b/examples/data/problem_cn.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..2a993a09a027ffbb99468c8354e19ce3beebb035 GIT binary patch literal 45120 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 Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let mut req = EmbeddingRequest::new(TEXT_EMBEDDING_3_SMALL.to_string(), "story time".to_string()); req.dimensions = Some(10); - let result = client.embedding(req)?; + let result = client.embedding(req).await?; println!("{:?}", result.data); Ok(()) diff --git a/examples/function_call.rs b/examples/function_call.rs index 335be7b..27c6375 100644 --- a/examples/function_call.rs +++ b/examples/function_call.rs @@ -1,6 +1,6 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest}; -use openai_api_rs::v1::common::GPT3_5_TURBO_0613; +use openai_api_rs::v1::common::GPT4_O; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::{env, vec}; @@ -14,8 +14,9 @@ fn get_coin_price(coin: &str) -> f64 { } } -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let mut properties = HashMap::new(); properties.insert( @@ -28,7 +29,7 @@ fn main() -> Result<(), Box> { ); let req = ChatCompletionRequest::new( - GPT3_5_TURBO_0613.to_string(), + GPT4_O.to_string(), vec![chat_completion::ChatCompletionMessage { role: chat_completion::MessageRole::user, content: chat_completion::Content::Text(String::from("What is the price of Ethereum?")), @@ -53,7 +54,7 @@ fn main() -> Result<(), Box> { // let serialized = serde_json::to_string(&req).unwrap(); // println!("{}", serialized); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; match result.choices[0].finish_reason { None => { diff --git a/examples/function_call_role.rs b/examples/function_call_role.rs index eb55dd7..dcdf7ad 100644 --- a/examples/function_call_role.rs +++ b/examples/function_call_role.rs @@ -1,6 +1,6 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest}; -use openai_api_rs::v1::common::GPT3_5_TURBO_0613; +use openai_api_rs::v1::common::GPT4_O; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::{env, vec}; @@ -14,8 +14,9 @@ fn get_coin_price(coin: &str) -> f64 { } } -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let mut properties = HashMap::new(); properties.insert( @@ -28,7 +29,7 @@ fn main() -> Result<(), Box> { ); let req = ChatCompletionRequest::new( - GPT3_5_TURBO_0613.to_string(), + GPT4_O.to_string(), vec![chat_completion::ChatCompletionMessage { role: chat_completion::MessageRole::user, content: chat_completion::Content::Text(String::from("What is the price of Ethereum?")), @@ -48,7 +49,7 @@ fn main() -> Result<(), Box> { }, }]); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; match result.choices[0].finish_reason { None => { @@ -79,7 +80,7 @@ fn main() -> Result<(), Box> { println!("price: {}", price); let req = ChatCompletionRequest::new( - GPT3_5_TURBO_0613.to_string(), + GPT4_O.to_string(), vec![ chat_completion::ChatCompletionMessage { role: chat_completion::MessageRole::user, @@ -99,7 +100,7 @@ fn main() -> Result<(), Box> { ], ); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; println!("{:?}", result.choices[0].message.content); } } diff --git a/examples/text_to_speech.rs b/examples/text_to_speech.rs deleted file mode 100644 index 43b5c4c..0000000 --- a/examples/text_to_speech.rs +++ /dev/null @@ -1,21 +0,0 @@ -use openai_api_rs::v1::api::Client; -use openai_api_rs::v1::audio::{self, AudioSpeechRequest, TTS_1}; -use std::env; - -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); - - let req = AudioSpeechRequest::new( - TTS_1.to_string(), - String::from("Money is not problem, Problem is no money"), - audio::VOICE_ALLOY.to_string(), - String::from("problem.mp3"), - ); - - let result = client.audio_speech(req)?; - println!("{:?}", result); - - Ok(()) -} - -// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example text_to_speech diff --git a/examples/vision.rs b/examples/vision.rs index 195c4c0..b62a653 100644 --- a/examples/vision.rs +++ b/examples/vision.rs @@ -1,10 +1,11 @@ -use openai_api_rs::v1::api::Client; +use openai_api_rs::v1::api::OpenAIClient; use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest}; use openai_api_rs::v1::common::GPT4_VISION_PREVIEW; use std::env; -fn main() -> Result<(), Box> { - let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string()); +#[tokio::main] +async fn main() -> Result<(), Box> { + let client = OpenAIClient::new(env::var("OPENAI_API_KEY").unwrap().to_string()); let req = ChatCompletionRequest::new( GPT4_VISION_PREVIEW.to_string(), @@ -30,7 +31,7 @@ fn main() -> Result<(), Box> { }], ); - let result = client.chat_completion(req)?; + let result = client.chat_completion(req).await?; println!("{:?}", result.choices[0].message.content); Ok(()) diff --git a/src/v1/api.rs b/src/v1/api.rs index 7b520bc..1f3cf66 100644 --- a/src/v1/api.rs +++ b/src/v1/api.rs @@ -36,14 +36,19 @@ use crate::v1::run::{ }; use crate::v1::thread::{CreateThreadRequest, ModifyThreadRequest, ThreadObject}; -use minreq::Response; +use reqwest::multipart::{Form, Part}; +use reqwest::{Client, Method, Response}; +use serde::Serialize; +use serde_json::Value; + use std::fs::{create_dir_all, File}; +use std::io::Read; use std::io::Write; use std::path::Path; const API_URL_V1: &str = "https://api.openai.com/v1"; -pub struct Client { +pub struct OpenAIClient { pub api_endpoint: String, pub api_key: String, pub organization: Option, @@ -51,7 +56,7 @@ pub struct Client { pub timeout: Option, } -impl Client { +impl OpenAIClient { pub fn new(api_key: String) -> Self { let endpoint = std::env::var("OPENAI_API_BASE").unwrap_or_else(|_| API_URL_V1.to_owned()); Self::new_with_endpoint(endpoint, api_key) @@ -72,7 +77,7 @@ impl Client { Self { api_endpoint: endpoint, api_key, - organization: organization.into(), + organization: Some(organization), proxy: None, timeout: None, } @@ -100,536 +105,336 @@ impl Client { } } - pub fn build_request(&self, request: minreq::Request, is_beta: bool) -> minreq::Request { - let mut request = request - .with_header("Content-Type", "application/json") - .with_header("Authorization", format!("Bearer {}", self.api_key)); + async fn build_request(&self, method: Method, path: &str) -> reqwest::RequestBuilder { + let url = format!("{}/{}", self.api_endpoint, path); + let client = Client::builder(); + + let client = if let Some(timeout) = self.timeout { + client.timeout(std::time::Duration::from_secs(timeout)) + } else { + client + }; + + let client = if let Some(proxy) = &self.proxy { + client.proxy(reqwest::Proxy::http(proxy).unwrap()) + } else { + client + }; + + let client = client.build().unwrap(); + + let mut request = client + .request(method, url) + // .header("Content-Type", "application/json") + .header("Authorization", format!("Bearer {}", self.api_key)); + if let Some(organization) = &self.organization { - request = request.with_header("openai-organization", organization); + request = request.header("openai-organization", organization); } - if is_beta { - request = request.with_header("OpenAI-Beta", "assistants=v2"); - } - if let Some(proxy) = &self.proxy { - request = request.with_proxy(minreq::Proxy::new(proxy).unwrap()); - } - if let Some(timeout) = self.timeout { - request = request.with_timeout(timeout); + + if Self::is_beta(path) { + request = request.header("OpenAI-Beta", "assistants=v2"); } + request } - pub fn post( + async fn post( &self, path: &str, - params: &T, - ) -> Result { - let url = format!( - "{api_endpoint}{path}", - api_endpoint = self.api_endpoint, - path = path - ); - let request = self.build_request(minreq::post(url), Self::is_beta(path)); - let res = request.with_json(params).unwrap().send(); - match res { - Ok(res) => { - if (200..=299).contains(&res.status_code) { - Ok(res) - } else { - Err(APIError { - message: format!("{}: {}", res.status_code, res.as_str().unwrap()), - }) - } - } - Err(e) => Err(self.new_error(e)), + body: &impl serde::ser::Serialize, + ) -> Result { + let request = self.build_request(Method::POST, path).await; + let request = request.json(body); + let response = request.send().await?; + self.handle_response(response).await + } + + async fn get(&self, path: &str) -> Result { + let request = self.build_request(Method::GET, path).await; + let response = request.send().await?; + self.handle_response(response).await + } + + async fn delete(&self, path: &str) -> Result { + let request = self.build_request(Method::DELETE, path).await; + let response = request.send().await?; + self.handle_response(response).await + } + + async fn post_form( + &self, + path: &str, + form: Form, + ) -> Result { + let request = self.build_request(Method::POST, path).await; + let request = request.multipart(form); + let response = request.send().await?; + self.handle_response(response).await + } + + async fn handle_response( + &self, + response: Response, + ) -> Result { + let status = response.status(); + if status.is_success() { + let parsed = response.json::().await?; + Ok(parsed) + } else { + let error_message = response + .text() + .await + .unwrap_or_else(|_| "Unknown error".to_string()); + Err(APIError::CustomError { + message: format!("{}: {}", status, error_message), + }) } } - pub fn get(&self, path: &str) -> Result { - let url = format!( - "{api_endpoint}{path}", - api_endpoint = self.api_endpoint, - path = path - ); - let request = self.build_request(minreq::get(url), Self::is_beta(path)); - let res = request.send(); - match res { - Ok(res) => { - if (200..=299).contains(&res.status_code) { - Ok(res) - } else { - Err(APIError { - message: format!("{}: {}", res.status_code, res.as_str().unwrap()), - }) - } - } - Err(e) => Err(self.new_error(e)), - } + pub async fn completion(&self, req: CompletionRequest) -> Result { + self.post("completions", &req).await } - pub fn delete(&self, path: &str) -> Result { - let url = format!( - "{api_endpoint}{path}", - api_endpoint = self.api_endpoint, - path = path - ); - let request = self.build_request(minreq::delete(url), Self::is_beta(path)); - let res = request.send(); - match res { - Ok(res) => { - if (200..=299).contains(&res.status_code) { - Ok(res) - } else { - Err(APIError { - message: format!("{}: {}", res.status_code, res.as_str().unwrap()), - }) - } - } - Err(e) => Err(self.new_error(e)), - } + pub async fn edit(&self, req: EditRequest) -> Result { + self.post("edits", &req).await } - pub fn completion(&self, req: CompletionRequest) -> Result { - let res = self.post("/completions", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } - } - - pub fn edit(&self, req: EditRequest) -> Result { - let res = self.post("/edits", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } - } - - pub fn image_generation( + pub async fn image_generation( &self, req: ImageGenerationRequest, ) -> Result { - let res = self.post("/images/generations", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("images/generations", &req).await } - pub fn image_edit(&self, req: ImageEditRequest) -> Result { - let res = self.post("/images/edits", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn image_edit(&self, req: ImageEditRequest) -> Result { + self.post("images/edits", &req).await } - pub fn image_variation( + pub async fn image_variation( &self, req: ImageVariationRequest, ) -> Result { - let res = self.post("/images/variations", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("images/variations", &req).await } - pub fn embedding(&self, req: EmbeddingRequest) -> Result { - let res = self.post("/embeddings", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn embedding(&self, req: EmbeddingRequest) -> Result { + self.post("embeddings", &req).await } - pub fn file_list(&self) -> Result { - let res = self.get("/files")?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn file_list(&self) -> Result { + self.get("files").await } - pub fn file_upload(&self, req: FileUploadRequest) -> Result { - let res = self.post("/files", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn file_upload( + &self, + req: FileUploadRequest, + ) -> Result { + self.post("files", &req).await } - pub fn file_delete(&self, req: FileDeleteRequest) -> Result { - let res = self.delete(&format!("{}/{}", "/files", req.file_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn file_delete( + &self, + req: FileDeleteRequest, + ) -> Result { + self.delete(&format!("files/{}", req.file_id)).await } - pub fn file_retrieve( + pub async fn file_retrieve( &self, req: FileRetrieveRequest, ) -> Result { - let res = self.get(&format!("{}/{}", "/files", req.file_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get(&format!("files/{}", req.file_id)).await } - pub fn file_retrieve_content( + pub async fn file_retrieve_content( &self, req: FileRetrieveContentRequest, ) -> Result { - let res = self.get(&format!("{}/{}/content", "/files", req.file_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get(&format!("files/{}/content", req.file_id)).await } - pub fn chat_completion( + pub async fn chat_completion( &self, req: ChatCompletionRequest, ) -> Result { - let res = self.post("/chat/completions", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("chat/completions", &req).await } - pub fn audio_transcription( + pub async fn audio_transcription( &self, req: AudioTranscriptionRequest, ) -> Result { - let res = self.post("/audio/transcriptions", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let form = Self::create_form(&req, "file")?; + self.post_form("audio/transcriptions", form).await } - pub fn audio_translation( + pub async fn audio_translation( &self, req: AudioTranslationRequest, ) -> Result { - let res = self.post("/audio/translations", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let form = Self::create_form(&req, "file")?; + self.post_form("audio/translations", form).await } - pub fn audio_speech(&self, req: AudioSpeechRequest) -> Result { - let res = self.post("/audio/speech", &req)?; - let bytes = res.as_bytes(); - let path = req.output.as_str(); - let path = Path::new(path); + pub async fn audio_speech( + &self, + req: AudioSpeechRequest, + ) -> Result { + let request = self.build_request(Method::POST, "audio/speech").await; + let request = request.json(&req); + let response = request.send().await?; + let headers = response.headers().clone(); + let bytes = response.bytes().await?; + let path = Path::new(req.output.as_str()); if let Some(parent) = path.parent() { match create_dir_all(parent) { Ok(_) => {} Err(e) => { - return Err(APIError { + return Err(APIError::CustomError { message: e.to_string(), }) } } } match File::create(path) { - Ok(mut file) => match file.write_all(bytes) { + Ok(mut file) => match file.write_all(&bytes) { Ok(_) => {} Err(e) => { - return Err(APIError { + return Err(APIError::CustomError { message: e.to_string(), }) } }, Err(e) => { - return Err(APIError { + return Err(APIError::CustomError { message: e.to_string(), }) } } + Ok(AudioSpeechResponse { result: true, - headers: Some(res.headers), + headers: Some(headers), }) } - pub fn create_fine_tuning_job( + pub async fn create_fine_tuning_job( &self, req: CreateFineTuningJobRequest, ) -> Result { - let res = self.post("/fine_tuning/jobs", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("fine_tuning/jobs", &req).await } - pub fn list_fine_tuning_jobs( + pub async fn list_fine_tuning_jobs( &self, ) -> Result, APIError> { - let res = self.get("/fine_tuning/jobs")?; - let r = res.json::>(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get("fine_tuning/jobs").await } - pub fn list_fine_tuning_job_events( + pub async fn list_fine_tuning_job_events( &self, req: ListFineTuningJobEventsRequest, ) -> Result, APIError> { - let res = self.get(&format!( - "/fine_tuning/jobs/{}/events", + self.get(&format!( + "fine_tuning/jobs/{}/events", req.fine_tuning_job_id - ))?; - let r = res.json::>(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + )) + .await } - pub fn retrieve_fine_tuning_job( + pub async fn retrieve_fine_tuning_job( &self, req: RetrieveFineTuningJobRequest, ) -> Result { - let res = self.get(&format!("/fine_tuning/jobs/{}", req.fine_tuning_job_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get(&format!("fine_tuning/jobs/{}", req.fine_tuning_job_id)) + .await } - pub fn cancel_fine_tuning_job( + pub async fn cancel_fine_tuning_job( &self, req: CancelFineTuningJobRequest, ) -> Result { - let res = self.post( - &format!("/fine_tuning/jobs/{}/cancel", req.fine_tuning_job_id), + self.post( + &format!("fine_tuning/jobs/{}/cancel", req.fine_tuning_job_id), &req, - )?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + ) + .await } - pub fn create_moderation( + pub async fn create_moderation( &self, req: CreateModerationRequest, ) -> Result { - let res = self.post("/moderations", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("moderations", &req).await } - pub fn create_assistant(&self, req: AssistantRequest) -> Result { - let res = self.post("/assistants", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn create_assistant( + &self, + req: AssistantRequest, + ) -> Result { + self.post("assistants", &req).await } - pub fn retrieve_assistant(&self, assistant_id: String) -> Result { - let res = self.get(&format!("/assistants/{}", assistant_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn retrieve_assistant( + &self, + assistant_id: String, + ) -> Result { + self.get(&format!("assistants/{}", assistant_id)).await } - pub fn modify_assistant( + pub async fn modify_assistant( &self, assistant_id: String, req: AssistantRequest, ) -> Result { - let res = self.post(&format!("/assistants/{}", assistant_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("assistants/{}", assistant_id), &req) + .await } - pub fn delete_assistant(&self, assistant_id: String) -> Result { - let res = self.delete(&format!("/assistants/{}", assistant_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn delete_assistant(&self, assistant_id: String) -> Result { + self.delete(&format!("assistants/{}", assistant_id)).await } - pub fn list_assistant( + pub async fn list_assistant( &self, limit: Option, order: Option, after: Option, before: Option, ) -> Result { - let mut url = "/assistants".to_owned(); - url = Self::query_params(limit, order, after, before, url); - let res = self.get(&url)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let url = Self::query_params(limit, order, after, before, "assistants".to_string()); + self.get(&url).await } - pub fn create_assistant_file( + pub async fn create_assistant_file( &self, assistant_id: String, req: AssistantFileRequest, ) -> Result { - let res = self.post(&format!("/assistants/{}/files", assistant_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("assistants/{}/files", assistant_id), &req) + .await } - pub fn retrieve_assistant_file( + pub async fn retrieve_assistant_file( &self, assistant_id: String, file_id: String, ) -> Result { - let res = self.get(&format!("/assistants/{}/files/{}", assistant_id, file_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get(&format!("assistants/{}/files/{}", assistant_id, file_id)) + .await } - pub fn delete_assistant_file( + pub async fn delete_assistant_file( &self, assistant_id: String, file_id: String, ) -> Result { - let res = self.delete(&format!("/assistants/{}/files/{}", assistant_id, file_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.delete(&format!("assistants/{}/files/{}", assistant_id, file_id)) + .await } - pub fn list_assistant_file( + pub async fn list_assistant_file( &self, assistant_id: String, limit: Option, @@ -637,156 +442,85 @@ impl Client { after: Option, before: Option, ) -> Result { - let mut url = format!("/assistants/{}/files", assistant_id); - url = Self::query_params(limit, order, after, before, url); - let res = self.get(&url)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let url = Self::query_params( + limit, + order, + after, + before, + format!("assistants/{}/files", assistant_id), + ); + self.get(&url).await } - pub fn create_thread(&self, req: CreateThreadRequest) -> Result { - let res = self.post("/threads", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn create_thread(&self, req: CreateThreadRequest) -> Result { + self.post("threads", &req).await } - pub fn retrieve_thread(&self, thread_id: String) -> Result { - let res = self.get(&format!("/threads/{}", thread_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn retrieve_thread(&self, thread_id: String) -> Result { + self.get(&format!("threads/{}", thread_id)).await } - pub fn modify_thread( + pub async fn modify_thread( &self, thread_id: String, req: ModifyThreadRequest, ) -> Result { - let res = self.post(&format!("/threads/{}", thread_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("threads/{}", thread_id), &req).await } - pub fn delete_thread(&self, thread_id: String) -> Result { - let res = self.delete(&format!("/threads/{}", thread_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn delete_thread(&self, thread_id: String) -> Result { + self.delete(&format!("threads/{}", thread_id)).await } - pub fn create_message( + pub async fn create_message( &self, thread_id: String, req: CreateMessageRequest, ) -> Result { - let res = self.post(&format!("/threads/{}/messages", thread_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("threads/{}/messages", thread_id), &req) + .await } - pub fn retrieve_message( + pub async fn retrieve_message( &self, thread_id: String, message_id: String, ) -> Result { - let res = self.get(&format!("/threads/{}/messages/{}", thread_id, message_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.get(&format!("threads/{}/messages/{}", thread_id, message_id)) + .await } - pub fn modify_message( + pub async fn modify_message( &self, thread_id: String, message_id: String, req: ModifyMessageRequest, ) -> Result { - let res = self.post( - &format!("/threads/{}/messages/{}", thread_id, message_id), + self.post( + &format!("threads/{}/messages/{}", thread_id, message_id), &req, - )?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + ) + .await } - pub fn list_messages(&self, thread_id: String) -> Result { - let res = self.get(&format!("/threads/{}/messages", thread_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn list_messages(&self, thread_id: String) -> Result { + self.get(&format!("threads/{}/messages", thread_id)).await } - pub fn retrieve_message_file( + pub async fn retrieve_message_file( &self, thread_id: String, message_id: String, file_id: String, ) -> Result { - let res = self.get(&format!( - "/threads/{}/messages/{}/files/{}", + self.get(&format!( + "threads/{}/messages/{}/files/{}", thread_id, message_id, file_id - ))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + )) + .await } - pub fn list_message_file( + pub async fn list_message_file( &self, thread_id: String, message_id: String, @@ -795,65 +529,45 @@ impl Client { after: Option, before: Option, ) -> Result { - let mut url = format!("/threads/{}/messages/{}/files", thread_id, message_id); - url = Self::query_params(limit, order, after, before, url); - let res = self.get(&url)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let url = Self::query_params( + limit, + order, + after, + before, + format!("threads/{}/messages/{}/files", thread_id, message_id), + ); + self.get(&url).await } - pub fn create_run( + pub async fn create_run( &self, thread_id: String, req: CreateRunRequest, ) -> Result { - let res = self.post(&format!("/threads/{}/runs", thread_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("threads/{}/runs", thread_id), &req) + .await } - pub fn retrieve_run(&self, thread_id: String, run_id: String) -> Result { - let res = self.get(&format!("/threads/{}/runs/{}", thread_id, run_id))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn retrieve_run( + &self, + thread_id: String, + run_id: String, + ) -> Result { + self.get(&format!("threads/{}/runs/{}", thread_id, run_id)) + .await } - pub fn modify_run( + pub async fn modify_run( &self, thread_id: String, run_id: String, req: ModifyRunRequest, ) -> Result { - let res = self.post(&format!("/threads/{}/runs/{}", thread_id, run_id), &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post(&format!("threads/{}/runs/{}", thread_id, run_id), &req) + .await } - pub fn list_run( + pub async fn list_run( &self, thread_id: String, limit: Option, @@ -861,71 +575,49 @@ impl Client { after: Option, before: Option, ) -> Result { - let mut url = format!("/threads/{}/runs", thread_id); - url = Self::query_params(limit, order, after, before, url); - let res = self.get(&url)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + let url = Self::query_params( + limit, + order, + after, + before, + format!("threads/{}/runs", thread_id), + ); + self.get(&url).await } - pub fn cancel_run(&self, thread_id: String, run_id: String) -> Result { - let empty_req = ModifyRunRequest::new(); - let res = self.post( - &format!("/threads/{}/runs/{}/cancel", thread_id, run_id), - &empty_req, - )?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + pub async fn cancel_run( + &self, + thread_id: String, + run_id: String, + ) -> Result { + self.post( + &format!("threads/{}/runs/{}/cancel", thread_id, run_id), + &ModifyRunRequest::default(), + ) + .await } - pub fn create_thread_and_run( + pub async fn create_thread_and_run( &self, req: CreateThreadAndRunRequest, ) -> Result { - let res = self.post("/threads/runs", &req)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + self.post("threads/runs", &req).await } - pub fn retrieve_run_step( + pub async fn retrieve_run_step( &self, thread_id: String, run_id: String, step_id: String, ) -> Result { - let res = self.get(&format!( - "/threads/{}/runs/{}/steps/{}", + self.get(&format!( + "threads/{}/runs/{}/steps/{}", thread_id, run_id, step_id - ))?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } + )) + .await } - pub fn list_run_step( + pub async fn list_run_step( &self, thread_id: String, run_id: String, @@ -934,27 +626,14 @@ impl Client { after: Option, before: Option, ) -> Result { - let mut url = format!("/threads/{}/runs/{}/steps", thread_id, run_id); - url = Self::query_params(limit, order, after, before, url); - let res = self.get(&url)?; - let r = res.json::(); - match r { - Ok(mut r) => { - r.headers = Some(res.headers); - Ok(r) - } - Err(e) => Err(self.new_error(e)), - } - } - - fn new_error(&self, err: minreq::Error) -> APIError { - APIError { - message: err.to_string(), - } - } - - fn is_beta(path: &str) -> bool { - path.starts_with("/assistants") || path.starts_with("/threads") + let url = Self::query_params( + limit, + order, + after, + before, + format!("threads/{}/runs/{}/steps", thread_id, run_id), + ); + self.get(&url).await } fn query_params( @@ -982,4 +661,72 @@ impl Client { } url } + + fn is_beta(path: &str) -> bool { + path.starts_with("assistants") || path.starts_with("threads") + } + + fn create_form(req: &T, file_field: &str) -> Result + where + T: Serialize, + { + let json = match serde_json::to_value(req) { + Ok(json) => json, + Err(e) => { + return Err(APIError::CustomError { + message: e.to_string(), + }) + } + }; + let file_path = if let Value::Object(map) = &json { + map.get(file_field) + .and_then(|v| v.as_str()) + .ok_or(APIError::CustomError { + message: format!("Field '{}' not found or not a string", file_field), + })? + } else { + return Err(APIError::CustomError { + message: "Request is not a JSON object".to_string(), + }); + }; + + let mut file = match File::open(file_path) { + Ok(file) => file, + Err(e) => { + return Err(APIError::CustomError { + message: e.to_string(), + }) + } + }; + let mut buffer = Vec::new(); + match file.read_to_end(&mut buffer) { + Ok(_) => {} + Err(e) => { + return Err(APIError::CustomError { + message: e.to_string(), + }) + } + } + + let mut form = + Form::new().part("file", Part::bytes(buffer).file_name(file_path.to_string())); + + if let Value::Object(map) = json { + for (key, value) in map.into_iter() { + if key != file_field { + match value { + Value::String(s) => { + form = form.text(key, s); + } + Value::Number(n) => { + form = form.text(key, n.to_string()); + } + _ => {} + } + } + } + } + + Ok(form) + } } diff --git a/src/v1/audio.rs b/src/v1/audio.rs index 07e53bd..b2c87f8 100644 --- a/src/v1/audio.rs +++ b/src/v1/audio.rs @@ -1,6 +1,6 @@ -use std::collections::HashMap; - +use reqwest::header::HeaderMap; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use crate::impl_builder_methods; @@ -115,8 +115,8 @@ impl AudioSpeechRequest { impl_builder_methods!(AudioSpeechRequest,); -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug)] pub struct AudioSpeechResponse { pub result: bool, - pub headers: Option>, + pub headers: Option, } diff --git a/src/v1/error.rs b/src/v1/error.rs index b2d2bf0..d1625a2 100644 --- a/src/v1/error.rs +++ b/src/v1/error.rs @@ -1,15 +1,26 @@ +use reqwest::{self}; use std::error::Error; use std::fmt; #[derive(Debug)] -pub struct APIError { - pub message: String, +pub enum APIError { + ReqwestError(reqwest::Error), + CustomError { message: String }, } impl fmt::Display for APIError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "APIError: {}", self.message) + match self { + APIError::ReqwestError(err) => write!(f, "ReqwestError: {}", err), + APIError::CustomError { message } => write!(f, "APIError: {}", message), + } } } impl Error for APIError {} + +impl From for APIError { + fn from(err: reqwest::Error) -> APIError { + APIError::ReqwestError(err) + } +}