deepseek_api/async_impl/client.rs
1use super::error::ToApiError;
2use super::json_stream::JsonStream;
3use crate::{
4 response::{BalanceResp, ChatResponse, ModelResp},
5 RequestBuilder,
6};
7use anyhow::Result;
8use reqwest::Client as ReqwestClient;
9
10#[derive(Clone)]
11/// A client for interacting with the DeepSeek API.
12///
13/// # Example
14///
15/// ```no_run
16/// #[tokio::main]
17/// async fn main() {
18/// use deepseek_api::DeepSeekClientBuilder;
19///
20/// let api_key = "your_api_key".to_string();
21/// let client = DeepSeekClientBuilder::new(api_key).build().unwrap();
22///
23/// // Get available models
24/// let models = client.models().await.unwrap();
25///
26/// // Get user balance
27/// let balance = client.balance().await.unwrap();
28/// }
29/// ```
30///
31/// # Fields
32///
33/// * `client` - The underlying HTTP client.
34/// * `host` - The base URL for the DeepSeek API.
35pub struct DeepSeekClient {
36 pub(crate) client: ReqwestClient,
37 pub(crate) host: String,
38}
39
40impl DeepSeekClient {
41 /// Retrieves the list of available models from the DeepSeek API.
42 ///
43 /// This method sends a GET request to the `/models` endpoint of the DeepSeek API
44 /// and returns a `Result` containing a `ModelResp` on success.
45 ///
46 /// # Errors
47 ///
48 /// This function will return an error if the request fails or if the response
49 /// cannot be deserialized into a `ModelResp`.
50 ///
51 /// # Example
52 ///
53 /// ```no_run
54 /// #[tokio::main]
55 /// async fn main() {
56 /// use deepseek_api::DeepSeekClientBuilder;
57 ///
58 /// let api_key = "your_api_key".to_string();
59 /// let client = DeepSeekClientBuilder::new(api_key).build().unwrap();
60 /// let models = client.models().await.unwrap();
61 /// println!("{:?}", models);
62 /// }
63 /// ```
64 ///
65 /// For more information, see the [DeepSeek API documentation](https://api-docs.deepseek.com/zh-cn/api/list-models).
66 pub async fn models(&self) -> Result<ModelResp> {
67 Ok(self
68 .client
69 .get(self.host.to_owned() + "/models")
70 .send()
71 .await?
72 .json()
73 .await?)
74 }
75
76 /// Retrieves the balance information of the user from the DeepSeek API.
77 ///
78 /// This method sends a GET request to the `/user/balance` endpoint of the DeepSeek API
79 /// and returns a `Result` containing a `BalanceResp` on success.
80 ///
81 /// # Errors
82 ///
83 /// This function will return an error if the request fails or if the response
84 /// cannot be deserialized into a `BalanceResp`.
85 ///
86 /// # Example
87 ///
88 /// ```no_run
89 /// #[tokio::main]
90 /// async fn main() {
91 /// use deepseek_api::DeepSeekClientBuilder;
92 ///
93 /// let api_key = "your_api_key".to_string();
94 /// let client = DeepSeekClientBuilder::new(api_key).build().unwrap();
95 /// let balance = client.balance().await.unwrap();
96 /// println!("{:?}", balance);
97 /// }
98 /// ```
99 ///
100 /// For more information, see the [DeepSeek API documentation](https://api-docs.deepseek.com/zh-cn/api/get-user-balance).
101 pub async fn balance(&self) -> Result<BalanceResp> {
102 Ok(self
103 .client
104 .get(self.host.to_owned() + "/user/balance")
105 .send()
106 .await?
107 .json()
108 .await?)
109 }
110
111 /// Sends a completion request to the DeepSeek API.
112 ///
113 /// This method constructs a request using the provided `RequestBuilder` and sends it
114 /// to the appropriate endpoint of the DeepSeek API. Depending on whether the request
115 /// is for a beta feature or not, it will target either the `/beta/completions` or
116 /// `/chat/completions` endpoint. The response can be either a full response or a
117 /// streaming response, based on the `stream` optional of the `RequestBuilder`.
118 ///
119 /// # Type Parameters
120 ///
121 /// * `Builder` - A type that implements the `RequestBuilder` trait, used to construct
122 /// the request payload.
123 ///
124 /// # Arguments
125 ///
126 /// * `request_builder` - An instance of a type implementing the `RequestBuilder` trait,
127 /// which is used to build the request payload.
128 ///
129 /// # Returns
130 ///
131 /// A `Result` containing a `ChatResponse` on success. The `ChatResponse` can either be
132 /// a full response or a streaming response, depending on the request.
133 ///
134 /// # Errors
135 ///
136 /// This function will return an error if:
137 /// - The request fails to send.
138 /// - The response contains an API error.
139 /// - The response cannot be deserialized into the expected type.
140 ///
141 /// # Example
142 ///
143 /// ```no_run
144 /// #[tokio::main]
145 /// async fn main() {
146 /// use deepseek_api::{request::MessageRequest, DeepSeekClientBuilder, CompletionsRequestBuilder};
147 /// use deepseek_api::response::ChatResponse;
148 /// use futures_util::StreamExt;
149 ///
150 /// let api_key = "your_api_key".to_string();
151 /// let client = DeepSeekClientBuilder::new(api_key).build().unwrap();
152 /// let msgs = &[MessageRequest::user("Hello, DeepSeek!")];
153 /// let request_builder = CompletionsRequestBuilder::new(msgs);
154 ///
155 /// let response = client.send_completion_request(request_builder).await.unwrap();
156 /// match response {
157 /// ChatResponse::Full(full_response) => println!("{:?}", full_response),
158 /// ChatResponse::Stream(mut stream) => {
159 /// while let Some(item) = stream.next().await {
160 /// println!("{:?}", item);
161 /// }
162 /// }
163 /// }
164 /// }
165 /// ```
166 ///
167 /// For more information, see the [DeepSeek API documentation](https://api-docs.deepseek.com/zh-cn/api).
168 pub async fn send_completion_request<Builder>(
169 &self,
170 request_builder: Builder,
171 ) -> Result<ChatResponse<Builder::Response, Builder::Item>>
172 where
173 Builder: RequestBuilder + Send + Sized,
174 {
175 let host = if request_builder.is_beta() {
176 self.host.to_owned() + "/beta/completions"
177 } else {
178 self.host.to_owned() + "/chat/completions"
179 };
180 let is_stream = request_builder.is_stream();
181
182 let request = request_builder.build();
183 let resp = self
184 .client
185 .post(&host)
186 .json(&request)
187 .send()
188 .await?
189 .to_api_err()
190 .await?;
191 if is_stream {
192 Ok(ChatResponse::Stream(JsonStream::new(resp)))
193 } else {
194 Ok(ChatResponse::Full(resp.json().await?))
195 }
196 }
197}