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