jarvis-ai-assistant 0.1.45__py3-none-any.whl → 0.1.46__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.
jarvis/models/kimi.py CHANGED
@@ -8,31 +8,46 @@ from jarvis.models.base import BasePlatform
8
8
  from jarvis.utils import PrettyOutput, OutputType
9
9
  from jarvis.utils import while_success
10
10
 
11
+
11
12
  class KimiModel(BasePlatform):
12
13
  """Kimi模型实现"""
13
14
 
14
15
  platform_name = "kimi"
15
-
16
+
16
17
  def __init__(self):
17
18
  """
18
19
  初始化Kimi模型
19
20
  """
20
21
  self.api_key = os.getenv("KIMI_API_KEY")
21
22
  if not self.api_key:
22
- PrettyOutput.print("\n需要设置 KIMI_API_KEY 才能使用 Jarvis。请按以下步骤操作:", OutputType.INFO)
23
+ PrettyOutput.print(
24
+ "\n需要设置 KIMI_API_KEY 才能使用 Jarvis。请按以下步骤操作:",
25
+ OutputType.INFO)
23
26
  PrettyOutput.print("\n1. 获取 Kimi API Key:", OutputType.INFO)
24
- PrettyOutput.print(" • 访问 Kimi AI 平台: https://kimi.moonshot.cn", OutputType.INFO)
27
+ PrettyOutput.print(
28
+ " • 访问 Kimi AI 平台: https://kimi.moonshot.cn",
29
+ OutputType.INFO)
25
30
  PrettyOutput.print(" • 登录您的账号", OutputType.INFO)
26
- PrettyOutput.print(" • 打开浏览器开发者工具 (F12 或右键 -> 检查)", OutputType.INFO)
31
+ PrettyOutput.print(
32
+ " • 打开浏览器开发者工具 (F12 或右键 -> 检查)",
33
+ OutputType.INFO)
27
34
  PrettyOutput.print(" • 切换到 Network 标签页", OutputType.INFO)
28
35
  PrettyOutput.print(" • 发送任意消息", OutputType.INFO)
29
36
  PrettyOutput.print(" • 在请求中找到 Authorization 头部", OutputType.INFO)
30
- PrettyOutput.print(" • 复制 token 值(去掉 'Bearer ' 前缀)", OutputType.INFO)
37
+ PrettyOutput.print(
38
+ " • 复制 token 值(去掉 'Bearer ' 前缀)",
39
+ OutputType.INFO)
31
40
  PrettyOutput.print("\n2. 设置环境变量:", OutputType.INFO)
32
- PrettyOutput.print(" 方法 1: 创建或编辑 ~/.jarvis_env 文件:", OutputType.INFO)
33
- PrettyOutput.print(" echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis_env", OutputType.INFO)
41
+ PrettyOutput.print(
42
+ " 方法 1: 创建或编辑 ~/.jarvis_env 文件:",
43
+ OutputType.INFO)
44
+ PrettyOutput.print(
45
+ " echo 'KIMI_API_KEY=your_key_here' > ~/.jarvis_env",
46
+ OutputType.INFO)
34
47
  PrettyOutput.print("\n 方法 2: 直接设置环境变量:", OutputType.INFO)
35
- PrettyOutput.print(" export KIMI_API_KEY=your_key_here", OutputType.INFO)
48
+ PrettyOutput.print(
49
+ " export KIMI_API_KEY=your_key_here",
50
+ OutputType.INFO)
36
51
  PrettyOutput.print("\n设置完成后重新运行 Jarvis。", OutputType.INFO)
37
52
  raise Exception("KIMI_API_KEY is not set")
38
53
  self.auth_header = f"Bearer {self.api_key}"
@@ -62,30 +77,41 @@ class KimiModel(BasePlatform):
62
77
  'Content-Type': 'application/json'
63
78
  }
64
79
  try:
65
- response = while_success(lambda: requests.request("POST", url, headers=headers, data=payload), sleep_time=5)
80
+ response = while_success(
81
+ lambda: requests.request(
82
+ "POST",
83
+ url,
84
+ headers=headers,
85
+ data=payload),
86
+ sleep_time=5)
66
87
  self.chat_id = response.json()["id"]
67
88
  return True
68
89
  except Exception as e:
