ds_api/simple_chatter.rs
1//! 简化的聊天客户端模块
2//!
3//! 提供简单易用的聊天客户端实现,内置历史记录管理功能。
4//!
5//! # 主要特性
6//!
7//! - **内置历史记录**: 自动管理对话历史记录
8//! - **系统提示词**: 支持自定义系统提示词
9//! - **简单易用**: 无需手动管理历史记录
10//! - **JSON 响应**: 支持 JSON 格式的响应
11//! - **异步处理**: 基于 `tokio` 的异步实现
12//!
13//! # 示例
14//!
15//! ## 基本使用
16//!
17//! ```rust,no_run
18//! use ds_api::SimpleChatter;
19//!
20//! #[tokio::main]
21//! async fn main() -> ds_api::error::Result<()> {
22//! let token = "your_deepseek_api_token".to_string();
23//! let system_prompt = "You are a helpful assistant.".to_string();
24//! let mut chatter = SimpleChatter::new(token, system_prompt);
25//!
26//! let response = chatter.chat("What is Rust?").await?;
27//! println!("Assistant: {}", response);
28//!
29//! // 继续对话,历史记录会自动维护
30//! let response = chatter.chat("Tell me more about it.").await?;
31//! println!("Assistant: {}", response);
32//!
33//! Ok(())
34//! }
35//! ```
36//!
37//! ## 使用 JSON 响应
38//!
39//! ```rust,no_run
40//! use ds_api::SimpleChatter;
41//! use serde_json::Value;
42//!
43//! #[tokio::main]
44//! async fn main() -> ds_api::error::Result<()> {
45//! let token = "your_deepseek_api_token".to_string();
46//! let system_prompt = "You are a helpful assistant that responds in JSON format.".to_string();
47//! let mut chatter = SimpleChatter::new(token, system_prompt);
48//!
49//! let json_response = chatter.chat_json("Give me information about Paris in JSON format").await?;
50//! println!("JSON response: {}", serde_json::to_string_pretty(&json_response)?);
51//!
52//! Ok(())
53//! }
54//! ```
55//!
56//! ## 修改系统提示词
57//!
58//! ```rust,no_run
59//! use ds_api::SimpleChatter;
60//!
61//! #[tokio::main]
62//! async fn main() -> ds_api::error::Result<()> {
63//! let token = "your_deepseek_api_token".to_string();
64//! let system_prompt = "You are a helpful assistant.".to_string();
65//! let mut chatter = SimpleChatter::new(token, system_prompt);
66//!
67//! // 修改系统提示词
68//! if let Some(prompt) = chatter.system_prompt_mut() {
69//! *prompt = "You are a sarcastic assistant.".to_string();
70//! }
71//!
72//! let response = chatter.chat("What is the weather like?").await?;
73//! println!("Assistant: {}", response);
74//!
75//! Ok(())
76//! }
77//! ```
78//!
79//! # 注意事项
80//!
81//! - 当前实现不支持流式响应
82//! - 历史记录会不断增长,需要手动管理或实现自动截断
83//! - 系统提示词是历史记录中的第一条消息
84//!
85
86use crate::error::Result;
87
88use crate::{normal_chatter::NormalChatter, request::*};
89
90/// 简化的聊天客户端,内置历史记录管理
91///
92/// 这个结构体提供了简单易用的聊天接口,自动管理对话历史记录,
93/// 用户无需关心历史记录的存储和传递。
94///
95/// # 字段
96///
97/// - `history`: 对话历史记录,第一条消息是系统提示词
98/// - `chatter`: 底层的聊天客户端实例
99///
100/// # 设计说明
101///
102/// - 历史记录中的第一条消息是系统提示词(System Prompt)
103/// - 后续消息是用户(User)和助手(Assistant)的对话内容
104/// - 每次聊天都会自动更新历史记录
105/// - 历史记录会不断增长,需要注意上下文长度限制
106///
107/// # 使用建议
108///
109/// 对于简单的聊天应用,推荐使用 `SimpleChatter`,因为它提供了最简单易用的接口。
110/// 对于需要自定义历史记录管理的复杂应用,请使用 [`NormalChatter`]。
111///
112pub struct SimpleChatter {
113 /// 对话历史记录
114 ///
115 /// 包含系统提示词和所有用户与助手的对话消息。
116 /// 第一条消息通常是系统提示词。
117 pub history: Vec<Message>,
118
119 /// 底层的聊天客户端实例
120 ///
121 /// 用于实际发送请求和处理响应。
122 pub chatter: NormalChatter,
123}
124
125impl SimpleChatter {
126 /// 创建一个新的 `SimpleChatter` 实例
127 ///
128 /// # 参数
129 ///
130 /// * `token` - DeepSeek API 访问令牌
131 /// * `system_prompt` - 系统提示词,用于定义助手的行为和角色
132 ///
133 /// # 示例
134 ///
135 /// ```rust
136 /// use ds_api::SimpleChatter;
137 ///
138 /// let token = "your_deepseek_api_token".to_string();
139 /// let system_prompt = "You are a helpful assistant.".to_string();
140 /// let chatter = SimpleChatter::new(token, system_prompt);
141 /// ```
142 pub fn new(token: String, system_prompt: String) -> Self {
143 Self {
144 history: vec![Message::new(Role::System, &system_prompt)],
145 chatter: NormalChatter::new(token),
146 }
147 }
148
149 /// 发送聊天消息并获取文本响应
150 ///
151 /// 这个方法会自动将用户消息添加到历史记录中,发送请求到 DeepSeek API,
152 /// 然后将助手的响应也添加到历史记录中,最后返回响应文本。
153 ///
154 /// # 参数
155 ///
156 /// * `user_message` - 用户消息内容
157 ///
158 /// # 返回
159 ///
160 /// 返回助手的响应文本,如果发生错误则返回错误信息。
161 ///
162 /// # 示例
163 ///
164 /// ```rust,no_run
165 /// use ds_api::SimpleChatter;
166 ///
167 /// #[tokio::main]
168 /// async fn main() -> ds_api::error::Result<()> {
169 /// let token = "your_token".to_string();
170 /// let system_prompt = "You are a helpful assistant.".to_string();
171 /// let mut chatter = SimpleChatter::new(token, system_prompt);
172 ///
173 /// let response = chatter.chat("Hello, world!").await?;
174 /// println!("Assistant: {}", response);
175 ///
176 /// Ok(())
177 /// }
178 /// ```
179 pub async fn chat<T: AsRef<str>>(&mut self, user_message: T) -> Result<String> {
180 self.chatter.chat(user_message, &mut self.history).await
181 }
182
183 /// 发送聊天消息并获取 JSON 格式的响应
184 ///
185 /// 这个方法与 [`SimpleChatter::chat`] 类似,但会启用 JSON 响应模式,并返回解析后的 JSON 值。
186 ///
187 /// # 参数
188 ///
189 /// * `user_message` - 用户消息内容
190 ///
191 /// # 返回
192 ///
193 /// 返回解析后的 JSON 值,如果发生错误则返回错误信息。
194 ///
195 /// # 注意事项
196 ///
197 /// 使用此方法前,确保在系统提示词中指示模型返回 JSON 格式的响应。
198 ///
199 /// # 示例
200 ///
201 /// ```rust,no_run
202 /// use ds_api::SimpleChatter;
203 /// use serde_json::Value;
204 ///
205 /// #[tokio::main]
206 /// async fn main() -> ds_api::error::Result<()> {
207 /// let token = "your_token".to_string();
208 /// let system_prompt = "You are a helpful assistant that responds in JSON format.".to_string();
209 /// let mut chatter = SimpleChatter::new(token, system_prompt);
210 ///
211 /// let json_response = chatter.chat_json("Give me information about Paris").await?;
212 /// println!("JSON response: {}", serde_json::to_string_pretty(&json_response)?);
213 ///
214 /// Ok(())
215 /// }
216 /// ```
217 pub async fn chat_json<T: AsRef<str>>(&mut self, user_message: T) -> Result<serde_json::Value> {
218 self.chatter
219 .chat_json(user_message, &mut self.history)
220 .await
221 }
222
223 /// 获取系统提示词的可变引用
224 ///
225 /// 这个方法允许在运行时修改系统提示词。
226 ///
227 /// # 返回
228 ///
229 /// 返回 `Option<&mut String>`:当 `history` 为空或系统提示词不可用时返回 `None`。
230 ///
231 /// # 示例
232 ///
233 /// ```rust,no_run
234 /// use ds_api::SimpleChatter;
235 ///
236 /// #[tokio::main]
237 /// async fn main() -> ds_api::error::Result<()> {
238 /// let token = "your_token".to_string();
239 /// let system_prompt = "You are a helpful assistant.".to_string();
240 /// let mut chatter = SimpleChatter::new(token, system_prompt);
241 ///
242 /// // 修改系统提示词(安全用法)
243 /// if let Some(prompt) = chatter.system_prompt_mut() {
244 /// *prompt = "You are a sarcastic assistant.".to_string();
245 /// }
246 ///
247 /// let response = chatter.chat("What is the weather like?").await?;
248 /// println!("Assistant: {}", response);
249 ///
250 /// Ok(())
251 /// }
252 /// ```
253 pub fn system_prompt_mut(&mut self) -> Option<&mut String> {
254 self.history.get_mut(0).and_then(|m| m.content.as_mut())
255 }
256}