chat_prompts/chat/
deepseek.rs

1use crate::{
2    error::{PromptError, Result},
3    BuildChatPrompt,
4};
5use endpoints::chat::{
6    ChatCompletionAssistantMessage, ChatCompletionRequestMessage, ChatCompletionSystemMessage,
7    ChatCompletionUserMessage, ChatCompletionUserMessageContent, ContentPart,
8};
9
10/// Generate prompts for the `DeepSeek-LLM-Chat` model.
11#[derive(Debug, Default, Clone)]
12pub struct DeepseekChatPrompt;
13impl DeepseekChatPrompt {
14    /// Create a user prompt from a chat completion request message.
15    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    /// create an assistant prompt from a chat completion request message.
45    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            // Note that the content is optional if `tool_calls` is specified.
53            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        // append user/assistant messages
73        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/// Generate prompts for the `DeepSeek-Coder` model.
93#[derive(Debug, Default, Clone)]
94pub struct DeepseekCoderPrompt;
95impl DeepseekCoderPrompt {
96    /// Create a system prompt from a chat completion request message.
97    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    /// Create a user prompt from a chat completion request message.
106    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    /// create an assistant prompt from a chat completion request message.
141    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            // Note that the content is optional if `tool_calls` is specified.
149            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        // system prompt
169        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        // append user/assistant messages
177        if messages.is_empty() {
178            return Err(crate::error::PromptError::NoMessages);
179        }
180
181        // append user/assistant messages
182        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/// Generate prompts for the `DeepSeek-V2` models.
202#[derive(Debug, Default, Clone)]
203pub struct DeepseekChat2Prompt;
204impl DeepseekChat2Prompt {
205    /// Create a system prompt from a chat completion request message.
206    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    /// Create a user prompt from a chat completion request message.
215    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    /// create an assistant prompt from a chat completion request message.
250    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            // Note that the content is optional if `tool_calls` is specified.
258            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        // system prompt
278        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        // append user/assistant messages
286        if messages.is_empty() {
287            return Err(crate::error::PromptError::NoMessages);
288        }
289
290        // append user/assistant messages
291        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/// Generate prompts for the `DeepSeek-v2.5` and `DeepSeek-v3` models.
311#[derive(Debug, Default, Clone)]
312pub struct DeepseekChat25Prompt;
313impl DeepseekChat25Prompt {
314    /// Create a system prompt from a chat completion request message.
315    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    /// Create a user prompt from a chat completion request message.
324    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    /// create an assistant prompt from a chat completion request message.
359    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            // Note that the content is optional if `tool_calls` is specified.
367            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        // system prompt
387        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        // append user/assistant messages
393        if messages.is_empty() {
394            return Err(crate::error::PromptError::NoMessages);
395        }
396
397        // append user/assistant messages
398        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}