69
- PrettyOutput.print(f"Error: Failed to create chat: {e}", OutputType.ERROR)
90
+ PrettyOutput.print(
91
+ f"Error: Failed to create chat: {e}",
92
+ OutputType.ERROR)
70
93
  return False
71
94
 
72
95
  def _get_presigned_url(self, filename: str, action: str) -> Dict:
73
96
  """获取预签名上传URL"""
74
97
  url = "https://kimi.moonshot.cn/api/pre-sign-url"
75
-
76
-
77
-
98
+
78
99
  payload = json.dumps({
79
100
  "action": action,
80
101
  "name": os.path.basename(filename)
81
102
  }, ensure_ascii=False)
82
-
103
+
83
104
  headers = {
84
105
  'Authorization': self.auth_header,
85
106
  'Content-Type': 'application/json'
86
107
  }
87
-
88
- response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
108
+
109
+ response = while_success(
110
+ lambda: requests.post(
111
+ url,
112
+ headers=headers,
113
+ data=payload),
114
+ sleep_time=5)
89
115
  return response.json()
90
116
 
91
117
  def _upload_file(self, file_path: str, presigned_url: str) -> bool:
@@ -93,13 +119,20 @@ class KimiModel(BasePlatform):
93
119
  try:
94
120
  with open(file_path, 'rb') as f:
95
121
  content = f.read()
96
- response = while_success(lambda: requests.put(presigned_url, data=content), sleep_time=5)
122
+ response = while_success(
123
+ lambda: requests.put(
124
+ presigned_url,
125
+ data=content),
126
+ sleep_time=5)
97
127
  return response.status_code == 200
98
128
  except Exception as e:
99
- PrettyOutput.print(f"Error: Failed to upload file: {e}", OutputType.ERROR)
129
+ PrettyOutput.print(
130
+ f"Error: Failed to upload file: {e}",
131
+ OutputType.ERROR)
100
132
  return False
101
133
 
102
- def _get_file_info(self, file_data: Dict, name: str, file_type: str) -> Dict:
134
+ def _get_file_info(self, file_data: Dict, name: str,
135
+ file_type: str) -> Dict:
103
136
  """获取文件信息"""
104
137
  url = "https://kimi.moonshot.cn/api/file"
105
138
  payload = json.dumps({
@@ -109,13 +142,18 @@ class KimiModel(BasePlatform):
109
142
  "chat_id": self.chat_id,
110
143
  "file_id": file_data.get("file_id", "")
111
144
  }, ensure_ascii=False)
112
-
145
+
113
146
  headers = {
114
147
  'Authorization': self.auth_header,
115
148
  'Content-Type': 'application/json'
116
149
  }
117
-
118
- response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
150
+
151
+ response = while_success(
152
+ lambda: requests.post(
153
+ url,
154
+ headers=headers,
155
+ data=payload),
156
+ sleep_time=5)
119
157
  return response.json()
120
158
 
121
159
  def _wait_for_parse(self, file_id: str) -> bool:
@@ -125,22 +163,28 @@ class KimiModel(BasePlatform):
125
163
  'Authorization': self.auth_header,
126
164
  'Content-Type': 'application/json'
127
165
  }
128
-
166
+
129
167
  max_retries = 30
130
168
  retry_count = 0
131
-
169
+
132
170
  while retry_count < max_retries:
133
171
  payload = json.dumps({"ids": [file_id]}, ensure_ascii=False)
134
- response = while_success(lambda: requests.post(url, headers=headers, data=payload, stream=True), sleep_time=5)
135
-
172
+ response = while_success(
173
+ lambda: requests.post(
174
+ url,
175
+ headers=headers,
176
+ data=payload,
177
+ stream=True),
178
+ sleep_time=5)
179
+
136
180
  for line in response.iter_lines():
137
181
  if not line:
138
182
  continue
139
-
183
+
140
184
  line = line.decode('utf-8')
141
185
  if not line.startswith("data: "):
142
186
  continue
143
-
187
+
144
188
  try:
145
189
  data = json.loads(line[6:])
146
190
  if data.get("event") == "resp":
@@ -151,18 +195,19 @@ class KimiModel(BasePlatform):
151
195
  return False
152
196
  except json.JSONDecodeError:
153
197
  continue
154
-
198
+
155
199
  retry_count += 1
156
200
  time.sleep(1)
157
-
201
+
158
202
  return False
203
+
159
204
  def upload_files(self, file_list: List[str]) -> List[Dict]:
