jarvis-ai-assistant 0.1.46__py3-none-any.whl → 0.1.48__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- jarvis/__init__.py +1 -1
- jarvis/agent.py +32 -47
- jarvis/main.py +35 -51
- jarvis/models/__init__.py +1 -1
- jarvis/models/ai8.py +58 -88
- jarvis/models/base.py +6 -6
- jarvis/models/kimi.py +80 -171
- jarvis/models/openai.py +23 -43
- jarvis/models/oyi.py +91 -113
- jarvis/models/registry.py +44 -63
- jarvis/tools/__init__.py +1 -1
- jarvis/tools/base.py +2 -2
- jarvis/tools/file_ops.py +15 -19
- jarvis/tools/generator.py +12 -15
- jarvis/tools/methodology.py +20 -20
- jarvis/tools/registry.py +30 -44
- jarvis/tools/shell.py +11 -12
- jarvis/tools/sub_agent.py +2 -1
- jarvis/utils.py +27 -47
- {jarvis_ai_assistant-0.1.46.dist-info → jarvis_ai_assistant-0.1.48.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.48.dist-info/RECORD +25 -0
- jarvis_ai_assistant-0.1.46.dist-info/RECORD +0 -25
- {jarvis_ai_assistant-0.1.46.dist-info → jarvis_ai_assistant-0.1.48.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.46.dist-info → jarvis_ai_assistant-0.1.48.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.46.dist-info → jarvis_ai_assistant-0.1.48.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.46.dist-info → jarvis_ai_assistant-0.1.48.dist-info}/top_level.txt +0 -0
jarvis/models/ai8.py
CHANGED
@@ -6,13 +6,12 @@ import requests
|
|
6
6
|
import json
|
7
7
|
import base64
|
8
8
|
|
9
|
-
|
10
9
|
class AI8Model(BasePlatform):
|
11
10
|
"""AI8 model implementation"""
|
12
|
-
|
11
|
+
|
13
12
|
platform_name = "ai8"
|
14
13
|
BASE_URL = "https://ai8.rcouyi.com"
|
15
|
-
|
14
|
+
|
16
15
|
def __init__(self):
|
17
16
|
"""Initialize model"""
|
18
17
|
self.system_message = ""
|
@@ -22,23 +21,23 @@ class AI8Model(BasePlatform):
|
|
22
21
|
|
23
22
|
# 获取可用模型列表
|
24
23
|
available_models = self.get_available_models()
|
25
|
-
|
24
|
+
|
26
25
|
if available_models:
|
27
26
|
PrettyOutput.section("支持的模型", OutputType.SUCCESS)
|
28
27
|
for model in self.models.values():
|
29
28
|
# 格式化显示模型信息
|
30
29
|
model_str = f"{model['value']:<30}"
|
31
|
-
|
30
|
+
|
32
31
|
# 添加标签
|
33
32
|
model_str += f"{model['label']}"
|
34
|
-
|
33
|
+
|
35
34
|
# 添加标签和积分信息
|
36
35
|
attrs = []
|
37
36
|
if model['attr'].get('tag'):
|
38
37
|
attrs.append(model['attr']['tag'])
|
39
38
|
if model['attr'].get('integral'):
|
40
39
|
attrs.append(model['attr']['integral'])
|
41
|
-
|
40
|
+
|
42
41
|
# 添加特性标记
|
43
42
|
features = []
|
44
43
|
if model['attr'].get('multimodal'):
|
@@ -49,11 +48,11 @@ class AI8Model(BasePlatform):
|
|
49
48
|
features.append("图像支持")
|
50
49
|
if features:
|
51
50
|
model_str += f" [{'|'.join(features)}]"
|
52
|
-
|
51
|
+
|
53
52
|
# 添加备注
|
54
53
|
if model['attr'].get('note'):
|
55
54
|
model_str += f" - {model['attr']['note']}"
|
56
|
-
|
55
|
+
|
57
56
|
PrettyOutput.print(model_str, OutputType.INFO)
|
58
57
|
else:
|
59
58
|
PrettyOutput.print("获取模型列表失败", OutputType.WARNING)
|
@@ -61,22 +60,19 @@ class AI8Model(BasePlatform):
|
|
61
60
|
self.token = os.getenv("AI8_API_KEY")
|
62
61
|
if not self.token:
|
63
62
|
raise Exception("AI8_API_KEY is not set")
|
64
|
-
|
63
|
+
|
65
64
|
PrettyOutput.print("使用AI8_MODEL环境变量配置模型", OutputType.SUCCESS)
|
66
|
-
|
65
|
+
|
67
66
|
self.model_name = os.getenv("AI8_MODEL") or "deepseek-chat"
|
68
67
|
if self.model_name not in self.models:
|
69
|
-
PrettyOutput.print(
|
70
|
-
|
71
|
-
self.model_name} 不在可用列表中",
|
72
|
-
OutputType.WARNING)
|
73
|
-
|
68
|
+
PrettyOutput.print(f"警告: 当前选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING)
|
69
|
+
|
74
70
|
PrettyOutput.print(f"当前使用模型: {self.model_name}", OutputType.SYSTEM)
|
75
71
|
|
76
72
|
def set_model_name(self, model_name: str):
|
77
73
|
"""设置模型名称"""
|
78
74
|
self.model_name = model_name
|
79
|
-
|
75
|
+
|
80
76
|
def create_conversation(self) -> bool:
|
81
77
|
"""Create a new conversation"""
|
82
78
|
try:
|
@@ -89,36 +85,25 @@ class AI8Model(BasePlatform):
|
|
89
85
|
'Origin': self.BASE_URL,
|
90
86
|
'Referer': f'{self.BASE_URL}/chat?_userMenuKey=chat'
|
91
87
|
}
|
92
|
-
|
88
|
+
|
93
89
|
# 1. 创建会话
|
94
90
|
response = requests.post(
|
95
91
|
f"{self.BASE_URL}/api/chat/session",
|
96
92
|
headers=headers
|
97
93
|
)
|
98
|
-
|
94
|
+
|
99
95
|
if response.status_code != 200:
|
100
|
-
PrettyOutput.print(
|
101
|
-
f"创建会话失败: {
|
102
|
-
response.status_code}",
|
103
|
-
OutputType.ERROR)
|
96
|
+
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.ERROR)
|
104
97
|
return False
|
105
|
-
|
98
|
+
|
106
99
|
data = response.json()
|
107
100
|
if data['code'] != 0:
|
108
|
-
PrettyOutput.print(
|
109
|
-
f"创建会话失败: {
|
110
|
-
data.get(
|
111
|
-
'msg',
|
112
|
-
'未知错误')}",
|
113
|
-
OutputType.ERROR)
|
101
|
+
PrettyOutput.print(f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.ERROR)
|
114
102
|
return False
|
115
|
-
|
103
|
+
|
116
104
|
self.conversation = data['data']
|
117
|
-
PrettyOutput.print(
|
118
|
-
|
119
|
-
data['data']['id']}",
|
120
|
-
OutputType.SUCCESS)
|
121
|
-
|
105
|
+
PrettyOutput.print(f"创建会话成功: {data['data']['id']}", OutputType.SUCCESS)
|
106
|
+
|
122
107
|
# 2. 更新会话设置
|
123
108
|
session_data = {
|
124
109
|
**self.conversation,
|
@@ -129,13 +114,13 @@ class AI8Model(BasePlatform):
|
|
129
114
|
"localPlugins": None,
|
130
115
|
"useAppId": 0
|
131
116
|
}
|
132
|
-
|
117
|
+
|
133
118
|
response = requests.put(
|
134
119
|
f"{self.BASE_URL}/api/chat/session/{self.conversation['id']}",
|
135
120
|
headers=headers,
|
136
121
|
json=session_data
|
137
122
|
)
|
138
|
-
|
123
|
+
|
139
124
|
if response.status_code == 200:
|
140
125
|
data = response.json()
|
141
126
|
if data['code'] == 0:
|
@@ -143,24 +128,16 @@ class AI8Model(BasePlatform):
|
|
143
128
|
PrettyOutput.print("会话设置更新成功", OutputType.SUCCESS)
|
144
129
|
return True
|
145
130
|
else:
|
146
|
-
PrettyOutput.print(
|
147
|
-
f"更新会话设置失败: {
|
148
|
-
data.get(
|
149
|
-
'msg',
|
150
|
-
'未知错误')}",
|
151
|
-
OutputType.ERROR)
|
131
|
+
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.ERROR)
|
152
132
|
return False
|
153
133
|
else:
|
154
|
-
PrettyOutput.print(
|
155
|
-
f"更新会话设置失败: {
|
156
|
-
response.status_code}",
|
157
|
-
OutputType.ERROR)
|
134
|
+
PrettyOutput.print(f"更新会话设置失败: {response.status_code}", OutputType.ERROR)
|
158
135
|
return False
|
159
|
-
|
136
|
+
|
160
137
|
except Exception as e:
|
161
138
|
PrettyOutput.print(f"创建会话异常: {str(e)}", OutputType.ERROR)
|
162
139
|
return False
|
163
|
-
|
140
|
+
|
164
141
|
def upload_files(self, file_list: List[str]) -> List[Dict]:
|
165
142
|
for file_path in file_list:
|
166
143
|
name = os.path.basename(file_path)
|
@@ -172,17 +149,17 @@ class AI8Model(BasePlatform):
|
|
172
149
|
"data": f"data:image/png;base64,{base64_data}"
|
173
150
|
})
|
174
151
|
PrettyOutput.print(f"文件 {name} 已准备好发送", OutputType.SUCCESS)
|
175
|
-
|
152
|
+
|
176
153
|
def set_system_message(self, message: str):
|
177
154
|
"""Set system message"""
|
178
155
|
self.system_message = message
|
179
|
-
|
156
|
+
|
180
157
|
def chat(self, message: str) -> str:
|
181
158
|
"""Execute chat with the model
|
182
|
-
|
159
|
+
|
183
160
|
Args:
|
184
161
|
message: User input message
|
185
|
-
|
162
|
+
|
186
163
|
Returns:
|
187
164
|
str: Model response
|
188
165
|
"""
|
@@ -191,7 +168,7 @@ class AI8Model(BasePlatform):
|
|
191
168
|
if not self.conversation:
|
192
169
|
if not self.create_conversation():
|
193
170
|
raise Exception("Failed to create conversation")
|
194
|
-
|
171
|
+
|
195
172
|
headers = {
|
196
173
|
'Authorization': self.token,
|
197
174
|
'Content-Type': 'application/json',
|
@@ -201,13 +178,13 @@ class AI8Model(BasePlatform):
|
|
201
178
|
'Origin': self.BASE_URL,
|
202
179
|
'Referer': f'{self.BASE_URL}/chat?_userMenuKey=chat'
|
203
180
|
}
|
204
|
-
|
181
|
+
|
205
182
|
payload = {
|
206
183
|
"text": message,
|
207
184
|
"sessionId": self.conversation['id'],
|
208
185
|
"files": []
|
209
186
|
}
|
210
|
-
|
187
|
+
|
211
188
|
# 如果有文件需要发送
|
212
189
|
if self.files:
|
213
190
|
for file_data in self.files:
|
@@ -216,19 +193,19 @@ class AI8Model(BasePlatform):
|
|
216
193
|
"data": file_data["data"]
|
217
194
|
})
|
218
195
|
self.files = [] # 清空已使用的文件
|
219
|
-
|
196
|
+
|
220
197
|
response = requests.post(
|
221
198
|
f"{self.BASE_URL}/api/chat/completions",
|
222
199
|
headers=headers,
|
223
200
|
json=payload,
|
224
201
|
stream=True
|
225
202
|
)
|
226
|
-
|
203
|
+
|
227
204
|
if response.status_code != 200:
|
228
205
|
error_msg = f"聊天请求失败: {response.status_code}"
|
229
206
|
PrettyOutput.print(error_msg, OutputType.ERROR)
|
230
207
|
raise Exception(error_msg)
|
231
|
-
|
208
|
+
|
232
209
|
# 处理流式响应
|
233
210
|
full_response = ""
|
234
211
|
for line in response.iter_lines():
|
@@ -245,30 +222,30 @@ class AI8Model(BasePlatform):
|
|
245
222
|
|
246
223
|
except json.JSONDecodeError:
|
247
224
|
continue
|
248
|
-
|
225
|
+
|
249
226
|
PrettyOutput.print_stream_end()
|
250
227
|
|
251
228
|
return full_response
|
252
|
-
|
229
|
+
|
253
230
|
except Exception as e:
|
254
231
|
PrettyOutput.print(f"聊天异常: {str(e)}", OutputType.ERROR)
|
255
232
|
raise e
|
256
|
-
|
233
|
+
|
257
234
|
def name(self) -> str:
|
258
235
|
"""Return model name"""
|
259
236
|
return self.model_name
|
260
|
-
|
237
|
+
|
261
238
|
def reset(self):
|
262
239
|
"""Reset model state"""
|
263
240
|
self.conversation = None
|
264
241
|
self.files = [] # 清空文件列表
|
265
|
-
|
242
|
+
|
266
243
|
def delete_chat(self) -> bool:
|
267
244
|
"""Delete current chat session"""
|
268
245
|
try:
|
269
246
|
if not self.conversation:
|
270
247
|
return True
|
271
|
-
|
248
|
+
|
272
249
|
headers = {
|
273
250
|
'Authorization': self.token,
|
274
251
|
'Content-Type': 'application/json',
|
@@ -278,12 +255,12 @@ class AI8Model(BasePlatform):
|
|
278
255
|
'Origin': self.BASE_URL,
|
279
256
|
'Referer': f'{self.BASE_URL}/chat?_userMenuKey=chat'
|
280
257
|
}
|
281
|
-
|
258
|
+
|
282
259
|
response = requests.delete(
|
283
260
|
f"{self.BASE_URL}/api/chat/session/{self.conversation['id']}",
|
284
261
|
headers=headers
|
285
262
|
)
|
286
|
-
|
263
|
+
|
287
264
|
if response.status_code == 200:
|
288
265
|
data = response.json()
|
289
266
|
if data['code'] == 0:
|
@@ -298,14 +275,14 @@ class AI8Model(BasePlatform):
|
|
298
275
|
error_msg = f"删除会话请求失败: {response.status_code}"
|
299
276
|
PrettyOutput.print(error_msg, OutputType.ERROR)
|
300
277
|
return False
|
301
|
-
|
278
|
+
|
302
279
|
except Exception as e:
|
303
280
|
PrettyOutput.print(f"删除会话异常: {str(e)}", OutputType.ERROR)
|
304
281
|
return False
|
305
|
-
|
282
|
+
|
306
283
|
def get_available_models(self) -> List[str]:
|
307
284
|
"""获取可用的模型列表
|
308
|
-
|
285
|
+
|
309
286
|
Returns:
|
310
287
|
List[str]: 可用模型名称列表
|
311
288
|
"""
|
@@ -318,37 +295,30 @@ class AI8Model(BasePlatform):
|
|
318
295
|
'Origin': self.BASE_URL,
|
319
296
|
'Referer': f'{self.BASE_URL}/chat?_userMenuKey=chat'
|
320
297
|
}
|
321
|
-
|
298
|
+
|
322
299
|
response = requests.get(
|
323
300
|
f"{self.BASE_URL}/api/chat/template",
|
324
301
|
headers=headers
|
325
302
|
)
|
326
|
-
|
303
|
+
|
327
304
|
if response.status_code != 200:
|
328
|
-
PrettyOutput.print(
|
329
|
-
f"获取模型列表失败: {
|
330
|
-
response.status_code}",
|
331
|
-
OutputType.ERROR)
|
305
|
+
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.ERROR)
|
332
306
|
return []
|
333
|
-
|
307
|
+
|
334
308
|
data = response.json()
|
335
309
|
if data['code'] != 0:
|
336
|
-
PrettyOutput.print(
|
337
|
-
f"获取模型列表失败: {
|
338
|
-
data.get(
|
339
|
-
'msg',
|
340
|
-
'未知错误')}",
|
341
|
-
OutputType.ERROR)
|
310
|
+
PrettyOutput.print(f"获取模型列表失败: {data.get('msg', '未知错误')}", OutputType.ERROR)
|
342
311
|
return []
|
343
|
-
|
312
|
+
|
344
313
|
# 保存模型信息
|
345
314
|
self.models = {
|
346
|
-
model['value']: model
|
315
|
+
model['value']: model
|
347
316
|
for model in data['data']['models']
|
348
317
|
}
|
349
|
-
|
318
|
+
|
350
319
|
return list(self.models.keys())
|
351
|
-
|
320
|
+
|
352
321
|
except Exception as e:
|
353
322
|
PrettyOutput.print(f"获取模型列表异常: {str(e)}", OutputType.ERROR)
|
354
323
|
return []
|
324
|
+
|
jarvis/models/base.py
CHANGED
@@ -4,7 +4,7 @@ from typing import Dict, List
|
|
4
4
|
|
5
5
|
class BasePlatform(ABC):
|
6
6
|
"""大语言模型基类"""
|
7
|
-
|
7
|
+
|
8
8
|
def __init__(self):
|
9
9
|
"""初始化模型"""
|
10
10
|
pass
|
@@ -12,7 +12,7 @@ class BasePlatform(ABC):
|
|
12
12
|
def set_model_name(self, model_name: str):
|
13
13
|
"""设置模型名称"""
|
14
14
|
raise NotImplementedError("set_model_name is not implemented")
|
15
|
-
|
15
|
+
|
16
16
|
@abstractmethod
|
17
17
|
def chat(self, message: str) -> str:
|
18
18
|
"""执行对话"""
|
@@ -25,17 +25,17 @@ class BasePlatform(ABC):
|
|
25
25
|
def reset(self):
|
26
26
|
"""重置模型"""
|
27
27
|
raise NotImplementedError("reset is not implemented")
|
28
|
-
|
28
|
+
|
29
29
|
@abstractmethod
|
30
30
|
def name(self) -> str:
|
31
31
|
"""模型名称"""
|
32
32
|
raise NotImplementedError("name is not implemented")
|
33
|
-
|
33
|
+
|
34
34
|
@abstractmethod
|
35
|
-
def delete_chat(self)
|
35
|
+
def delete_chat(self)->bool:
|
36
36
|
"""删除对话"""
|
37
37
|
raise NotImplementedError("delete_chat is not implemented")
|
38
|
-
|
38
|
+
|
39
39
|
def set_system_message(self, message: str):
|
40
40
|
"""设置系统消息"""
|
41
41
|
raise NotImplementedError("set_system_message is not implemented")
|