Skip to main content

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}