160
205
  """上传文件列表并返回文件信息"""
161
206
  if not file_list:
162
207
  return []
163
208
 
164
209
  PrettyOutput.print("Progress: 开始处理文件上传...", OutputType.PROGRESS)
165
-
210
+
166
211
  if not self.chat_id:
167
212
  PrettyOutput.print("创建新的对话会话...", OutputType.PROGRESS)
168
213
  if not self._create_chat():
@@ -171,21 +216,24 @@ class KimiModel(BasePlatform):
171
216
  uploaded_files = []
172
217
  for index, file_path in enumerate(file_list, 1):
173
218
  try:
174
- PrettyOutput.print(f"处理文件 [{index}/{len(file_list)}]: {file_path}", OutputType.PROGRESS)
219
+ PrettyOutput.print(
220
+ f"处理文件 [{index}/{len(file_list)}]: {file_path}", OutputType.PROGRESS)
175
221
 
176
222
  mime_type, _ = mimetypes.guess_type(file_path)
177
- action = "image" if mime_type and mime_type.startswith('image/') else "file"
178
-
223
+ action = "image" if mime_type and mime_type.startswith(
224
+ 'image/') else "file"
225
+
179
226
  # 获取预签名URL
180
227
  PrettyOutput.print("获取上传URL...", OutputType.PROGRESS)
181
228
  presigned_data = self._get_presigned_url(file_path, action)
182
-
229
+
183
230
  # 上传文件
184
231
  PrettyOutput.print("上传文件内容...", OutputType.PROGRESS)
185
232
  if self._upload_file(file_path, presigned_data["url"]):
186
233
  # 获取文件信息
187
234
  PrettyOutput.print("获取文件信息...", OutputType.PROGRESS)
188
- file_info = self._get_file_info(presigned_data, os.path.basename(file_path), action)
235
+ file_info = self._get_file_info(
236
+ presigned_data, os.path.basename(file_path), action)
189
237
  # 等待文件解析
190
238
  PrettyOutput.print("等待文件解析完成...", OutputType.PROGRESS)
191
239
 
@@ -193,24 +241,31 @@ class KimiModel(BasePlatform):
193
241
  if action == "file":
194
242
  if self._wait_for_parse(file_info["id"]):
195
243
  uploaded_files.append(file_info)
196
- PrettyOutput.print(f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
244
+ PrettyOutput.print(
245
+ f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
197
246
  else:
198
- PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.ERROR)
247
+ PrettyOutput.print(
248
+ f"✗ 文件解析失败: {file_path}", OutputType.ERROR)
199
249
  else:
200
250
  uploaded_files.append(file_info)
201
- PrettyOutput.print(f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
251
+ PrettyOutput.print(
252
+ f"Success: 文件处理成功: {file_path}", OutputType.SUCCESS)
202
253
  else:
203
- PrettyOutput.print(f"Error: 文件上传失败: {file_path}", OutputType.ERROR)
204
-
254
+ PrettyOutput.print(
255
+ f"Error: 文件上传失败: {file_path}", OutputType.ERROR)
256
+
205
257
  except Exception as e:
206
- PrettyOutput.print(f"✗ 处理文件出错 {file_path}: {str(e)}", OutputType.ERROR)
258
+ PrettyOutput.print(
259
+ f"✗ 处理文件出错 {file_path}: {
260
+ str(e)}", OutputType.ERROR)
207
261
  continue
208
-
262
+
209
263
  if uploaded_files:
210
- PrettyOutput.print(f"成功处理 {len(uploaded_files)}/{len(file_list)} 个文件", OutputType.SUCCESS)
264
+ PrettyOutput.print(
265
+ f"成功处理 {len(uploaded_files)}/{len(file_list)} 个文件", OutputType.SUCCESS)
211
266
  else:
212
267
  PrettyOutput.print("没有文件成功处理", OutputType.ERROR)
213
-
268
+
214
269
  self.uploaded_files = uploaded_files
215
270
  return uploaded_files
216
271
 
@@ -221,19 +276,21 @@ class KimiModel(BasePlatform):
221
276
  if not self._create_chat():
222
277
  raise Exception("Failed to create chat session")
223
278
 
224
- url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}/completion/stream"
225
-
279
+ url = f"https://kimi.moonshot.cn/api/chat/{
280
+ self.chat_id}/completion/stream"
281
+
226
282
  # 只在第一次对话时带上文件引用
