rusty_openai/
openai.rs

1use crate::{
2    error_handling::OpenAIResult,
3    openai_api::{
4        assistants::AssistantsApi, audio::AudioApi, client::ClientApi, completion::CompletionsApi,
5        embeddings::EmbeddingsApi, fine_tuning::FineTuningApi, images::ImagesApi,
6        moderations::ModerationApi, threads::ThreadsApi, vectors::VectorsApi,
7        projects::ProjectsApi,
8    },
9};
10use reqwest::{multipart::Form, Client};
11use serde::{de::DeserializeOwned, Serialize};
12
13pub struct OpenAI<'a> {
14    pub(crate) client: Client,
15    authorization: String,
16    base_url: &'a str,
17}
18
19impl<'a> OpenAI<'a> {
20    pub fn new(api_key: &str, base_url: &'a str) -> Self {
21        let default_base_url = "https://api.openai.com/v1";
22
23        Self {
24            client: Client::new(),
25            authorization: format!("Bearer {api_key}"),
26            base_url: {
27                if base_url.is_empty() {
28                    default_base_url
29                } else {
30                    base_url
31                }
32            },
33        }
34    }
35
36    pub async fn get<T: DeserializeOwned>(&self, url: &str) -> OpenAIResult<T> {
37        Ok(self
38            .client
39            .get(format!("{}{url}", self.base_url))
40            .header("Authorization", &self.authorization)
41            .send()
42            .await?
43            .json()
44            .await?)
45    }
46
47    pub async fn post_json<B: Serialize + ?Sized, T: DeserializeOwned>(
48        &self,
49        url: &str,
50        body: &B,
51    ) -> OpenAIResult<T> {
52        Ok(self
53            .client
54            .post(format!("{}{url}", self.base_url))
55            .header("Authorization", &self.authorization)
56            .header("Content-Type", "application/json")
57            .json(body)
58            .send()
59            .await?
60            .json()
61            .await?)
62    }
63
64    pub async fn post_form<T: DeserializeOwned>(&self, url: &str, form: Form) -> OpenAIResult<T> {
65        Ok(self
66            .client
67            .post(format!("{}{url}", self.base_url))
68            .header("Authorization", &self.authorization)
69            .multipart(form)
70            .send()
71            .await?
72            .json()
73            .await?)
74    }
75
76    pub async fn delete<T: DeserializeOwned>(&self, url: &str) -> OpenAIResult<T> {
77        Ok(self
78            .client
79            .delete(format!("{}{url}", self.base_url))
80            .header("Authorization", &self.authorization)
81            .send()
82            .await?
83            .json()
84            .await?)
85    }
86
87    pub const fn get_base_url(&self) -> &str {
88        self.base_url
89    }
90
91    pub fn set_base_url(&mut self, base_url: &'a str) {
92        self.base_url = base_url;
93    }
94
95    pub const fn client(&self) -> ClientApi {
96        ClientApi(self)
97    }
98
99    pub const fn completions(&self) -> CompletionsApi {
100        CompletionsApi(self)
101    }
102
103    pub const fn audio(&self) -> AudioApi {
104        AudioApi(self)
105    }
106
107    pub const fn images(&self) -> ImagesApi {
108        ImagesApi(self)
109    }
110
111    pub const fn fine_tuning(&self) -> FineTuningApi {
112        FineTuningApi(self)
113    }
114
115    pub const fn moderation(&self) -> ModerationApi {
116        ModerationApi(self)
117    }
118
119    pub const fn embeddings(&self) -> EmbeddingsApi {
120        EmbeddingsApi(self)
121    }
122
123    pub const fn assistants(&self) -> AssistantsApi {
124        AssistantsApi(self)
125    }
126
127    pub const fn threads(&self) -> ThreadsApi {
128        ThreadsApi(self)
129    }
130
131    pub const fn vectors(&self) -> VectorsApi {
132        VectorsApi(self)
133    }
134
135    pub const fn projects(&self) -> ProjectsApi {
136        ProjectsApi(self)
137    }
138}