jarvis-ai-assistant 0.1.32__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. jarvis/__init__.py +3 -0
  2. jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  3. jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  4. jarvis/__pycache__/main.cpython-313.pyc +0 -0
  5. jarvis/__pycache__/models.cpython-313.pyc +0 -0
  6. jarvis/__pycache__/tools.cpython-313.pyc +0 -0
  7. jarvis/__pycache__/utils.cpython-313.pyc +0 -0
  8. jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
  9. jarvis/agent.py +289 -0
  10. jarvis/main.py +148 -0
  11. jarvis/models/__init__.py +3 -0
  12. jarvis/models/__pycache__/__init__.cpython-313.pyc +0 -0
  13. jarvis/models/__pycache__/base.cpython-313.pyc +0 -0
  14. jarvis/models/__pycache__/kimi.cpython-313.pyc +0 -0
  15. jarvis/models/__pycache__/openai.cpython-313.pyc +0 -0
  16. jarvis/models/__pycache__/oyi.cpython-313.pyc +0 -0
  17. jarvis/models/__pycache__/registry.cpython-313.pyc +0 -0
  18. jarvis/models/base.py +39 -0
  19. jarvis/models/kimi.py +389 -0
  20. jarvis/models/openai.py +96 -0
  21. jarvis/models/oyi.py +271 -0
  22. jarvis/models/registry.py +199 -0
  23. jarvis/tools/__init__.py +5 -0
  24. jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  25. jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
  26. jarvis/tools/__pycache__/bing_search.cpython-313.pyc +0 -0
  27. jarvis/tools/__pycache__/calculator.cpython-313.pyc +0 -0
  28. jarvis/tools/__pycache__/calculator_tool.cpython-313.pyc +0 -0
  29. jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
  30. jarvis/tools/__pycache__/generator.cpython-313.pyc +0 -0
  31. jarvis/tools/__pycache__/methodology.cpython-313.pyc +0 -0
  32. jarvis/tools/__pycache__/python_script.cpython-313.pyc +0 -0
  33. jarvis/tools/__pycache__/rag.cpython-313.pyc +0 -0
  34. jarvis/tools/__pycache__/registry.cpython-313.pyc +0 -0
  35. jarvis/tools/__pycache__/search.cpython-313.pyc +0 -0
  36. jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
  37. jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
  38. jarvis/tools/__pycache__/user_confirmation.cpython-313.pyc +0 -0
  39. jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
  40. jarvis/tools/__pycache__/user_interaction.cpython-313.pyc +0 -0
  41. jarvis/tools/__pycache__/webpage.cpython-313.pyc +0 -0
  42. jarvis/tools/base.py +23 -0
  43. jarvis/tools/file_ops.py +110 -0
  44. jarvis/tools/generator.py +172 -0
  45. jarvis/tools/methodology.py +145 -0
  46. jarvis/tools/registry.py +183 -0
  47. jarvis/tools/shell.py +78 -0
  48. jarvis/tools/sub_agent.py +82 -0
  49. jarvis/utils.py +202 -0
  50. jarvis_ai_assistant-0.1.32.dist-info/LICENSE +21 -0
  51. jarvis_ai_assistant-0.1.32.dist-info/METADATA +345 -0
  52. jarvis_ai_assistant-0.1.32.dist-info/RECORD +55 -0
  53. jarvis_ai_assistant-0.1.32.dist-info/WHEEL +5 -0
  54. jarvis_ai_assistant-0.1.32.dist-info/entry_points.txt +2 -0
  55. jarvis_ai_assistant-0.1.32.dist-info/top_level.txt +1 -0
