jarvis-ai-assistant 0.2.4__py3-none-any.whl → 0.2.5__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 +13 -7
- jarvis/jarvis_agent/edit_file_handler.py +1 -2
- jarvis/jarvis_code_agent/code_agent.py +7 -13
- jarvis/jarvis_data/config_schema.json +2 -19
- jarvis/jarvis_stats/cli.py +72 -5
- jarvis/jarvis_stats/stats.py +175 -70
- jarvis/jarvis_stats/storage.py +53 -1
- jarvis/jarvis_stats/visualizer.py +63 -224
- jarvis/jarvis_tools/cli/main.py +7 -9
- jarvis/jarvis_tools/registry.py +2 -5
- jarvis/jarvis_utils/config.py +6 -8
- jarvis/jarvis_utils/methodology.py +74 -67
- jarvis/jarvis_utils/utils.py +342 -119
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/METADATA +11 -2
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/RECORD +20 -20
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.2.4.dist-info → jarvis_ai_assistant-0.2.5.dist-info}/top_level.txt +0 -0
@@ -5,9 +5,10 @@
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import os
|
8
|
-
|
8
|
+
import io
|
9
9
|
from typing import Dict, List, Optional, Any
|
10
10
|
from collections import OrderedDict
|
11
|
+
import plotext as plt
|
11
12
|
from rich.console import Console
|
12
13
|
from rich.table import Table
|
13
14
|
from rich.panel import Panel
|
@@ -51,106 +52,50 @@ class StatsVisualizer:
|
|
51
52
|
show_values: bool = True,
|
52
53
|
) -> str:
|
53
54
|
"""
|
54
|
-
绘制折线图
|
55
|
-
|
56
|
-
Args:
|
57
|
-
data: 数据字典,键为时间标签,值为数值
|
58
|
-
title: 图表标题
|
59
|
-
unit: 单位
|
60
|
-
show_values: 是否显示数值
|
61
|
-
|
62
|
-
Returns:
|
63
|
-
图表字符串
|
55
|
+
使用 plotext 绘制折线图
|
64
56
|
"""
|
65
57
|
if not data:
|
66
58
|
return "无数据可显示"
|
67
59
|
|
68
|
-
# 排序数据
|
69
60
|
sorted_data = OrderedDict(sorted(data.items()))
|
70
|
-
|
71
|
-
# 提取值和标签
|
72
61
|
labels = list(sorted_data.keys())
|
73
62
|
values = list(sorted_data.values())
|
74
63
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# 如果所有值相同,调整范围
|
80
|
-
if min_val == max_val:
|
81
|
-
if min_val == 0:
|
82
|
-
min_val = -1
|
83
|
-
max_val = 1
|
84
|
-
else:
|
85
|
-
min_val = min_val * 0.9
|
86
|
-
max_val = max_val * 1.1
|
87
|
-
|
88
|
-
# 创建图表画布
|
89
|
-
chart_width = self.width - 10 # 留出y轴标签空间
|
90
|
-
chart_height = self.height - 5 # 留出x轴标签空间
|
91
|
-
|
92
|
-
# 初始化画布
|
93
|
-
canvas = [[" " for _ in range(chart_width)] for _ in range(chart_height)]
|
94
|
-
|
95
|
-
# 计算缩放因子
|
96
|
-
x_scale = (chart_width - 1) / max(len(values) - 1, 1)
|
97
|
-
y_scale = (chart_height - 1) / (max_val - min_val)
|
98
|
-
|
99
|
-
# 绘制坐标轴
|
100
|
-
for i in range(chart_height):
|
101
|
-
canvas[i][0] = "│"
|
102
|
-
for j in range(chart_width):
|
103
|
-
canvas[chart_height - 1][j] = "─"
|
104
|
-
canvas[chart_height - 1][0] = "└"
|
105
|
-
|
106
|
-
# 绘制数据点和连线
|
107
|
-
points = []
|
108
|
-
for i, value in enumerate(values):
|
109
|
-
x = int(i * x_scale) + 1
|
110
|
-
y = chart_height - 1 - int((value - min_val) * y_scale)
|
111
|
-
y = max(0, min(chart_height - 1, y)) # 确保在范围内
|
112
|
-
|
113
|
-
if 0 <= x < chart_width and 0 <= y < chart_height:
|
114
|
-
points.append((x, y, value))
|
115
|
-
canvas[y][x] = "●"
|
116
|
-
|
117
|
-
# 连接数据点
|
118
|
-
for i in range(len(points) - 1):
|
119
|
-
x1, y1, _ = points[i]
|
120
|
-
x2, y2, _ = points[i + 1]
|
121
|
-
self._draw_line(canvas, x1, y1, x2, y2)
|
122
|
-
|
123
|
-
# 构建输出
|
124
|
-
output = []
|
125
|
-
|
126
|
-
# 标题
|
64
|
+
plt.clf()
|
65
|
+
plt.plotsize(self.width, self.height)
|
66
|
+
plt.plot(values)
|
67
|
+
plt.xticks(range(len(labels)), labels)
|
127
68
|
if title:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# Y轴标签和图表
|
132
|
-
y_labels = self._generate_y_labels(min_val, max_val, chart_height)
|
133
|
-
|
134
|
-
for i, row in enumerate(canvas):
|
135
|
-
label = y_labels.get(i, "")
|
136
|
-
line = f"{label:>8} " + "".join(row)
|
137
|
-
output.append(line)
|
69
|
+
plt.title(title)
|
70
|
+
if unit:
|
71
|
+
plt.ylabel(unit)
|
138
72
|
|
139
|
-
|
140
|
-
x_labels = self._generate_x_labels(labels, chart_width)
|
141
|
-
output.append(" " * 9 + x_labels)
|
73
|
+
chart = plt.build()
|
142
74
|
|
143
|
-
|
144
|
-
|
145
|
-
|
75
|
+
if show_values and values:
|
76
|
+
min_val = min(values)
|
77
|
+
max_val = max(values)
|
78
|
+
avg_val = sum(values) / len(values)
|
79
|
+
stats_info_text = (
|
80
|
+
f"最小值: {min_val:.2f}, 最大值: {max_val:.2f}, 平均值: {avg_val:.2f}"
|
81
|
+
)
|
146
82
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
83
|
+
# 使用StringIO捕获Panel输出
|
84
|
+
string_io = io.StringIO()
|
85
|
+
temp_console = Console(file=string_io, width=self.width)
|
86
|
+
temp_console.print(
|
87
|
+
Panel(
|
88
|
+
stats_info_text,
|
89
|
+
title="[bold]数据统计[/bold]",
|
90
|
+
expand=False,
|
91
|
+
style="dim",
|
92
|
+
border_style="blue",
|
93
|
+
)
|
151
94
|
)
|
95
|
+
stats_panel_str = string_io.getvalue()
|
152
96
|
|
153
|
-
|
97
|
+
return chart + "\n" + stats_panel_str.strip()
|
98
|
+
return chart
|
154
99
|
|
155
100
|
def plot_bar_chart(
|
156
101
|
self,
|
@@ -160,75 +105,27 @@ class StatsVisualizer:
|
|
160
105
|
horizontal: bool = False,
|
161
106
|
) -> str:
|
162
107
|
"""
|
163
|
-
绘制柱状图
|
164
|
-
|
165
|
-
Args:
|
166
|
-
data: 数据字典
|
167
|
-
title: 图表标题
|
168
|
-
unit: 单位
|
169
|
-
horizontal: 是否横向
|
170
|
-
|
171
|
-
Returns:
|
172
|
-
图表字符串
|
108
|
+
使用 plotext 绘制柱状图
|
173
109
|
"""
|
174
110
|
if not data:
|
175
111
|
return "无数据可显示"
|
176
112
|
|
177
|
-
|
178
|
-
|
179
|
-
# 标题
|
180
|
-
if title:
|
181
|
-
output.append(f"\n{title.center(self.width)}")
|
182
|
-
output.append("=" * self.width)
|
113
|
+
labels = list(data.keys())
|
114
|
+
values = list(data.values())
|
183
115
|
|
184
|
-
|
185
|
-
|
116
|
+
plt.clf()
|
117
|
+
plt.plotsize(self.width, self.height)
|
186
118
|
|
187
119
|
if horizontal:
|
188
|
-
|
189
|
-
max_label_len = max(len(str(k)) for k in data.keys())
|
190
|
-
bar_width = self.width - max_label_len - 15
|
191
|
-
|
192
|
-
for label, value in data.items():
|
193
|
-
bar_len = int((value / max_value) * bar_width)
|
194
|
-
bar = "█" * bar_len
|
195
|
-
output.append(f"{str(label):>{max_label_len}} │{bar} {value:.2f}")
|
120
|
+
plt.bar(labels, values, orientation="horizontal")
|
196
121
|
else:
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
values = list(data.values())
|
201
|
-
|
202
|
-
# 创建画布
|
203
|
-
canvas = [[" " for _ in range(len(labels) * 4)] for _ in range(bar_height)]
|
204
|
-
|
205
|
-
# 绘制柱子
|
206
|
-
for i, (label, value) in enumerate(zip(labels, values)):
|
207
|
-
height = int((value / max_value) * bar_height)
|
208
|
-
x = i * 4 + 1
|
209
|
-
|
210
|
-
for y in range(bar_height - height, bar_height):
|
211
|
-
if y >= 0 and x < len(canvas[0]):
|
212
|
-
canvas[y][x] = "█"
|
213
|
-
if x + 1 < len(canvas[0]):
|
214
|
-
canvas[y][x + 1] = "█"
|
215
|
-
|
216
|
-
# 输出画布
|
217
|
-
for row in canvas:
|
218
|
-
output.append("".join(row))
|
219
|
-
|
220
|
-
# X轴标签
|
221
|
-
label_line = ""
|
222
|
-
for i, label in enumerate(labels):
|
223
|
-
x = i * 4
|
224
|
-
label_line += f"{label[:3]:>4}"
|
225
|
-
output.append(label_line)
|
226
|
-
|
227
|
-
# 单位
|
122
|
+
plt.bar(labels, values)
|
123
|
+
if title:
|
124
|
+
plt.title(title)
|
228
125
|
if unit:
|
229
|
-
|
126
|
+
plt.ylabel(unit)
|
230
127
|
|
231
|
-
return
|
128
|
+
return plt.build()
|
232
129
|
|
233
130
|
def show_summary(
|
234
131
|
self,
|
@@ -346,98 +243,40 @@ class StatsVisualizer:
|
|
346
243
|
if unit:
|
347
244
|
info_items.append(f"单位: {unit}")
|
348
245
|
if start_time and end_time:
|
349
|
-
info_items.append(f"时间范围: {start_time} ~ {end_time}")
|
246
|
+
info_items.append(f"时间范围: [cyan]{start_time}[/] ~ [cyan]{end_time}[/]")
|
350
247
|
if tags_filter:
|
351
248
|
filter_str = ", ".join([f"{k}={v}" for k, v in tags_filter.items()])
|
352
249
|
info_items.append(f"过滤条件: {filter_str}")
|
353
250
|
|
354
251
|
if info_items:
|
355
|
-
self.console.print(
|
252
|
+
self.console.print(
|
253
|
+
Panel(
|
254
|
+
" | ".join(info_items),
|
255
|
+
title="[bold]查询详情[/bold]",
|
256
|
+
expand=False,
|
257
|
+
style="dim",
|
258
|
+
border_style="green",
|
259
|
+
)
|
260
|
+
)
|
356
261
|
|
357
262
|
# 统计信息
|
358
263
|
if len(records) > 0:
|
359
264
|
values = [r["value"] for r in records]
|
360
|
-
|
265
|
+
stats_info_text = (
|
361
266
|
f"总记录数: {len(records)} | "
|
362
267
|
f"显示: {len(display_records)} | "
|
363
268
|
f"最小值: {min(values):.2f} | "
|
364
269
|
f"最大值: {max(values):.2f} | "
|
365
270
|
f"平均值: {sum(values)/len(values):.2f}"
|
366
271
|
)
|
367
|
-
self.console.print(
|
272
|
+
self.console.print(
|
273
|
+
Panel(
|
274
|
+
stats_info_text,
|
275
|
+
title="[bold]数据统计[/bold]",
|
276
|
+
expand=False,
|
277
|
+
style="dim",
|
278
|
+
border_style="blue",
|
279
|
+
)
|
280
|
+
)
|
368
281
|
|
369
282
|
return ""
|
370
|
-
|
371
|
-
def _draw_line(self, canvas: List[List[str]], x1: int, y1: int, x2: int, y2: int):
|
372
|
-
"""在画布上绘制线条"""
|
373
|
-
# 使用Bresenham算法绘制线条
|
374
|
-
dx = abs(x2 - x1)
|
375
|
-
dy = abs(y2 - y1)
|
376
|
-
sx = 1 if x1 < x2 else -1
|
377
|
-
sy = 1 if y1 < y2 else -1
|
378
|
-
err = dx - dy
|
379
|
-
|
380
|
-
x, y = x1, y1
|
381
|
-
|
382
|
-
while True:
|
383
|
-
if 0 <= x < len(canvas[0]) and 0 <= y < len(canvas):
|
384
|
-
if canvas[y][x] == " ":
|
385
|
-
if dx > dy:
|
386
|
-
canvas[y][x] = "─"
|
387
|
-
else:
|
388
|
-
canvas[y][x] = "│"
|
389
|
-
|
390
|
-
if x == x2 and y == y2:
|
391
|
-
break
|
392
|
-
|
393
|
-
e2 = 2 * err
|
394
|
-
if e2 > -dy:
|
395
|
-
err -= dy
|
396
|
-
x += sx
|
397
|
-
if e2 < dx:
|
398
|
-
err += dx
|
399
|
-
y += sy
|
400
|
-
|
401
|
-
def _generate_y_labels(
|
402
|
-
self, min_val: float, max_val: float, height: int
|
403
|
-
) -> Dict[int, str]:
|
404
|
-
"""生成Y轴标签"""
|
405
|
-
labels = {}
|
406
|
-
|
407
|
-
# 在顶部、中部和底部放置标签
|
408
|
-
positions = [0, height // 2, height - 1]
|
409
|
-
values = [max_val, (max_val + min_val) / 2, min_val]
|
410
|
-
|
411
|
-
for pos, val in zip(positions, values):
|
412
|
-
labels[pos] = f"{val:.1f}"
|
413
|
-
|
414
|
-
return labels
|
415
|
-
|
416
|
-
def _generate_x_labels(self, labels: List[str], width: int) -> str:
|
417
|
-
"""生成X轴标签"""
|
418
|
-
if not labels:
|
419
|
-
return ""
|
420
|
-
|
421
|
-
# 简化标签(如果是时间格式)
|
422
|
-
simplified_labels = []
|
423
|
-
for label in labels:
|
424
|
-
if len(label) > 10:
|
425
|
-
# 尝试提取时间部分
|
426
|
-
parts = label.split()
|
427
|
-
if len(parts) >= 2:
|
428
|
-
simplified_labels.append(parts[1][:5]) # 只取时间
|
429
|
-
else:
|
430
|
-
simplified_labels.append(label[:8])
|
431
|
-
else:
|
432
|
-
simplified_labels.append(label)
|
433
|
-
|
434
|
-
# 根据空间决定显示多少标签
|
435
|
-
max_labels = width // 10
|
436
|
-
step = max(1, len(simplified_labels) // max_labels)
|
437
|
-
|
438
|
-
label_line = ""
|
439
|
-
for i in range(0, len(simplified_labels), step):
|
440
|
-
if i < len(simplified_labels):
|
441
|
-
label_line += f"{simplified_labels[i]:>10}"
|
442
|
-
|
443
|
-
return label_line
|
jarvis/jarvis_tools/cli/main.py
CHANGED
@@ -48,8 +48,6 @@ def stat_tools(
|
|
48
48
|
"""显示工具调用统计信息"""
|
49
49
|
from jarvis.jarvis_stats.stats import StatsManager
|
50
50
|
|
51
|
-
stats_manager = StatsManager()
|
52
|
-
|
53
51
|
if format == "table":
|
54
52
|
registry = ToolRegistry()
|
55
53
|
stats = registry._get_tool_stats()
|
@@ -78,13 +76,13 @@ def stat_tools(
|
|
78
76
|
# 使用 stats 系统的高级功能
|
79
77
|
PrettyOutput.section("工具组统计", OutputType.SYSTEM)
|
80
78
|
# 显示所有标记为 tool 组的指标
|
81
|
-
metrics =
|
79
|
+
metrics = StatsManager.list_metrics()
|
82
80
|
tool_metrics = []
|
83
81
|
|
84
82
|
for metric in metrics:
|
85
83
|
# 检查是否是工具组的指标
|
86
84
|
if last_days:
|
87
|
-
stats_data =
|
85
|
+
stats_data = StatsManager.get_stats(
|
88
86
|
metric_name=metric,
|
89
87
|
last_days=last_days,
|
90
88
|
tags={"group": "tool"}
|
@@ -92,7 +90,7 @@ def stat_tools(
|
|
92
90
|
else:
|
93
91
|
# 获取所有历史数据
|
94
92
|
from datetime import datetime
|
95
|
-
stats_data =
|
93
|
+
stats_data = StatsManager.get_stats(
|
96
94
|
metric_name=metric,
|
97
95
|
start_time=datetime(2000, 1, 1),
|
98
96
|
end_time=datetime.now(),
|
@@ -105,10 +103,10 @@ def stat_tools(
|
|
105
103
|
for metric in tool_metrics:
|
106
104
|
if format == "chart":
|
107
105
|
if last_days:
|
108
|
-
|
106
|
+
StatsManager.plot(metric, last_days=last_days, tags={"group": "tool"})
|
109
107
|
else:
|
110
108
|
from datetime import datetime
|
111
|
-
|
109
|
+
StatsManager.plot(
|
112
110
|
metric,
|
113
111
|
start_time=datetime(2000, 1, 1),
|
114
112
|
end_time=datetime.now(),
|
@@ -116,10 +114,10 @@ def stat_tools(
|
|
116
114
|
)
|
117
115
|
elif format == "summary":
|
118
116
|
if last_days:
|
119
|
-
|
117
|
+
StatsManager.show(metric, last_days=last_days, format="summary", tags={"group": "tool"})
|
120
118
|
else:
|
121
119
|
from datetime import datetime
|
122
|
-
|
120
|
+
StatsManager.show(
|
123
121
|
metric,
|
124
122
|
start_time=datetime(2000, 1, 1),
|
125
123
|
end_time=datetime.now(),
|
jarvis/jarvis_tools/registry.py
CHANGED
@@ -203,8 +203,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
203
203
|
from jarvis.jarvis_stats.stats import StatsManager
|
204
204
|
from datetime import datetime, timedelta
|
205
205
|
|
206
|
-
stats_manager = StatsManager()
|
207
|
-
|
208
206
|
# 获取所有工具的统计数据
|
209
207
|
tool_stats = {}
|
210
208
|
tools = self.get_all_tools()
|
@@ -216,7 +214,7 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
216
214
|
for tool in tools:
|
217
215
|
tool_name = tool["name"]
|
218
216
|
# 获取该工具的统计数据
|
219
|
-
stats_data =
|
217
|
+
stats_data = StatsManager.get_stats(
|
220
218
|
metric_name=tool_name,
|
221
219
|
start_time=start_time,
|
222
220
|
end_time=end_time,
|
@@ -236,8 +234,7 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
236
234
|
"""更新工具调用统计"""
|
237
235
|
from jarvis.jarvis_stats.stats import StatsManager
|
238
236
|
|
239
|
-
|
240
|
-
stats_manager.increment(name, group="tool")
|
237
|
+
StatsManager.increment(name, group="tool")
|
241
238
|
|
242
239
|
def use_tools(self, name: List[str]) -> None:
|
243
240
|
"""使用指定工具
|
jarvis/jarvis_utils/config.py
CHANGED
@@ -81,10 +81,10 @@ def get_max_token_count(model_group_override: Optional[str] = None) -> int:
|
|
81
81
|
获取模型允许的最大token数量。
|
82
82
|
|
83
83
|
返回:
|
84
|
-
int: 模型能处理的最大token
|
84
|
+
int: 模型能处理的最大token数量,为最大输入token数量的100倍。
|
85
85
|
"""
|
86
|
-
|
87
|
-
return
|
86
|
+
max_input_tokens = get_max_input_token_count(model_group_override)
|
87
|
+
return max_input_tokens * 100
|
88
88
|
|
89
89
|
|
90
90
|
def get_max_input_token_count(model_group_override: Optional[str] = None) -> int:
|
@@ -151,9 +151,7 @@ def _get_resolved_model_config(
|
|
151
151
|
"JARVIS_MODEL",
|
152
152
|
"JARVIS_THINKING_PLATFORM",
|
153
153
|
"JARVIS_THINKING_MODEL",
|
154
|
-
"JARVIS_MAX_TOKEN_COUNT",
|
155
154
|
"JARVIS_MAX_INPUT_TOKEN_COUNT",
|
156
|
-
"JARVIS_MAX_BIG_CONTENT_SIZE",
|
157
155
|
]:
|
158
156
|
if key in GLOBAL_CONFIG_DATA:
|
159
157
|
resolved_config[key] = GLOBAL_CONFIG_DATA[key]
|
@@ -249,10 +247,10 @@ def get_max_big_content_size(model_group_override: Optional[str] = None) -> int:
|
|
249
247
|
获取最大大内容大小。
|
250
248
|
|
251
249
|
返回:
|
252
|
-
int:
|
250
|
+
int: 最大大内容大小,为最大输入token数量的5倍
|
253
251
|
"""
|
254
|
-
|
255
|
-
return
|
252
|
+
max_input_tokens = get_max_input_token_count(model_group_override)
|
253
|
+
return max_input_tokens * 5
|
256
254
|
|
257
255
|
|
258
256
|
def get_pretty_output() -> bool:
|
@@ -149,6 +149,7 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
|
|
149
149
|
|
150
150
|
参数:
|
151
151
|
user_input: 用户输入文本,用于提示大模型
|
152
|
+
tool_registery: 工具注册表,用于获取工具列表
|
152
153
|
|
153
154
|
返回:
|
154
155
|
str: 相关的方法论提示,如果未找到方法论则返回空字符串
|
@@ -170,70 +171,87 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
|
|
170
171
|
return ""
|
171
172
|
print(f"✅ 加载方法论文件完成 (共 {len(methodologies)} 个)")
|
172
173
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
else:
|
179
|
-
platform = PlatformRegistry().get_normal_platform()
|
180
|
-
model_group = None
|
181
|
-
platform.set_suppress_output(False)
|
182
|
-
if not platform:
|
183
|
-
return ""
|
174
|
+
platform = PlatformRegistry().get_normal_platform()
|
175
|
+
platform.set_suppress_output(True)
|
176
|
+
|
177
|
+
# 步骤1:获取所有方法论的标题
|
178
|
+
methodology_titles = list(methodologies.keys())
|
184
179
|
|
185
|
-
#
|
186
|
-
|
180
|
+
# 步骤2:让大模型选择相关性高的方法论
|
181
|
+
selection_prompt = f"""以下是所有可用的方法论标题:
|
187
182
|
|
188
183
|
"""
|
189
|
-
|
190
|
-
|
191
|
-
for problem_type, content in methodologies.items():
|
192
|
-
full_content += f"## {problem_type}\n\n{content}\n\n---\n\n"
|
184
|
+
for i, title in enumerate(methodology_titles, 1):
|
185
|
+
selection_prompt += f"{i}. {title}\n"
|
193
186
|
|
194
|
-
|
195
|
-
|
187
|
+
selection_prompt += f"""
|
188
|
+
以下是可用的工具列表:
|
189
|
+
{prompt}
|
196
190
|
|
197
|
-
|
198
|
-
full_content += f"""
|
199
|
-
请根据以上方法论和可调用的工具内容,规划/总结出以下用户需求的执行步骤: {user_input}
|
191
|
+
用户需求:{user_input}
|
200
192
|
|
201
|
-
|
202
|
-
### 与该任务/需求相关的方法论
|
203
|
-
1. [方法论名字]
|
204
|
-
2. [方法论名字]
|
205
|
-
### 根据以上方法论,规划/总结出执行步骤
|
206
|
-
1. [步骤1]
|
207
|
-
2. [步骤2]
|
208
|
-
3. [步骤3]
|
193
|
+
请分析用户需求,从上述方法论中选择出与需求相关性较高的方法论(可以选择多个)。
|
209
194
|
|
210
|
-
|
211
|
-
|
195
|
+
请严格按照以下格式返回序号:
|
196
|
+
<NUM>序号1,序号2,序号3</NUM>
|
197
|
+
|
198
|
+
例如:<NUM>1,3,5</NUM>
|
199
|
+
|
200
|
+
如果没有相关的方法论,请返回:<NUM>none</NUM>
|
201
|
+
|
202
|
+
注意:只返回<NUM>标签内的内容,不要有其他任何输出。
|
212
203
|
"""
|
213
204
|
|
214
|
-
#
|
215
|
-
|
216
|
-
|
205
|
+
# 获取大模型选择的方法论序号
|
206
|
+
response = platform.chat_until_success(selection_prompt).strip()
|
207
|
+
|
208
|
+
# 重置平台,恢复输出
|
209
|
+
platform.reset()
|
210
|
+
platform.set_suppress_output(False)
|
211
|
+
|
212
|
+
# 从响应中提取<NUM>标签内的内容
|
213
|
+
import re
|
214
|
+
num_match = re.search(r'<NUM>(.*?)</NUM>', response, re.DOTALL)
|
215
|
+
|
216
|
+
if not num_match:
|
217
|
+
# 如果没有找到<NUM>标签,尝试直接解析响应
|
218
|
+
selected_indices_str = response
|
219
|
+
else:
|
220
|
+
selected_indices_str = num_match.group(1).strip()
|
221
|
+
|
222
|
+
if selected_indices_str.lower() == "none":
|
223
|
+
return "没有历史方法论可参考"
|
217
224
|
|
225
|
+
# 解析选择的序号
|
226
|
+
selected_methodologies = {}
|
218
227
|
try:
|
219
|
-
if
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
228
|
+
if selected_indices_str:
|
229
|
+
indices = [int(idx.strip()) for idx in selected_indices_str.split(",") if idx.strip().isdigit()]
|
230
|
+
for idx in indices:
|
231
|
+
if 1 <= idx <= len(methodology_titles):
|
232
|
+
title = methodology_titles[idx - 1]
|
233
|
+
selected_methodologies[title] = methodologies[title]
|
234
|
+
except Exception:
|
235
|
+
# 如果解析失败,返回空结果
|
236
|
+
return "没有历史方法论可参考"
|
237
|
+
|
238
|
+
if not selected_methodologies:
|
239
|
+
return "没有历史方法论可参考"
|
240
|
+
|
241
|
+
# 步骤3:将选择出来的方法论内容提供给大模型生成步骤
|
242
|
+
final_prompt = f"""以下是与用户需求相关的方法论内容:
|
243
|
+
|
244
|
+
"""
|
245
|
+
for problem_type, content in selected_methodologies.items():
|
246
|
+
final_prompt += f"## {problem_type}\n\n{content}\n\n---\n\n"
|
247
|
+
|
248
|
+
final_prompt += f"""以下是所有可用的工具内容:
|
249
|
+
|
250
|
+
{prompt}
|
251
|
+
|
252
|
+
用户需求:{user_input}
|
253
|
+
|
254
|
+
请根据以上方法论和可调用的工具内容,规划/总结出执行步骤。
|
237
255
|
|
238
256
|
请按以下格式回复:
|
239
257
|
### 与该任务/需求相关的方法论
|
@@ -244,22 +262,11 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
|
|
244
262
|
2. [步骤2]
|
245
263
|
3. [步骤3]
|
246
264
|
|
247
|
-
如果没有匹配的方法论,请输出:没有历史方法论可参考
|
248
265
|
除以上要求外,不要输出任何内容
|
249
266
|
"""
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
# 如果内容不大或上传失败,直接使用chat_until_success
|
254
|
-
return platform.chat_until_success(full_content)
|
255
|
-
|
256
|
-
finally:
|
257
|
-
# 清理临时文件
|
258
|
-
if temp_file_path and os.path.exists(temp_file_path):
|
259
|
-
try:
|
260
|
-
os.remove(temp_file_path)
|
261
|
-
except Exception:
|
262
|
-
pass
|
267
|
+
|
268
|
+
# 如果内容不大,直接使用chat_until_success
|
269
|
+
return platform.chat_until_success(final_prompt)
|
263
270
|
|
264
271
|
except Exception as e:
|
265
272
|
PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
|