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}