jarvis-ai-assistant 0.1.85__py3-none-any.whl → 0.1.86__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.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/agent.py +8 -7
- jarvis/jarvis_codebase/main.py +8 -8
- jarvis/jarvis_coder/main.py +15 -15
- jarvis/jarvis_rag/main.py +2 -2
- jarvis/models/ollama.py +150 -0
- jarvis/models/openai.py +2 -2
- jarvis/tools/ask_user.py +13 -15
- jarvis/tools/registry.py +5 -5
- jarvis/utils.py +7 -1
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/METADATA +2 -3
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/RECORD +16 -15
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/agent.py
CHANGED
|
@@ -8,7 +8,7 @@ import json
|
|
|
8
8
|
|
|
9
9
|
from .models.registry import PlatformRegistry
|
|
10
10
|
from .tools import ToolRegistry
|
|
11
|
-
from .utils import PrettyOutput, OutputType, get_multiline_input, load_embedding_model, while_success
|
|
11
|
+
from .utils import PrettyOutput, OutputType, get_max_context_length, get_multiline_input, load_embedding_model, while_success
|
|
12
12
|
import os
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from prompt_toolkit import prompt
|
|
@@ -33,7 +33,7 @@ class Agent:
|
|
|
33
33
|
|
|
34
34
|
# 从环境变量加载配置
|
|
35
35
|
self.embedding_dimension = 1536 # Default for many embedding models
|
|
36
|
-
self.max_context_length =
|
|
36
|
+
self.max_context_length = get_max_context_length()
|
|
37
37
|
|
|
38
38
|
# 初始化嵌入模型
|
|
39
39
|
try:
|
|
@@ -72,10 +72,10 @@ class Agent:
|
|
|
72
72
|
|
|
73
73
|
# 逐行处理
|
|
74
74
|
for line in lines:
|
|
75
|
-
if '<
|
|
75
|
+
if '<TOOL_CALL>' in line:
|
|
76
76
|
in_tool_call = True
|
|
77
77
|
continue
|
|
78
|
-
elif '
|
|
78
|
+
elif '</TOOL_CALL>' in line:
|
|
79
79
|
if in_tool_call and tool_call_lines:
|
|
80
80
|
try:
|
|
81
81
|
# 直接解析YAML
|
|
@@ -344,7 +344,7 @@ class Agent:
|
|
|
344
344
|
4. 生成解决方案:生成一个或者多个具备可操作性的解决方案
|
|
345
345
|
5. 评估解决方案:从众多解决方案中选择一种最优的方案
|
|
346
346
|
6. 制定行动计划:根据目前可以使用的工具制定行动计划,使用 PlantUML 格式输出明确的执行流程
|
|
347
|
-
7.
|
|
347
|
+
7. 执行行动计划:每步执行一个步骤,**最多使用一个工具**(工具执行完成后,等待工具结果再执行下一步)
|
|
348
348
|
8. 监控与调整:如果执行结果与预期不符,则反思并调整行动计划,迭代之前的步骤
|
|
349
349
|
9. 方法论:如果当前任务具有通用性且执行过程中遇到了值得记录的经验,使用方法论工具记录方法论,以提升后期处理类似问题的能力
|
|
350
350
|
10. 任务结束:如果任务已经完成,使用任务结束指令结束任务
|
|
@@ -362,12 +362,12 @@ class Agent:
|
|
|
362
362
|
|
|
363
363
|
工具使用格式:
|
|
364
364
|
|
|
365
|
-
<
|
|
365
|
+
<TOOL_CALL>
|
|
366
366
|
name: tool_name
|
|
367
367
|
arguments:
|
|
368
368
|
param1: value1
|
|
369
369
|
param2: value2
|
|
370
|
-
|
|
370
|
+
</TOOL_CALL>
|
|
371
371
|
|
|
372
372
|
-------------------------------------------------------------
|
|
373
373
|
|
|
@@ -381,6 +381,7 @@ arguments:
|
|
|
381
381
|
7. 在执行一些可能对系统或者用户代码库造成破坏的工具时,请先询问用户
|
|
382
382
|
8. 在多次迭代却没有任何进展时,可请求用户指导
|
|
383
383
|
9. 如果返回的yaml字符串中包含冒号,请将整个字符串用引号包裹,避免yaml解析错误
|
|
384
|
+
10. yaml中包含多行字符串时,请使用 | 语法
|
|
384
385
|
|
|
385
386
|
{methodology_prompt}
|
|
386
387
|
|
jarvis/jarvis_codebase/main.py
CHANGED
|
@@ -7,7 +7,7 @@ from jarvis.models.registry import PlatformRegistry
|
|
|
7
7
|
import concurrent.futures
|
|
8
8
|
from threading import Lock
|
|
9
9
|
from concurrent.futures import ThreadPoolExecutor
|
|
10
|
-
from jarvis.utils import OutputType, PrettyOutput, find_git_root, load_embedding_model
|
|
10
|
+
from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_max_context_length, get_thread_count, load_embedding_model
|
|
11
11
|
from jarvis.utils import load_env_from_file
|
|
12
12
|
import argparse
|
|
13
13
|
from sentence_transformers import SentenceTransformer
|
|
@@ -18,8 +18,8 @@ class CodeBase:
|
|
|
18
18
|
load_env_from_file()
|
|
19
19
|
self.root_dir = root_dir
|
|
20
20
|
os.chdir(self.root_dir)
|
|
21
|
-
self.thread_count =
|
|
22
|
-
self.max_context_length =
|
|
21
|
+
self.thread_count = get_thread_count()
|
|
22
|
+
self.max_context_length = get_max_context_length()
|
|
23
23
|
|
|
24
24
|
# 初始化数据目录
|
|
25
25
|
self.data_dir = os.path.join(self.root_dir, ".jarvis-codebase")
|
|
@@ -408,10 +408,10 @@ class CodeBase:
|
|
|
408
408
|
# 构建重排序的prompt
|
|
409
409
|
prompt = f"""请根据用户的查询,对以下代码文件进行相关性排序。对每个文件给出0-100的相关性分数,分数越高表示越相关。
|
|
410
410
|
只需要输出每个文件的分数,格式为:
|
|
411
|
-
<
|
|
411
|
+
<RERANK>
|
|
412
412
|
文件路径: 分数
|
|
413
413
|
文件路径: 分数
|
|
414
|
-
|
|
414
|
+
</RERANK>
|
|
415
415
|
|
|
416
416
|
用户查询: {query}
|
|
417
417
|
|
|
@@ -426,9 +426,9 @@ class CodeBase:
|
|
|
426
426
|
|
|
427
427
|
response = model.chat(prompt)
|
|
428
428
|
|
|
429
|
-
# 提取<
|
|
430
|
-
start_tag = "<
|
|
431
|
-
end_tag = "
|
|
429
|
+
# 提取<RERANK>和</RERANK>之间的内容
|
|
430
|
+
start_tag = "<RERANK>"
|
|
431
|
+
end_tag = "</RERANK>"
|
|
432
432
|
if start_tag in response and end_tag in response:
|
|
433
433
|
response = response[response.find(start_tag) + len(start_tag):response.find(end_tag)]
|
|
434
434
|
|
jarvis/jarvis_coder/main.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import Dict, Any, List, Tuple
|
|
|
6
6
|
|
|
7
7
|
import yaml
|
|
8
8
|
from jarvis.models.base import BasePlatform
|
|
9
|
-
from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_multiline_input, load_env_from_file
|
|
9
|
+
from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_max_context_length, get_multiline_input, load_env_from_file
|
|
10
10
|
from jarvis.models.registry import PlatformRegistry
|
|
11
11
|
from jarvis.jarvis_codebase.main import CodeBase
|
|
12
12
|
from prompt_toolkit import PromptSession
|
|
@@ -22,7 +22,7 @@ class JarvisCoder:
|
|
|
22
22
|
def __init__(self, root_dir: str, language: str):
|
|
23
23
|
"""初始化代码修改工具"""
|
|
24
24
|
|
|
25
|
-
self.max_context_length =
|
|
25
|
+
self.max_context_length = get_max_context_length()
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
self.root_dir = find_git_root(root_dir)
|
|
@@ -113,8 +113,8 @@ class JarvisCoder:
|
|
|
113
113
|
return []
|
|
114
114
|
|
|
115
115
|
try:
|
|
116
|
-
patches = re.findall(r'<
|
|
117
|
-
return [patch.replace('<
|
|
116
|
+
patches = re.findall(r'<PATCH>.*?</PATCH>', response, re.DOTALL)
|
|
117
|
+
return [patch.replace('<PATCH>', '').replace('</PATCH>', '').strip()
|
|
118
118
|
for patch in patches if patch.strip()]
|
|
119
119
|
except Exception as e:
|
|
120
120
|
PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.WARNING)
|
|
@@ -126,29 +126,29 @@ class JarvisCoder:
|
|
|
126
126
|
|
|
127
127
|
修改格式说明:
|
|
128
128
|
1. 每个修改块格式如下:
|
|
129
|
-
<
|
|
129
|
+
<PATCH>
|
|
130
130
|
>>>>>> path/to/file
|
|
131
131
|
要替换的内容
|
|
132
132
|
=======
|
|
133
133
|
新的内容
|
|
134
134
|
>>>>>>
|
|
135
|
-
|
|
135
|
+
</PATCH>
|
|
136
136
|
|
|
137
137
|
2. 如果是新文件或者替换整个文件内容,格式如下:
|
|
138
|
-
<
|
|
138
|
+
<PATCH>
|
|
139
139
|
>>>>>> path/to/new/file
|
|
140
140
|
=======
|
|
141
141
|
新文件的完整内容
|
|
142
142
|
>>>>>>
|
|
143
|
-
|
|
143
|
+
</PATCH>
|
|
144
144
|
|
|
145
145
|
3. 如果要删除文件中的某一段,格式如下:
|
|
146
|
-
<
|
|
146
|
+
<PATCH>
|
|
147
147
|
>>>>>> path/to/file
|
|
148
148
|
要删除的内容
|
|
149
149
|
=======
|
|
150
150
|
>>>>>>
|
|
151
|
-
|
|
151
|
+
</PATCH>
|
|
152
152
|
|
|
153
153
|
文件列表如下:
|
|
154
154
|
"""
|
|
@@ -158,14 +158,14 @@ class JarvisCoder:
|
|
|
158
158
|
continue
|
|
159
159
|
prompt += f"""{i}. {file["file_path"]}\n"""
|
|
160
160
|
prompt += f"""文件内容:\n"""
|
|
161
|
-
prompt += f"<
|
|
161
|
+
prompt += f"<FILE_CONTENT>\n"
|
|
162
162
|
prompt += f'{file["file_content"]}\n'
|
|
163
|
-
prompt += f"
|
|
163
|
+
prompt += f"</FILE_CONTENT>\n"
|
|
164
164
|
|
|
165
165
|
prompt += f"\n需求描述: {feature}\n"
|
|
166
166
|
prompt += """
|
|
167
167
|
注意事项:
|
|
168
|
-
1、仅输出补丁内容,不要输出任何其他内容,每个补丁必须用<
|
|
168
|
+
1、仅输出补丁内容,不要输出任何其他内容,每个补丁必须用<PATCH>和</PATCH>标记
|
|
169
169
|
2、如果在大段代码中有零星修改,生成多个补丁
|
|
170
170
|
3、要替换的内容,一定要与文件内容完全一致,不要有任何多余或者缺失的内容
|
|
171
171
|
4、每个patch不超过20行,超出20行,请生成多个patch
|
|
@@ -177,8 +177,8 @@ class JarvisCoder:
|
|
|
177
177
|
|
|
178
178
|
try:
|
|
179
179
|
# 使用正则表达式匹配每个patch块
|
|
180
|
-
patches = re.findall(r'<
|
|
181
|
-
return [patch.replace('<
|
|
180
|
+
patches = re.findall(r'<PATCH>.*?</PATCH>', response, re.DOTALL)
|
|
181
|
+
return [patch.replace('<PATCH>', '').replace('</PATCH>', '').strip()
|
|
182
182
|
for patch in patches if patch.strip()]
|
|
183
183
|
except Exception as e:
|
|
184
184
|
PrettyOutput.print(f"解析patch失败: {str(e)}", OutputType.WARNING)
|
jarvis/jarvis_rag/main.py
CHANGED
|
@@ -5,7 +5,7 @@ import faiss
|
|
|
5
5
|
from typing import List, Tuple, Optional, Dict
|
|
6
6
|
from sentence_transformers import SentenceTransformer
|
|
7
7
|
import pickle
|
|
8
|
-
from jarvis.utils import OutputType, PrettyOutput, find_git_root, load_embedding_model
|
|
8
|
+
from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_max_context_length, load_embedding_model
|
|
9
9
|
from jarvis.utils import load_env_from_file
|
|
10
10
|
import tiktoken
|
|
11
11
|
from dataclasses import dataclass
|
|
@@ -161,7 +161,7 @@ class RAGTool:
|
|
|
161
161
|
self.cache_path = os.path.join(self.data_dir, "cache.pkl")
|
|
162
162
|
self.documents: List[Document] = []
|
|
163
163
|
self.index = None
|
|
164
|
-
self.max_context_length =
|
|
164
|
+
self.max_context_length = get_max_context_length()
|
|
165
165
|
|
|
166
166
|
# 加载缓存
|
|
167
167
|
self._load_cache()
|
jarvis/models/ollama.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
from jarvis.models.base import BasePlatform
|
|
4
|
+
from jarvis.utils import OutputType, PrettyOutput
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
class OllamaPlatform(BasePlatform):
|
|
9
|
+
"""Ollama 平台实现"""
|
|
10
|
+
|
|
11
|
+
platform_name = "ollama"
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
"""初始化模型"""
|
|
15
|
+
super().__init__()
|
|
16
|
+
|
|
17
|
+
# 检查环境变量并提供帮助信息
|
|
18
|
+
self.api_base = os.getenv("OLLAMA_API_BASE", "http://localhost:11434")
|
|
19
|
+
self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-r1:1.5b"
|
|
20
|
+
|
|
21
|
+
# 检查 Ollama 服务是否可用
|
|
22
|
+
try:
|
|
23
|
+
PrettyOutput.print(f"正在连接 Ollama 服务 ({self.api_base})...", OutputType.INFO)
|
|
24
|
+
response = requests.get(f"{self.api_base}/api/tags")
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
available_models = [model["name"] for model in response.json().get("models", [])]
|
|
27
|
+
|
|
28
|
+
if not available_models:
|
|
29
|
+
PrettyOutput.print("\n需要先下载 Ollama 模型才能使用:", OutputType.INFO)
|
|
30
|
+
PrettyOutput.print("1. 安装 Ollama: https://ollama.ai", OutputType.INFO)
|
|
31
|
+
PrettyOutput.print("2. 下载模型:", OutputType.INFO)
|
|
32
|
+
PrettyOutput.print(f" ollama pull {self.model_name}", OutputType.INFO)
|
|
33
|
+
raise Exception("No available models found")
|
|
34
|
+
|
|
35
|
+
PrettyOutput.print(f"可用模型: {', '.join(available_models)}", OutputType.INFO)
|
|
36
|
+
|
|
37
|
+
if self.model_name not in available_models:
|
|
38
|
+
PrettyOutput.print(f"\n警告:模型 {self.model_name} 未下载", OutputType.WARNING)
|
|
39
|
+
PrettyOutput.print("\n请使用以下命令下载模型:", OutputType.INFO)
|
|
40
|
+
PrettyOutput.print(f"ollama pull {self.model_name}", OutputType.INFO)
|
|
41
|
+
raise Exception(f"Model {self.model_name} is not available")
|
|
42
|
+
|
|
43
|
+
PrettyOutput.print(f"使用模型: {self.model_name}", OutputType.SUCCESS)
|
|
44
|
+
|
|
45
|
+
except requests.exceptions.ConnectionError:
|
|
46
|
+
PrettyOutput.print("\nOllama 服务未启动或无法连接", OutputType.ERROR)
|
|
47
|
+
PrettyOutput.print("请确保已经:", OutputType.INFO)
|
|
48
|
+
PrettyOutput.print("1. 安装了 Ollama: https://ollama.ai", OutputType.INFO)
|
|
49
|
+
PrettyOutput.print("2. 启动了 Ollama 服务", OutputType.INFO)
|
|
50
|
+
PrettyOutput.print("3. 服务地址配置正确 (默认: http://localhost:11434)", OutputType.INFO)
|
|
51
|
+
raise Exception("Ollama service is not available")
|
|
52
|
+
|
|
53
|
+
self.messages = []
|
|
54
|
+
self.system_message = ""
|
|
55
|
+
|
|
56
|
+
def set_model_name(self, model_name: str):
|
|
57
|
+
"""设置模型名称"""
|
|
58
|
+
self.model_name = model_name
|
|
59
|
+
|
|
60
|
+
def chat(self, message: str) -> str:
|
|
61
|
+
"""执行对话"""
|
|
62
|
+
try:
|
|
63
|
+
# 构建消息列表
|
|
64
|
+
messages = []
|
|
65
|
+
if self.system_message:
|
|
66
|
+
messages.append({"role": "system", "content": self.system_message})
|
|
67
|
+
messages.extend(self.messages)
|
|
68
|
+
messages.append({"role": "user", "content": message})
|
|
69
|
+
|
|
70
|
+
# 构建请求数据
|
|
71
|
+
data = {
|
|
72
|
+
"model": self.model_name,
|
|
73
|
+
"messages": messages,
|
|
74
|
+
"stream": True # 启用流式输出
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# 发送请求
|
|
78
|
+
response = requests.post(
|
|
79
|
+
f"{self.api_base}/api/chat",
|
|
80
|
+
json=data,
|
|
81
|
+
stream=True
|
|
82
|
+
)
|
|
83
|
+
response.raise_for_status()
|
|
84
|
+
|
|
85
|
+
# 处理流式响应
|
|
86
|
+
full_response = ""
|
|
87
|
+
for line in response.iter_lines():
|
|
88
|
+
if line:
|
|
89
|
+
chunk = line.decode()
|
|
90
|
+
try:
|
|
91
|
+
result = json.loads(chunk)
|
|
92
|
+
if "message" in result and "content" in result["message"]:
|
|
93
|
+
text = result["message"]["content"]
|
|
94
|
+
if not self.suppress_output:
|
|
95
|
+
PrettyOutput.print_stream(text)
|
|
96
|
+
full_response += text
|
|
97
|
+
except json.JSONDecodeError:
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
if not self.suppress_output:
|
|
101
|
+
PrettyOutput.print_stream_end()
|
|
102
|
+
|
|
103
|
+
# 更新消息历史
|
|
104
|
+
self.messages.append({"role": "user", "content": message})
|
|
105
|
+
self.messages.append({"role": "assistant", "content": full_response})
|
|
106
|
+
|
|
107
|
+
return full_response
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
PrettyOutput.print(f"对话失败: {str(e)}", OutputType.ERROR)
|
|
111
|
+
raise Exception(f"Chat failed: {str(e)}")
|
|
112
|
+
|
|
113
|
+
def upload_files(self, file_list: List[str]) -> List[Dict]:
|
|
114
|
+
"""上传文件 (Ollama 不支持文件上传)"""
|
|
115
|
+
PrettyOutput.print("Ollama 不支持文件上传", output_type=OutputType.WARNING)
|
|
116
|
+
return []
|
|
117
|
+
|
|
118
|
+
def reset(self):
|
|
119
|
+
"""重置模型状态"""
|
|
120
|
+
self.messages = []
|
|
121
|
+
if self.system_message:
|
|
122
|
+
self.messages.append({"role": "system", "content": self.system_message})
|
|
123
|
+
|
|
124
|
+
def name(self) -> str:
|
|
125
|
+
"""返回模型名称"""
|
|
126
|
+
return self.model_name
|
|
127
|
+
|
|
128
|
+
def delete_chat(self) -> bool:
|
|
129
|
+
"""删除当前聊天会话"""
|
|
130
|
+
self.reset()
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
def set_system_message(self, message: str):
|
|
134
|
+
"""设置系统消息"""
|
|
135
|
+
self.system_message = message
|
|
136
|
+
self.reset() # 重置会话以应用新的系统消息
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
try:
|
|
141
|
+
ollama = OllamaPlatform()
|
|
142
|
+
while True:
|
|
143
|
+
try:
|
|
144
|
+
message = input("\n输入问题(Ctrl+C退出): ")
|
|
145
|
+
ollama.chat(message)
|
|
146
|
+
except KeyboardInterrupt:
|
|
147
|
+
print("\n再见!")
|
|
148
|
+
break
|
|
149
|
+
except Exception as e:
|
|
150
|
+
PrettyOutput.print(f"程序异常退出: {str(e)}", OutputType.ERROR)
|
jarvis/models/openai.py
CHANGED
|
@@ -30,8 +30,8 @@ class OpenAIModel(BasePlatform):
|
|
|
30
30
|
PrettyOutput.print(" export OPENAI_MODEL_NAME=your_model_name", OutputType.INFO)
|
|
31
31
|
raise Exception("OPENAI_API_KEY is not set")
|
|
32
32
|
|
|
33
|
-
self.base_url = os.getenv("OPENAI_API_BASE", "https://api.
|
|
34
|
-
self.model_name =
|
|
33
|
+
self.base_url = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
|
|
34
|
+
self.model_name = os.getenv("JARVIS_MODEL") or "gpt-4o"
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
self.client = OpenAI(
|
jarvis/tools/ask_user.py
CHANGED
|
@@ -2,11 +2,9 @@ from typing import Dict, Any
|
|
|
2
2
|
from jarvis.tools.base import Tool
|
|
3
3
|
from jarvis.utils import get_multiline_input, PrettyOutput, OutputType
|
|
4
4
|
|
|
5
|
-
class AskUserTool
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
name="ask_user",
|
|
9
|
-
description="""当缺少完成任务的信息或有关键决策信息缺失时,询问用户。
|
|
5
|
+
class AskUserTool:
|
|
6
|
+
name="ask_user",
|
|
7
|
+
description="""当缺少完成任务的信息或有关键决策信息缺失时,询问用户。
|
|
10
8
|
用户可以输入多行文本,空行结束输入。
|
|
11
9
|
|
|
12
10
|
使用场景:
|
|
@@ -17,17 +15,17 @@ class AskUserTool(Tool):
|
|
|
17
15
|
|
|
18
16
|
参数说明:
|
|
19
17
|
- question: 要询问用户的问题,应该清晰明确""",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"required": ["question"]
|
|
18
|
+
parameters={
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"question": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "要询问用户的问题"
|
|
29
24
|
}
|
|
30
|
-
|
|
25
|
+
},
|
|
26
|
+
"required": ["question"]
|
|
27
|
+
}
|
|
28
|
+
|
|
31
29
|
|
|
32
30
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
33
31
|
"""执行询问用户操作
|
jarvis/tools/registry.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Any, Callable, Dict, List, Optional
|
|
|
7
7
|
|
|
8
8
|
from jarvis.models.registry import PlatformRegistry
|
|
9
9
|
from jarvis.tools.base import Tool
|
|
10
|
-
from jarvis.utils import OutputType, PrettyOutput
|
|
10
|
+
from jarvis.utils import OutputType, PrettyOutput, get_max_context_length
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class ToolRegistry:
|
|
@@ -19,7 +19,7 @@ class ToolRegistry:
|
|
|
19
19
|
# 加载内置工具和外部工具
|
|
20
20
|
self._load_builtin_tools()
|
|
21
21
|
self._load_external_tools()
|
|
22
|
-
self.max_context_length =
|
|
22
|
+
self.max_context_length = get_max_context_length() * 0.8
|
|
23
23
|
|
|
24
24
|
@staticmethod
|
|
25
25
|
def get_global_tool_registry():
|
|
@@ -176,7 +176,7 @@ class ToolRegistry:
|
|
|
176
176
|
PrettyOutput.section("执行成功", OutputType.SUCCESS)
|
|
177
177
|
|
|
178
178
|
# 如果输出超过4k字符,使用大模型总结
|
|
179
|
-
if len(output) >
|
|
179
|
+
if len(output) > self.max_context_length:
|
|
180
180
|
try:
|
|
181
181
|
PrettyOutput.print("输出较长,正在总结...", OutputType.PROGRESS)
|
|
182
182
|
model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
@@ -184,7 +184,7 @@ class ToolRegistry:
|
|
|
184
184
|
# 如果输出超过30k,只取最后30k字符
|
|
185
185
|
if len(output) > self.max_context_length:
|
|
186
186
|
output_to_summarize = output[-self.max_context_length:]
|
|
187
|
-
truncation_notice = "\n(注意: 由于输出过长,仅总结最后
|
|
187
|
+
truncation_notice = f"\n(注意: 由于输出过长,仅总结最后{self.max_context_length}字符)"
|
|
188
188
|
else:
|
|
189
189
|
output_to_summarize = output
|
|
190
190
|
truncation_notice = ""
|
|
@@ -209,7 +209,7 @@ class ToolRegistry:
|
|
|
209
209
|
--- 总结结束 ---"""
|
|
210
210
|
|
|
211
211
|
except Exception as e:
|
|
212
|
-
PrettyOutput.print(f"总结失败: {str(e)}", OutputType.
|
|
212
|
+
PrettyOutput.print(f"总结失败: {str(e)}", OutputType.ERROR)
|
|
213
213
|
output = f"输出较长 ({len(output)} 字符),建议查看原始输出。\n前300字符预览:\n{output[:300]}..."
|
|
214
214
|
|
|
215
215
|
else:
|
jarvis/utils.py
CHANGED
|
@@ -232,4 +232,10 @@ def load_embedding_model():
|
|
|
232
232
|
)
|
|
233
233
|
PrettyOutput.print("模型下载并加载成功", OutputType.SUCCESS)
|
|
234
234
|
|
|
235
|
-
return embedding_model
|
|
235
|
+
return embedding_model
|
|
236
|
+
|
|
237
|
+
def get_max_context_length():
|
|
238
|
+
return int(os.getenv('JARVIS_MAX_CONTEXT_LENGTH', '131072')) # 默认128k
|
|
239
|
+
|
|
240
|
+
def get_thread_count():
|
|
241
|
+
return int(os.getenv('JARVIS_THREAD_COUNT', '1'))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.86
|
|
4
4
|
Summary: Jarvis: An AI assistant that uses tools to interact with the system
|
|
5
5
|
Home-page: https://github.com/skyfireitdiy/Jarvis
|
|
6
6
|
Author: skyfire
|
|
@@ -139,10 +139,9 @@ Jarvis supports configuration through environment variables that can be set in t
|
|
|
139
139
|
| OPENAI_API_BASE | Base URL for OpenAI API | https://api.deepseek.com | No |
|
|
140
140
|
| OPENAI_MODEL_NAME | Model name for OpenAI | deepseek-chat | No |
|
|
141
141
|
| AI8_API_KEY | API key for AI8 platform | - | Required for AI8 |
|
|
142
|
-
| AI8_MODEL | Model name for AI8 platform | deepseek-chat | No |
|
|
143
142
|
| KIMI_API_KEY | API key for Kimi platform | - | Required for Kimi |
|
|
144
143
|
| OYI_API_KEY | API key for OYI platform | - | Required for OYI |
|
|
145
|
-
|
|
|
144
|
+
| OLLAMA_API_BASE | Base URL for Ollama API | http://localhost:11434 | No |
|
|
146
145
|
|
|
147
146
|
|
|
148
147
|
## 🎯 Usage
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/agent.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=JHFLrXriYNDlOYQBu7ACyKopCI0UKUIw-vMqVgihz1I,50
|
|
2
|
+
jarvis/agent.py,sha256=_qh4mSojAgClOEz5pTiRIfRJU-5_3QGzBAU09roCjtk,19095
|
|
3
3
|
jarvis/main.py,sha256=ksZkJzqc4oow6wB-7QbGJLejGblrbZtRI3fdciS5DS4,5455
|
|
4
|
-
jarvis/utils.py,sha256=
|
|
4
|
+
jarvis/utils.py,sha256=7TPdMlQWJr2AbI9QnSS7vq4rRETDP1CBXUEyq3VlUy0,8831
|
|
5
5
|
jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
jarvis/jarvis_codebase/main.py,sha256=
|
|
6
|
+
jarvis/jarvis_codebase/main.py,sha256=snqC-zdIHVQVAVTv-hv1nY6CKW1o8OZ5b5sz1Cnr8sA,24932
|
|
7
7
|
jarvis/jarvis_coder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
jarvis/jarvis_coder/main.py,sha256=
|
|
8
|
+
jarvis/jarvis_coder/main.py,sha256=GEQgrcEubisVinwLxywJGY8G8RA1UQIiZSm_31H_6io,23536
|
|
9
9
|
jarvis/jarvis_rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
jarvis/jarvis_rag/main.py,sha256=
|
|
10
|
+
jarvis/jarvis_rag/main.py,sha256=2FRuMd7MeOGCyF7M8MClNOVtrLIs7fKe7Nqjoe_6i38,22930
|
|
11
11
|
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
jarvis/jarvis_smart_shell/main.py,sha256=QgR1CZRcTVfC8a5hMso3onH3pFdDoniRjr0YQvY2jXQ,3809
|
|
13
13
|
jarvis/models/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
|
|
14
14
|
jarvis/models/ai8.py,sha256=P_p1ceyjn_olFk38WsubHGavWI9bMEBzo-1vo97HLPE,12215
|
|
15
15
|
jarvis/models/base.py,sha256=vQmgr-l0fRzVTUX4orbQZIKsXEInagjFdYv1cL9Hp7U,1511
|
|
16
16
|
jarvis/models/kimi.py,sha256=ltYoHQDn9vfZyhZ25eUVKMBpxKKlqlw4kManozVF7uo,16135
|
|
17
|
-
jarvis/models/
|
|
17
|
+
jarvis/models/ollama.py,sha256=iPCsJKZs3kXtuJyVBo6d6Ls5qBkSRgtuqF38PDFadso,6097
|
|
18
|
+
jarvis/models/openai.py,sha256=Ns_kpJcWoQuxdKScOFlfkSGjrL2dVGzgmvcnP44sEgs,4044
|
|
18
19
|
jarvis/models/oyi.py,sha256=tdsBf3gegrEDkZf2VOJF9SRLwe9s2g8Al9s-qR9YQRg,14633
|
|
19
20
|
jarvis/models/registry.py,sha256=Lt8IdVBAEx_CCFtfZJPgw3nxSEjfFcqI47I-U64kIbg,8257
|
|
20
21
|
jarvis/tools/__init__.py,sha256=7Rqyj5hBAv5cWDVr5T9ZTZASO7ssBHeQNm2_4ZARdkA,72
|
|
21
|
-
jarvis/tools/ask_user.py,sha256=
|
|
22
|
+
jarvis/tools/ask_user.py,sha256=OELDt7oTCjI2G-CebvnBSxFJhqkIWcugLStU-XxouzE,1998
|
|
22
23
|
jarvis/tools/base.py,sha256=EGRGbdfbLXDLwtyoWdvp9rlxNX7bzc20t0Vc2VkwIEY,652
|
|
23
24
|
jarvis/tools/chdir.py,sha256=TjfPbX8yvNKgUNJEMXh3ZlVDEIse_Fo8xMoVsiK7_dA,2688
|
|
24
25
|
jarvis/tools/codebase_qa.py,sha256=LsowsgL7HBmdBwa7zXcYi_OkwOok4qbnzYWYsuZxHtU,2413
|
|
@@ -26,14 +27,14 @@ jarvis/tools/coder.py,sha256=kmotT2Klsug44S51QoSW9DzkxLzcF-XonyYAEoWZV6c,2295
|
|
|
26
27
|
jarvis/tools/file_ops.py,sha256=h8g0eT9UvlJf4kt0DLXvdSsjcPj7x19lxWdDApeDfpg,3842
|
|
27
28
|
jarvis/tools/generator.py,sha256=TB1zcw_JmRL2W9w6L4IxtrLF3gjnNw5Jj2Zrowj0eSg,5763
|
|
28
29
|
jarvis/tools/methodology.py,sha256=UG6s5VYRcd9wrKX4cg6f7zJhet5AIcthFGMOAdevBiw,5175
|
|
29
|
-
jarvis/tools/registry.py,sha256=
|
|
30
|
+
jarvis/tools/registry.py,sha256=N0SQttUTeiuzGSiW_haVzdvq1922mnOQqHQj5JHKz9Y,9101
|
|
30
31
|
jarvis/tools/search.py,sha256=c9dXtyICdl8Lm8shNPNyIx9k67uY0rMF8xnIKu2RsnE,8787
|
|
31
32
|
jarvis/tools/shell.py,sha256=UPKshPyOaUwTngresUw-ot1jHjQIb4wCY5nkJqa38lU,2520
|
|
32
33
|
jarvis/tools/sub_agent.py,sha256=rEtAmSVY2ZjFOZEKr5m5wpACOQIiM9Zr_3dT92FhXYU,2621
|
|
33
34
|
jarvis/tools/webpage.py,sha256=d3w3Jcjcu1ESciezTkz3n3Zf-rp_l91PrVoDEZnckOo,2391
|
|
34
|
-
jarvis_ai_assistant-0.1.
|
|
35
|
-
jarvis_ai_assistant-0.1.
|
|
36
|
-
jarvis_ai_assistant-0.1.
|
|
37
|
-
jarvis_ai_assistant-0.1.
|
|
38
|
-
jarvis_ai_assistant-0.1.
|
|
39
|
-
jarvis_ai_assistant-0.1.
|
|
35
|
+
jarvis_ai_assistant-0.1.86.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
36
|
+
jarvis_ai_assistant-0.1.86.dist-info/METADATA,sha256=5rg-7E1HHtIVvC8QyQ-lbSYu9RuNrR-p0hFRbos1j6k,12682
|
|
37
|
+
jarvis_ai_assistant-0.1.86.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
38
|
+
jarvis_ai_assistant-0.1.86.dist-info/entry_points.txt,sha256=sdmIO86MrIUepJTGyHs0i_Ho9VGf1q9YRP4RgQvGWcI,280
|
|
39
|
+
jarvis_ai_assistant-0.1.86.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
40
|
+
jarvis_ai_assistant-0.1.86.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
{jarvis_ai_assistant-0.1.85.dist-info → jarvis_ai_assistant-0.1.86.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|