227
283
  refs = []
228
284
  refs_file = []
229
285
  if self.first_chat:
230
286
  if self.uploaded_files:
231
- PrettyOutput.print(f"首次对话,引用 {len(self.uploaded_files)} 个文件...", OutputType.PROGRESS)
287
+ PrettyOutput.print(
288
+ f"首次对话,引用 {len(self.uploaded_files)} 个文件...", OutputType.PROGRESS)
232
289
  refs = [f["id"] for f in self.uploaded_files]
233
290
  refs_file = self.uploaded_files
234
291
  message = self.system_message + "\n" + message
235
292
  self.first_chat = False
236
-
293
+
237
294
  PrettyOutput.print("发送请求...", OutputType.PROGRESS)
238
295
  payload = {
239
296
  "messages": [{"role": "user", "content": message}],
@@ -252,33 +309,39 @@ class KimiModel(BasePlatform):
252
309
  }
253
310
 
254
311
  try:
255
- response = while_success(lambda: requests.post(url, headers=headers, json=payload, stream=True), sleep_time=5)
312
+ response = while_success(
313
+ lambda: requests.post(
314
+ url,
315
+ headers=headers,
316
+ json=payload,
317
+ stream=True),
318
+ sleep_time=5)
256
319
  full_response = ""
257
-
320
+
258
321
  # 收集搜索和引用结果
259
322
  search_results = []
260
323
  ref_sources = []
261
-
324
+
262
325
  PrettyOutput.print("接收响应...", OutputType.PROGRESS)
263
326
  for line in response.iter_lines():
264
327
  if not line:
265
328
  continue
266
-
329
+
267
330
  line = line.decode('utf-8')
268
331
  if not line.startswith("data: "):
269
332
  continue
270
-
333
+
271
334
  try:
272
335
  data = json.loads(line[6:])
273
336
  event = data.get("event")
274
-
337
+
275
338
  if event == "cmpl":
276
339
  # 处理补全文本
277
340
  text = data.get("text", "")
278
341
  if text:
279
342
  PrettyOutput.print_stream(text)
280
343
  full_response += text
281
-
344
+
282
345
  elif event == "search_plus":
283
346
  # 收集搜索结果
284
347
  msg = data.get("msg", {})
@@ -291,7 +354,7 @@ class KimiModel(BasePlatform):
291
354
  "type": msg.get("type", ""),
292
355
  "url": msg.get("url", "")
293
356
  })
294
-
357
+
295
358
  elif event == "ref_docs":
296
359
  # 收集引用来源
297
360
  ref_cards = data.get("ref_cards", [])
@@ -307,52 +370,75 @@ class KimiModel(BasePlatform):
307
370
  "rag_segments": card.get("rag_segments", []),
308
371
  "origin": card.get("origin", {})
309
372
  })
310
-
373
+
311
374
  except json.JSONDecodeError:
312
375
  continue
313
-
376
+
314
377
  PrettyOutput.print_stream_end()
315
-
316
378
 
317
379
  # 显示搜索结果摘要
318
380
  if search_results:
319
381
  PrettyOutput.print("\n搜索结果:", OutputType.PROGRESS)
320
382
  for result in search_results:
321
- PrettyOutput.print(f"- {result['title']}", OutputType.PROGRESS)
383
+ PrettyOutput.print(
384
+ f"- {result['title']}", OutputType.PROGRESS)
322
385
  if result['date']:
323
- PrettyOutput.print(f" 日期: {result['date']}", OutputType.PROGRESS)
324
- PrettyOutput.print(f" 来源: {result['site_name']}", OutputType.PROGRESS)
386
+ PrettyOutput.print(
387
+ f" 日期: {
388
+ result['date']}",
389
+ OutputType.PROGRESS)
390
+ PrettyOutput.print(
391
+ f" 来源: {
392
+ result['site_name']}",
393
+ OutputType.PROGRESS)
325
394
  if result['snippet']:
326
- PrettyOutput.print(f" 摘要: {result['snippet']}", OutputType.PROGRESS)
327
- PrettyOutput.print(f" 链接: {result['url']}", OutputType.PROGRESS)
395
+ PrettyOutput.print(
396
+ f" 摘要: {
397
+ result['snippet']}",
398
+ OutputType.PROGRESS)
399
+ PrettyOutput.print(
400
+ f" 链接: {
401
+ result['url']}",
402
+ OutputType.PROGRESS)
328
403
  PrettyOutput.print("", OutputType.PROGRESS)
