jarvis-ai-assistant 0.2.7__py3-none-any.whl → 0.3.0__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 +267 -240
- jarvis/jarvis_agent/agent_manager.py +85 -0
- jarvis/jarvis_agent/config_editor.py +53 -0
- jarvis/jarvis_agent/file_methodology_manager.py +105 -0
- jarvis/jarvis_agent/jarvis.py +37 -398
- jarvis/jarvis_agent/memory_manager.py +133 -0
- jarvis/jarvis_agent/methodology_share_manager.py +174 -0
- jarvis/jarvis_agent/prompts.py +18 -3
- jarvis/jarvis_agent/share_manager.py +176 -0
- jarvis/jarvis_agent/task_analyzer.py +126 -0
- jarvis/jarvis_agent/task_manager.py +111 -0
- jarvis/jarvis_agent/tool_share_manager.py +139 -0
- jarvis/jarvis_code_agent/code_agent.py +26 -20
- jarvis/jarvis_data/config_schema.json +37 -0
- jarvis/jarvis_platform/ai8.py +13 -1
- jarvis/jarvis_platform/base.py +20 -5
- jarvis/jarvis_platform/human.py +11 -1
- jarvis/jarvis_platform/kimi.py +10 -0
- jarvis/jarvis_platform/openai.py +20 -0
- jarvis/jarvis_platform/tongyi.py +14 -9
- jarvis/jarvis_platform/yuanbao.py +10 -0
- jarvis/jarvis_platform_manager/main.py +12 -12
- jarvis/jarvis_tools/registry.py +79 -20
- jarvis/jarvis_tools/retrieve_memory.py +36 -8
- jarvis/jarvis_utils/clipboard.py +90 -0
- jarvis/jarvis_utils/config.py +64 -0
- jarvis/jarvis_utils/git_utils.py +17 -7
- jarvis/jarvis_utils/globals.py +18 -12
- jarvis/jarvis_utils/input.py +118 -16
- jarvis/jarvis_utils/methodology.py +48 -5
- jarvis/jarvis_utils/utils.py +196 -106
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/RECORD +38 -28
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""工具分享管理模块"""
|
3
|
+
import os
|
4
|
+
import glob
|
5
|
+
import shutil
|
6
|
+
from typing import List, Dict, Any, Set
|
7
|
+
|
8
|
+
import typer
|
9
|
+
|
10
|
+
from jarvis.jarvis_agent import OutputType, PrettyOutput, user_confirm
|
11
|
+
from jarvis.jarvis_agent.share_manager import ShareManager
|
12
|
+
from jarvis.jarvis_utils.config import get_central_tool_repo, get_data_dir
|
13
|
+
|
14
|
+
|
15
|
+
class ToolShareManager(ShareManager):
|
16
|
+
"""工具分享管理器"""
|
17
|
+
|
18
|
+
def __init__(self):
|
19
|
+
central_repo = get_central_tool_repo()
|
20
|
+
if not central_repo:
|
21
|
+
PrettyOutput.print(
|
22
|
+
"错误:未配置中心工具仓库(JARVIS_CENTRAL_TOOL_REPO)",
|
23
|
+
OutputType.ERROR,
|
24
|
+
)
|
25
|
+
PrettyOutput.print(
|
26
|
+
"请在配置文件中设置中心工具仓库的Git地址", OutputType.INFO
|
27
|
+
)
|
28
|
+
raise typer.Exit(code=1)
|
29
|
+
|
30
|
+
super().__init__(central_repo, "central_tool_repo")
|
31
|
+
|
32
|
+
def get_resource_type(self) -> str:
|
33
|
+
"""获取资源类型名称"""
|
34
|
+
return "工具"
|
35
|
+
|
36
|
+
def format_resource_display(self, resource: Dict[str, Any]) -> str:
|
37
|
+
"""格式化资源显示"""
|
38
|
+
return f"{resource['tool_name']} ({resource['filename']})"
|
39
|
+
|
40
|
+
def get_existing_resources(self) -> Set[str]:
|
41
|
+
"""获取中心仓库中已有的工具文件名"""
|
42
|
+
existing_tools = set()
|
43
|
+
for filepath in glob.glob(os.path.join(self.repo_path, "*.py")):
|
44
|
+
existing_tools.add(os.path.basename(filepath))
|
45
|
+
return existing_tools
|
46
|
+
|
47
|
+
def get_local_resources(self) -> List[Dict[str, Any]]:
|
48
|
+
"""获取本地工具"""
|
49
|
+
# 获取中心仓库中已有的工具文件名
|
50
|
+
existing_tools = self.get_existing_resources()
|
51
|
+
|
52
|
+
# 只从数据目录的tools目录获取工具
|
53
|
+
local_tools_dir = os.path.join(get_data_dir(), "tools")
|
54
|
+
if not os.path.exists(local_tools_dir):
|
55
|
+
PrettyOutput.print(
|
56
|
+
f"本地工具目录不存在: {local_tools_dir}",
|
57
|
+
OutputType.WARNING,
|
58
|
+
)
|
59
|
+
return []
|
60
|
+
|
61
|
+
# 收集本地工具文件(排除已存在的)
|
62
|
+
tool_files = []
|
63
|
+
for filepath in glob.glob(os.path.join(local_tools_dir, "*.py")):
|
64
|
+
filename = os.path.basename(filepath)
|
65
|
+
# 跳过__init__.py和已存在的文件
|
66
|
+
if filename == "__init__.py" or filename in existing_tools:
|
67
|
+
continue
|
68
|
+
|
69
|
+
# 尝试获取工具名称(通过简单解析)
|
70
|
+
tool_name = filename[:-3] # 移除.py后缀
|
71
|
+
tool_files.append(
|
72
|
+
{
|
73
|
+
"path": filepath,
|
74
|
+
"filename": filename,
|
75
|
+
"tool_name": tool_name,
|
76
|
+
}
|
77
|
+
)
|
78
|
+
|
79
|
+
return tool_files
|
80
|
+
|
81
|
+
def share_resources(self, resources: List[Dict[str, Any]]) -> List[str]:
|
82
|
+
"""分享工具到中心仓库"""
|
83
|
+
# 确认操作
|
84
|
+
share_list = ["\n将要分享以下工具到中心仓库(注意:文件将被移动而非复制):"]
|
85
|
+
for tool in resources:
|
86
|
+
share_list.append(f"- {tool['tool_name']} ({tool['filename']})")
|
87
|
+
PrettyOutput.print("\n".join(share_list), OutputType.WARNING)
|
88
|
+
|
89
|
+
if not user_confirm("确认移动这些工具到中心仓库吗?(原文件将被删除)"):
|
90
|
+
return []
|
91
|
+
|
92
|
+
# 移动选中的工具到中心仓库
|
93
|
+
moved_list = []
|
94
|
+
for tool in resources:
|
95
|
+
src_file = tool["path"]
|
96
|
+
dst_file = os.path.join(self.repo_path, tool["filename"])
|
97
|
+
shutil.move(src_file, dst_file) # 使用move而不是copy
|
98
|
+
moved_list.append(f"已移动: {tool['tool_name']}")
|
99
|
+
|
100
|
+
return moved_list
|
101
|
+
|
102
|
+
def run(self) -> None:
|
103
|
+
"""执行工具分享流程"""
|
104
|
+
try:
|
105
|
+
# 更新中心仓库
|
106
|
+
self.update_central_repo()
|
107
|
+
|
108
|
+
# 获取本地资源
|
109
|
+
local_resources = self.get_local_resources()
|
110
|
+
if not local_resources:
|
111
|
+
PrettyOutput.print(
|
112
|
+
"没有找到新的工具文件(所有工具可能已存在于中心仓库)",
|
113
|
+
OutputType.WARNING,
|
114
|
+
)
|
115
|
+
raise typer.Exit(code=0)
|
116
|
+
|
117
|
+
# 选择要分享的资源
|
118
|
+
selected_resources = self.select_resources(local_resources)
|
119
|
+
if not selected_resources:
|
120
|
+
raise typer.Exit(code=0)
|
121
|
+
|
122
|
+
# 分享资源
|
123
|
+
moved_list = self.share_resources(selected_resources)
|
124
|
+
if moved_list:
|
125
|
+
# 一次性显示所有移动结果
|
126
|
+
PrettyOutput.print("\n".join(moved_list), OutputType.SUCCESS)
|
127
|
+
|
128
|
+
# 提交并推送
|
129
|
+
self.commit_and_push(len(selected_resources))
|
130
|
+
|
131
|
+
PrettyOutput.print("\n工具已成功分享到中心仓库!", OutputType.SUCCESS)
|
132
|
+
PrettyOutput.print(
|
133
|
+
f"原文件已从 {os.path.join(get_data_dir(), 'tools')} 移动到中心仓库",
|
134
|
+
OutputType.INFO,
|
135
|
+
)
|
136
|
+
|
137
|
+
except Exception as e:
|
138
|
+
PrettyOutput.print(f"分享工具时出错: {str(e)}", OutputType.ERROR)
|
139
|
+
raise typer.Exit(code=1)
|
@@ -17,7 +17,6 @@ from jarvis.jarvis_agent.edit_file_handler import EditFileHandler
|
|
17
17
|
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
18
18
|
from jarvis.jarvis_code_agent.lint import get_lint_tools
|
19
19
|
from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
|
20
|
-
from jarvis.jarvis_platform.registry import PlatformRegistry
|
21
20
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
22
21
|
from jarvis.jarvis_utils.config import (
|
23
22
|
is_confirm_before_apply_patch,
|
@@ -70,7 +69,25 @@ class CodeAgent:
|
|
70
69
|
"clear_memory",
|
71
70
|
]
|
72
71
|
)
|
73
|
-
code_system_prompt =
|
72
|
+
code_system_prompt = self._get_system_prompt()
|
73
|
+
self.agent = Agent(
|
74
|
+
system_prompt=code_system_prompt,
|
75
|
+
name="CodeAgent",
|
76
|
+
auto_complete=False,
|
77
|
+
output_handler=[tool_registry, EditFileHandler()], # type: ignore
|
78
|
+
llm_type=llm_type,
|
79
|
+
model_group=model_group,
|
80
|
+
input_handler=[shell_input_handler, builtin_input_handler],
|
81
|
+
need_summary=need_summary,
|
82
|
+
use_methodology=False, # 禁用方法论
|
83
|
+
use_analysis=False, # 禁用分析
|
84
|
+
)
|
85
|
+
|
86
|
+
self.agent.set_after_tool_call_cb(self.after_tool_call_cb)
|
87
|
+
|
88
|
+
def _get_system_prompt(self) -> str:
|
89
|
+
"""获取代码工程师的系统提示词"""
|
90
|
+
return """
|
74
91
|
<code_engineer_guide>
|
75
92
|
## 角色定位
|
76
93
|
你是Jarvis系统的代码工程师,一个专业的代码分析和修改助手。你的职责是:
|
@@ -124,20 +141,6 @@ class CodeAgent:
|
|
124
141
|
10. 我不订阅闲 AI
|
125
142
|
</say_to_llm>
|
126
143
|
"""
|
127
|
-
self.agent = Agent(
|
128
|
-
system_prompt=code_system_prompt,
|
129
|
-
name="CodeAgent",
|
130
|
-
auto_complete=False,
|
131
|
-
output_handler=[tool_registry, EditFileHandler()], # type: ignore
|
132
|
-
llm_type=llm_type,
|
133
|
-
model_group=model_group,
|
134
|
-
input_handler=[shell_input_handler, builtin_input_handler],
|
135
|
-
need_summary=need_summary,
|
136
|
-
use_methodology=False, # 禁用方法论
|
137
|
-
use_analysis=False, # 禁用分析
|
138
|
-
)
|
139
|
-
|
140
|
-
self.agent.set_after_tool_call_cb(self.after_tool_call_cb)
|
141
144
|
|
142
145
|
def _check_git_config(self) -> None:
|
143
146
|
"""检查 git username 和 email 是否已设置,如果没有则提示并退出"""
|
@@ -209,11 +212,11 @@ class CodeAgent:
|
|
209
212
|
jarvis_ignore = ".jarvis"
|
210
213
|
|
211
214
|
if not os.path.exists(gitignore_path):
|
212
|
-
with open(gitignore_path, "w") as f:
|
215
|
+
with open(gitignore_path, "w", encoding="utf-8") as f:
|
213
216
|
f.write(f"{jarvis_ignore}\n")
|
214
217
|
print(f"✅ 已创建.gitignore文件并添加'{jarvis_ignore}'")
|
215
218
|
else:
|
216
|
-
with open(gitignore_path, "r+") as f:
|
219
|
+
with open(gitignore_path, "r+", encoding="utf-8") as f:
|
217
220
|
content = f.read()
|
218
221
|
if jarvis_ignore not in content.splitlines():
|
219
222
|
f.write(f"\n{jarvis_ignore}\n")
|
@@ -260,7 +263,10 @@ class CodeAgent:
|
|
260
263
|
current_settings = {}
|
261
264
|
for key, target_value in target_settings.items():
|
262
265
|
result = subprocess.run(
|
263
|
-
["git", "config", "--get", key],
|
266
|
+
["git", "config", "--get", key],
|
267
|
+
capture_output=True,
|
268
|
+
text=True,
|
269
|
+
check=False,
|
264
270
|
)
|
265
271
|
current_value = result.stdout.strip()
|
266
272
|
current_settings[key] = current_value
|
@@ -522,7 +528,7 @@ class CodeAgent:
|
|
522
528
|
|
523
529
|
if project_info:
|
524
530
|
enhanced_input = (
|
525
|
-
|
531
|
+
"项目概况:\n"
|
526
532
|
+ "\n\n".join(project_info)
|
527
533
|
+ "\n\n"
|
528
534
|
+ first_tip
|
@@ -230,6 +230,11 @@
|
|
230
230
|
"description": "中心方法论Git仓库地址,该仓库会自动添加到方法论加载路径中",
|
231
231
|
"default": ""
|
232
232
|
},
|
233
|
+
"JARVIS_CENTRAL_TOOL_REPO": {
|
234
|
+
"type": "string",
|
235
|
+
"description": "中心工具库Git仓库地址,该仓库会自动克隆到数据目录并加载其中的工具",
|
236
|
+
"default": ""
|
237
|
+
},
|
233
238
|
"JARVIS_PRINT_PROMPT": {
|
234
239
|
"type": "boolean",
|
235
240
|
"description": "是否打印提示",
|
@@ -240,6 +245,38 @@
|
|
240
245
|
"description": "是否启用静态代码分析",
|
241
246
|
"default": true
|
242
247
|
},
|
248
|
+
"JARVIS_TOOL_GROUP": {
|
249
|
+
"type": "string",
|
250
|
+
"description": "选择一个预定义的工具配置组",
|
251
|
+
"default": ""
|
252
|
+
},
|
253
|
+
"JARVIS_TOOL_GROUPS": {
|
254
|
+
"type": "array",
|
255
|
+
"description": "预定义的工具配置组",
|
256
|
+
"default": [],
|
257
|
+
"items": {
|
258
|
+
"type": "object",
|
259
|
+
"additionalProperties": {
|
260
|
+
"type": "object",
|
261
|
+
"properties": {
|
262
|
+
"use": {
|
263
|
+
"type": "array",
|
264
|
+
"description": "要使用的工具名称列表",
|
265
|
+
"items": {
|
266
|
+
"type": "string"
|
267
|
+
}
|
268
|
+
},
|
269
|
+
"dont_use": {
|
270
|
+
"type": "array",
|
271
|
+
"description": "不使用的工具名称列表",
|
272
|
+
"items": {
|
273
|
+
"type": "string"
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
}
|
279
|
+
},
|
243
280
|
"JARVIS_RAG_GROUP": {
|
244
281
|
"type": "string",
|
245
282
|
"description": "选择一个预定义的RAG配置组",
|
jarvis/jarvis_platform/ai8.py
CHANGED
@@ -250,7 +250,9 @@ class AI8Model(BasePlatform):
|
|
250
250
|
PrettyOutput.print(f"会话文件未找到: {file_path}", OutputType.ERROR)
|
251
251
|
return False
|
252
252
|
except KeyError as e:
|
253
|
-
PrettyOutput.print(
|
253
|
+
PrettyOutput.print(
|
254
|
+
f"恢复失败: 会话文件格式不正确,缺少键 {e}", OutputType.ERROR
|
255
|
+
)
|
254
256
|
return False
|
255
257
|
except Exception as e:
|
256
258
|
PrettyOutput.print(f"恢复会话失败: {str(e)}", OutputType.ERROR)
|
@@ -322,3 +324,13 @@ class AI8Model(BasePlatform):
|
|
322
324
|
|
323
325
|
def upload_files(self, file_list: List[str]) -> bool:
|
324
326
|
return False
|
327
|
+
|
328
|
+
@classmethod
|
329
|
+
def get_required_env_keys(cls) -> List[str]:
|
330
|
+
"""
|
331
|
+
获取AI8平台所需的环境变量键列表
|
332
|
+
|
333
|
+
返回:
|
334
|
+
List[str]: 环境变量键的列表
|
335
|
+
"""
|
336
|
+
return ["AI8_API_KEY"]
|
jarvis/jarvis_platform/base.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import re
|
3
3
|
from abc import ABC, abstractmethod
|
4
4
|
from types import TracebackType
|
5
|
-
from typing import Generator, List, Optional, Tuple, Type
|
5
|
+
from typing import Dict, Generator, List, Optional, Tuple, Type
|
6
6
|
|
7
7
|
from typing_extensions import Self
|
8
8
|
|
@@ -87,7 +87,7 @@ class BasePlatform(ABC):
|
|
87
87
|
prefix_prompt = f"""
|
88
88
|
我将分多次提供大量内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出"已收到",明白请输出"开始接收输入"。
|
89
89
|
"""
|
90
|
-
while_true(lambda: while_success(lambda: self.
|
90
|
+
while_true(lambda: while_success(lambda: self._chat(prefix_prompt), 5), 5)
|
91
91
|
submit_count = 0
|
92
92
|
length = 0
|
93
93
|
response = ""
|
@@ -101,7 +101,7 @@ class BasePlatform(ABC):
|
|
101
101
|
response += "\n"
|
102
102
|
for trunk in while_true(
|
103
103
|
lambda: while_success(
|
104
|
-
lambda: self.
|
104
|
+
lambda: self._chat(
|
105
105
|
f"<part_content>{input}</part_content>\n\n请返回<已收到>,不需要返回其他任何内容"
|
106
106
|
),
|
107
107
|
5,
|
@@ -110,10 +110,14 @@ class BasePlatform(ABC):
|
|
110
110
|
):
|
111
111
|
response += trunk
|
112
112
|
|
113
|
-
print(
|
113
|
+
print(
|
114
|
+
f"📤 提交第{submit_count}部分完成,当前进度:{length}/{len(message)}"
|
115
|
+
)
|
114
116
|
print("✅ 提交完成")
|
115
117
|
response += "\n" + while_true(
|
116
|
-
lambda: while_success(
|
118
|
+
lambda: while_success(
|
119
|
+
lambda: self._chat("内容已经全部提供完毕,请根据内容继续"), 5
|
120
|
+
),
|
117
121
|
5,
|
118
122
|
)
|
119
123
|
else:
|
@@ -240,6 +244,17 @@ class BasePlatform(ABC):
|
|
240
244
|
"""Get model list"""
|
241
245
|
raise NotImplementedError("get_model_list is not implemented")
|
242
246
|
|
247
|
+
@classmethod
|
248
|
+
@abstractmethod
|
249
|
+
def get_required_env_keys(cls) -> List[str]:
|
250
|
+
"""Get required env keys"""
|
251
|
+
raise NotImplementedError("get_required_env_keys is not implemented")
|
252
|
+
|
253
|
+
@classmethod
|
254
|
+
def get_env_defaults(cls) -> Dict[str, str]:
|
255
|
+
"""Get env default values"""
|
256
|
+
return {}
|
257
|
+
|
243
258
|
def set_suppress_output(self, suppress: bool):
|
244
259
|
"""Set whether to suppress output"""
|
245
260
|
self.suppress_output = suppress
|
jarvis/jarvis_platform/human.py
CHANGED
@@ -10,9 +10,9 @@ import string
|
|
10
10
|
from typing import Generator, List, Tuple
|
11
11
|
|
12
12
|
from jarvis.jarvis_platform.base import BasePlatform
|
13
|
+
from jarvis.jarvis_utils.clipboard import copy_to_clipboard
|
13
14
|
from jarvis.jarvis_utils.input import get_multiline_input
|
14
15
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
15
|
-
from jarvis.jarvis_utils.utils import copy_to_clipboard
|
16
16
|
|
17
17
|
|
18
18
|
class HumanPlatform(BasePlatform):
|
@@ -131,3 +131,13 @@ class HumanPlatform(BasePlatform):
|
|
131
131
|
def support_upload_files(self) -> bool:
|
132
132
|
"""是否支持文件上传功能"""
|
133
133
|
return False
|
134
|
+
|
135
|
+
@classmethod
|
136
|
+
def get_required_env_keys(cls) -> List[str]:
|
137
|
+
"""
|
138
|
+
获取Human平台所需的环境变量键列表
|
139
|
+
|
140
|
+
返回:
|
141
|
+
List[str]: 环境变量键的列表
|
142
|
+
"""
|
143
|
+
return []
|
jarvis/jarvis_platform/kimi.py
CHANGED
@@ -395,3 +395,13 @@ class KimiModel(BasePlatform):
|
|
395
395
|
def support_web(self) -> bool:
|
396
396
|
"""Kimi平台支持web功能"""
|
397
397
|
return True
|
398
|
+
|
399
|
+
@classmethod
|
400
|
+
def get_required_env_keys(cls) -> List[str]:
|
401
|
+
"""
|
402
|
+
获取Kimi平台所需的环境变量键列表
|
403
|
+
|
404
|
+
返回:
|
405
|
+
List[str]: 环境变量键的列表
|
406
|
+
"""
|
407
|
+
return ["KIMI_API_KEY"]
|
jarvis/jarvis_platform/openai.py
CHANGED
@@ -211,3 +211,23 @@ class OpenAIModel(BasePlatform):
|
|
211
211
|
bool: 当前是否支持上传文件 (OpenAI平台始终返回False)
|
212
212
|
"""
|
213
213
|
return False
|
214
|
+
|
215
|
+
@classmethod
|
216
|
+
def get_required_env_keys(cls) -> List[str]:
|
217
|
+
"""
|
218
|
+
获取OpenAI平台所需的环境变量键列表
|
219
|
+
|
220
|
+
返回:
|
221
|
+
List[str]: 环境变量键的列表
|
222
|
+
"""
|
223
|
+
return ["OPENAI_API_KEY", "OPENAI_API_BASE"]
|
224
|
+
|
225
|
+
@classmethod
|
226
|
+
def get_env_defaults(cls) -> Dict[str, str]:
|
227
|
+
"""
|
228
|
+
获取OpenAI平台环境变量的默认值
|
229
|
+
|
230
|
+
返回:
|
231
|
+
Dict[str, str]: 环境变量默认值的字典
|
232
|
+
"""
|
233
|
+
return {"OPENAI_API_BASE": "https://api.openai.com/v1"}
|
jarvis/jarvis_platform/tongyi.py
CHANGED
@@ -11,6 +11,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
11
11
|
from jarvis.jarvis_utils.tag import ot, ct
|
12
12
|
from jarvis.jarvis_utils.utils import while_success
|
13
13
|
|
14
|
+
|
14
15
|
class TongyiPlatform(BasePlatform):
|
15
16
|
"""Tongyi platform implementation"""
|
16
17
|
|
@@ -200,12 +201,8 @@ class TongyiPlatform(BasePlatform):
|
|
200
201
|
tmp_content = json.loads(
|
201
202
|
content.get("content")
|
202
203
|
)["content"]
|
203
|
-
if len(thinking_content) < len(
|
204
|
-
tmp_content
|
205
|
-
):
|
206
|
-
yield tmp_content[
|
207
|
-
len(thinking_content) :
|
208
|
-
]
|
204
|
+
if len(thinking_content) < len(tmp_content):
|
205
|
+
yield tmp_content[len(thinking_content) :]
|
209
206
|
thinking_content = tmp_content
|
210
207
|
else:
|
211
208
|
yield f"\r\n{ct('think')}\n"[
|
@@ -224,9 +221,7 @@ class TongyiPlatform(BasePlatform):
|
|
224
221
|
else:
|
225
222
|
tmp_content = content.get("content")
|
226
223
|
if len(text_content) < len(tmp_content):
|
227
|
-
yield tmp_content[
|
228
|
-
len(text_content) :
|
229
|
-
]
|
224
|
+
yield tmp_content[len(text_content) :]
|
230
225
|
text_content = tmp_content
|
231
226
|
|
232
227
|
except json.JSONDecodeError:
|
@@ -562,3 +557,13 @@ class TongyiPlatform(BasePlatform):
|
|
562
557
|
bool: True if web is supported, False otherwise
|
563
558
|
"""
|
564
559
|
return True
|
560
|
+
|
561
|
+
@classmethod
|
562
|
+
def get_required_env_keys(cls) -> List[str]:
|
563
|
+
"""
|
564
|
+
获取通义平台所需的环境变量键列表
|
565
|
+
|
566
|
+
返回:
|
567
|
+
List[str]: 环境变量键的列表
|
568
|
+
"""
|
569
|
+
return ["TONGYI_COOKIES"]
|
@@ -623,3 +623,13 @@ class YuanbaoPlatform(BasePlatform):
|
|
623
623
|
def support_web(self) -> bool:
|
624
624
|
"""Yuanbao平台支持web功能"""
|
625
625
|
return True
|
626
|
+
|
627
|
+
@classmethod
|
628
|
+
def get_required_env_keys(cls) -> List[str]:
|
629
|
+
"""
|
630
|
+
获取元宝平台所需的环境变量键列表
|
631
|
+
|
632
|
+
返回:
|
633
|
+
List[str]: 环境变量键的列表
|
634
|
+
"""
|
635
|
+
return ["YUANBAO_COOKIES"]
|
@@ -27,13 +27,13 @@ def list_platforms() -> None:
|
|
27
27
|
PrettyOutput.section("Supported platforms and models", OutputType.SUCCESS)
|
28
28
|
|
29
29
|
for platform_name in platforms:
|
30
|
-
# Create platform instance
|
31
|
-
platform = registry.create_platform(platform_name)
|
32
|
-
if not platform:
|
33
|
-
continue
|
34
|
-
|
35
|
-
# Get the list of models supported by the platform
|
36
30
|
try:
|
31
|
+
# Create platform instance
|
32
|
+
platform = registry.create_platform(platform_name)
|
33
|
+
if not platform:
|
34
|
+
continue
|
35
|
+
|
36
|
+
# Get the list of models supported by the platform
|
37
37
|
models = platform.get_model_list()
|
38
38
|
|
39
39
|
# Print platform name
|
@@ -51,10 +51,8 @@ def list_platforms() -> None:
|
|
51
51
|
else:
|
52
52
|
PrettyOutput.print(" • 没有可用的模型信息", OutputType.WARNING)
|
53
53
|
|
54
|
-
except Exception
|
55
|
-
PrettyOutput.print(
|
56
|
-
f"获取 {platform_name} 的模型列表失败: {str(exc)}", OutputType.WARNING
|
57
|
-
)
|
54
|
+
except Exception:
|
55
|
+
PrettyOutput.print(f"创建 {platform_name} 平台失败", OutputType.WARNING)
|
58
56
|
|
59
57
|
|
60
58
|
def chat_with_model(platform_name: str, model_name: str, system_prompt: str) -> None:
|
@@ -330,13 +328,15 @@ def validate_platform_model(platform: Optional[str], model: Optional[str]) -> bo
|
|
330
328
|
|
331
329
|
@app.command("chat")
|
332
330
|
def chat_command(
|
333
|
-
platform: Optional[str] = typer.Option(
|
331
|
+
platform: Optional[str] = typer.Option(
|
332
|
+
None, "--platform", "-p", help="指定要使用的平台"
|
333
|
+
),
|
334
334
|
model: Optional[str] = typer.Option(None, "--model", "-m", help="指定要使用的模型"),
|
335
335
|
) -> None:
|
336
336
|
"""与指定平台和模型聊天。"""
|
337
337
|
if not validate_platform_model(platform, model):
|
338
338
|
return
|
339
|
-
chat_with_model(platform, model, "")
|
339
|
+
chat_with_model(platform, model, "") # type: ignore
|
340
340
|
|
341
341
|
|
342
342
|
@app.command("service")
|