Skip to main content

u_sdk/deep_seek/
types.rs

1use crate::deep_seek::Client;
2use bon::Builder;
3use serde::{Deserialize, Serialize};
4
5//region chat body
6#[derive(Builder, Serialize)]
7pub struct Chat<'a> {
8    #[builder(start_fn)]
9    #[serde(skip_serializing)]
10    pub(crate) client: &'a Client,
11    #[builder(field)]
12    stop: Vec<String>,
13    pub(crate) messages: &'a [Message],
14    model: &'a str,
15    frequency_penalty: Option<f32>, // Default 0.0 Possible values: >= -2 and <= 2
16    max_tokens: Option<u32>,        // Default 4096 Possible values: > 1
17    presence_penalty: Option<f32>,  // Default 0.0 Possible values: >= -2 and <= 2
18    response_format: Option<ResponseFormat<'a>>, // Default text
19    #[builder(default = false)]
20    pub(crate) stream: bool,
21    stream_options: Option<StreamOption>,
22    temperature: Option<f32>, // Default 1.0 Possible values: >= 0 and <= 2
23    top_p: Option<f32>,       // Default 1.0 Possible values: <= 1
24    // 下面两个未实现
25    // pub(crate) tools: Option<()>,
26    // #[serde(serialize_with = "serialize_tolls_choices")]
27    // pub(crate) tool_choice: Option<()>,
28    logprobs: Option<bool>,
29    top_logprobs: Option<u32>, // Possible values: >= 0 and <= 20 指定此参数时,logprobs 必须为 true。
30}
31
32#[derive(Serialize, Debug)]
33pub struct Message {
34    pub content: String,
35    pub role: Role,
36}
37
38#[derive(Serialize, Deserialize, PartialEq, Debug)]
39#[serde(rename_all = "lowercase")]
40pub enum Role {
41    System,
42    User,
43    Assistant,
44}
45
46#[derive(Serialize, Debug)]
47pub struct ResponseFormat<'a> {
48    pub r#type: &'a str,
49}
50
51#[derive(Serialize, Debug)]
52pub struct StreamOption {
53    pub include_usage: bool,
54}
55//endregion
56
57// chat response
58#[derive(Debug, Deserialize)]
59pub struct ChatResponse {
60    pub id: String,
61    pub choices: Vec<Choice>,
62    pub created: i64,
63    pub model: String,
64    pub system_fingerprint: String,
65    pub object: String,
66    pub usage: Usage,
67}
68
69#[derive(Debug, Deserialize)]
70pub struct Choice {
71    // logprobs 未实现
72    pub finish_reason: String,
73    pub index: i32,
74    pub message: ChoiceMessage,
75}
76
77#[derive(Debug, Deserialize)]
78pub struct ChoiceMessage {
79    // toll_calls没实现
80    pub content: String,
81    pub role: Role, // Role::Assistant
82    // 仅适用于 deepseek-reasoner 模型。内容为 assistant 消息中在最终答案之前的推理内容。
83    pub reasoning_content: Option<String>,
84}
85
86#[derive(Debug, Deserialize)]
87pub struct Usage {
88    pub completion_tokens: i32,
89    pub prompt_tokens: i32,
90    pub prompt_cache_hit_tokens: i32,
91    pub prompt_cache_miss_tokens: i32,
92    pub total_tokens: i32,
93    pub completion_tokens_details: Option<CompletionTokensDetails>,
94}
95
96#[derive(Debug, Deserialize)]
97pub struct CompletionTokensDetails {
98    pub reasoning_tokens: i32,
99}
100
101#[test]
102fn check_response_deserialize() {
103    let json = r#"
104{
105  "id": "string", "choices": [
106    {
107      "finish_reason": "stop", "index": 0,
108      "message": {
109        "content": "string", "reasoning_content": "string",
110        "tool_calls": [
111          {
112            "id": "string", "type": "function",
113            "function": { "name": "string", "arguments": "string" }
114          }
115        ],
116        "role": "assistant"
117      },
118      "logprobs": {
119        "content": [
120          {
121            "token": "string", "logprob": 0, "bytes": [0],
122            "top_logprobs": [
123              { "token": "string", "logprob": 0, "bytes": [0] }
124            ]
125          }
126        ]
127      }
128    }
129  ],
130  "created": 0, "model": "string", "system_fingerprint": "string",
131  "object": "chat.completion",
132  "usage": {
133    "completion_tokens": 0, "prompt_tokens": 0,
134    "prompt_cache_hit_tokens": 0, "prompt_cache_miss_tokens": 0,
135    "total_tokens": 0,
136    "completion_tokens_details": { "reasoning_tokens": 0 }
137  }
138}
139"#;
140    let response = serde_json::from_str::<ChatResponse>(json);
141    assert!(
142        response.is_ok(),
143        "Failed to deserialize response: {:?}",
144        response.err()
145    );
146}
147
148//region stream event data
149#[derive(Deserialize, Debug)]
150pub struct StreamEventData {
151    pub id: String,
152    pub choices: Vec<StreamDataChoices>,
153    pub created: i64,
154    pub model: String,
155    pub system_fingerprint: String,
156    pub object: String,
157}
158
159#[derive(Deserialize, Debug)]
160pub struct StreamDataChoices {
161    pub delta: Delta,
162    pub finish_reason: Option<String>,
163    pub index: i32,
164}
165
166#[derive(Deserialize, Debug)]
167pub struct Delta {
168    pub content: Option<String>,
169    pub reasoning_content: Option<String>,
170    pub role: Option<Role>,
171}
172
173#[test]
174fn check_stream_event_data_deserialize() {
175    let json1 = r#"
176{
177  "id": "1f633d8bfc032625086f14113c411638",
178  "choices": [
179    {
180      "index": 0,
181      "delta": { "content": "", "role": "assistant" },
182      "finish_reason": null,
183      "logprobs": null
184    }
185  ],
186  "created": 1718345013,
187  "model": "deepseek-chat",
188  "system_fingerprint": "fp_a49d71b8a1",
189  "object": "chat.completion.chunk",
190  "usage": null
191}
192"#;
193    let json2 = r#"
194{
195  "choices": [
196    {
197      "delta": { "content": "", "role": null },
198      "finish_reason": "stop",
199      "index": 0,
200      "logprobs": null
201    }
202  ],
203  "created": 1718345013,
204  "id": "1f633d8bfc032625086f14113c411638",
205  "model": "deepseek-chat",
206  "object": "chat.completion.chunk",
207  "system_fingerprint": "fp_a49d71b8a1",
208  "usage": {
209    "completion_tokens": 9,
210    "prompt_tokens": 17,
211    "total_tokens": 26
212  }
213}
214    "#;
215
216    let response1 = serde_json::from_str::<StreamEventData>(json1);
217    let response2 = serde_json::from_str::<StreamEventData>(json2);
218
219    assert!(
220        response1.is_ok(),
221        "Failed to deserialize response1: {:?}",
222        response1.err()
223    );
224    assert!(
225        response2.is_ok(),
226        "Failed to deserialize response2: {:?}",
227        response2.err()
228    );
229}
230//endregion
231
232#[derive(Deserialize, Debug)]
233pub struct CheckBalanceResponse {
234    pub is_available: bool,
235    pub balance_infos: Vec<BalanceInfo>,
236}
237
238#[derive(Deserialize, Debug)]
239pub struct BalanceInfo {
240    pub currency: String,
241    pub total_balance: String,
242    pub granted_balance: String,
243    pub topped_up_balance: String,
244}