jarvis/models/kimi.py ADDED
@@ -0,0 +1,389 @@
1
+ from typing import Dict, List
2
+ import requests
3
+ import json
4
+ import os
5
+ import mimetypes
6
+ import time
7
+ from jarvis.models.base import BaseModel
8
+ from jarvis.utils import PrettyOutput, OutputType
9
+ from jarvis.utils import while_success
10
+
11
+ class KimiModel(BaseModel):
12
+ """Kimi模型实现"""
13
+
14
+ model_name = "kimi"
15
+
16
+ def __init__(self):
17
+ """
18
+ 初始化Kimi模型
19
+ """
20
+ self.api_key = os.getenv("KIMI_API_KEY")
21
+ if not self.api_key:
22
+ PrettyOutput.info("\n需要设置 KIMI_API_KEY 才能使用 Jarvis。请按以下步骤操作:")
23
+ PrettyOutput.info("\n1. 获取 Kimi API Key:")
24
+ PrettyOutput.info(" • 访问 Kimi AI 平台: https://kimi.moonshot.cn")
25
+ PrettyOutput.info(" • 登录您的账号")
26
+ PrettyOutput.info(" • 打开浏览器开发者工具 (F12 或右键 -> 检查)")
27
+ PrettyOutput.info(" • 切换到 Network 标签页")
28
+ PrettyOutput.info(" • 发送任意消息")
29
+ PrettyOutput.info(" • 在请求中找到 Authorization 头部")
30
+ PrettyOutput.info(" • 复制 token 值(去掉 'Bearer ' 前缀)")
31
+ PrettyOutput.info("\n2. 设置环境变量:")
32
+ PrettyOutput.info(" 方法 1: 创建或编辑 ~/.jarvis_env 文件:")
33
+ PrettyOutput.info(" echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis_env")
34
+ PrettyOutput.info("\n 方法 2: 直接设置环境变量:")
35
+ PrettyOutput.info(" export KIMI_API_KEY=your_key_here")
36
+ PrettyOutput.info("\n设置完成后重新运行 Jarvis。")
37
+ raise Exception("KIMI_API_KEY is not set")
38
+ self.auth_header = f"Bearer {self.api_key}"
39
+ self.chat_id = ""
40
+ self.uploaded_files = [] # 存储已上传文件的信息
41
+ self.first_chat = True # 添加标记,用于判断是否是第一次对话
42
+ self.system_message = ""
43
+
44
+ def set_system_message(self, message: str):
45
+ """设置系统消息"""
46
+ self.system_message = message
47
+
48
+ def _create_chat(self) -> bool:
49
+ """创建新的对话会话"""
50
+ url = "https://kimi.moonshot.cn/api/chat"
51
+ payload = json.dumps({
52
+ "name": "未命名会话",
53
+ "is_example": False,
54
+ "kimiplus_id": "kimi"
55
+ })
56
+ headers = {
57
+ 'Authorization': self.auth_header,
58
+ 'Content-Type': 'application/json'
59
+ }
60
+ try:
61
+ response = while_success(lambda: requests.request("POST", url, headers=headers, data=payload), sleep_time=5)
62
+ self.chat_id = response.json()["id"]
63
+ return True
64
+ except Exception as e:
65
+ PrettyOutput.print(f"Error: Failed to create chat: {e}", OutputType.ERROR)
66
+ return False
67
+
68
+ def _get_presigned_url(self, filename: str, action: str) -> Dict:
69
+ """获取预签名上传URL"""
70
+ url = "https://kimi.moonshot.cn/api/pre-sign-url"
71
+
72
+
73
+
74
+ payload = json.dumps({
75
+ "action": action,
76
+ "name": os.path.basename(filename)
77
+ }, ensure_ascii=False)
78
+
79
+ headers = {
80
+ 'Authorization': self.auth_header,
81
+ 'Content-Type': 'application/json'
82
+ }
83
+
84
+ response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
85
+ return response.json()
86
+
87
+ def _upload_file(self, file_path: str, presigned_url: str) -> bool:
88
+ """上传文件到预签名URL"""
89
+ try:
90
+ with open(file_path, 'rb') as f:
91
+ content = f.read()
92
+ response = while_success(lambda: requests.put(presigned_url, data=content), sleep_time=5)
93
+ return response.status_code == 200
94
+ except Exception as e:
95
+ PrettyOutput.print(f"Error: Failed to upload file: {e}", OutputType.ERROR)
96
+ return False
97
+
98
+ def _get_file_info(self, file_data: Dict, name: str, file_type: str) -> Dict:
99
+ """获取文件信息"""
100
+ url = "https://kimi.moonshot.cn/api/file"
101
+ payload = json.dumps({
102
+ "type": file_type,
103
+ "name": name,
104
+ "object_name": file_data["object_name"],
105
+ "chat_id": self.chat_id,
106
+ "file_id": file_data.get("file_id", "")
107
+ }, ensure_ascii=False)
108
+
109
+ headers = {
110
+ 'Authorization': self.auth_header,
111
+ 'Content-Type': 'application/json'
112
+ }
113
+
114
+ response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
115
+ return response.json()
116
+
117
+ def _wait_for_parse(self, file_id: str) -> bool:
118
+ """等待文件解析完成"""
119
+ url = "https://kimi.moonshot.cn/api/file/parse_process"
120
+ headers = {
121
+ 'Authorization': self.auth_header,
122
+ 'Content-Type': 'application/json'
123
+ }
124
+
125
+ max_retries = 30
126
+ retry_count = 0
127
+
128
+ while retry_count < max_retries:
129
+ payload = json.dumps({"ids": [file_id]}, ensure_ascii=False)
130
+ response = while_success(lambda: requests.post(url, headers=headers, data=payload, stream=True), sleep_time=5)
131
+
132
+ for line in response.iter_lines():
133
+ if not line:
134
+ continue
135
+
136
+ line = line.decode('utf-8')
137
+ if not line.startswith("data: "):
138
+ continue
139
+
140
+ try:
141
+ data = json.loads(line[6:])
142
+ if data.get("event") == "resp":
143
+ status = data.get("file_info", {}).get("status")
144
+ if status == "parsed":
145
+ return True
146
+ elif status == "failed":
147
+ return False
148
+ except json.JSONDecodeError:
149
+ continue
150
+
151
+ retry_count += 1
152
+ time.sleep(1)
153
+
154
+ return False
155
+ def upload_files(self, file_list: List[str]) -> List[Dict]:
156
+ """上传文件列表并返回文件信息"""
157
+ if not file_list:
158
+ return []
159
+
160
+ PrettyOutput.print("Progress: 开始处理文件上传...", OutputType.PROGRESS)
161
+
162
+ if not self.chat_id:
163
+ PrettyOutput.print("创建新的对话会话...", OutputType.PROGRESS)
164
+ if not self._create_chat():
165
+ raise Exception("Failed to create chat session")
166
+
167
+ uploaded_files = []
168
+ for index, file_path in enumerate(file_list, 1):
169
+ try:
170
+ PrettyOutput.print(f"处理文件 [{index}/{len(file_list)}]: {file_path}", OutputType.PROGRESS)
171
+
172
+ mime_type, _ = mimetypes.guess_type(file_path)
173
+ action = "image" if mime_type and mime_type.startswith('image/') else "file"
174
+
175
+ # 获取预签名URL
176
+ PrettyOutput.print("获取上传URL...", OutputType.PROGRESS)
177
+ presigned_data = self._get_presigned_url(file_path, action)
178
+
179
+ # 上传文件
180
+ PrettyOutput.print("上传文件内容...", OutputType.PROGRESS)
181
+ if self._upload_file(file_path, presigned_data["url"]):
182
+ # 获取文件信息
183
+ PrettyOutput.print("获取文件信息...", OutputType.PROGRESS)
184
+ file_info = self._get_file_info(presigned_data, os.path.basename(file_path), action)
185
+ # 等待文件解析
186
+ PrettyOutput.print("等待文件解析完成...", OutputType.PROGRESS)
187
+
188
+ # 只有文件需要解析
189
+ if action == "file":
190
+ if self._wait_for_parse(file_info["id"]):
191
+ uploaded_files.append(file_info)
192
+ PrettyOutput.print(f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
193
+ else:
194
+ PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.ERROR)
195
+ else:
196
+ uploaded_files.append(file_info)
197
+ PrettyOutput.print(f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
198
+ else:
199
+ PrettyOutput.print(f"Error: 文件上传失败: {file_path}", OutputType.ERROR)
200
+
201
+ except Exception as e:
202
+ PrettyOutput.print(f"✗ 处理文件出错 {file_path}: {str(e)}", OutputType.ERROR)
203
+ continue
204
+
205
+ if uploaded_files:
206
+ PrettyOutput.print(f"成功处理 {len(uploaded_files)}/{len(file_list)} 个文件", OutputType.SUCCESS)
207
+ else:
208
+ PrettyOutput.print("没有文件成功处理", OutputType.ERROR)
209
+
210
+ self.uploaded_files = uploaded_files
211
+ return uploaded_files
212
+
213
+ def chat(self, message: str) -> str:
214
+ """发送消息并获取响应"""
215
+ if not self.chat_id:
216
+ PrettyOutput.print("创建新的对话会话...", OutputType.PROGRESS)
217
+ if not self._create_chat():
218
+ raise Exception("Failed to create chat session")
219
+
220
+ url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}/completion/stream"
221
+
222
+ # 只在第一次对话时带上文件引用
223
+ refs = []
224
+ refs_file = []
225
+ if self.first_chat:
226
+ if self.uploaded_files:
227
+ PrettyOutput.print(f"首次对话,引用 {len(self.uploaded_files)} 个文件...", OutputType.PROGRESS)
228
+ refs = [f["id"] for f in self.uploaded_files]
229
+ refs_file = self.uploaded_files
230
+ message = self.system_message + "\n" + message
231
+ self.first_chat = False
232
+
233
+ PrettyOutput.print("发送请求...", OutputType.PROGRESS)
234
+ payload = {
235
+ "messages": [{"role": "user", "content": message}],
236
+ "use_search": True,
237
+ "extend": {"sidebar": True},
238
+ "kimiplus_id": "kimi",
239
+ "use_research": False,
240
+ "use_math": False,
241
+ "refs": refs,
242
+ "refs_file": refs_file
243
+ }
244
+
245
+ headers = {
246
+ 'Authorization': self.auth_header,
247
+ 'Content-Type': 'application/json'
248
+ }
249
+
250
+ try:
251
+ response = while_success(lambda: requests.post(url, headers=headers, json=payload, stream=True), sleep_time=5)
252
+ full_response = ""
253
+
254
+ # 收集搜索和引用结果
255
+ search_results = []
256
+ ref_sources = []
257
+
258
+ PrettyOutput.print("接收响应...", OutputType.PROGRESS)
259
+ for line in response.iter_lines():
260
+ if not line:
261
+ continue
262
+
263
+ line = line.decode('utf-8')
264
+ if not line.startswith("data: "):
265
+ continue
266
+
267
+ try:
268
+ data = json.loads(line[6:])
269
+ event = data.get("event")
270
+
271
+ if event == "cmpl":
272
+ # 处理补全文本
273
+ text = data.get("text", "")
274
+ if text:
275
+ PrettyOutput.print_stream(text)
276
+ full_response += text
277
+
278
+ elif event == "search_plus":
279
+ # 收集搜索结果
280
+ msg = data.get("msg", {})
281
+ if msg.get("type") == "get_res":
282
+ search_results.append({
283
+ "date": msg.get("date", ""),
284
+ "site_name": msg.get("site_name", ""),
285
+ "snippet": msg.get("snippet", ""),
286
+ "title": msg.get("title", ""),
287
+ "type": msg.get("type", ""),
288
+ "url": msg.get("url", "")
289
+ })
290
+
291
+ elif event == "ref_docs":
292
+ # 收集引用来源
293
+ ref_cards = data.get("ref_cards", [])
294
+ for card in ref_cards:
295
+ ref_sources.append({
296
+ "idx_s": card.get("idx_s", ""),
297
+ "idx_z": card.get("idx_z", ""),
298
+ "ref_id": card.get("ref_id", ""),
299
+ "url": card.get("url", ""),
300
+ "title": card.get("title", ""),
301
+ "abstract": card.get("abstract", ""),
302
+ "source": card.get("source_label", ""),
303
+ "rag_segments": card.get("rag_segments", []),
304
+ "origin": card.get("origin", {})
305
+ })
306
+
307
+ except json.JSONDecodeError:
308
+ continue
309
+
310
+ PrettyOutput.print_stream_end()
311
+
312
+
313
+ # 显示搜索结果摘要
314
+ if search_results:
315
+ PrettyOutput.print("\n搜索结果:", OutputType.PROGRESS)
316
+ for result in search_results:
317
+ PrettyOutput.print(f"- {result['title']}", OutputType.PROGRESS)
318
+ if result['date']:
319
+ PrettyOutput.print(f" 日期: {result['date']}", OutputType.PROGRESS)
320
+ PrettyOutput.print(f" 来源: {result['site_name']}", OutputType.PROGRESS)
321
+ if result['snippet']:
322
+ PrettyOutput.print(f" 摘要: {result['snippet']}", OutputType.PROGRESS)
323
+ PrettyOutput.print(f" 链接: {result['url']}", OutputType.PROGRESS)
324
+ PrettyOutput.print("", OutputType.PROGRESS)
325
+
326
+ # 显示引用来源
327
+ if ref_sources:
328
+ PrettyOutput.print("\n引用来源:", OutputType.PROGRESS)
329
+ for source in ref_sources:
330
+ PrettyOutput.print(f"- [{source['ref_id']}] {source['title']} ({source['source']})", OutputType.PROGRESS)
331
+ PrettyOutput.print(f" 链接: {source['url']}", OutputType.PROGRESS)
332
+ if source['abstract']:
333
+ PrettyOutput.print(f" 摘要: {source['abstract']}", OutputType.PROGRESS)
334
+
335
+ # 显示相关段落
336
+ if source['rag_segments']:
337
+ PrettyOutput.print(" 相关段落:", OutputType.PROGRESS)
338
+ for segment in source['rag_segments']:
339
+ text = segment.get('text', '').replace('\n', ' ').strip()
340
+ if text:
341
+ PrettyOutput.print(f" - {text}", OutputType.PROGRESS)
342
+
343
+ # 显示原文引用
344
+ origin = source['origin']
345
+ if origin:
346
+ text = origin.get('text', '')
347
+ if text:
348
+ PrettyOutput.print(f" 原文: {text}", OutputType.PROGRESS)
349
+
350
+ PrettyOutput.print("", OutputType.PROGRESS)
351
+
352
+ return full_response
353
+
354
+ except Exception as e:
355
+ raise Exception(f"Chat failed: {str(e)}")
356
+
357
+ def delete_chat(self) -> bool:
358
+ """删除当前会话"""
359
+ if not self.chat_id:
360
+ return True # 如果没有会话ID,视为删除成功
361
+
362
+ url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}"
363
+ headers = {
364
+ 'Authorization': self.auth_header,
365
+ 'Content-Type': 'application/json'
366
+ }
367
+
368
+ try:
369
+ response = while_success(lambda: requests.delete(url, headers=headers), sleep_time=5)
370
+ if response.status_code == 200:
371
+ PrettyOutput.print("会话已删除", OutputType.SUCCESS)
372
+ self.reset()
373
+ return True
374
+ else:
375
+ PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.ERROR)
376
+ return False
377
+ except Exception as e:
378
+ PrettyOutput.print(f"删除会话时发生错误: {str(e)}", OutputType.ERROR)
379
+ return False
380
+
381
+ def reset(self):
382
+ """重置对话"""
383
+ self.chat_id = ""
384
+ self.uploaded_files = []
385
+ self.first_chat = True # 重置first_chat标记
386
+
387
+ def name(self) -> str:
388
+ """模型名称"""
389
+ return "kimi"
@@ -0,0 +1,96 @@
1
+ from typing import Dict, List
2
+ import os
3
+ from openai import OpenAI
4
+ from jarvis.models.base import BaseModel
5
+ from jarvis.utils import PrettyOutput, OutputType
6
+
7
+ class OpenAIModel(BaseModel):
8
+ """DeepSeek模型实现"""
9
+
10
+ model_name = "openai"
11
+
12
+ def __init__(self):
13
+ """
14
+ 初始化DeepSeek模型
15
+ """
16
+ self.api_key = os.getenv("OPENAI_API_KEY")
17
+ if not self.api_key:
18
+ PrettyOutput.print("\n需要设置以下环境变量才能使用 OpenAI 模型:", OutputType.INFO)
19
+ PrettyOutput.print(" • OPENAI_API_KEY: API 密钥", OutputType.INFO)
20
+ PrettyOutput.print(" • OPENAI_API_BASE: (可选) API 基础地址,默认使用 https://api.deepseek.com", OutputType.INFO)
21
+ PrettyOutput.print("\n可以通过以下方式设置:", OutputType.INFO)
22
+ PrettyOutput.print("1. 创建或编辑 ~/.jarvis_env 文件:", OutputType.INFO)
23
+ PrettyOutput.print(" OPENAI_API_KEY=your_api_key", OutputType.INFO)
24
+ PrettyOutput.print(" OPENAI_API_BASE=your_api_base", OutputType.INFO)
25
+ PrettyOutput.print(" OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
26
+ PrettyOutput.print("\n2. 或者直接设置环境变量:", OutputType.INFO)
27
+ PrettyOutput.print(" export OPENAI_API_KEY=your_api_key", OutputType.INFO)
28
+ PrettyOutput.print(" export OPENAI_API_BASE=your_api_base", OutputType.INFO)
29
+ PrettyOutput.print(" export OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
30
+ raise Exception("OPENAI_API_KEY is not set")
31
+
32
+ self.base_url = os.getenv("OPENAI_API_BASE", "https://api.deepseek.com")
33
+ self.model_name = os.getenv("OPENAI_MODEL_NAME", "deepseek-chat")
34
+
35
+ self.client = OpenAI(
36
+ api_key=self.api_key,
37
+ base_url=self.base_url
38
+ )
39
+ self.messages: List[Dict[str, str]] = []
40
+ self.system_message = ""
41
+
42
+ def set_system_message(self, message: str):
43
+ """设置系统消息"""
44
+ self.system_message = message
45
+ self.messages.append({"role": "system", "content": self.system_message})
46
+
47
+ def chat(self, message: str) -> str:
48
+ """执行对话"""
49
+ try:
50
+ PrettyOutput.print("发送请求...", OutputType.PROGRESS)
51
+
52
+ # 添加用户消息到历史记录
53
+ self.messages.append({"role": "user", "content": message})
54
+
55
+ response = self.client.chat.completions.create(
56
+ model=self.model_name, # 使用配置的模型名称
57
+ messages=self.messages,
58
+ stream=True
59
+ )
60
+
61
+ PrettyOutput.print("接收响应...", OutputType.PROGRESS)
62
+ full_response = ""
63
+
64
+ for chunk in response:
65
+ if chunk.choices[0].delta.content:
66
+ text = chunk.choices[0].delta.content
67
+ PrettyOutput.print_stream(text)
68
+ full_response += text
69
+
70
+ PrettyOutput.print_stream_end()
71
+
72
+ # 添加助手回复到历史记录
73
+ self.messages.append({"role": "assistant", "content": full_response})
74
+
75
+ return full_response
76
+
77
+ except Exception as e:
78
+ PrettyOutput.print(f"对话失败: {str(e)}", OutputType.ERROR)
79
+ raise Exception(f"Chat failed: {str(e)}")
80
+
81
+ def name(self) -> str:
82
+ """返回模型名称"""
83
+ return self.model_name
84
+
85
+ def reset(self):
86
+ """重置模型状态"""
87
+ # 清空对话历史,只保留system message
88
+ if self.system_message:
89
+ self.messages = [{"role": "system", "content": self.system_message}]
90
+ else:
91
+ self.messages = []
92
+
93
+ def delete_chat(self)->bool:
94
+ """删除对话"""
95
+ self.reset()
96
+ return True