pub struct SimpleMemory { /* private fields */ }Implementations§
Source§impl SimpleMemory
impl SimpleMemory
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/mcp_agent_client_chatbot.rs (line 64)
15async fn main() {
16 // 初始化日志记录器
17 env_logger::Builder::new()
18 .filter_level(LevelFilter::Info)
19 .init();
20
21 info!("=== Rust Agent MCP 客户端调用服务端工具示例 ===");
22
23 // 从环境变量获取 MCP 服务器 URL
24 let mcp_url = std::env::var("MCP_URL").unwrap_or("http://127.0.0.1:6000".to_string());
25
26 // 创建 OpenAI 模型实例(可选,用于智能决策是否调用工具)
27 // 如果没有设置 API 密钥,则使用一个占位符
28 let api_key = std::env::var("OPENAI_API_KEY").unwrap_or_else(|_| "sk-00000".to_string());
29 let base_url = std::env::var("OPENAI_API_URL").unwrap_or("https://api.deepseek.com/v1".to_string());
30 let model = OpenAIChatModel::new(api_key.clone(), Some(base_url))
31 .with_model(std::env::var("OPENAI_API_MODEL").unwrap_or_else(|_| "deepseek-chat".to_string()))
32 .with_temperature(0.7)
33 .with_max_tokens(8*1024);
34
35 // 初始化 MCP 客户端
36 let mut mcp_client = SimpleMcpClient::new(mcp_url.clone());
37
38 // 清空默认工具(可选)
39 mcp_client.clear_tools();
40
41 // 不添加任何本地工具,完全依赖服务端工具
42 info!("Not adding any local tools, will use server-side tools only...");
43
44 // 注意:客户端不需要实现工具处理器,因为工具实际在服务端执行
45 // 客户端只需要知道工具的名称和描述即可
46
47 // 连接到 MCP 服务器
48 info!("正在连接到 MCP 服务器: {}", mcp_url);
49 if let Err(e) = mcp_client.connect(&mcp_url).await {
50 error!("连接到 MCP 服务器失败: {}", e);
51 return;
52 } else {
53 mcp_client.set_server_connected(true);
54 }
55 info!("成功连接到 MCP 服务器");
56
57 // let model_name = model.model_name().map_or("未指定模型".to_string(), |v| v.to_string());
58
59 info!("----------------------------------------");
60
61 let client_arc: Arc<dyn McpClient> = Arc::new(mcp_client);
62
63 // 创建记忆模块实例
64 let memory = SimpleMemory::new();
65
66 // 创建 Agent 实例
67 let mut agent = McpAgent::with_openai_model_and_memory(
68 client_arc.clone(),
69 "You are an AI assistant that can use tools to answer user questions. Please decide whether to use tools based on the user's needs.".to_string(),
70 model.clone(),
71 Box::new(memory.clone())
72 );
73
74 // 自动从 MCP 客户端获取工具并添加到 Agent
75 if let Err(e) = agent.auto_add_tools().await {
76 error!("自动添加工具到 Agent 失败: {}", e);
77 return;
78 }
79
80 println!("MCP 客户端 Agent 已启动!");
81 println!("输入'退出'结束对话");
82 println!("----------------------------------------");
83
84 // 获取并显示可用工具
85 let tools = client_arc.get_tools().await.unwrap_or_else(|e| {
86 error!("获取工具列表失败: {}", e);
87 vec![]
88 });
89
90 println!("可用工具:");
91 for (index, tool) in tools.iter().enumerate() {
92 println!("{}. {}: {}", index + 1, tool.name, tool.description);
93 }
94
95 println!("----------------------------------------");
96
97 // 演示直接调用工具
98 println!("演示直接调用工具:");
99
100 // 调用天气工具
101 println!("\n1. 调用天气工具获取北京天气: What's the weather like in Beijing?");
102 let mut weather_params = HashMap::new();
103 weather_params.insert("city".to_string(), Value::String("Beijing".to_string()));
104
105 match client_arc.call_tool("get_weather", weather_params).await {
106 Ok(result) => {
107 println!("天气查询结果: {}", serde_json::to_string_pretty(&result).unwrap_or_else(|_| "无法格式化结果".to_string()));
108 },
109 Err(e) => {
110 println!("调用天气工具失败: {}", e);
111 }
112 }
113
114 // 调用计算工具
115 println!("\n2. 调用计算工具计算: 'What is 15.5 plus 24.3?'");
116 let calc_params = json!({
117 "expression": "15.5 + 24.3"
118 });
119 let calc_params_map: HashMap<String, Value> = serde_json::from_value(calc_params).unwrap();
120
121 match client_arc.call_tool("simple_calculate", calc_params_map).await {
122 Ok(result) => {
123 println!("计算结果: {}", serde_json::to_string_pretty(&result).unwrap_or_else(|_| "无法格式化结果".to_string()));
124 },
125 Err(e) => {
126 println!("调用计算工具失败: {}", e);
127 }
128 }
129
130 println!("----------------------------------------");
131
132 // 交互式对话循环
133 println!("现在进入交互模式,您可以询问天气或数学计算问题:");
134 loop {
135 println!("\n您: ");
136 let mut user_input = String::new();
137 std::io::stdin().read_line(&mut user_input).expect("读取输入失败");
138 let user_input = user_input.trim();
139
140 if user_input.to_lowercase() == "退出" || user_input.to_lowercase() == "exit" {
141 println!("再见!");
142 break;
143 }
144
145 if user_input.is_empty() {
146 continue;
147 }
148
149 // 运行 Agent
150 match run_agent(&agent, user_input.to_string()).await {
151 Ok(response) => {
152 // 尝试解析 response 为 JSON 并提取 content 字段
153 if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(&response) {
154 if let Some(content) = json_value.get("content").and_then(|v| v.as_str()) {
155 println!("助手: {}", content);
156 } else {
157 println!("助手: {}", response);
158 }
159 } else {
160 println!("助手: {}", response);
161 }
162 },
163 Err(e) => {
164 println!("助手: 抱歉,处理您的请求时出现错误: {}", e);
165 },
166 }
167 }
168
169 // 打印对话历史
170 info!("\n对话历史:");
171 match memory.load_memory_variables(&HashMap::new()).await {
172 Ok(memories) => {
173 if let Some(chat_history) = memories.get("chat_history") {
174 if let serde_json::Value::Array(messages) = chat_history {
175 for (i, message) in messages.iter().enumerate() {
176 if let serde_json::Value::Object(msg) = message {
177 let role = msg.get("role").and_then(|v| v.as_str()).unwrap_or("unknown");
178 let content = msg.get("content").and_then(|v| v.as_str()).unwrap_or("");
179 info!("{}. {}: {}", i + 1, role, content);
180 }
181 }
182 }
183 }
184 },
185 Err(e) => {
186 error!("加载记忆变量失败: {}", e);
187 }
188 }
189
190 // 断开 MCP 连接
191 if let Err(e) = client_arc.disconnect().await {
192 error!("断开 MCP 客户端连接失败: {}", e);
193 }
194
195 info!("\nMCP 客户端示例结束");
196}More examples
examples/mcp_agent_local_chatbot.rs (line 116)
16async fn main() {
17 // 初始化日志记录器
18 env_logger::Builder::new()
19 .filter_level(LevelFilter::Info)
20 .init();
21
22 info!("=== Rust Agent 使用示例 ===");
23
24 // 获取记忆类型配置
25 let memory_type = std::env::var("MEMORY_TYPE").unwrap_or_else(|_| "composite".to_string());
26 let summary_threshold = std::env::var("SUMMARY_THRESHOLD")
27 .ok()
28 .and_then(|s| s.parse().ok())
29 .unwrap_or(200);
30 let recent_messages_count = std::env::var("RECENT_MESSAGES_COUNT")
31 .ok()
32 .and_then(|s| s.parse().ok())
33 .unwrap_or(10);
34
35 info!("使用记忆类型: {}", memory_type);
36 info!("摘要阈值: {}", summary_threshold);
37 info!("保留最近消息数: {}", recent_messages_count);
38
39 // 从环境变量获取API密钥和基本URL
40 let api_key = std::env::var("OPENAI_API_KEY").unwrap_or_else(|_| "OPENAI_API_KEY".to_string());
41 let base_url = std::env::var("OPENAI_API_URL").ok();
42 let mcp_url = std::env::var("MCP_URL").unwrap_or("http://localhost:8000/mcp".to_string());
43
44 // 创建OpenAI模型实例 - 支持Openai兼容 API
45 let model = OpenAIChatModel::new(api_key.clone(), base_url)
46 .with_model(std::env::var("OPENAI_API_MODEL").unwrap_or_else(|_| "gpt-3.5-turbo".to_string()))
47 .with_temperature(0.7)
48 .with_max_tokens(8*1024);
49
50 // 初始化MCP客户端
51 // 在初始化 MCP 客户端后,自定义工具和工具处理器
52 let mut mcp_client = SimpleMcpClient::new(mcp_url.clone());
53
54 // 清空默认工具(可选)
55 mcp_client.clear_tools();
56
57 // 添加自定义工具
58 mcp_client.add_tools(vec![
59 McpTool {
60 name: "get_weather".to_string(),
61 description: format!(
62 "Get weather information for a specified city. For example: 'What's the weather like in Beijing?'.
63 The parameter request body you should extract is: '\"parameters\": {{ \"city\": \"{}\" }}'",
64 "city".to_string()),
65 },
66 McpTool {
67 name: "simple_calculate".to_string(),
68 description: format!(
69 "Execute simple mathematical calculations. For example: 'What is 9.11 plus 9.8?'.
70 The parameter request body you should extract is: '\"parameters\": {{ \"expression\": \"{}\" }}'",
71 "expression".to_string()),
72 },
73 ]);
74
75 // 注册自定义工具处理器
76 mcp_client.register_tool_handler("get_weather".to_string(), |params: HashMap<String, Value>| async move {
77 let default_city = Value::String("Shanghai".to_string());
78 let city_value = params.get("city").unwrap_or(&default_city);
79 let city = city_value.as_str().unwrap_or("Shanghai");
80 Ok(json!({
81 "city": city,
82 "temperature": "25°C",
83 "weather": "Sunny",
84 "humidity": "40%",
85 "updated_at": chrono::Utc::now().to_rfc3339()
86 }))
87 });
88
89 mcp_client.register_tool_handler("simple_calculate".to_string(), |params: HashMap<String, Value>| async move {
90 let expression_value = params.get("expression").ok_or_else(|| Error::msg("Missing calculation expression"))?;
91 let expression = expression_value.as_str().ok_or_else(|| Error::msg("Expression format error"))?;
92
93 // 解析表达式,提取操作数和运算符
94 let result = parse_and_calculate(expression)?;
95
96 Ok(json!({
97 "expression": expression,
98 "result": result,
99 "calculated_at": chrono::Utc::now().to_rfc3339()
100 }))
101 });
102
103 // 不连接到 MCP 服务器,仅使用本地工具
104 info!("Using local tools only, not connecting to MCP server...");
105
106 info!("Using model: {}", model.model_name().map_or("Model not specified", |v| v));
107 info!("Using API URL: {}", model.base_url());
108 info!("----------------------------------------");
109
110 let client_arc: Arc<dyn McpClient> = Arc::new(mcp_client);
111
112 // 根据配置创建不同类型的记忆模块实例
113 let memory: Box<dyn BaseMemory> = match memory_type.as_str() {
114 "simple" => {
115 info!("使用SimpleMemory (仅内存记忆)");
116 Box::new(SimpleMemory::new())
117 },
118 "composite" => {
119 info!("使用CompositeMemory (组合记忆 - 支持中长期记忆和摘要记忆)");
120 // 使用新的简化接口,只需要提供必要的参数
121 // session_id将在内部自动生成
122 let memory = CompositeMemory::with_basic_params(
123 PathBuf::from("./data/memory"),
124 summary_threshold,
125 recent_messages_count,
126 ).await.expect("Failed to create composite memory");
127
128 Box::new(memory)
129 },
130 _ => {
131 error!("未知的记忆类型: {}, 使用默认的SimpleMemory", memory_type);
132 Box::new(SimpleMemory::new())
133 }
134 };
135
136 // 创建Agent实例,并传递temperature、max_tokens和memory参数
137 let user_system_prompt = "You are an AI assistant that can use tools to answer user questions. Please decide whether to use tools based on the user's needs.".to_string();
138
139 let mut agent = McpAgent::with_openai_model_and_memory(
140 client_arc.clone(),
141 user_system_prompt,
142 model.clone(),
143 memory
144 );
145
146 // 尝试从MCP服务器自动获取工具并添加到Agent
147 if let Err(e) = agent.auto_add_tools().await {
148 error!("Failed to auto add tools from MCP server: {}", e);
149 }
150
151 println!("基于MCP的AI Agent聊天机器人已启动!");
152 println!("记忆类型: {}", memory_type);
153 if memory_type == "composite" {
154 println!("摘要功能: 已启用 (阈值: {} 条消息)", summary_threshold);
155 println!("中长期记忆: 已启用");
156 }
157 println!("输入'退出'结束对话");
158 println!("----------------------------------------");
159 println!("Using tools example:");
160 let tools = client_arc.get_tools().await.unwrap_or_else(|e| {
161 error!("Failed to get tools from MCP server: {}", e);
162 // 返回本地工具列表
163 vec![
164 McpTool {
165 name: "get_weather".to_string(),
166 description: "Get the weather information for a specified city. For example: 'What's the weather like in Beijing?'".to_string(),
167 },
168 McpTool {
169 name: "simple_calculate".to_string(),
170 description: "Perform simple mathematical calculations. For example: 'What is 9.11 plus 9.8?'".to_string(),
171 },
172 ]
173 });
174
175 // 打印工具列表
176 let mut index = 0;
177 for tool in &tools {
178 index += 1;
179
180 println!("{index}. {}: {}", tool.name, tool.description);
181 }
182
183 println!("----------------------------------------");
184 // 对话循环
185 loop {
186 let mut user_input = String::new();
187 println!("你: ");
188 std::io::stdin().read_line(&mut user_input).expect("读取输入失败");
189 println!("");
190 let user_input = user_input.trim();
191
192 if user_input.to_lowercase() == "退出" || user_input.to_lowercase() == "exit" {
193 println!("再见!");
194 break;
195 }
196
197 // 创建输入上下文
198 let mut inputs = HashMap::new();
199 inputs.insert("input".to_string(), serde_json::Value::String(user_input.to_string()));
200
201 // 运行Agent
202 match run_agent(&agent, user_input.to_string()).await {
203 Ok(response) => {
204 // 尝试解析response为JSON并提取content字段
205 if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(&response) {
206 if let Some(content) = json_value.get("content").and_then(|v| v.as_str()) {
207 println!("助手: {}", content);
208 } else {
209 println!("助手: {}", response);
210 }
211 } else {
212 println!("助手: {}", response);
213 }
214 },
215 Err(e) => {
216 println!("助手: 抱歉,处理您的请求时出现错误: {}", e);
217 },
218 }
219
220 info!("----------------------------------------");
221 }
222
223 // 打印对话历史
224 info!("对话历史:");
225 if let Some(memory) = agent.get_memory() {
226 match memory.load_memory_variables(&HashMap::new()).await {
227 Ok(memories) => {
228 if let Some(chat_history) = memories.get("chat_history") {
229 if let serde_json::Value::Array(messages) = chat_history {
230 info!("总消息数: {}", messages.len());
231 for (i, message) in messages.iter().enumerate() {
232 if let serde_json::Value::Object(msg) = message {
233 let role = msg.get("role").and_then(|v| v.as_str()).unwrap_or("unknown");
234 let content = msg.get("content").and_then(|v| v.as_str()).unwrap_or("");
235 // 限制内容长度以便显示
236 let display_content = if content.len() > 100 {
237 format!("{}...", &content[..100])
238 } else {
239 content.to_string()
240 };
241 info!("{}. {}: {}", i + 1, role, display_content);
242 }
243 }
244 }
245 }
246
247 // 如果有摘要,也打印出来
248 if let Some(summary) = memories.get("summary") {
249 if let serde_json::Value::String(summary_text) = summary {
250 info!("对话摘要: {}", summary_text);
251 }
252 }
253 },
254 Err(e) => {
255 info!("Failed to load memory variables: {}", e);
256 }
257 }
258 } else {
259 info!("No memory available");
260 }
261
262 // 断开MCP连接
263 if let Err(e) = client_arc.disconnect().await {
264 error!("Failed to disconnect MCP client: {}", e);
265 }
266}pub fn with_memory_key(memory_key: String) -> Self
pub fn with_memories(memories: HashMap<String, Value>) -> Self
pub async fn add_message(&self, message: Value) -> Result<(), Error>
pub fn get_memory_key(&self) -> String
Trait Implementations§
Source§impl BaseMemory for SimpleMemory
impl BaseMemory for SimpleMemory
fn memory_variables(&self) -> Vec<String>
fn load_memory_variables<'a>( &'a self, _inputs: &'a HashMap<String, Value>, ) -> Pin<Box<dyn Future<Output = Result<HashMap<String, Value>, Error>> + Send + 'a>>
fn save_context<'a>( &'a self, inputs: &'a HashMap<String, Value>, outputs: &'a HashMap<String, Value>, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
fn clear<'a>( &'a self, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>>
fn clone_box(&self) -> Box<dyn BaseMemory>
fn get_session_id(&self) -> Option<&str>
fn set_session_id(&mut self, session_id: String)
fn get_token_count(&self) -> Result<usize, Error>
fn as_any(&self) -> &dyn Any
Source§impl Clone for SimpleMemory
impl Clone for SimpleMemory
Source§impl Debug for SimpleMemory
impl Debug for SimpleMemory
Auto Trait Implementations§
impl Freeze for SimpleMemory
impl !RefUnwindSafe for SimpleMemory
impl Send for SimpleMemory
impl Sync for SimpleMemory
impl Unpin for SimpleMemory
impl !UnwindSafe for SimpleMemory
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more