329
-
404
+
330
405
  # 显示引用来源
331
406
  if ref_sources:
332
407
  PrettyOutput.print("\n引用来源:", OutputType.PROGRESS)
333
408
  for source in ref_sources:
334
- PrettyOutput.print(f"- [{source['ref_id']}] {source['title']} ({source['source']})", OutputType.PROGRESS)
335
- PrettyOutput.print(f" 链接: {source['url']}", OutputType.PROGRESS)
409
+ PrettyOutput.print(
410
+ f"- [{source['ref_id']}] {source['title']} ({source['source']})", OutputType.PROGRESS)
411
+ PrettyOutput.print(
412
+ f" 链接: {
413
+ source['url']}",
414
+ OutputType.PROGRESS)
336
415
  if source['abstract']:
337
- PrettyOutput.print(f" 摘要: {source['abstract']}", OutputType.PROGRESS)
338
-
416
+ PrettyOutput.print(
417
+ f" 摘要: {
418
+ source['abstract']}",
419
+ OutputType.PROGRESS)
420
+
339
421
  # 显示相关段落
340
422
  if source['rag_segments']:
341
423
  PrettyOutput.print(" 相关段落:", OutputType.PROGRESS)
342
424
  for segment in source['rag_segments']:
343
- text = segment.get('text', '').replace('\n', ' ').strip()
425
+ text = segment.get(
426
+ 'text', '').replace(
427
+ '\n', ' ').strip()
344
428
  if text:
345
- PrettyOutput.print(f" - {text}", OutputType.PROGRESS)
346
-
429
+ PrettyOutput.print(
430
+ f" - {text}", OutputType.PROGRESS)
431
+
347
432
  # 显示原文引用
348
433
  origin = source['origin']
349
434
  if origin:
350
435
  text = origin.get('text', '')
351
436
  if text:
352
- PrettyOutput.print(f" 原文: {text}", OutputType.PROGRESS)
353
-
437
+ PrettyOutput.print(
438
+ f" 原文: {text}", OutputType.PROGRESS)
439
+
354
440
  PrettyOutput.print("", OutputType.PROGRESS)
355
-
441
+
356
442
  return full_response
357
443
 
358
444
  except Exception as e:
@@ -362,21 +448,26 @@ class KimiModel(BasePlatform):
362
448
  """删除当前会话"""
363
449
  if not self.chat_id:
364
450
  return True # 如果没有会话ID,视为删除成功
365
-
451
+
366
452
  url = f"https://kimi.moonshot.cn/api/chat/{self.chat_id}"
367
453
  headers = {
368
454
  'Authorization': self.auth_header,
369
455
  'Content-Type': 'application/json'
370
456
  }
371
-
457
+
372
458
  try:
373
- response = while_success(lambda: requests.delete(url, headers=headers), sleep_time=5)
459
+ response = while_success(
460
+ lambda: requests.delete(
461
+ url, headers=headers), sleep_time=5)
374
462
  if response.status_code == 200:
375
463
  PrettyOutput.print("会话已删除", OutputType.SUCCESS)
376
464
  self.reset()
377
465
  return True
378
466
  else:
379
- PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.ERROR)
467
+ PrettyOutput.print(
468
+ f"删除会话失败: HTTP {
469
+ response.status_code}",
470
+ OutputType.ERROR)
380
471
  return False
381
472
  except Exception as e:
382
473
  PrettyOutput.print(f"删除会话时发生错误: {str(e)}", OutputType.ERROR)
jarvis/models/openai.py CHANGED
@@ -4,11 +4,12 @@ from openai import OpenAI
4
4
  from jarvis.models.base import BasePlatform
5
5
  from jarvis.utils import PrettyOutput, OutputType
6
6
 
7
+
7
8
  class OpenAIModel(BasePlatform):
8
9
  """DeepSeek模型实现"""
9
10
 
10
11
  platform_name = "openai"
11
-
12
+
12
13
  def __init__(self):
