jarvis-ai-assistant 0.1.96__py3-none-any.whl → 0.1.98__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 +138 -144
- jarvis/jarvis_codebase/main.py +87 -54
- jarvis/jarvis_coder/git_utils.py +22 -25
- jarvis/jarvis_coder/main.py +166 -171
- jarvis/jarvis_coder/patch_handler.py +153 -453
- jarvis/jarvis_coder/plan_generator.py +76 -48
- jarvis/jarvis_platform/main.py +39 -39
- jarvis/jarvis_rag/main.py +182 -182
- jarvis/jarvis_smart_shell/main.py +34 -34
- jarvis/main.py +24 -24
- jarvis/models/ai8.py +22 -22
- jarvis/models/base.py +17 -13
- jarvis/models/kimi.py +31 -31
- jarvis/models/ollama.py +28 -28
- jarvis/models/openai.py +22 -24
- jarvis/models/oyi.py +25 -25
- jarvis/models/registry.py +33 -34
- jarvis/tools/ask_user.py +5 -5
- jarvis/tools/base.py +2 -2
- jarvis/tools/chdir.py +9 -9
- jarvis/tools/codebase_qa.py +4 -4
- jarvis/tools/coder.py +4 -4
- jarvis/tools/file_ops.py +1 -1
- jarvis/tools/generator.py +23 -23
- jarvis/tools/methodology.py +4 -4
- jarvis/tools/rag.py +4 -4
- jarvis/tools/registry.py +38 -38
- jarvis/tools/search.py +42 -42
- jarvis/tools/shell.py +13 -13
- jarvis/tools/sub_agent.py +16 -16
- jarvis/tools/thinker.py +41 -41
- jarvis/tools/webpage.py +17 -17
- jarvis/utils.py +59 -60
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.98.dist-info/RECORD +47 -0
- jarvis_ai_assistant-0.1.96.dist-info/RECORD +0 -47
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/top_level.txt +0 -0
jarvis/tools/search.py
CHANGED
|
@@ -58,26 +58,26 @@ def bing_search(query):
|
|
|
58
58
|
return summaries
|
|
59
59
|
|
|
60
60
|
except Exception as error:
|
|
61
|
-
PrettyOutput.print(f"
|
|
61
|
+
PrettyOutput.print(f"Search error: {str(error)}", OutputType.ERROR)
|
|
62
62
|
return None
|
|
63
63
|
|
|
64
64
|
class SearchTool:
|
|
65
65
|
name = "search"
|
|
66
|
-
description = "
|
|
66
|
+
description = "Use Bing search engine to search for information, and extract key information based on the question"
|
|
67
67
|
parameters = {
|
|
68
68
|
"type": "object",
|
|
69
69
|
"properties": {
|
|
70
70
|
"query": {
|
|
71
71
|
"type": "string",
|
|
72
|
-
"description": "
|
|
72
|
+
"description": "Search keywords"
|
|
73
73
|
},
|
|
74
74
|
"question": {
|
|
75
75
|
"type": "string",
|
|
76
|
-
"description": "
|
|
76
|
+
"description": "Specific question to answer, used to extract relevant information from search results"
|
|
77
77
|
},
|
|
78
78
|
"max_results": {
|
|
79
79
|
"type": "integer",
|
|
80
|
-
"description": "
|
|
80
|
+
"description": "Maximum number of search results",
|
|
81
81
|
"default": 3
|
|
82
82
|
}
|
|
83
83
|
},
|
|
@@ -85,12 +85,12 @@ class SearchTool:
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
def __init__(self):
|
|
88
|
-
"""
|
|
88
|
+
"""Initialize the search tool, need to pass in the language model for information extraction"""
|
|
89
89
|
self.model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
90
90
|
self.webpage_tool = WebpageTool()
|
|
91
91
|
|
|
92
92
|
def _search(self, query: str, max_results: int) -> List[Dict]:
|
|
93
|
-
"""
|
|
93
|
+
"""Execute search request"""
|
|
94
94
|
try:
|
|
95
95
|
results = bing_search(query)
|
|
96
96
|
if not results:
|
|
@@ -106,76 +106,76 @@ class SearchTool:
|
|
|
106
106
|
})
|
|
107
107
|
return formatted_results
|
|
108
108
|
except Exception as e:
|
|
109
|
-
PrettyOutput.print(f"
|
|
109
|
+
PrettyOutput.print(f"Search request failed: {str(e)}", OutputType.ERROR)
|
|
110
110
|
return []
|
|
111
111
|
|
|
112
112
|
def _extract_info(self, contents: List[str], question: str) -> str:
|
|
113
|
-
"""
|
|
114
|
-
prompt = f"""
|
|
113
|
+
"""Use language model to extract key information from web content"""
|
|
114
|
+
prompt = f"""Please answer the question based on the following search results: {question}
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
Search results content:
|
|
117
117
|
{'-' * 40}
|
|
118
118
|
{''.join(contents)}
|
|
119
119
|
{'-' * 40}
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
1.
|
|
124
|
-
2.
|
|
125
|
-
3.
|
|
126
|
-
4.
|
|
121
|
+
Please provide a concise and accurate answer, focusing on information directly related to the question. If there is no relevant information in the search results, please clearly state that.
|
|
122
|
+
When answering, pay attention to:
|
|
123
|
+
1. Maintain objectivity, providing information based solely on search results
|
|
124
|
+
2. If there are conflicts between different sources, point out the differences
|
|
125
|
+
3. Appropriately cite information sources
|
|
126
|
+
4. If the information is incomplete or uncertain, please explain"""
|
|
127
127
|
|
|
128
128
|
try:
|
|
129
|
-
response = self.model.
|
|
129
|
+
response = self.model.chat_until_success(prompt)
|
|
130
130
|
return response
|
|
131
131
|
except Exception as e:
|
|
132
|
-
return f"
|
|
132
|
+
return f"Information extraction failed: {str(e)}"
|
|
133
133
|
|
|
134
134
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
135
|
-
"""
|
|
135
|
+
"""Execute search and extract information"""
|
|
136
136
|
try:
|
|
137
137
|
query = args["query"]
|
|
138
138
|
question = args["question"]
|
|
139
139
|
max_results = args.get("max_results", 3)
|
|
140
140
|
|
|
141
|
-
#
|
|
142
|
-
PrettyOutput.print(f"
|
|
143
|
-
PrettyOutput.print(f"
|
|
141
|
+
# Print search information
|
|
142
|
+
PrettyOutput.print(f"Search query: {query}", OutputType.INFO)
|
|
143
|
+
PrettyOutput.print(f"Related question: {question}", OutputType.INFO)
|
|
144
144
|
|
|
145
145
|
# 获取搜索结果
|
|
146
146
|
results = self._search(query, max_results)
|
|
147
147
|
if not results:
|
|
148
148
|
return {
|
|
149
149
|
"success": False,
|
|
150
|
-
"error": "
|
|
150
|
+
"error": "No search results found"
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
# 收集网页内容
|
|
154
154
|
contents = []
|
|
155
155
|
for i, result in enumerate(results, 1):
|
|
156
156
|
try:
|
|
157
|
-
PrettyOutput.print(f"
|
|
157
|
+
PrettyOutput.print(f"Reading result {i}/{len(results)}... {result['title']} - {result['href']}", OutputType.PROGRESS)
|
|
158
158
|
webpage_result = self.webpage_tool.execute({"url": result["href"]})
|
|
159
159
|
if webpage_result["success"]:
|
|
160
|
-
contents.append(f"\
|
|
160
|
+
contents.append(f"\nSource {i}: {result['href']}\n")
|
|
161
161
|
contents.append(webpage_result["stdout"])
|
|
162
162
|
except Exception as e:
|
|
163
|
-
PrettyOutput.print(f"
|
|
163
|
+
PrettyOutput.print(f"Failed to read result {i}: {str(e)}", OutputType.WARNING)
|
|
164
164
|
continue
|
|
165
165
|
|
|
166
166
|
if not contents:
|
|
167
167
|
return {
|
|
168
168
|
"success": False,
|
|
169
|
-
"error": "
|
|
169
|
+
"error": "No valid search results found"
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
#
|
|
173
|
-
PrettyOutput.print("
|
|
172
|
+
# Extract information
|
|
173
|
+
PrettyOutput.print("Analyzing search results...", OutputType.PROGRESS)
|
|
174
174
|
analysis = self._extract_info(contents, question)
|
|
175
175
|
|
|
176
176
|
return {
|
|
177
177
|
"success": True,
|
|
178
|
-
"stdout": f"
|
|
178
|
+
"stdout": f"Search analysis results:\n\n{analysis}",
|
|
179
179
|
"stderr": ""
|
|
180
180
|
}
|
|
181
181
|
|
|
@@ -190,22 +190,22 @@ def main():
|
|
|
190
190
|
import argparse
|
|
191
191
|
import sys
|
|
192
192
|
|
|
193
|
-
parser = argparse.ArgumentParser(description='Bing
|
|
194
|
-
parser.add_argument('query', help='
|
|
195
|
-
parser.add_argument('--max', type=int, default=5, help='
|
|
196
|
-
parser.add_argument('--url-only', action='store_true', help='
|
|
193
|
+
parser = argparse.ArgumentParser(description='Bing search tool')
|
|
194
|
+
parser.add_argument('query', help='Search keywords')
|
|
195
|
+
parser.add_argument('--max', type=int, default=5, help='Maximum number of results (default 5)')
|
|
196
|
+
parser.add_argument('--url-only', action='store_true', help='Only display URL')
|
|
197
197
|
args = parser.parse_args()
|
|
198
198
|
|
|
199
199
|
try:
|
|
200
|
-
PrettyOutput.print(f"
|
|
200
|
+
PrettyOutput.print(f"Searching: {args.query}", OutputType.INFO)
|
|
201
201
|
|
|
202
202
|
results = bing_search(args.query)
|
|
203
203
|
|
|
204
204
|
if not results:
|
|
205
|
-
PrettyOutput.print("
|
|
205
|
+
PrettyOutput.print("No search results found", OutputType.WARNING)
|
|
206
206
|
sys.exit(1)
|
|
207
207
|
|
|
208
|
-
PrettyOutput.print(f"\
|
|
208
|
+
PrettyOutput.print(f"\nFound {len(results)} results:", OutputType.INFO)
|
|
209
209
|
|
|
210
210
|
for i, result in enumerate(results[:args.max], 1):
|
|
211
211
|
PrettyOutput.print(f"\n{'-'*50}", OutputType.INFO)
|
|
@@ -213,15 +213,15 @@ def main():
|
|
|
213
213
|
PrettyOutput.print(f"{i}. {result['href']}", OutputType.INFO)
|
|
214
214
|
else:
|
|
215
215
|
PrettyOutput.print(f"{i}. {result['title']}", OutputType.INFO)
|
|
216
|
-
PrettyOutput.print(f"
|
|
216
|
+
PrettyOutput.print(f"Link: {result['href']}", OutputType.INFO)
|
|
217
217
|
if result['abstract']:
|
|
218
|
-
PrettyOutput.print(f"
|
|
218
|
+
PrettyOutput.print(f"Abstract: {result['abstract']}", OutputType.INFO)
|
|
219
219
|
|
|
220
220
|
except KeyboardInterrupt:
|
|
221
|
-
PrettyOutput.print("\
|
|
221
|
+
PrettyOutput.print("\nSearch cancelled", OutputType.WARNING)
|
|
222
222
|
sys.exit(1)
|
|
223
223
|
except Exception as e:
|
|
224
|
-
PrettyOutput.print(f"
|
|
224
|
+
PrettyOutput.print(f"Execution error: {str(e)}", OutputType.ERROR)
|
|
225
225
|
sys.exit(1)
|
|
226
226
|
|
|
227
227
|
if __name__ == "__main__":
|
jarvis/tools/shell.py
CHANGED
|
@@ -8,7 +8,7 @@ from jarvis.utils import OutputType, PrettyOutput
|
|
|
8
8
|
|
|
9
9
|
class ShellTool:
|
|
10
10
|
name = "execute_shell"
|
|
11
|
-
description = """
|
|
11
|
+
description = """Execute shell command and return result"""
|
|
12
12
|
|
|
13
13
|
parameters = {
|
|
14
14
|
"type": "object",
|
|
@@ -23,41 +23,41 @@ class ShellTool:
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _escape_command(self, cmd: str) -> str:
|
|
26
|
-
"""
|
|
26
|
+
"""Escape special characters in command"""
|
|
27
27
|
return cmd.replace("'", "'\"'\"'")
|
|
28
28
|
|
|
29
29
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
30
|
-
"""
|
|
30
|
+
"""Execute shell command"""
|
|
31
31
|
try:
|
|
32
32
|
command = args["command"]
|
|
33
33
|
|
|
34
|
-
#
|
|
34
|
+
# Generate temporary file name
|
|
35
35
|
output_file = os.path.join(tempfile.gettempdir(), f"jarvis_shell_{os.getpid()}.log")
|
|
36
36
|
|
|
37
|
-
#
|
|
37
|
+
# Escape special characters in command
|
|
38
38
|
escaped_command = self._escape_command(command)
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Modify command to use script
|
|
41
41
|
tee_command = f"script -q -c '{escaped_command}' {output_file}"
|
|
42
42
|
|
|
43
|
-
PrettyOutput.print(f"
|
|
43
|
+
PrettyOutput.print(f"Execute command: {command}", OutputType.INFO)
|
|
44
44
|
|
|
45
|
-
#
|
|
45
|
+
# Execute command
|
|
46
46
|
return_code = os.system(tee_command)
|
|
47
47
|
|
|
48
|
-
#
|
|
48
|
+
# Read output file
|
|
49
49
|
try:
|
|
50
50
|
with open(output_file, 'r', encoding='utf-8', errors='replace') as f:
|
|
51
51
|
output = f.read()
|
|
52
|
-
#
|
|
52
|
+
# Remove header and footer added by script
|
|
53
53
|
if output:
|
|
54
54
|
lines = output.splitlines()
|
|
55
55
|
if len(lines) > 2:
|
|
56
56
|
output = "\n".join(lines[1:-1])
|
|
57
57
|
except Exception as e:
|
|
58
|
-
output = f"
|
|
58
|
+
output = f"Failed to read output file: {str(e)}"
|
|
59
59
|
finally:
|
|
60
|
-
#
|
|
60
|
+
# Clean up temporary file
|
|
61
61
|
Path(output_file).unlink(missing_ok=True)
|
|
62
62
|
|
|
63
63
|
return {
|
|
@@ -68,7 +68,7 @@ class ShellTool:
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
except Exception as e:
|
|
71
|
-
#
|
|
71
|
+
# Ensure temporary file is cleaned up
|
|
72
72
|
if 'output_file' in locals():
|
|
73
73
|
Path(output_file).unlink(missing_ok=True)
|
|
74
74
|
PrettyOutput.print(str(e), OutputType.ERROR)
|
jarvis/tools/sub_agent.py
CHANGED
|
@@ -7,32 +7,32 @@ from jarvis.utils import OutputType, PrettyOutput
|
|
|
7
7
|
|
|
8
8
|
class SubAgentTool:
|
|
9
9
|
name = "create_sub_agent"
|
|
10
|
-
description = "
|
|
10
|
+
description = "Create a sub-agent to handle specific tasks, the sub-agent will generate a task summary report"
|
|
11
11
|
parameters = {
|
|
12
12
|
"type": "object",
|
|
13
13
|
"properties": {
|
|
14
14
|
"agent_name": {
|
|
15
15
|
"type": "string",
|
|
16
|
-
"description": "
|
|
16
|
+
"description": "Sub-agent name"
|
|
17
17
|
},
|
|
18
18
|
"task": {
|
|
19
19
|
"type": "string",
|
|
20
|
-
"description": "
|
|
20
|
+
"description": "Specific task to complete"
|
|
21
21
|
},
|
|
22
22
|
"context": {
|
|
23
23
|
"type": "string",
|
|
24
|
-
"description": "
|
|
24
|
+
"description": "Context information related to the task",
|
|
25
25
|
"default": ""
|
|
26
26
|
},
|
|
27
27
|
"goal": {
|
|
28
28
|
"type": "string",
|
|
29
|
-
"description": "
|
|
29
|
+
"description": "Completion goal of the task",
|
|
30
30
|
"default": ""
|
|
31
31
|
},
|
|
32
32
|
"files": {
|
|
33
33
|
"type": "array",
|
|
34
34
|
"items": {"type": "string"},
|
|
35
|
-
"description": "
|
|
35
|
+
"description": "Related file path list, used for file question answering and processing",
|
|
36
36
|
"default": []
|
|
37
37
|
}
|
|
38
38
|
},
|
|
@@ -41,7 +41,7 @@ class SubAgentTool:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
44
|
-
"""
|
|
44
|
+
"""Create and run sub-agent"""
|
|
45
45
|
try:
|
|
46
46
|
agent_name = args["agent_name"]
|
|
47
47
|
task = args["task"]
|
|
@@ -49,28 +49,28 @@ class SubAgentTool:
|
|
|
49
49
|
goal = args.get("goal", "")
|
|
50
50
|
files = args.get("files", [])
|
|
51
51
|
|
|
52
|
-
PrettyOutput.print(f"
|
|
52
|
+
PrettyOutput.print(f"Create sub-agent: {agent_name}", OutputType.INFO)
|
|
53
53
|
|
|
54
|
-
#
|
|
54
|
+
# Build task description
|
|
55
55
|
task_description = task
|
|
56
56
|
if context:
|
|
57
|
-
task_description = f"
|
|
57
|
+
task_description = f"Context information:\n{context}\n\nTask:\n{task}"
|
|
58
58
|
if goal:
|
|
59
|
-
task_description += f"\n\n
|
|
59
|
+
task_description += f"\n\nCompletion goal:\n{goal}"
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
# Create sub-agent
|
|
62
62
|
sub_agent = Agent(
|
|
63
63
|
name=agent_name,
|
|
64
64
|
is_sub_agent=True
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
#
|
|
68
|
-
PrettyOutput.print("
|
|
67
|
+
# Run sub-agent, pass file list
|
|
68
|
+
PrettyOutput.print("Sub-agent starts executing task...", OutputType.INFO)
|
|
69
69
|
result = sub_agent.run(task_description, file_list=files)
|
|
70
70
|
|
|
71
71
|
return {
|
|
72
72
|
"success": True,
|
|
73
|
-
"stdout": f"
|
|
73
|
+
"stdout": f"Sub-agent task completed\n\n{result}",
|
|
74
74
|
"stderr": ""
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -78,5 +78,5 @@ class SubAgentTool:
|
|
|
78
78
|
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
79
79
|
return {
|
|
80
80
|
"success": False,
|
|
81
|
-
"error": f"
|
|
81
|
+
"error": f"Sub-agent execution failed: {str(e)}"
|
|
82
82
|
}
|
jarvis/tools/thinker.py
CHANGED
|
@@ -4,22 +4,22 @@ from jarvis.models.registry import PlatformRegistry
|
|
|
4
4
|
|
|
5
5
|
class ThinkerTool:
|
|
6
6
|
name = "thinker"
|
|
7
|
-
description = "
|
|
7
|
+
description = "Use chain of thought reasoning to analyze complex problems, suitable for scenarios that require multi-step reasoning, logical analysis, or creative thinking"
|
|
8
8
|
parameters = {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
11
11
|
"question": {
|
|
12
12
|
"type": "string",
|
|
13
|
-
"description": "
|
|
13
|
+
"description": "The problem or task to analyze"
|
|
14
14
|
},
|
|
15
15
|
"context": {
|
|
16
16
|
"type": "string",
|
|
17
|
-
"description": "
|
|
17
|
+
"description": "Context information or background knowledge related to the problem",
|
|
18
18
|
"default": ""
|
|
19
19
|
},
|
|
20
20
|
"goal": {
|
|
21
21
|
"type": "string",
|
|
22
|
-
"description": "
|
|
22
|
+
"description": "The specific goal or result to achieve",
|
|
23
23
|
"default": ""
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -27,63 +27,63 @@ class ThinkerTool:
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
def __init__(self):
|
|
30
|
-
"""
|
|
30
|
+
"""Initialize thinker tool"""
|
|
31
31
|
self.model = PlatformRegistry.get_global_platform_registry().get_thinking_platform()
|
|
32
32
|
|
|
33
33
|
def _generate_prompt(self, question: str, context: str, goal: str) -> str:
|
|
34
|
-
"""
|
|
34
|
+
"""Generate prompt
|
|
35
35
|
|
|
36
36
|
Args:
|
|
37
|
-
question:
|
|
38
|
-
context:
|
|
39
|
-
goal:
|
|
37
|
+
question: problem
|
|
38
|
+
context: context
|
|
39
|
+
goal: goal
|
|
40
40
|
|
|
41
41
|
Returns:
|
|
42
|
-
str:
|
|
42
|
+
str: complete prompt
|
|
43
43
|
"""
|
|
44
44
|
# 基础提示词
|
|
45
|
-
prompt = f"""
|
|
45
|
+
prompt = f"""You are a helpful assistant that is good at deep thinking and logical reasoning. Please help analyze the problem and provide a solution.
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
1.
|
|
49
|
-
2.
|
|
50
|
-
3.
|
|
51
|
-
4.
|
|
47
|
+
Please think as follows:
|
|
48
|
+
1. Carefully understand the problem and goal
|
|
49
|
+
2. Conduct a systematic analysis and reasoning
|
|
50
|
+
3. Consider multiple possible solutions
|
|
51
|
+
4. Provide the best suggestions and specific action steps
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Problem:
|
|
54
54
|
{question}
|
|
55
55
|
"""
|
|
56
56
|
# 如果有目标,添加到提示词中
|
|
57
57
|
if goal:
|
|
58
58
|
prompt += f"""
|
|
59
|
-
|
|
59
|
+
Goal:
|
|
60
60
|
{goal}
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
63
|
# 如果有上下文,添加到提示词中
|
|
64
64
|
if context:
|
|
65
65
|
prompt += f"""
|
|
66
|
-
|
|
66
|
+
Related context:
|
|
67
67
|
{context}
|
|
68
68
|
"""
|
|
69
69
|
|
|
70
|
-
prompt += "\
|
|
70
|
+
prompt += "\nPlease start analyzing:"
|
|
71
71
|
return prompt
|
|
72
72
|
|
|
73
73
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
74
|
-
"""
|
|
74
|
+
"""Execute thinking analysis
|
|
75
75
|
|
|
76
76
|
Args:
|
|
77
|
-
args:
|
|
78
|
-
- question:
|
|
79
|
-
- context:
|
|
80
|
-
- goal:
|
|
77
|
+
args: dictionary containing parameters
|
|
78
|
+
- question: problem
|
|
79
|
+
- context: context (optional)
|
|
80
|
+
- goal: goal (optional)
|
|
81
81
|
|
|
82
82
|
Returns:
|
|
83
|
-
Dict[str, Any]:
|
|
83
|
+
Dict[str, Any]: execution result
|
|
84
84
|
"""
|
|
85
85
|
try:
|
|
86
|
-
#
|
|
86
|
+
# Get parameters
|
|
87
87
|
question = args["question"]
|
|
88
88
|
context = args.get("context", "")
|
|
89
89
|
goal = args.get("goal", "")
|
|
@@ -91,20 +91,20 @@ class ThinkerTool:
|
|
|
91
91
|
# 生成提示词
|
|
92
92
|
prompt = self._generate_prompt(question, context, goal)
|
|
93
93
|
|
|
94
|
-
#
|
|
95
|
-
PrettyOutput.print(f"
|
|
94
|
+
# Record start analysis
|
|
95
|
+
PrettyOutput.print(f"Start analyzing problem: {question}", OutputType.INFO)
|
|
96
96
|
if context:
|
|
97
|
-
PrettyOutput.print("
|
|
97
|
+
PrettyOutput.print("Contains context information", OutputType.INFO)
|
|
98
98
|
if goal:
|
|
99
|
-
PrettyOutput.print(f"
|
|
99
|
+
PrettyOutput.print(f"Goal: {goal}", OutputType.INFO)
|
|
100
100
|
|
|
101
101
|
# 调用模型进行分析
|
|
102
|
-
response = self.model.
|
|
102
|
+
response = self.model.chat_until_success(prompt)
|
|
103
103
|
|
|
104
104
|
if not response:
|
|
105
105
|
return {
|
|
106
106
|
"success": False,
|
|
107
|
-
"error": "
|
|
107
|
+
"error": "Failed to obtain valid analysis results"
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
return {
|
|
@@ -114,22 +114,22 @@ class ThinkerTool:
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
except Exception as e:
|
|
117
|
-
PrettyOutput.print(f"
|
|
117
|
+
PrettyOutput.print(f"Thinking analysis failed: {str(e)}", OutputType.ERROR)
|
|
118
118
|
return {
|
|
119
119
|
"success": False,
|
|
120
|
-
"error": f"
|
|
120
|
+
"error": f"Execution failed: {str(e)}"
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
def main():
|
|
124
|
-
"""
|
|
124
|
+
"""Run tool directly from command line"""
|
|
125
125
|
import argparse
|
|
126
126
|
|
|
127
127
|
load_env_from_file()
|
|
128
128
|
|
|
129
|
-
parser = argparse.ArgumentParser(description='
|
|
130
|
-
parser.add_argument('--question', required=True, help='
|
|
131
|
-
parser.add_argument('--context', help='
|
|
132
|
-
parser.add_argument('--goal', help='
|
|
129
|
+
parser = argparse.ArgumentParser(description='Deep thinking analysis tool')
|
|
130
|
+
parser.add_argument('--question', required=True, help='The problem to analyze')
|
|
131
|
+
parser.add_argument('--context', help='Context information related to the problem')
|
|
132
|
+
parser.add_argument('--goal', help='Specific goal or result to achieve')
|
|
133
133
|
args = parser.parse_args()
|
|
134
134
|
|
|
135
135
|
tool = ThinkerTool()
|
|
@@ -140,7 +140,7 @@ def main():
|
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
if result["success"]:
|
|
143
|
-
PrettyOutput.print("\
|
|
143
|
+
PrettyOutput.print("\nAnalysis results:", OutputType.INFO)
|
|
144
144
|
PrettyOutput.print(result["stdout"], OutputType.INFO)
|
|
145
145
|
else:
|
|
146
146
|
PrettyOutput.print(result["error"], OutputType.ERROR)
|
jarvis/tools/webpage.py
CHANGED
|
@@ -5,56 +5,56 @@ from jarvis.utils import PrettyOutput, OutputType
|
|
|
5
5
|
|
|
6
6
|
class WebpageTool:
|
|
7
7
|
name = "read_webpage"
|
|
8
|
-
description = "
|
|
8
|
+
description = "Read webpage content, extract title and text"
|
|
9
9
|
parameters = {
|
|
10
10
|
"type": "object",
|
|
11
11
|
"properties": {
|
|
12
12
|
"url": {
|
|
13
13
|
"type": "string",
|
|
14
|
-
"description": "
|
|
14
|
+
"description": "The URL of the webpage to read"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"required": ["url"]
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
21
|
-
"""
|
|
21
|
+
"""Read webpage content"""
|
|
22
22
|
try:
|
|
23
23
|
url = args["url"]
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Set request headers
|
|
26
26
|
headers = {
|
|
27
27
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
#
|
|
31
|
-
PrettyOutput.print(f"
|
|
30
|
+
# Send request
|
|
31
|
+
PrettyOutput.print(f"Reading webpage: {url}", OutputType.INFO)
|
|
32
32
|
response = requests.get(url, headers=headers, timeout=10)
|
|
33
33
|
response.raise_for_status()
|
|
34
34
|
|
|
35
|
-
#
|
|
35
|
+
# Use correct encoding
|
|
36
36
|
response.encoding = response.apparent_encoding
|
|
37
37
|
|
|
38
|
-
#
|
|
38
|
+
# Parse HTML
|
|
39
39
|
soup = BeautifulSoup(response.text, 'html.parser')
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# Remove script and style tags
|
|
42
42
|
for script in soup(["script", "style"]):
|
|
43
43
|
script.decompose()
|
|
44
44
|
|
|
45
|
-
#
|
|
45
|
+
# Extract title
|
|
46
46
|
title = soup.title.string if soup.title else ""
|
|
47
|
-
title = title.strip() if title else "
|
|
47
|
+
title = title.strip() if title else "No title"
|
|
48
48
|
|
|
49
|
-
#
|
|
49
|
+
# Extract text
|
|
50
50
|
text = soup.get_text(separator='\n', strip=True)
|
|
51
51
|
lines = [line.strip() for line in text.splitlines() if line.strip()]
|
|
52
52
|
|
|
53
|
-
#
|
|
53
|
+
# Build output
|
|
54
54
|
output = [
|
|
55
|
-
f"
|
|
55
|
+
f"Title: {title}",
|
|
56
56
|
"",
|
|
57
|
-
"
|
|
57
|
+
"Text content:",
|
|
58
58
|
"\n".join(lines)
|
|
59
59
|
]
|
|
60
60
|
|
|
@@ -67,10 +67,10 @@ class WebpageTool:
|
|
|
67
67
|
except requests.RequestException as e:
|
|
68
68
|
return {
|
|
69
69
|
"success": False,
|
|
70
|
-
"error": f"
|
|
70
|
+
"error": f"Webpage request failed: {str(e)}"
|
|
71
71
|
}
|
|
72
72
|
except Exception as e:
|
|
73
73
|
return {
|
|
74
74
|
"success": False,
|
|
75
|
-
"error": f"
|
|
75
|
+
"error": f"Failed to parse webpage: {str(e)}"
|
|
76
76
|
}
|