jarvis-ai-assistant 0.1.212__py3-none-any.whl → 0.1.214__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/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +43 -20
- jarvis/jarvis_agent/builtin_input_handler.py +12 -1
- jarvis/jarvis_agent/edit_file_handler.py +44 -32
- jarvis/jarvis_code_agent/code_agent.py +10 -4
- jarvis/jarvis_platform/ai8.py +153 -114
- jarvis/jarvis_platform/base.py +33 -7
- jarvis/jarvis_platform/human.py +43 -1
- jarvis/jarvis_platform/kimi.py +50 -6
- jarvis/jarvis_platform/openai.py +38 -1
- jarvis/jarvis_platform/oyi.py +162 -125
- jarvis/jarvis_platform/tongyi.py +53 -7
- jarvis/jarvis_platform/yuanbao.py +47 -4
- jarvis/jarvis_platform_manager/main.py +65 -19
- jarvis/jarvis_platform_manager/service.py +66 -100
- jarvis/jarvis_utils/input.py +6 -5
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/METADATA +2 -2
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/RECORD +22 -22
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.212.dist-info → jarvis_ai_assistant-0.1.214.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/oyi.py
CHANGED
@@ -2,10 +2,12 @@ import mimetypes
|
|
2
2
|
import os
|
3
3
|
from typing import Dict, Generator, List, Tuple
|
4
4
|
from jarvis.jarvis_platform.base import BasePlatform
|
5
|
-
import requests
|
6
5
|
import json
|
7
6
|
|
7
|
+
from jarvis.jarvis_utils import http
|
8
8
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
9
|
+
from jarvis.jarvis_utils.utils import while_success
|
10
|
+
|
9
11
|
|
10
12
|
class OyiModel(BasePlatform):
|
11
13
|
"""Oyi model implementation"""
|
@@ -16,7 +18,7 @@ class OyiModel(BasePlatform):
|
|
16
18
|
def get_model_list(self) -> List[Tuple[str, str]]:
|
17
19
|
"""Get model list"""
|
18
20
|
self.get_available_models()
|
19
|
-
return [(name,info[
|
21
|
+
return [(name, info["desc"]) for name, info in self.models.items()]
|
20
22
|
|
21
23
|
def __init__(self):
|
22
24
|
"""Initialize model"""
|
@@ -33,23 +35,23 @@ class OyiModel(BasePlatform):
|
|
33
35
|
|
34
36
|
self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
|
35
37
|
if self.model_name not in [m.split()[0] for m in self.get_available_models()]:
|
36
|
-
PrettyOutput.print(
|
37
|
-
|
38
|
+
PrettyOutput.print(
|
39
|
+
f"警告: 选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING
|
40
|
+
)
|
38
41
|
|
39
42
|
def set_model_name(self, model_name: str):
|
40
43
|
"""Set model name"""
|
41
44
|
|
42
45
|
self.model_name = model_name
|
43
46
|
|
44
|
-
|
45
47
|
def create_conversation(self) -> bool:
|
46
48
|
"""Create a new conversation"""
|
47
49
|
try:
|
48
50
|
headers = {
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
"Authorization": f"Bearer {self.token}",
|
52
|
+
"Content-Type": "application/json",
|
53
|
+
"Accept": "application/json",
|
54
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
53
55
|
}
|
54
56
|
|
55
57
|
payload = {
|
@@ -58,35 +60,34 @@ class OyiModel(BasePlatform):
|
|
58
60
|
"title": "New conversation",
|
59
61
|
"isLock": False,
|
60
62
|
"systemMessage": "",
|
61
|
-
"params": json.dumps(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
"params": json.dumps(
|
64
|
+
{
|
65
|
+
"model": self.model_name,
|
66
|
+
"is_webSearch": True,
|
67
|
+
"message": [],
|
68
|
+
"systemMessage": None,
|
69
|
+
"requestMsgCount": 65536,
|
70
|
+
"temperature": 0.8,
|
71
|
+
"speechVoice": "Alloy",
|
72
|
+
"max_tokens": 8192,
|
73
|
+
"chatPluginIds": [],
|
74
|
+
}
|
75
|
+
),
|
72
76
|
}
|
73
77
|
|
74
|
-
response =
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
+
response = while_success(
|
79
|
+
lambda: http.post(
|
80
|
+
f"{self.BASE_URL}/chatapi/chat/save", headers=headers, json=payload
|
81
|
+
),
|
82
|
+
sleep_time=5,
|
78
83
|
)
|
79
84
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
return True
|
85
|
-
else:
|
86
|
-
PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.WARNING)
|
87
|
-
return False
|
85
|
+
data = response.json()
|
86
|
+
if data["code"] == 200 and data["type"] == "success":
|
87
|
+
self.conversation = data
|
88
|
+
return True
|
88
89
|
else:
|
89
|
-
PrettyOutput.print(f"创建会话失败: {
|
90
|
+
PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.WARNING)
|
90
91
|
return False
|
91
92
|
|
92
93
|
except Exception as e:
|
@@ -114,19 +115,21 @@ class OyiModel(BasePlatform):
|
|
114
115
|
|
115
116
|
# 1. 发送消息
|
116
117
|
headers = {
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
118
|
+
"Authorization": f"Bearer {self.token}",
|
119
|
+
"Content-Type": "application/json",
|
120
|
+
"Accept": "application/json, text/plain, */*",
|
121
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
122
|
+
"Origin": "https://ai.rcouyi.com",
|
123
|
+
"Referer": "https://ai.rcouyi.com/",
|
123
124
|
}
|
124
125
|
|
125
126
|
payload = {
|
126
|
-
"topicId":
|
127
|
+
"topicId": (
|
128
|
+
self.conversation["result"]["id"] if self.conversation else None
|
129
|
+
),
|
127
130
|
"messages": self.messages,
|
128
131
|
"content": message,
|
129
|
-
"contentFiles": []
|
132
|
+
"contentFiles": [],
|
130
133
|
}
|
131
134
|
|
132
135
|
# 如果有上传的文件,添加到请求中
|
@@ -138,52 +141,47 @@ class OyiModel(BasePlatform):
|
|
138
141
|
self.messages.append({"role": "user", "content": message})
|
139
142
|
|
140
143
|
# 发送消息
|
141
|
-
response =
|
142
|
-
|
143
|
-
|
144
|
-
|
144
|
+
response = while_success(
|
145
|
+
lambda: http.post(
|
146
|
+
f"{self.BASE_URL}/chatapi/chat/message",
|
147
|
+
headers=headers,
|
148
|
+
json=payload,
|
149
|
+
),
|
150
|
+
sleep_time=5,
|
145
151
|
)
|
146
152
|
|
147
|
-
if response.status_code != 200:
|
148
|
-
error_msg = f"聊天请求失败: {response.status_code}"
|
149
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
150
|
-
raise Exception(error_msg)
|
151
|
-
|
152
153
|
data = response.json()
|
153
|
-
if data[
|
154
|
+
if data["code"] != 200 or data["type"] != "success":
|
154
155
|
error_msg = f"聊天失败: {data.get('message', '未知错误')}"
|
155
156
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
156
157
|
raise Exception(error_msg)
|
157
158
|
|
158
|
-
message_id = data[
|
159
|
+
message_id = data["result"][-1]
|
159
160
|
|
160
161
|
# 获取响应内容
|
161
|
-
response =
|
162
|
-
|
163
|
-
|
164
|
-
|
162
|
+
response = while_success(
|
163
|
+
lambda: http.stream_post(
|
164
|
+
f"{self.BASE_URL}/chatapi/chat/message/{message_id}",
|
165
|
+
headers=headers,
|
166
|
+
),
|
167
|
+
sleep_time=5,
|
165
168
|
)
|
166
169
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
return None
|
183
|
-
else:
|
184
|
-
error_msg = f"获取响应失败: {response.status_code}"
|
185
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
186
|
-
raise Exception(error_msg)
|
170
|
+
full_response = ""
|
171
|
+
bin = b""
|
172
|
+
for chunk in response:
|
173
|
+
if chunk:
|
174
|
+
bin += chunk
|
175
|
+
try:
|
176
|
+
text = bin.decode("utf-8")
|
177
|
+
except UnicodeDecodeError:
|
178
|
+
continue
|
179
|
+
full_response += text
|
180
|
+
bin = b""
|
181
|
+
yield text
|
182
|
+
|
183
|
+
self.messages.append({"role": "assistant", "content": full_response})
|
184
|
+
return None
|
187
185
|
except Exception as e:
|
188
186
|
PrettyOutput.print(f"聊天失败: {str(e)}", OutputType.ERROR)
|
189
187
|
raise e
|
@@ -192,7 +190,6 @@ class OyiModel(BasePlatform):
|
|
192
190
|
"""Return model name"""
|
193
191
|
return self.model_name
|
194
192
|
|
195
|
-
|
196
193
|
def delete_chat(self) -> bool:
|
197
194
|
"""Delete current chat session"""
|
198
195
|
try:
|
@@ -200,41 +197,84 @@ class OyiModel(BasePlatform):
|
|
200
197
|
return True
|
201
198
|
|
202
199
|
headers = {
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
200
|
+
"Authorization": f"Bearer {self.token}",
|
201
|
+
"Content-Type": "application/json",
|
202
|
+
"Accept": "application/json, text/plain, */*",
|
203
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
204
|
+
"Origin": "https://ai.rcouyi.com",
|
205
|
+
"Referer": "https://ai.rcouyi.com/",
|
209
206
|
}
|
210
207
|
|
211
|
-
response =
|
212
|
-
|
213
|
-
|
214
|
-
|
208
|
+
response = while_success(
|
209
|
+
lambda: http.post(
|
210
|
+
f"{self.BASE_URL}/chatapi/chat/{self.conversation['result']['id']}", # type: ignore
|
211
|
+
headers=headers,
|
212
|
+
json={},
|
213
|
+
),
|
214
|
+
sleep_time=5,
|
215
215
|
)
|
216
216
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
return True
|
224
|
-
else:
|
225
|
-
error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
|
226
|
-
PrettyOutput.print(error_msg, OutputType.WARNING)
|
227
|
-
return False
|
217
|
+
data = response.json()
|
218
|
+
if data["code"] == 200 and data["type"] == "success":
|
219
|
+
self.messages = []
|
220
|
+
self.conversation = None
|
221
|
+
self.first_chat = True
|
222
|
+
return True
|
228
223
|
else:
|
229
|
-
error_msg = f"
|
224
|
+
error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
|
230
225
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
231
226
|
return False
|
232
227
|
|
233
|
-
|
234
228
|
except Exception as e:
|
235
229
|
PrettyOutput.print(f"删除会话失败: {str(e)}", OutputType.ERROR)
|
236
230
|
return False
|
237
231
|
|
232
|
+
def save(self, file_path: str) -> bool:
|
233
|
+
"""Save chat session to a file."""
|
234
|
+
if not self.conversation:
|
235
|
+
PrettyOutput.print("没有活动的会话可供保存", OutputType.WARNING)
|
236
|
+
return False
|
237
|
+
|
238
|
+
state = {
|
239
|
+
"conversation": self.conversation,
|
240
|
+
"messages": self.messages,
|
241
|
+
"model_name": self.model_name,
|
242
|
+
"system_prompt": self.system_prompt,
|
243
|
+
"first_chat": self.first_chat,
|
244
|
+
}
|
245
|
+
|
246
|
+
try:
|
247
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
248
|
+
json.dump(state, f, ensure_ascii=False, indent=4)
|
249
|
+
self._saved = True
|
250
|
+
PrettyOutput.print(f"会话已成功保存到 {file_path}", OutputType.SUCCESS)
|
251
|
+
return True
|
252
|
+
except Exception as e:
|
253
|
+
PrettyOutput.print(f"保存会话失败: {str(e)}", OutputType.ERROR)
|
254
|
+
return False
|
255
|
+
|
256
|
+
def restore(self, file_path: str) -> bool:
|
257
|
+
"""Restore chat session from a file."""
|
258
|
+
try:
|
259
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
260
|
+
state = json.load(f)
|
261
|
+
|
262
|
+
self.conversation = state.get("conversation")
|
263
|
+
self.messages = state.get("messages", [])
|
264
|
+
self.model_name = state.get("model_name", "deepseek-chat")
|
265
|
+
self.system_prompt = state.get("system_prompt", "")
|
266
|
+
self.first_chat = state.get("first_chat", True)
|
267
|
+
self._saved = True
|
268
|
+
|
269
|
+
PrettyOutput.print(f"从 {file_path} 成功恢复会话", OutputType.SUCCESS)
|
270
|
+
return True
|
271
|
+
except FileNotFoundError:
|
272
|
+
PrettyOutput.print(f"会话文件未找到: {file_path}", OutputType.ERROR)
|
273
|
+
return False
|
274
|
+
except Exception as e:
|
275
|
+
PrettyOutput.print(f"恢复会话失败: {str(e)}", OutputType.ERROR)
|
276
|
+
return False
|
277
|
+
|
238
278
|
def get_available_models(self) -> List[str]:
|
239
279
|
"""Get available model list
|
240
280
|
|
@@ -246,55 +286,53 @@ class OyiModel(BasePlatform):
|
|
246
286
|
return list(self.models.keys())
|
247
287
|
|
248
288
|
headers = {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
289
|
+
"Content-Type": "application/json",
|
290
|
+
"Accept": "application/json, text/plain, */*",
|
291
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
292
|
+
"Origin": "https://ai.rcouyi.com",
|
293
|
+
"Referer": "https://ai.rcouyi.com/",
|
254
294
|
}
|
255
295
|
|
256
|
-
response =
|
257
|
-
|
258
|
-
|
296
|
+
response = while_success(
|
297
|
+
lambda: http.get(
|
298
|
+
"https://ai.rcouyi.com/config/system.json", headers=headers
|
299
|
+
),
|
300
|
+
sleep_time=5,
|
259
301
|
)
|
260
302
|
|
261
|
-
if response.status_code != 200:
|
262
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
263
|
-
return []
|
264
|
-
|
265
303
|
data = response.json()
|
266
304
|
|
267
305
|
# 保存模型信息
|
268
306
|
self.models = {
|
269
|
-
model[
|
270
|
-
for model in data.get(
|
271
|
-
if model.get(
|
307
|
+
model["value"]: model
|
308
|
+
for model in data.get("model", [])
|
309
|
+
if model.get("enable", False) # 只保存启用的模型
|
272
310
|
}
|
273
311
|
|
274
312
|
# 格式化显示
|
275
313
|
models = []
|
276
314
|
for model in self.models.values():
|
277
315
|
# 基本信息
|
278
|
-
model_name = model[
|
279
|
-
model_str = model[
|
316
|
+
model_name = model["value"]
|
317
|
+
model_str = model["label"]
|
280
318
|
|
281
319
|
# 添加后缀标签
|
282
|
-
suffix = model.get(
|
320
|
+
suffix = model.get("suffix", [])
|
283
321
|
if suffix:
|
284
322
|
# 处理新格式的suffix (字典列表)
|
285
323
|
if suffix and isinstance(suffix[0], dict):
|
286
|
-
suffix_str =
|
324
|
+
suffix_str = ", ".join(s.get("tag", "") for s in suffix)
|
287
325
|
# 处理旧格式的suffix (字符串列表)
|
288
326
|
else:
|
289
|
-
suffix_str =
|
327
|
+
suffix_str = ", ".join(str(s) for s in suffix)
|
290
328
|
model_str += f" ({suffix_str})"
|
291
329
|
|
292
330
|
# 添加描述或提示
|
293
|
-
info = model.get(
|
331
|
+
info = model.get("tooltip") or model.get("description", "")
|
294
332
|
if info:
|
295
333
|
model_str += f" - {info}"
|
296
334
|
|
297
|
-
model[
|
335
|
+
model["desc"] = model_str
|
298
336
|
models.append(model_name)
|
299
337
|
|
300
338
|
return sorted(models)
|
@@ -305,10 +343,9 @@ class OyiModel(BasePlatform):
|
|
305
343
|
|
306
344
|
def support_upload_files(self) -> bool:
|
307
345
|
return False
|
308
|
-
|
309
|
-
|
346
|
+
|
310
347
|
def support_web(self) -> bool:
|
311
348
|
return False
|
312
|
-
|
349
|
+
|
313
350
|
def upload_files(self, file_list: List[str]) -> bool:
|
314
351
|
return False
|
jarvis/jarvis_platform/tongyi.py
CHANGED
@@ -264,7 +264,7 @@ class TongyiPlatform(BasePlatform):
|
|
264
264
|
"""
|
265
265
|
url = "https://api.tongyi.com/dialog/uploadToken"
|
266
266
|
headers = self._get_base_headers()
|
267
|
-
payload = {}
|
267
|
+
payload: Dict[str, Any] = {}
|
268
268
|
|
269
269
|
try:
|
270
270
|
response = while_success(
|
@@ -395,16 +395,12 @@ class TongyiPlatform(BasePlatform):
|
|
395
395
|
add_url, headers=headers, json=add_payload
|
396
396
|
)
|
397
397
|
if add_response.status_code != 200:
|
398
|
-
print(
|
399
|
-
f"❌ 添加文件到对话失败: HTTP {add_response.status_code}"
|
400
|
-
)
|
398
|
+
print(f"❌ 添加文件到对话失败: HTTP {add_response.status_code}")
|
401
399
|
continue
|
402
400
|
|
403
401
|
add_result = add_response.json()
|
404
402
|
if not add_result.get("success"):
|
405
|
-
print(
|
406
|
-
f"❌ 添加文件到对话失败: {add_result.get('errorMsg')}"
|
407
|
-
)
|
403
|
+
print(f"❌ 添加文件到对话失败: {add_result.get('errorMsg')}")
|
408
404
|
continue
|
409
405
|
|
410
406
|
file_info.update(add_result.get("data", {}))
|
@@ -491,6 +487,56 @@ class TongyiPlatform(BasePlatform):
|
|
491
487
|
PrettyOutput.print(f"Error deleting chat: {str(e)}", OutputType.ERROR)
|
492
488
|
return False
|
493
489
|
|
490
|
+
def save(self, file_path: str) -> bool:
|
491
|
+
"""Save chat session to a file."""
|
492
|
+
if not self.session_id:
|
493
|
+
PrettyOutput.print("没有活动的会话可供保存", OutputType.WARNING)
|
494
|
+
return False
|
495
|
+
|
496
|
+
state = {
|
497
|
+
"session_id": self.session_id,
|
498
|
+
"request_id": self.request_id,
|
499
|
+
"msg_id": self.msg_id,
|
500
|
+
"model_name": self.model_name,
|
501
|
+
"uploaded_file_info": self.uploaded_file_info,
|
502
|
+
"system_message": self.system_message,
|
503
|
+
"first_chat": self.first_chat,
|
504
|
+
}
|
505
|
+
|
506
|
+
try:
|
507
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
508
|
+
json.dump(state, f, ensure_ascii=False, indent=4)
|
509
|
+
self._saved = True
|
510
|
+
PrettyOutput.print(f"会话已成功保存到 {file_path}", OutputType.SUCCESS)
|
511
|
+
return True
|
512
|
+
except Exception as e:
|
513
|
+
PrettyOutput.print(f"保存会话失败: {str(e)}", OutputType.ERROR)
|
514
|
+
return False
|
515
|
+
|
516
|
+
def restore(self, file_path: str) -> bool:
|
517
|
+
"""Restore chat session from a file."""
|
518
|
+
try:
|
519
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
520
|
+
state = json.load(f)
|
521
|
+
|
522
|
+
self.session_id = state.get("session_id", "")
|
523
|
+
self.request_id = state.get("request_id", "")
|
524
|
+
self.msg_id = state.get("msg_id", "")
|
525
|
+
self.model_name = state.get("model_name", "")
|
526
|
+
self.uploaded_file_info = state.get("uploaded_file_info", [])
|
527
|
+
self.system_message = state.get("system_message", "")
|
528
|
+
self.first_chat = state.get("first_chat", True)
|
529
|
+
self._saved = True
|
530
|
+
|
531
|
+
PrettyOutput.print(f"从 {file_path} 成功恢复会话", OutputType.SUCCESS)
|
532
|
+
return True
|
533
|
+
except FileNotFoundError:
|
534
|
+
PrettyOutput.print(f"会话文件未找到: {file_path}", OutputType.ERROR)
|
535
|
+
return False
|
536
|
+
except Exception as e:
|
537
|
+
PrettyOutput.print(f"恢复会话失败: {str(e)}", OutputType.ERROR)
|
538
|
+
return False
|
539
|
+
|
494
540
|
def set_system_prompt(self, message: str):
|
495
541
|
"""Set system message
|
496
542
|
|
@@ -104,9 +104,7 @@ class YuanbaoPlatform(BasePlatform):
|
|
104
104
|
self.conversation_id = response_json["id"]
|
105
105
|
return True
|
106
106
|
else:
|
107
|
-
PrettyOutput.print(
|
108
|
-
f"错误:创建会话失败,响应: {response_json}", OutputType.ERROR
|
109
|
-
)
|
107
|
+
PrettyOutput.print(f"错误:创建会话失败,响应: {response_json}", OutputType.ERROR)
|
110
108
|
return False
|
111
109
|
except Exception as e:
|
112
110
|
PrettyOutput.print(f"错误:创建会话失败:{e}", OutputType.ERROR)
|
@@ -135,7 +133,6 @@ class YuanbaoPlatform(BasePlatform):
|
|
135
133
|
file_name = os.path.basename(file_path)
|
136
134
|
print(f"🔍 上传文件 {file_name}")
|
137
135
|
try:
|
138
|
-
|
139
136
|
# 1. Prepare the file information
|
140
137
|
print(f"🔍 准备文件信息: {file_name}")
|
141
138
|
file_size = os.path.getsize(file_path)
|
@@ -572,6 +569,52 @@ class YuanbaoPlatform(BasePlatform):
|
|
572
569
|
PrettyOutput.print(f"删除会话时发生错误: {str(e)}", OutputType.ERROR)
|
573
570
|
return False
|
574
571
|
|
572
|
+
def save(self, file_path: str) -> bool:
|
573
|
+
"""Save chat session to a file."""
|
574
|
+
if not self.conversation_id:
|
575
|
+
PrettyOutput.print("没有活动的会话可供保存", OutputType.WARNING)
|
576
|
+
return False
|
577
|
+
|
578
|
+
state = {
|
579
|
+
"conversation_id": self.conversation_id,
|
580
|
+
"system_message": self.system_message,
|
581
|
+
"first_chat": self.first_chat,
|
582
|
+
"model_name": self.model_name,
|
583
|
+
"multimedia": self.multimedia,
|
584
|
+
}
|
585
|
+
|
586
|
+
try:
|
587
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
588
|
+
json.dump(state, f, ensure_ascii=False, indent=4)
|
589
|
+
self._saved = True
|
590
|
+
PrettyOutput.print(f"会话已成功保存到 {file_path}", OutputType.SUCCESS)
|
591
|
+
return True
|
592
|
+
except Exception as e:
|
593
|
+
PrettyOutput.print(f"保存会话失败: {str(e)}", OutputType.ERROR)
|
594
|
+
return False
|
595
|
+
|
596
|
+
def restore(self, file_path: str) -> bool:
|
597
|
+
"""Restore chat session from a file."""
|
598
|
+
try:
|
599
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
600
|
+
state = json.load(f)
|
601
|
+
|
602
|
+
self.conversation_id = state.get("conversation_id", "")
|
603
|
+
self.system_message = state.get("system_message", "")
|
604
|
+
self.first_chat = state.get("first_chat", True)
|
605
|
+
self.model_name = state.get("model_name", "deep_seek_v3")
|
606
|
+
self.multimedia = state.get("multimedia", [])
|
607
|
+
self._saved = True
|
608
|
+
|
609
|
+
PrettyOutput.print(f"从 {file_path} 成功恢复会话", OutputType.SUCCESS)
|
610
|
+
return True
|
611
|
+
except FileNotFoundError:
|
612
|
+
PrettyOutput.print(f"会话文件未找到: {file_path}", OutputType.ERROR)
|
613
|
+
return False
|
614
|
+
except Exception as e:
|
615
|
+
PrettyOutput.print(f"恢复会话失败: {str(e)}", OutputType.ERROR)
|
616
|
+
return False
|
617
|
+
|
575
618
|
def name(self) -> str:
|
576
619
|
"""模型名称"""
|
577
620
|
return self.model_name
|