13
14
  """
14
15
  初始化DeepSeek模型
@@ -17,23 +18,39 @@ class OpenAIModel(BasePlatform):
17
18
  if not self.api_key:
18
19
  PrettyOutput.print("\n需要设置以下环境变量才能使用 OpenAI 模型:", OutputType.INFO)
19
20
  PrettyOutput.print(" • OPENAI_API_KEY: API 密钥", OutputType.INFO)
20
- PrettyOutput.print(" • OPENAI_API_BASE: (可选) API 基础地址,默认使用 https://api.deepseek.com", OutputType.INFO)
21
+ PrettyOutput.print(
22
+ " • OPENAI_API_BASE: (可选) API 基础地址,默认使用 https://api.deepseek.com",
23
+ OutputType.INFO)
21
24
  PrettyOutput.print("\n可以通过以下方式设置:", OutputType.INFO)
22
25
  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(
27
+ " OPENAI_API_KEY=your_api_key",
28
+ OutputType.INFO)
29
+ PrettyOutput.print(
30
+ " OPENAI_API_BASE=your_api_base",
31
+ OutputType.INFO)
32
+ PrettyOutput.print(
33
+ " OPENAI_MODEL_NAME=your_model_name",
34
+ OutputType.INFO)
26
35
  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)
36
+ PrettyOutput.print(
37
+ " export OPENAI_API_KEY=your_api_key",
38
+ OutputType.INFO)
39
+ PrettyOutput.print(
40
+ " export OPENAI_API_BASE=your_api_base",
41
+ OutputType.INFO)
42
+ PrettyOutput.print(
43
+ " export OPENAI_MODEL_NAME=your_model_name",
44
+ OutputType.INFO)
30
45
  raise Exception("OPENAI_API_KEY is not set")
31
-
32
- self.base_url = os.getenv("OPENAI_API_BASE", "https://api.deepseek.com")
46
+
47
+ self.base_url = os.getenv(
48
+ "OPENAI_API_BASE",
49
+ "https://api.deepseek.com")
33
50
  self.model_name = os.getenv("OPENAI_MODEL_NAME", "deepseek-chat")
34
51
 
35
52
  PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
36
-
53
+
37
54
  self.client = OpenAI(
38
55
  api_key=self.api_key,
39
56
  base_url=self.base_url
@@ -48,38 +65,40 @@ class OpenAIModel(BasePlatform):
48
65
  def set_system_message(self, message: str):
49
66
  """设置系统消息"""
50
67
  self.system_message = message
51
- self.messages.append({"role": "system", "content": self.system_message})
68
+ self.messages.append(
69
+ {"role": "system", "content": self.system_message})
52
70
 
53
71
  def chat(self, message: str) -> str:
54
72
  """执行对话"""
55
73
  try:
56
74
  PrettyOutput.print("发送请求...", OutputType.PROGRESS)
57
-
75
+
58
76
  # 添加用户消息到历史记录
59
77
  self.messages.append({"role": "user", "content": message})
60
-
78
+
61
79
  response = self.client.chat.completions.create(
62
80
  model=self.model_name, # 使用配置的模型名称
63
81
  messages=self.messages,
64
82
  stream=True
65
83
  )
66
-
84
+
67
85
  PrettyOutput.print("接收响应...", OutputType.PROGRESS)
68
86
  full_response = ""
69
-
87
+
70
88
  for chunk in response:
71
89
  if chunk.choices[0].delta.content:
72
90
  text = chunk.choices[0].delta.content
73
91
  PrettyOutput.print_stream(text)
74
92
  full_response += text
75
-
93
+
76
94
  PrettyOutput.print_stream_end()
77
-
95
+
78
96
  # 添加助手回复到历史记录
79
- self.messages.append({"role": "assistant", "content": full_response})
80
-
97
+ self.messages.append(
98
+ {"role": "assistant", "content": full_response})
99
+
81
100
  return full_response
82
-
101
+
83
102
  except Exception as e:
84
103
  PrettyOutput.print(f"对话失败: {str(e)}", OutputType.ERROR)
85
104
  raise Exception(f"Chat failed: {str(e)}")
@@ -92,11 +111,12 @@ class OpenAIModel(BasePlatform):
92
111
  """重置模型状态"""
93
112
  # 清空对话历史,只保留system message
94
113
  if self.system_message:
95
- self.messages = [{"role": "system", "content": self.system_message}]
114
+ self.messages = [
115
+ {"role": "system", "content": self.system_message}]
96
116
  else:
97
117
  self.messages = []
98
118
 
99
- def delete_chat(self)->bool:
119
+ def delete_chat(self) -> bool:
100
120
  """删除对话"""
101
121
  self.reset()
102
122
  return True