1use crate::{
2 error::{PromptError, Result},
3 BuildChatPrompt,
4};
5use endpoints::chat::{
6 ChatCompletionAssistantMessage, ChatCompletionRequestMessage, ChatCompletionSystemMessage,
7 ChatCompletionUserMessage, ChatCompletionUserMessageContent, ContentPart,
8};
9
10#[derive(Debug, Default, Clone)]
12pub struct DeepseekChatPrompt;
13impl DeepseekChatPrompt {
14 fn append_user_message(
16 &self,
17 chat_history: impl AsRef<str>,
18 message: &ChatCompletionUserMessage,
19 ) -> String {
20 let content = match message.content() {
21 ChatCompletionUserMessageContent::Text(text) => text.to_string(),
22 ChatCompletionUserMessageContent::Parts(parts) => {
23 let mut content = String::new();
24 for part in parts {
25 if let ContentPart::Text(text_content) = part {
26 content.push_str(text_content.text());
27 content.push('\n');
28 }
29 }
30 content
31 }
32 };
33
34 match chat_history.as_ref().is_empty() {
35 true => format!("User: {user_message}", user_message = content.trim(),),
36 false => format!(
37 "{chat_history}User: {user_message}",
38 chat_history = chat_history.as_ref().trim(),
39 user_message = content.trim(),
40 ),
41 }
42 }
43
44 fn append_assistant_message(
46 &self,
47 chat_history: impl AsRef<str>,
48 message: &ChatCompletionAssistantMessage,
49 ) -> Result<String> {
50 let content = match message.content() {
51 Some(content) => content.to_string(),
52 None => match message.tool_calls().is_some() {
54 true => String::new(),
55 false => return Err(PromptError::NoAssistantMessage),
56 },
57 };
58
59 Ok(format!(
60 "{chat_history}\n\nAssistant: {assistant_message}<|end_of_sentence|>",
61 chat_history = chat_history.as_ref().trim(),
62 assistant_message = content.trim(),
63 ))
64 }
65}
66impl BuildChatPrompt for DeepseekChatPrompt {
67 fn build(&self, messages: &mut Vec<ChatCompletionRequestMessage>) -> Result<String> {
68 if messages.is_empty() {
69 return Err(crate::error::PromptError::NoMessages);
70 }
71
72 let mut prompt = String::new();
74 for message in messages {
75 match message {
76 ChatCompletionRequestMessage::User(message) => {
77 prompt = self.append_user_message(&prompt, message);
78 }
79 ChatCompletionRequestMessage::Assistant(message) => {
80 prompt = self.append_assistant_message(&prompt, message)?;
81 }
82 _ => continue,
83 }
84 }
85
86 prompt.push_str("\n\nAssistant:");
87
88 Ok(prompt)
89 }
90}
91
92#[derive(Debug, Default, Clone)]
94pub struct DeepseekCoderPrompt;
95impl DeepseekCoderPrompt {
96 fn create_system_prompt(&self, message: &ChatCompletionSystemMessage) -> String {
98 let content = message.content();
99 match content.is_empty() {
100 true => String::from("You are an AI programming assistant, utilizing the DeepSeek Coder model, developed by DeepSeek Company, and you only answer questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will refuse to answer."),
101 false => content.to_string(),
102 }
103 }
104
105 fn append_user_message(
107 &self,
108 chat_history: impl AsRef<str>,
109 system_prompt: impl AsRef<str>,
110 message: &ChatCompletionUserMessage,
111 ) -> String {
112 let content = match message.content() {
113 ChatCompletionUserMessageContent::Text(text) => text.to_string(),
114 ChatCompletionUserMessageContent::Parts(parts) => {
115 let mut content = String::new();
116 for part in parts {
117 if let ContentPart::Text(text_content) = part {
118 content.push_str(text_content.text());
119 content.push('\n');
120 }
121 }
122 content
123 }
124 };
125
126 match chat_history.as_ref().is_empty() {
127 true => format!(
128 "{system_prompt}\n### Instruction:\n{user_message}",
129 system_prompt = system_prompt.as_ref().trim(),
130 user_message = content.trim(),
131 ),
132 false => format!(
133 "{chat_history}\n### Instruction:\n{user_message}",
134 chat_history = chat_history.as_ref().trim(),
135 user_message = content.trim(),
136 ),
137 }
138 }
139
140 fn append_assistant_message(
142 &self,
143 chat_history: impl AsRef<str>,
144 message: &ChatCompletionAssistantMessage,
145 ) -> Result<String> {
146 let content = match message.content() {
147 Some(content) => content.to_string(),
148 None => match message.tool_calls().is_some() {
150 true => String::new(),
151 false => return Err(PromptError::NoAssistantMessage),
152 },
153 };
154
155 Ok(format!(
156 "{chat_histroy}\n### Response:\n{assistant_message}\n<|EOT|>",
157 chat_histroy = chat_history.as_ref().trim(),
158 assistant_message = content.trim(),
159 ))
160 }
161}
162impl BuildChatPrompt for DeepseekCoderPrompt {
163 fn build(&self, messages: &mut Vec<ChatCompletionRequestMessage>) -> Result<String> {
164 if messages.is_empty() {
165 return Err(crate::error::PromptError::NoMessages);
166 }
167
168 let system_prompt = match messages[0] {
170 ChatCompletionRequestMessage::System(ref message) => {
171 self.create_system_prompt(message)
172 }
173 _ => String::from("You are an AI programming assistant, utilizing the DeepSeek Coder model, developed by DeepSeek Company, and you only answer questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will refuse to answer."),
174 };
175
176 if messages.is_empty() {
178 return Err(crate::error::PromptError::NoMessages);
179 }
180
181 let mut prompt = String::new();
183 for message in messages {
184 match message {
185 ChatCompletionRequestMessage::User(message) => {
186 prompt = self.append_user_message(&prompt, &system_prompt, message);
187 }
188 ChatCompletionRequestMessage::Assistant(message) => {
189 prompt = self.append_assistant_message(&prompt, message)?;
190 }
191 _ => continue,
192 }
193 }
194
195 prompt.push_str("\n### Response:");
196
197 Ok(prompt)
198 }
199}
200
201#[derive(Debug, Default, Clone)]
203pub struct DeepseekChat2Prompt;
204impl DeepseekChat2Prompt {
205 fn create_system_prompt(&self, message: &ChatCompletionSystemMessage) -> String {
207 let content = message.content();
208 match content.is_empty() {
209 true => String::from("<|begin▁of▁sentence|>You are an AI programming assistant, utilizing the DeepSeek Coder model, developed by DeepSeek Company, and you only answer questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will refuse to answer."),
210 false => format!("<|begin▁of▁sentence|>{content}"),
211 }
212 }
213
214 fn append_user_message(
216 &self,
217 chat_history: impl AsRef<str>,
218 system_prompt: impl AsRef<str>,
219 message: &ChatCompletionUserMessage,
220 ) -> String {
221 let content = match message.content() {
222 ChatCompletionUserMessageContent::Text(text) => text.to_string(),
223 ChatCompletionUserMessageContent::Parts(parts) => {
224 let mut content = String::new();
225 for part in parts {
226 if let ContentPart::Text(text_content) = part {
227 content.push_str(text_content.text());
228 content.push('\n');
229 }
230 }
231 content
232 }
233 };
234
235 match chat_history.as_ref().is_empty() {
236 true => format!(
237 "{system_prompt}\n\nUser: {user_message}",
238 system_prompt = system_prompt.as_ref().trim(),
239 user_message = content.trim(),
240 ),
241 false => format!(
242 "{chat_history}User: {user_message}",
243 chat_history = chat_history.as_ref().trim(),
244 user_message = content.trim(),
245 ),
246 }
247 }
248
249 fn append_assistant_message(
251 &self,
252 chat_history: impl AsRef<str>,
253 message: &ChatCompletionAssistantMessage,
254 ) -> Result<String> {
255 let content = match message.content() {
256 Some(content) => content.to_string(),
257 None => match message.tool_calls().is_some() {
259 true => String::new(),
260 false => return Err(PromptError::NoAssistantMessage),
261 },
262 };
263
264 Ok(format!(
265 "{chat_histroy}\n\nAssistant: {assistant_message}<|end_of_sentence|>",
266 chat_histroy = chat_history.as_ref().trim(),
267 assistant_message = content.trim(),
268 ))
269 }
270}
271impl BuildChatPrompt for DeepseekChat2Prompt {
272 fn build(&self, messages: &mut Vec<ChatCompletionRequestMessage>) -> Result<String> {
273 if messages.is_empty() {
274 return Err(crate::error::PromptError::NoMessages);
275 }
276
277 let system_prompt = match messages[0] {
279 ChatCompletionRequestMessage::System(ref message) => {
280 self.create_system_prompt(message)
281 }
282 _ => String::from("<|begin▁of▁sentence|>You are an AI programming assistant, utilizing the DeepSeek Coder model, developed by DeepSeek Company, and you only answer questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will refuse to answer."),
283 };
284
285 if messages.is_empty() {
287 return Err(crate::error::PromptError::NoMessages);
288 }
289
290 let mut prompt = String::new();
292 for message in messages {
293 match message {
294 ChatCompletionRequestMessage::User(message) => {
295 prompt = self.append_user_message(&prompt, &system_prompt, message);
296 }
297 ChatCompletionRequestMessage::Assistant(message) => {
298 prompt = self.append_assistant_message(&prompt, message)?;
299 }
300 _ => continue,
301 }
302 }
303
304 prompt.push_str("\n\nAssistant:");
305
306 Ok(prompt)
307 }
308}
309
310#[derive(Debug, Default, Clone)]
312pub struct DeepseekChat25Prompt;
313impl DeepseekChat25Prompt {
314 fn create_system_prompt(&self, message: &ChatCompletionSystemMessage) -> String {
316 let content = message.content();
317 match content.is_empty() {
318 true => String::from("<|begin▁of▁sentence|>"),
319 false => format!("<|begin▁of▁sentence|>{content}"),
320 }
321 }
322
323 fn append_user_message(
325 &self,
326 chat_history: impl AsRef<str>,
327 system_prompt: impl AsRef<str>,
328 message: &ChatCompletionUserMessage,
329 ) -> String {
330 let content = match message.content() {
331 ChatCompletionUserMessageContent::Text(text) => text.to_string(),
332 ChatCompletionUserMessageContent::Parts(parts) => {
333 let mut content = String::new();
334 for part in parts {
335 if let ContentPart::Text(text_content) = part {
336 content.push_str(text_content.text());
337 content.push('\n');
338 }
339 }
340 content
341 }
342 };
343
344 match chat_history.as_ref().is_empty() {
345 true => format!(
346 "{system_prompt}<|User|>{user_message}",
347 system_prompt = system_prompt.as_ref().trim(),
348 user_message = content.trim(),
349 ),
350 false => format!(
351 "{chat_history}<|User|>{user_message}",
352 chat_history = chat_history.as_ref().trim(),
353 user_message = content.trim(),
354 ),
355 }
356 }
357
358 fn append_assistant_message(
360 &self,
361 chat_history: impl AsRef<str>,
362 message: &ChatCompletionAssistantMessage,
363 ) -> Result<String> {
364 let content = match message.content() {
365 Some(content) => content.to_string(),
366 None => match message.tool_calls().is_some() {
368 true => String::new(),
369 false => return Err(PromptError::NoAssistantMessage),
370 },
371 };
372
373 Ok(format!(
374 "{chat_histroy}<|Assistant|>{assistant_message}<|end_of_sentence|>",
375 chat_histroy = chat_history.as_ref().trim(),
376 assistant_message = content.trim(),
377 ))
378 }
379}
380impl BuildChatPrompt for DeepseekChat25Prompt {
381 fn build(&self, messages: &mut Vec<ChatCompletionRequestMessage>) -> Result<String> {
382 if messages.is_empty() {
383 return Err(crate::error::PromptError::NoMessages);
384 }
385
386 let system_prompt = match messages[0] {
388 ChatCompletionRequestMessage::System(ref message) => self.create_system_prompt(message),
389 _ => String::from("<|begin▁of▁sentence|>"),
390 };
391
392 if messages.is_empty() {
394 return Err(crate::error::PromptError::NoMessages);
395 }
396
397 let mut prompt = String::new();
399 for message in messages {
400 match message {
401 ChatCompletionRequestMessage::User(message) => {
402 prompt = self.append_user_message(&prompt, &system_prompt, message);
403 }
404 ChatCompletionRequestMessage::Assistant(message) => {
405 prompt = self.append_assistant_message(&prompt, message)?;
406 }
407 _ => continue,
408 }
409 }
410
411 prompt.push_str("<|Assistant|>");
412
413 Ok(prompt)
414 }
415}