just_deepseek/types/chat/
request.rs1use serde::{Deserialize, Serialize};
2
3use super::{
4 ResponseFormat, StopSequence, StreamOptions, ToolChoice, ToolDefinition,
5 shared::ChatCompletionToolCall,
6};
7
8#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
10pub struct ChatCompletionRequest {
11 pub model: String,
12 pub messages: Vec<ChatMessage>,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub thinking: Option<ThinkingConfig>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub max_tokens: Option<u32>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub response_format: Option<ResponseFormat>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub stop: Option<StopSequence>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub stream: Option<bool>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub stream_options: Option<StreamOptions>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub temperature: Option<f32>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub top_p: Option<f32>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub tools: Option<Vec<ToolDefinition>>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub tool_choice: Option<ToolChoice>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub logprobs: Option<bool>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub top_logprobs: Option<u8>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub reasoning_effort: Option<ReasoningEffort>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub user_id: Option<String>,
41}
42
43impl ChatCompletionRequest {
44 pub fn new(model: impl Into<String>, messages: Vec<ChatMessage>) -> Self {
46 Self {
47 model: model.into(),
48 messages,
49 thinking: None,
50 max_tokens: None,
51 response_format: None,
52 stop: None,
53 stream: None,
54 stream_options: None,
55 temperature: None,
56 top_p: None,
57 tools: None,
58 tool_choice: None,
59 logprobs: None,
60 top_logprobs: None,
61 reasoning_effort: None,
62 user_id: None,
63 }
64 }
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
69#[serde(untagged)]
70pub enum ChatMessage {
71 ToolCalls(ToolCallsMessage),
72 ToolResult(ToolResultMessage),
73 Message(TextMessage),
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
78#[serde(deny_unknown_fields)]
79pub struct TextMessage {
80 pub role: String,
83 pub content: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub name: Option<String>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub reasoning_content: Option<String>,
88}
89
90#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
92#[serde(deny_unknown_fields)]
93pub struct ToolCallsMessage {
94 pub role: String,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub content: Option<String>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub name: Option<String>,
101 pub tool_calls: Vec<ChatCompletionToolCall>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub reasoning_content: Option<String>,
104}
105
106#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
108#[serde(deny_unknown_fields)]
109pub struct ToolResultMessage {
110 pub role: String,
112 pub content: String,
113 pub tool_call_id: String,
114}
115
116impl ChatMessage {
117 pub fn new(role: impl Into<String>, content: impl Into<String>) -> Self {
119 Self::Message(TextMessage {
120 role: role.into(),
121 content: content.into(),
122 name: None,
123 reasoning_content: None,
124 })
125 }
126
127 pub fn named(
129 role: impl Into<String>,
130 content: impl Into<String>,
131 name: impl Into<String>,
132 ) -> Self {
133 Self::Message(TextMessage {
134 role: role.into(),
135 content: content.into(),
136 name: Some(name.into()),
137 reasoning_content: None,
138 })
139 }
140
141 pub fn system(content: impl Into<String>) -> Self {
143 Self::new("system", content)
144 }
145
146 pub fn user(content: impl Into<String>) -> Self {
148 Self::new("user", content)
149 }
150
151 pub fn assistant(content: impl Into<String>) -> Self {
153 Self::new("assistant", content)
154 }
155
156 pub fn assistant_tool_calls(tool_calls: Vec<ChatCompletionToolCall>) -> Self {
158 Self::ToolCalls(ToolCallsMessage {
159 role: "assistant".to_owned(),
160 content: None,
161 name: None,
162 tool_calls,
163 reasoning_content: None,
164 })
165 }
166
167 pub fn assistant_tool_calls_with_content(
169 content: impl Into<String>,
170 tool_calls: Vec<ChatCompletionToolCall>,
171 ) -> Self {
172 Self::ToolCalls(ToolCallsMessage {
173 role: "assistant".to_owned(),
174 content: Some(content.into()),
175 name: None,
176 tool_calls,
177 reasoning_content: None,
178 })
179 }
180
181 pub fn tool_result(content: impl Into<String>, tool_call_id: impl Into<String>) -> Self {
183 Self::ToolResult(ToolResultMessage {
184 role: "tool".to_owned(),
185 content: content.into(),
186 tool_call_id: tool_call_id.into(),
187 })
188 }
189
190 pub fn tool(content: impl Into<String>, tool_call_id: impl Into<String>) -> Self {
192 Self::tool_result(content, tool_call_id)
193 }
194}
195
196#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
198pub struct ThinkingConfig {
199 #[serde(rename = "type")]
200 pub kind: ThinkingMode,
201}
202
203#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
205#[serde(rename_all = "lowercase")]
206pub enum ThinkingMode {
207 Enabled,
208 Disabled,
209}
210
211#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
213#[serde(rename_all = "lowercase")]
214pub enum ReasoningEffort {
215 High,
216 Max,
217}