jarvis-ai-assistant 0.1.219__py3-none-any.whl → 0.1.221__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 +98 -440
- jarvis/jarvis_agent/edit_file_handler.py +32 -185
- jarvis/jarvis_agent/prompt_builder.py +57 -0
- jarvis/jarvis_agent/prompts.py +188 -0
- jarvis/jarvis_agent/protocols.py +30 -0
- jarvis/jarvis_agent/session_manager.py +84 -0
- jarvis/jarvis_agent/tool_executor.py +49 -0
- jarvis/jarvis_code_agent/code_agent.py +4 -4
- jarvis/jarvis_data/config_schema.json +20 -0
- jarvis/jarvis_platform/yuanbao.py +3 -1
- jarvis/jarvis_rag/__init__.py +11 -0
- jarvis/jarvis_rag/cache.py +85 -0
- jarvis/jarvis_rag/cli.py +386 -0
- jarvis/jarvis_rag/embedding_manager.py +95 -0
- jarvis/jarvis_rag/llm_interface.py +128 -0
- jarvis/jarvis_rag/query_rewriter.py +62 -0
- jarvis/jarvis_rag/rag_pipeline.py +174 -0
- jarvis/jarvis_rag/reranker.py +56 -0
- jarvis/jarvis_rag/retriever.py +201 -0
- jarvis/jarvis_tools/edit_file.py +11 -36
- jarvis/jarvis_utils/config.py +56 -0
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/METADATA +90 -8
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/RECORD +28 -14
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/entry_points.txt +1 -0
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.219.dist-info → jarvis_ai_assistant-0.1.221.dist-info}/top_level.txt +0 -0
jarvis/jarvis_agent/__init__.py
CHANGED
@@ -9,6 +9,16 @@ from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
|
9
9
|
|
10
10
|
# 本地库导入
|
11
11
|
# jarvis_agent 相关
|
12
|
+
from jarvis.jarvis_agent.prompt_builder import build_action_prompt
|
13
|
+
from jarvis.jarvis_agent.protocols import OutputHandlerProtocol
|
14
|
+
from jarvis.jarvis_agent.session_manager import SessionManager
|
15
|
+
from jarvis.jarvis_agent.tool_executor import execute_tool_call
|
16
|
+
from jarvis.jarvis_agent.prompts import (
|
17
|
+
DEFAULT_SUMMARY_PROMPT,
|
18
|
+
SUMMARY_REQUEST_PROMPT,
|
19
|
+
TASK_ANALYSIS_PROMPT,
|
20
|
+
)
|
21
|
+
|
12
22
|
# jarvis_platform 相关
|
13
23
|
from jarvis.jarvis_platform.base import BasePlatform
|
14
24
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
@@ -36,108 +46,43 @@ from jarvis.jarvis_utils.tag import ct, ot
|
|
36
46
|
origin_agent_system_prompt = f"""
|
37
47
|
<role>
|
38
48
|
# 🤖 角色
|
39
|
-
|
49
|
+
你是一个专业的任务执行助手,根据用户需求制定并执行详细的计划。
|
40
50
|
</role>
|
41
51
|
|
42
|
-
<
|
43
|
-
#
|
44
|
-
1.
|
45
|
-
2.
|
46
|
-
3.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
- 请求用户确认 → 永久挂起
|
54
|
-
</violations>
|
52
|
+
<rules>
|
53
|
+
# ❗ 核心规则
|
54
|
+
1. **单步操作**: 每个响应必须包含且仅包含一个工具调用。
|
55
|
+
2. **任务终结**: 当任务完成时,明确指出任务已完成。这是唯一可以不调用工具的例外。
|
56
|
+
3. **无响应错误**: 空响应或仅有分析无工具调用的响应是致命错误,会导致系统挂起。
|
57
|
+
4. **决策即工具**: 所有的决策和分析都必须通过工具调用来体现。
|
58
|
+
5. **等待结果**: 在继续下一步之前,必须等待当前工具的执行结果。
|
59
|
+
6. **持续推进**: 除非任务完成,否则必须生成可操作的下一步。
|
60
|
+
7. **记录沉淀**: 如果解决方案有普适价值,应记录为方法论。
|
61
|
+
8. **用户语言**: 始终使用用户的语言进行交流。
|
62
|
+
</rules>
|
55
63
|
|
56
64
|
<workflow>
|
57
|
-
# 🔄
|
58
|
-
1.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
→ 必须调用分析工具
|
63
|
-
|
64
|
-
2. 解决方案设计
|
65
|
-
- 生成多个可执行的解决方案
|
66
|
-
- 评估并选择最优方案
|
67
|
-
- 使用PlantUML创建详细行动计划
|
68
|
-
→ 必须调用设计工具
|
69
|
-
|
70
|
-
3. 执行
|
71
|
-
- 一次执行一个步骤
|
72
|
-
- 每个步骤只使用一个工具
|
73
|
-
- 等待工具结果后再继续
|
74
|
-
- 监控结果并根据需要调整
|
75
|
-
→ 必须调用执行工具
|
76
|
-
|
77
|
-
4. 任务完成
|
78
|
-
- 验证目标完成情况
|
79
|
-
- 如有价值则记录方法论
|
65
|
+
# 🔄 工作流程
|
66
|
+
1. **分析**: 理解和分析问题,定义清晰的目标。
|
67
|
+
2. **设计**: 设计解决方案并制定详细的行动计划。
|
68
|
+
3. **执行**: 按照计划,一次一个步骤地执行。
|
69
|
+
4. **完成**: 验证任务是否达成目标,并进行总结。
|
80
70
|
</workflow>
|
81
71
|
|
82
|
-
<principles>
|
83
|
-
# ⚖️ 操作原则
|
84
|
-
- 每个步骤一个操作
|
85
|
-
- 下一步前必须等待结果
|
86
|
-
- 除非任务完成否则必须生成可操作步骤
|
87
|
-
- 根据反馈调整计划
|
88
|
-
- 记录可复用的解决方案
|
89
|
-
- 使用完成命令结束任务
|
90
|
-
- 操作之间不能有中间思考状态
|
91
|
-
- 所有决策必须表现为工具调用
|
92
|
-
</principles>
|
93
|
-
|
94
|
-
<rules>
|
95
|
-
# ❗ 重要规则
|
96
|
-
1. 每个步骤只能使用一个操作
|
97
|
-
2. 必须等待操作执行结果
|
98
|
-
3. 必须验证任务完成情况
|
99
|
-
4. 必须生成可操作步骤
|
100
|
-
5. 如果无需操作必须使用完成命令
|
101
|
-
6. 永远不要使对话处于等待状态
|
102
|
-
7. 始终使用用户语言交流
|
103
|
-
8. 必须记录有价值的方法论
|
104
|
-
9. 违反操作协议将导致系统崩溃
|
105
|
-
10. 空响应会触发永久挂起
|
106
|
-
</rules>
|
107
|
-
|
108
72
|
<system_info>
|
109
|
-
#
|
110
|
-
{platform.platform()}
|
111
|
-
{
|
112
|
-
|
113
|
-
# 当前时间
|
114
|
-
{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
73
|
+
# 系统信息
|
74
|
+
- OS: {platform.platform()} {platform.version()}
|
75
|
+
- Time: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
|
115
76
|
</system_info>
|
116
77
|
"""
|
117
78
|
|
118
79
|
|
119
|
-
class OutputHandlerProtocol(Protocol):
|
120
|
-
def name(self) -> str: ...
|
121
|
-
|
122
|
-
def can_handle(self, response: str) -> bool: ...
|
123
|
-
|
124
|
-
def prompt(self) -> str: ...
|
125
|
-
|
126
|
-
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
|
127
|
-
|
128
|
-
|
129
80
|
class Agent:
|
130
81
|
def clear(self):
|
131
|
-
"""清除当前对话历史,保留系统消息。
|
132
|
-
|
133
|
-
该方法将:
|
134
|
-
1. 调用模型的delete_chat方法清除对话历史
|
135
|
-
2. 重置对话长度计数器
|
136
|
-
3. 清空当前提示
|
137
82
|
"""
|
138
|
-
|
139
|
-
|
140
|
-
self.
|
83
|
+
Clears the current conversation history by delegating to the session manager.
|
84
|
+
"""
|
85
|
+
self.session.clear()
|
141
86
|
|
142
87
|
def __del__(self):
|
143
88
|
# 只有在记录启动时才停止记录
|
@@ -207,6 +152,9 @@ class Agent:
|
|
207
152
|
|
208
153
|
self.model.set_suppress_output(False)
|
209
154
|
|
155
|
+
# Initialize the session manager
|
156
|
+
self.session = SessionManager(model=self.model, agent_name=self.name)
|
157
|
+
|
210
158
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
211
159
|
|
212
160
|
self.output_handler = output_handler if output_handler else [ToolRegistry()]
|
@@ -227,13 +175,10 @@ class Agent:
|
|
227
175
|
self.use_analysis = (
|
228
176
|
use_analysis if use_analysis is not None else is_use_analysis()
|
229
177
|
)
|
230
|
-
self.prompt = ""
|
231
|
-
self.conversation_length = 0 # Use length counter instead
|
232
178
|
self.system_prompt = system_prompt
|
233
179
|
self.input_handler = input_handler if input_handler is not None else []
|
234
180
|
self.need_summary = need_summary
|
235
181
|
# Load configuration from environment variables
|
236
|
-
self.addon_prompt = ""
|
237
182
|
|
238
183
|
self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
|
239
184
|
|
@@ -244,24 +189,7 @@ class Agent:
|
|
244
189
|
)
|
245
190
|
|
246
191
|
self.summary_prompt = (
|
247
|
-
summary_prompt
|
248
|
-
if summary_prompt
|
249
|
-
else f"""<report>
|
250
|
-
请生成任务执行的简明总结报告,包括:
|
251
|
-
|
252
|
-
<content>
|
253
|
-
1. 任务目标:任务重述
|
254
|
-
2. 执行结果:成功/失败
|
255
|
-
3. 关键信息:执行过程中提取的重要信息
|
256
|
-
4. 重要发现:任何值得注意的发现
|
257
|
-
5. 后续建议:如果有的话
|
258
|
-
</content>
|
259
|
-
|
260
|
-
<format>
|
261
|
-
请使用简洁的要点描述,突出重要信息。
|
262
|
-
</format>
|
263
|
-
</report>
|
264
|
-
"""
|
192
|
+
summary_prompt if summary_prompt else DEFAULT_SUMMARY_PROMPT
|
265
193
|
)
|
266
194
|
|
267
195
|
self.max_token_count = get_max_token_count()
|
@@ -270,46 +198,7 @@ class Agent:
|
|
270
198
|
|
271
199
|
PrettyOutput.print(welcome_message, OutputType.SYSTEM)
|
272
200
|
|
273
|
-
action_prompt =
|
274
|
-
<actions>
|
275
|
-
# 🧰 可用操作
|
276
|
-
以下是您可以使用的操作:
|
277
|
-
"""
|
278
|
-
|
279
|
-
# 添加工具列表概览
|
280
|
-
action_prompt += "\n<overview>\n## Action List\n"
|
281
|
-
action_prompt += (
|
282
|
-
"[" + ", ".join([handler.name() for handler in self.output_handler]) + "]"
|
283
|
-
)
|
284
|
-
action_prompt += "\n</overview>"
|
285
|
-
|
286
|
-
# 添加每个工具的详细说明
|
287
|
-
action_prompt += "\n\n<details>\n# 📝 Action Details\n"
|
288
|
-
for handler in self.output_handler:
|
289
|
-
action_prompt += f"\n<tool>\n## {handler.name()}\n"
|
290
|
-
# 获取工具的提示词并确保格式正确
|
291
|
-
handler_prompt = handler.prompt().strip()
|
292
|
-
# 调整缩进以保持层级结构
|
293
|
-
handler_prompt = "\n".join(
|
294
|
-
" " + line if line.strip() else line
|
295
|
-
for line in handler_prompt.split("\n")
|
296
|
-
)
|
297
|
-
action_prompt += handler_prompt + "\n</tool>\n"
|
298
|
-
|
299
|
-
# 添加工具使用总结
|
300
|
-
action_prompt += """
|
301
|
-
</details>
|
302
|
-
|
303
|
-
<rules>
|
304
|
-
# ❗ 重要操作使用规则
|
305
|
-
1. 一次对话只能使用一个操作,否则会出错
|
306
|
-
2. 严格按照每个操作的格式执行
|
307
|
-
3. 等待操作结果后再进行下一个操作
|
308
|
-
4. 处理完结果后再调用新的操作
|
309
|
-
5. 如果对操作使用不清楚,请请求帮助
|
310
|
-
</rules>
|
311
|
-
</actions>
|
312
|
-
"""
|
201
|
+
action_prompt = build_action_prompt(self.output_handler) # type: ignore
|
313
202
|
|
314
203
|
self.model.set_system_prompt(
|
315
204
|
f"""
|
@@ -321,12 +210,12 @@ class Agent:
|
|
321
210
|
self.first = True
|
322
211
|
|
323
212
|
def set_user_data(self, key: str, value: Any):
|
324
|
-
"""
|
325
|
-
self.
|
213
|
+
"""Sets user data in the session."""
|
214
|
+
self.session.set_user_data(key, value)
|
326
215
|
|
327
216
|
def get_user_data(self, key: str) -> Optional[Any]:
|
328
|
-
"""
|
329
|
-
return self.
|
217
|
+
"""Gets user data from the session."""
|
218
|
+
return self.session.get_user_data(key)
|
330
219
|
|
331
220
|
def set_use_tools(self, use_tools):
|
332
221
|
"""设置要使用的工具列表"""
|
@@ -339,12 +228,8 @@ class Agent:
|
|
339
228
|
break
|
340
229
|
|
341
230
|
def set_addon_prompt(self, addon_prompt: str):
|
342
|
-
"""
|
343
|
-
|
344
|
-
参数:
|
345
|
-
addon_prompt: 附加提示内容
|
346
|
-
"""
|
347
|
-
self.addon_prompt = addon_prompt
|
231
|
+
"""Sets the addon prompt in the session."""
|
232
|
+
self.session.set_addon_prompt(addon_prompt)
|
348
233
|
|
349
234
|
def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
|
350
235
|
"""设置工具调用后回调函数。
|
@@ -355,41 +240,12 @@ class Agent:
|
|
355
240
|
self.after_tool_call_cb = cb
|
356
241
|
|
357
242
|
def save_session(self) -> bool:
|
358
|
-
"""
|
359
|
-
|
360
|
-
PrettyOutput.print("没有可用的模型实例来保存会话。", OutputType.ERROR)
|
361
|
-
return False
|
362
|
-
session_dir = os.path.join(os.getcwd(), ".jarvis")
|
363
|
-
os.makedirs(session_dir, exist_ok=True)
|
364
|
-
platform_name = self.model.platform_name()
|
365
|
-
model_name = self.model.name().replace("/", "_").replace("\\", "_")
|
366
|
-
session_file = os.path.join(
|
367
|
-
session_dir, f"saved_session_{self.name}_{platform_name}_{model_name}.json"
|
368
|
-
)
|
369
|
-
return self.model.save(session_file)
|
243
|
+
"""Saves the current session state by delegating to the session manager."""
|
244
|
+
return self.session.save_session()
|
370
245
|
|
371
246
|
def restore_session(self) -> bool:
|
372
|
-
"""
|
373
|
-
|
374
|
-
return False # No model, cannot restore
|
375
|
-
platform_name = self.model.platform_name()
|
376
|
-
model_name = self.model.name().replace("/", "_").replace("\\", "_")
|
377
|
-
session_file = os.path.join(
|
378
|
-
os.getcwd(),
|
379
|
-
".jarvis",
|
380
|
-
f"saved_session_{self.name}_{platform_name}_{model_name}.json",
|
381
|
-
)
|
382
|
-
if not os.path.exists(session_file):
|
383
|
-
return False
|
384
|
-
|
385
|
-
if self.model.restore(session_file):
|
386
|
-
try:
|
387
|
-
os.remove(session_file)
|
388
|
-
PrettyOutput.print("会话已恢复,并已删除会话文件。", OutputType.SUCCESS)
|
389
|
-
except OSError as e:
|
390
|
-
PrettyOutput.print(f"删除会话文件失败: {e}", OutputType.ERROR)
|
391
|
-
return True
|
392
|
-
return False
|
247
|
+
"""Restores the session state by delegating to the session manager."""
|
248
|
+
return self.session.restore_session()
|
393
249
|
|
394
250
|
def get_tool_registry(self) -> Optional[Any]:
|
395
251
|
"""获取工具注册表实例"""
|
@@ -421,21 +277,23 @@ class Agent:
|
|
421
277
|
if need_return:
|
422
278
|
return message
|
423
279
|
|
424
|
-
if self.addon_prompt:
|
425
|
-
message += f"\n\n{self.addon_prompt}"
|
426
|
-
self.addon_prompt = ""
|
280
|
+
if self.session.addon_prompt:
|
281
|
+
message += f"\n\n{self.session.addon_prompt}"
|
282
|
+
self.session.addon_prompt = ""
|
427
283
|
else:
|
428
284
|
message += f"\n\n{self.make_default_addon_prompt(need_complete)}"
|
429
285
|
|
430
286
|
# 累加对话长度
|
431
|
-
self.conversation_length += get_context_token_count(message)
|
287
|
+
self.session.conversation_length += get_context_token_count(message)
|
432
288
|
|
433
|
-
if self.conversation_length > self.max_token_count:
|
289
|
+
if self.session.conversation_length > self.max_token_count:
|
434
290
|
message = self._summarize_and_clear_history() + "\n\n" + message
|
435
|
-
self.conversation_length += get_context_token_count(message)
|
291
|
+
self.session.conversation_length += get_context_token_count(message)
|
436
292
|
|
293
|
+
if not self.model:
|
294
|
+
raise RuntimeError("Model not initialized")
|
437
295
|
response = self.model.chat_until_success(message) # type: ignore
|
438
|
-
self.conversation_length += get_context_token_count(response)
|
296
|
+
self.session.conversation_length += get_context_token_count(response)
|
439
297
|
|
440
298
|
return response
|
441
299
|
|
@@ -449,31 +307,12 @@ class Agent:
|
|
449
307
|
仅生成摘要,不修改对话状态
|
450
308
|
"""
|
451
309
|
print("📄 正在总结对话历史...")
|
452
|
-
summary_prompt = """
|
453
|
-
<summary_request>
|
454
|
-
<objective>
|
455
|
-
请对当前对话历史进行简明扼要的总结,提取关键信息和重要决策点。这个总结将作为上下文继续任务,因此需要保留对后续对话至关重要的内容。
|
456
|
-
</objective>
|
457
|
-
|
458
|
-
<guidelines>
|
459
|
-
1. 提取关键信息:任务目标、已确定的事实、重要决策、达成的共识
|
460
|
-
2. 保留技术细节:命令、代码片段、文件路径、配置设置等技术细节
|
461
|
-
3. 记录任务进展:已完成的步骤、当前所处阶段、待解决的问题
|
462
|
-
4. 包含用户偏好:用户表达的明确偏好、限制条件或特殊要求
|
463
|
-
5. 省略冗余内容:问候语、重复信息、不相关的讨论
|
464
|
-
</guidelines>
|
465
|
-
|
466
|
-
<format>
|
467
|
-
- 使用简洁、客观的语言
|
468
|
-
- 按时间顺序或主题组织信息
|
469
|
-
- 使用要点列表增强可读性
|
470
|
-
- 总结应控制在500词以内
|
471
|
-
</format>
|
472
|
-
</summary_request>
|
473
|
-
"""
|
474
|
-
|
475
310
|
try:
|
476
|
-
|
311
|
+
if not self.model:
|
312
|
+
raise RuntimeError("Model not initialized")
|
313
|
+
summary = self.model.chat_until_success(
|
314
|
+
self.session.prompt + "\n" + SUMMARY_REQUEST_PROMPT
|
315
|
+
) # type: ignore
|
477
316
|
print("✅ 总结对话历史完成")
|
478
317
|
return summary
|
479
318
|
except Exception as e:
|
@@ -533,46 +372,10 @@ class Agent:
|
|
533
372
|
os.remove(tmp_file_name)
|
534
373
|
|
535
374
|
def _call_tools(self, response: str) -> Tuple[bool, Any]:
|
536
|
-
"""调用工具执行响应
|
537
|
-
|
538
|
-
参数:
|
539
|
-
response: 包含工具调用信息的响应字符串
|
540
|
-
|
541
|
-
返回:
|
542
|
-
Tuple[bool, Any]:
|
543
|
-
- 第一个元素表示是否需要返回结果
|
544
|
-
- 第二个元素是返回结果或错误信息
|
545
|
-
|
546
|
-
注意:
|
547
|
-
1. 一次只能执行一个工具
|
548
|
-
2. 如果配置了确认选项,会在执行前请求用户确认
|
549
|
-
3. 使用spinner显示执行状态
|
550
375
|
"""
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
tool_list.append(handler)
|
555
|
-
if len(tool_list) > 1:
|
556
|
-
PrettyOutput.print(
|
557
|
-
f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
|
558
|
-
OutputType.WARNING,
|
559
|
-
)
|
560
|
-
return (
|
561
|
-
False,
|
562
|
-
f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
|
563
|
-
)
|
564
|
-
if len(tool_list) == 0:
|
565
|
-
return False, ""
|
566
|
-
|
567
|
-
if not self.execute_tool_confirm or user_confirm(
|
568
|
-
f"需要执行{tool_list[0].name()}确认执行?", True
|
569
|
-
):
|
570
|
-
print(f"🔧 正在执行{tool_list[0].name()}...")
|
571
|
-
result = tool_list[0].handle(response, self)
|
572
|
-
print(f"✅ {tool_list[0].name()}执行完成")
|
573
|
-
|
574
|
-
return result
|
575
|
-
return False, ""
|
376
|
+
Delegates the tool execution to the external `execute_tool_call` function.
|
377
|
+
"""
|
378
|
+
return execute_tool_call(response, self)
|
576
379
|
|
577
380
|
def _complete_task(self) -> str:
|
578
381
|
"""完成任务并生成总结(如果需要)
|
@@ -589,8 +392,10 @@ class Agent:
|
|
589
392
|
self._analysis_task()
|
590
393
|
if self.need_summary:
|
591
394
|
print("📄 正在生成总结...")
|
592
|
-
self.prompt = self.summary_prompt
|
593
|
-
|
395
|
+
self.session.prompt = self.summary_prompt
|
396
|
+
if not self.model:
|
397
|
+
raise RuntimeError("Model not initialized")
|
398
|
+
ret = self.model.chat_until_success(self.session.prompt) # type: ignore
|
594
399
|
print("✅ 总结生成完成")
|
595
400
|
return ret
|
596
401
|
|
@@ -600,154 +405,12 @@ class Agent:
|
|
600
405
|
print("🔍 正在分析任务...")
|
601
406
|
try:
|
602
407
|
# 让模型判断是否需要生成方法论
|
603
|
-
analysis_prompt =
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
4. 如果无法通过编写通用工具完成,评估当前的执行流程是否可以总结为通用方法论
|
610
|
-
5. 如果以上都不可行,给出详细理由
|
611
|
-
请根据分析结果采取相应行动:说明现有工具/方法论、创建新工具、生成新方法论或说明原因。
|
612
|
-
</request>
|
613
|
-
<evaluation_criteria>
|
614
|
-
现有资源评估:
|
615
|
-
1. 现有工具 - 检查系统中是否已有可以完成该任务的工具
|
616
|
-
2. 现有方法论 - 检查是否已有适用于该任务的方法论
|
617
|
-
3. 组合使用 - 评估现有工具和方法论组合使用是否可以解决问题
|
618
|
-
工具评估标准:
|
619
|
-
1. 通用性 - 该工具是否可以解决一类问题,而不仅仅是当前特定问题
|
620
|
-
2. 自动化 - 该工具是否可以减少人工干预,提高效率
|
621
|
-
3. 可靠性 - 该工具是否可以在不同场景下稳定工作
|
622
|
-
4. 简单性 - 该工具是否易于使用,参数设计是否合理
|
623
|
-
方法论评估标准:
|
624
|
-
1. 方法论应聚焦于通用且可重复的解决方案流程
|
625
|
-
2. 方法论应该具备足够的通用性,可应用于同类问题
|
626
|
-
3. 特别注意用户在执行过程中提供的修正、反馈和改进建议
|
627
|
-
4. 如果用户明确指出了某个解决步骤的优化方向,这应该被纳入方法论
|
628
|
-
5. 方法论要严格按照实际的执行流程来总结,不要遗漏或增加任何步骤
|
629
|
-
</evaluation_criteria>
|
630
|
-
<tool_requirements>
|
631
|
-
工具代码要求:
|
632
|
-
1. 工具类名应与工具名称保持一致
|
633
|
-
2. 必须包含name、description、parameters属性
|
634
|
-
3. 必须实现execute方法处理输入参数
|
635
|
-
4. 可选实现check方法验证环境
|
636
|
-
5. 工具描述应详细说明用途、适用场景和使用示例
|
637
|
-
6. 参数定义应遵循JSON Schema格式
|
638
|
-
7. 不要包含特定任务的细节,保持通用性
|
639
|
-
工具设计关键点:
|
640
|
-
1. **使用PrettyOutput打印执行过程**:强烈建议在工具中使用PrettyOutput显示执行过程,
|
641
|
-
这样用户可以了解工具在做什么,提升用户体验。示例:
|
642
|
-
```python
|
643
|
-
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
644
|
-
# 执行中打印信息
|
645
|
-
PrettyOutput.print("正在处理数据...", OutputType.INFO)
|
646
|
-
# 成功信息
|
647
|
-
PrettyOutput.print("操作成功完成", OutputType.SUCCESS)
|
648
|
-
# 警告信息
|
649
|
-
PrettyOutput.print("发现潜在问题", OutputType.WARNING)
|
650
|
-
# 错误信息
|
651
|
-
PrettyOutput.print("操作失败", OutputType.ERROR)
|
652
|
-
```
|
653
|
-
2. **结构化返回结果**:工具应该始终返回结构化的结果字典,包含以下字段:
|
654
|
-
- success: 布尔值,表示操作是否成功
|
655
|
-
- stdout: 字符串,包含工具的主要输出内容
|
656
|
-
- stderr: 字符串,包含错误信息(如果有)
|
657
|
-
3. **异常处理**:工具应该妥善处理可能发生的异常,并在失败时清理已创建的资源
|
658
|
-
```python
|
659
|
-
try:
|
660
|
-
# 执行逻辑
|
661
|
-
return {{
|
662
|
-
"success": True,
|
663
|
-
"stdout": "成功结果",
|
664
|
-
"stderr": ""
|
665
|
-
}}
|
666
|
-
except Exception as e:
|
667
|
-
PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
|
668
|
-
# 清理资源(如果有创建)
|
669
|
-
return {{
|
670
|
-
"success": False,
|
671
|
-
"stdout": "",
|
672
|
-
"stderr": f"操作失败: {{str(e)}}"
|
673
|
-
}}
|
674
|
-
```
|
675
|
-
</tool_requirements>
|
676
|
-
<methodology_requirements>
|
677
|
-
方法论格式要求:
|
678
|
-
1. 问题重述: 简明扼要的问题归纳,不含特定细节
|
679
|
-
2. 最优解决方案: 经过用户验证的、最终有效的解决方案(将每个步骤要使用的工具也列举出来)
|
680
|
-
3. 注意事项: 执行中可能遇到的常见问题和注意点,尤其是用户指出的问题
|
681
|
-
4. 可选步骤: 对于有多种解决路径的问题,标注出可选步骤和适用场景
|
682
|
-
</methodology_requirements>
|
683
|
-
<output_requirements>
|
684
|
-
根据分析结果,输出以下三种情况之一:
|
685
|
-
1. 如果现有工具/方法论可以解决,直接输出说明:
|
686
|
-
已有工具/方法论可以解决该问题,无需创建新内容。
|
687
|
-
可用的工具/方法论:[列出工具名称或方法论名称]
|
688
|
-
使用方法:[简要说明如何使用]
|
689
|
-
2. 工具创建(如果需要创建新工具):
|
690
|
-
{ot("TOOL_CALL")}
|
691
|
-
want: 创建新工具来解决XXX问题
|
692
|
-
name: generate_new_tool
|
693
|
-
arguments:
|
694
|
-
tool_name: 工具名称
|
695
|
-
tool_code: |2
|
696
|
-
# -*- coding: utf-8 -*-
|
697
|
-
from typing import Dict, Any
|
698
|
-
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
699
|
-
class 工具名称:
|
700
|
-
name = "工具名称"
|
701
|
-
description = "Tool for text transformation"
|
702
|
-
Tool description
|
703
|
-
适用场景:1. 格式化文本; 2. 处理标题; 3. 标准化输出
|
704
|
-
\"\"\"
|
705
|
-
parameters = {{
|
706
|
-
"type": "object",
|
707
|
-
"properties": {{
|
708
|
-
# 参数定义
|
709
|
-
}},
|
710
|
-
"required": []
|
711
|
-
}}
|
712
|
-
@staticmethod
|
713
|
-
def check() -> bool:
|
714
|
-
return True
|
715
|
-
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
716
|
-
try:
|
717
|
-
# 使用PrettyOutput显示执行过程
|
718
|
-
PrettyOutput.print("开始执行操作...", OutputType.INFO)
|
719
|
-
# 实现逻辑
|
720
|
-
# ...
|
721
|
-
PrettyOutput.print("操作已完成", OutputType.SUCCESS)
|
722
|
-
return {{
|
723
|
-
"success": True,
|
724
|
-
"stdout": "结果输出",
|
725
|
-
"stderr": ""
|
726
|
-
}}
|
727
|
-
except Exception as e:
|
728
|
-
PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
|
729
|
-
return {{
|
730
|
-
"success": False,
|
731
|
-
"stdout": "",
|
732
|
-
"stderr": f"操作失败: {{str(e)}}"
|
733
|
-
}}
|
734
|
-
{ct("TOOL_CALL")}
|
735
|
-
3. 方法论创建(如果需要创建新方法论):
|
736
|
-
{ot("TOOL_CALL")}
|
737
|
-
want: 添加/更新xxxx的方法论
|
738
|
-
name: methodology
|
739
|
-
arguments:
|
740
|
-
operation: add/update
|
741
|
-
problem_type: 方法论类型,不要过于细节,也不要过于泛化
|
742
|
-
content: |2
|
743
|
-
方法论内容
|
744
|
-
{ct("TOOL_CALL")}
|
745
|
-
如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
|
746
|
-
</output_requirements>
|
747
|
-
</task_analysis>"""
|
748
|
-
|
749
|
-
self.prompt = analysis_prompt
|
750
|
-
response = self.model.chat_until_success(self.prompt) # type: ignore
|
408
|
+
analysis_prompt = TASK_ANALYSIS_PROMPT
|
409
|
+
|
410
|
+
self.session.prompt = analysis_prompt
|
411
|
+
if not self.model:
|
412
|
+
raise RuntimeError("Model not initialized")
|
413
|
+
response = self.model.chat_until_success(self.session.prompt) # type: ignore
|
751
414
|
self._call_tools(response)
|
752
415
|
print("✅ 分析完成")
|
753
416
|
except Exception as e:
|
@@ -803,7 +466,7 @@ arguments:
|
|
803
466
|
4. 自动加载相关方法论(如果是首次运行)
|
804
467
|
"""
|
805
468
|
|
806
|
-
self.prompt = f"{user_input}"
|
469
|
+
self.session.prompt = f"{user_input}"
|
807
470
|
try:
|
808
471
|
set_agent(self.name, self)
|
809
472
|
|
@@ -811,8 +474,8 @@ arguments:
|
|
811
474
|
if self.first:
|
812
475
|
self._first_run()
|
813
476
|
try:
|
814
|
-
current_response = self._call_model(self.prompt, True)
|
815
|
-
self.prompt = ""
|
477
|
+
current_response = self._call_model(self.session.prompt, True)
|
478
|
+
self.session.prompt = ""
|
816
479
|
|
817
480
|
if get_interrupt():
|
818
481
|
set_interrupt(False)
|
@@ -828,20 +491,24 @@ arguments:
|
|
828
491
|
if user_confirm(
|
829
492
|
"检测到有工具调用,是否继续处理工具调用?", True
|
830
493
|
):
|
831
|
-
self.prompt =
|
494
|
+
self.session.prompt = (
|
495
|
+
f"{user_input}\n\n{current_response}"
|
496
|
+
)
|
832
497
|
continue
|
833
|
-
self.prompt += f"{user_input}"
|
498
|
+
self.session.prompt += f"{user_input}"
|
834
499
|
continue
|
835
500
|
|
836
|
-
need_return, self.prompt = self._call_tools(
|
501
|
+
need_return, self.session.prompt = self._call_tools(
|
502
|
+
current_response
|
503
|
+
)
|
837
504
|
|
838
505
|
if need_return:
|
839
|
-
return self.prompt
|
506
|
+
return self.session.prompt
|
840
507
|
|
841
508
|
if self.after_tool_call_cb:
|
842
509
|
self.after_tool_call_cb(self)
|
843
510
|
|
844
|
-
if self.prompt or self.addon_prompt:
|
511
|
+
if self.session.prompt or self.session.addon_prompt:
|
845
512
|
continue
|
846
513
|
|
847
514
|
if self.auto_complete and ot("!!!COMPLETE!!!") in current_response:
|
@@ -853,7 +520,7 @@ arguments:
|
|
853
520
|
)
|
854
521
|
|
855
522
|
if user_input:
|
856
|
-
self.prompt = user_input
|
523
|
+
self.session.prompt = user_input
|
857
524
|
continue
|
858
525
|
|
859
526
|
if not user_input:
|
@@ -877,44 +544,35 @@ arguments:
|
|
877
544
|
"文件上传失败,将忽略文件列表", OutputType.WARNING
|
878
545
|
)
|
879
546
|
# 上传失败则回退到本地加载
|
880
|
-
msg = self.prompt
|
547
|
+
msg = self.session.prompt
|
881
548
|
for handler in self.input_handler:
|
882
549
|
msg, _ = handler(msg, self)
|
883
|
-
self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
550
|
+
self.session.prompt = f"{self.session.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
884
551
|
else:
|
885
552
|
if self.files:
|
886
|
-
self.prompt = f"{self.prompt}\n\n上传的文件包含历史对话信息和方法论文件,可以从中获取一些经验信息。"
|
553
|
+
self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息和方法论文件,可以从中获取一些经验信息。"
|
887
554
|
else:
|
888
|
-
self.prompt = f"{self.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
|
555
|
+
self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
|
889
556
|
elif self.files:
|
890
557
|
if not self.model.upload_files(self.files):
|
891
558
|
PrettyOutput.print(
|
892
559
|
"文件上传失败,将忽略文件列表", OutputType.WARNING
|
893
560
|
)
|
894
561
|
else:
|
895
|
-
self.prompt = f"{self.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
|
562
|
+
self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
|
896
563
|
else:
|
897
564
|
if self.files:
|
898
565
|
PrettyOutput.print("不支持上传文件,将忽略文件列表", OutputType.WARNING)
|
899
566
|
if self.use_methodology:
|
900
|
-
msg = self.prompt
|
567
|
+
msg = self.session.prompt
|
901
568
|
for handler in self.input_handler:
|
902
569
|
msg, _ = handler(msg, self)
|
903
|
-
self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
570
|
+
self.session.prompt = f"{self.session.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
904
571
|
|
905
572
|
self.first = False
|
906
573
|
|
907
574
|
def clear_history(self):
|
908
|
-
"""清空对话历史但保留系统提示
|
909
|
-
|
910
|
-
该方法将:
|
911
|
-
1. 清空当前提示
|
912
|
-
2. 重置模型状态
|
913
|
-
3. 重置对话长度计数器
|
914
|
-
|
915
|
-
注意:
|
916
|
-
用于重置Agent状态而不影响系统消息
|
917
575
|
"""
|
918
|
-
|
919
|
-
|
920
|
-
self.
|
576
|
+
Clears conversation history by delegating to the session manager.
|
577
|
+
"""
|
578
|
+
self.session.clear_history()
|