sync: 157 file da Baida98/AI@eeb3e0e9 (2026-08-15 15:39 UTC) [deploy-all]

#40
by Baida07 - opened
api/benchmark_handler.py CHANGED
@@ -36,6 +36,11 @@ _BENCH_SCRIPT = next(
36
  os.path.join(_REPO_ROOT, "benchmark-extended.mjs"),
37
  )
38
  _REPORT_V7 = "/tmp/agente-ai/benchmark-v5-latest.json"
 
 
 
 
 
39
  # 20 task seriali possono richiedere piΓΉ di 12 minuti con provider gratuiti.
40
  _BENCH_TIMEOUT = float(os.getenv("BENCH_TIMEOUT_SECS", "3600"))
41
 
@@ -50,12 +55,26 @@ async def run_benchmark_task(chat_id: int, send_reply_fn, mode: str = "full") ->
50
  "Il deployment non ha incluso <code>benchmark-extended.mjs</code>.")
51
  return
52
 
53
- flags = ["--full", "--json", f"--output={_REPORT_V7}", "--gap-analysis"]
54
- await send_reply_fn(
55
- chat_id,
56
- "πŸš€ <b>Benchmark Extended v5 avviato</b>\n"
57
- "<i>20/20 categorie Β· seed 1337 Β· task API moderna Β· durata variabile fino a ~60 min.</i>",
58
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  env = {
60
  **os.environ,
61
  "INTERNAL_TOKEN": os.getenv("INTERNAL_TOKEN", ""),
@@ -96,25 +115,26 @@ async def run_benchmark_task(chat_id: int, send_reply_fn, mode: str = "full") ->
96
  await send_reply_fn(chat_id, f"πŸ’₯ <b>Errore critico benchmark:</b> <code>{exc}</code>")
97
  return
98
 
99
- report_exists = await asyncio.to_thread(os.path.exists, _REPORT_V7)
100
  if not report_exists:
101
  await send_reply_fn(chat_id, "⚠️ <b>Benchmark Extended terminato ma report non trovato.</b>")
102
  return
103
  try:
104
- report: dict[str, Any] = await asyncio.to_thread(_read_json, _REPORT_V7)
105
  except Exception as exc:
106
  await send_reply_fn(chat_id, f"⚠️ <b>Report Extended non leggibile:</b> <code>{exc}</code>")
107
  return
108
 
109
  categories = {str(task.get("cat", "")) for task in report.get("tasks", []) if task.get("cat")}
110
- if len(categories) != 20:
111
- await send_reply_fn(chat_id, f"⚠️ <b>Run incompleta:</b> <code>{len(categories)}/20</code> categorie nel report."
 
112
  " Nessun risultato incompleto viene presentato come benchmark completo.")
113
  return
114
- await send_reply_fn(chat_id, _format_v7_report(report))
115
 
116
 
117
- def _format_v7_report(report: dict[str, Any]) -> str:
118
  """Formatta il report v7 per Telegram HTML."""
119
  s = report.get("summary", {})
120
  ts = (report.get("timestamp") or "")[:16].replace("T", " ")
@@ -132,7 +152,8 @@ def _format_v7_report(report: dict[str, Any]) -> str:
132
  lines: list[str] = [
133
  f"πŸ† <b>Benchmark {ver} completato!</b>\n\n"
134
  f"πŸ“Š <b>Score agente:</b> <code>{avg}/100</code>\n"
135
- f"πŸ“… <b>Run:</b> <code>{ts}</code>\n\n"
 
136
  "πŸ“ˆ <b>Confronto vs riferimenti:</b>\n"
137
  f" β€’ Replit: <code>{repl}/100</code>\n"
138
  f" β€’ Cursor: <code>{curs}/100</code>\n"
@@ -160,7 +181,7 @@ def _format_v7_report(report: dict[str, Any]) -> str:
160
  scored = s.get("scoredTaskCount", sum(len(v) for v in by_cat.values()))
161
  skipped = s.get("skippedTaskCount", max(0, attempted - scored))
162
  lines.append(
163
- f"πŸ§ͺ <b>Copertura:</b> <code>{len(attempted_categories)}/20 categorie tentate Β· "
164
  f"{scored} valutabili Β· {skipped} non valutabili</code>\n"
165
  )
166
  if by_cat:
 
36
  os.path.join(_REPO_ROOT, "benchmark-extended.mjs"),
37
  )
38
  _REPORT_V7 = "/tmp/agente-ai/benchmark-v5-latest.json"
39
+ _REPORT_V7_WEAK = "/tmp/agente-ai/benchmark-v5-weak-latest.json"
40
+ _WEAK_CATEGORIES = (
41
+ "sql", "context_window", "reasoning", "data_analysis", "research_synthesis",
42
+ "mmlu", "technical_writing", "code_correct", "feature", "security",
43
+ )
44
  # 20 task seriali possono richiedere piΓΉ di 12 minuti con provider gratuiti.
45
  _BENCH_TIMEOUT = float(os.getenv("BENCH_TIMEOUT_SECS", "3600"))
46
 
 
55
  "Il deployment non ha incluso <code>benchmark-extended.mjs</code>.")
56
  return
57
 
58
+ is_weak_run = mode == "weak"
59
+ if is_weak_run:
60
+ report_path = _REPORT_V7_WEAK
61
+ flags = [
62
+ f"--categories={','.join(_WEAK_CATEGORIES)}", "--json",
63
+ f"--output={report_path}", "--gap-analysis",
64
+ ]
65
+ await send_reply_fn(
66
+ chat_id,
67
+ "🎯 <b>Benchmark Extended v5 mirato avviato</b>\n"
68
+ "<i>10 categorie piΓΉ deboli della baseline 39,1 Β· seed 1337 Β· task API moderna.</i>",
69
+ )
70
+ else:
71
+ report_path = _REPORT_V7
72
+ flags = ["--full", "--json", f"--output={report_path}", "--gap-analysis"]
73
+ await send_reply_fn(
74
+ chat_id,
75
+ "πŸš€ <b>Benchmark Extended v5 avviato</b>\n"
76
+ "<i>20/20 categorie Β· seed 1337 Β· task API moderna Β· durata variabile fino a ~60 min.</i>",
77
+ )
78
  env = {
79
  **os.environ,
80
  "INTERNAL_TOKEN": os.getenv("INTERNAL_TOKEN", ""),
 
115
  await send_reply_fn(chat_id, f"πŸ’₯ <b>Errore critico benchmark:</b> <code>{exc}</code>")
116
  return
117
 
118
+ report_exists = await asyncio.to_thread(os.path.exists, report_path)
119
  if not report_exists:
120
  await send_reply_fn(chat_id, "⚠️ <b>Benchmark Extended terminato ma report non trovato.</b>")
121
  return
122
  try:
123
+ report: dict[str, Any] = await asyncio.to_thread(_read_json, report_path)
124
  except Exception as exc:
125
  await send_reply_fn(chat_id, f"⚠️ <b>Report Extended non leggibile:</b> <code>{exc}</code>")
126
  return
127
 
128
  categories = {str(task.get("cat", "")) for task in report.get("tasks", []) if task.get("cat")}
129
+ expected_categories = len(_WEAK_CATEGORIES) if is_weak_run else 20
130
+ if len(categories) != expected_categories:
131
+ await send_reply_fn(chat_id, f"⚠️ <b>Run incompleta:</b> <code>{len(categories)}/{expected_categories}</code> categorie nel report."
132
  " Nessun risultato incompleto viene presentato come benchmark completo.")
133
  return
134
+ await send_reply_fn(chat_id, _format_v7_report(report, expected_categories=expected_categories, run_label="mirato Β· categorie deboli" if is_weak_run else None))
135
 
136
 
137
+ def _format_v7_report(report: dict[str, Any], *, expected_categories: int = 20, run_label: str | None = None) -> str:
138
  """Formatta il report v7 per Telegram HTML."""
139
  s = report.get("summary", {})
140
  ts = (report.get("timestamp") or "")[:16].replace("T", " ")
 
152
  lines: list[str] = [
153
  f"πŸ† <b>Benchmark {ver} completato!</b>\n\n"
154
  f"πŸ“Š <b>Score agente:</b> <code>{avg}/100</code>\n"
155
+ f"πŸ“… <b>Run:</b> <code>{ts}</code>\n"
156
+ + (f"🎯 <b>Modalità:</b> <code>{run_label}</code>\n" if run_label else "") + "\n"
157
  "πŸ“ˆ <b>Confronto vs riferimenti:</b>\n"
158
  f" β€’ Replit: <code>{repl}/100</code>\n"
159
  f" β€’ Cursor: <code>{curs}/100</code>\n"
 
181
  scored = s.get("scoredTaskCount", sum(len(v) for v in by_cat.values()))
182
  skipped = s.get("skippedTaskCount", max(0, attempted - scored))
183
  lines.append(
184
+ f"πŸ§ͺ <b>Copertura:</b> <code>{len(attempted_categories)}/{expected_categories} categorie tentate Β· "
185
  f"{scored} valutabili Β· {skipped} non valutabili</code>\n"
186
  )
187
  if by_cat:
api/telegram_webhook.py CHANGED
@@ -1623,8 +1623,9 @@ async def _cmd_bench(chat_id: int, mode: str = "default") -> None:
1623
  """Avvia il benchmark Extended su tutte le 20 categorie in background."""
1624
  from .benchmark_handler import run_benchmark_task
1625
 
1626
- _BENCH_CACHE[chat_id] = {"mode": "extended-20", "run_url": "", "started_at": time.time()}
1627
- task = asyncio.create_task(run_benchmark_task(chat_id, _tg_reply, mode="full"))
 
1628
  task.add_done_callback(lambda completed: _logger.error(
1629
  "[bench-extended] background task failed: %s", completed.exception()
1630
  ) if not completed.cancelled() and completed.exception() else None)
@@ -2058,7 +2059,7 @@ async def telegram_webhook(request: Request) -> dict:
2058
  await _tg_reply(chat_id, "🧠 Uso: <code>/ask &lt;domanda&gt;</code>", keyboard=_MAIN_KB)
2059
  elif cmd == "/bench":
2060
  _mode = text[len(cmd):].strip() or "default"
2061
- if _mode not in ("default","full","coding-only","noncode-only","agentic-only"):
2062
  _mode = "default"
2063
  _t=asyncio.create_task(_cmd_bench(chat_id, _mode)); _t.add_done_callback(_log_tg_exc)
2064
  elif cmd == "/score":
 
1623
  """Avvia il benchmark Extended su tutte le 20 categorie in background."""
1624
  from .benchmark_handler import run_benchmark_task
1625
 
1626
+ normalized_mode = "weak" if mode == "weak" else "full"
1627
+ _BENCH_CACHE[chat_id] = {"mode": "extended-weak" if normalized_mode == "weak" else "extended-20", "run_url": "", "started_at": time.time()}
1628
+ task = asyncio.create_task(run_benchmark_task(chat_id, _tg_reply, mode=normalized_mode))
1629
  task.add_done_callback(lambda completed: _logger.error(
1630
  "[bench-extended] background task failed: %s", completed.exception()
1631
  ) if not completed.cancelled() and completed.exception() else None)
 
2059
  await _tg_reply(chat_id, "🧠 Uso: <code>/ask &lt;domanda&gt;</code>", keyboard=_MAIN_KB)
2060
  elif cmd == "/bench":
2061
  _mode = text[len(cmd):].strip() or "default"
2062
+ if _mode not in ("default","full","coding-only","noncode-only","agentic-only","weak"):
2063
  _mode = "default"
2064
  _t=asyncio.create_task(_cmd_bench(chat_id, _mode)); _t.add_done_callback(_log_tg_exc)
2065
  elif cmd == "/score":
benchmark-extended.mjs CHANGED
@@ -35,7 +35,7 @@
35
  * Usage:
36
  * node benchmark-extended.mjs [--seed N] [--compare N]
37
  * [--coding-only] [--noncode-only] [--agentic-only]
38
- * [--full] [--json] [--output=PATH] [--no-hf]
39
  * [--gap-analysis] # stampa gap cards per i fail
40
  * [--rotate] # seed casuale (default: 1337 canonico)
41
  *
@@ -67,6 +67,10 @@ const F_GAP = _A.includes("--gap-analysis");
67
  const _multi = _A.indexOf("--multi");
68
  const MULTI = _multi !== -1 ? Math.max(2, Math.min(10, parseInt(_A[_multi+1])||3)) : 1;
69
  const F_JUDGE = !_A.includes("--no-judge"); // semantic judge abilitato di default
 
 
 
 
70
 
71
  // ── Colors ────────────────────────────────────────────────────────────────────
72
  const G="\x1b[32m",R="\x1b[31m",Y="\x1b[33m",B="\x1b[34m",
@@ -2001,8 +2005,15 @@ async function runOneSeed(seed,opts={}){
2001
  ccTask,
2002
  ];
2003
 
 
2004
  let selected;
2005
- if(F_CODING){
 
 
 
 
 
 
2006
  selected=rng.shuffle(codingTasks).slice(0,7);
2007
  } else if(F_NONCODE){
2008
  selected=[rsTask,daTask,twTask,ryTask,sqlTask,cwTask,mmluTask];
 
35
  * Usage:
36
  * node benchmark-extended.mjs [--seed N] [--compare N]
37
  * [--coding-only] [--noncode-only] [--agentic-only]
38
+ * [--full] [--categories=a,b] [--json] [--output=PATH] [--no-hf]
39
  * [--gap-analysis] # stampa gap cards per i fail
40
  * [--rotate] # seed casuale (default: 1337 canonico)
41
  *
 
67
  const _multi = _A.indexOf("--multi");
68
  const MULTI = _multi !== -1 ? Math.max(2, Math.min(10, parseInt(_A[_multi+1])||3)) : 1;
69
  const F_JUDGE = !_A.includes("--no-judge"); // semantic judge abilitato di default
70
+ const _categoriesArg = _A.find(a=>a.startsWith("--categories="));
71
+ const TARGET_CATEGORIES = _categoriesArg
72
+ ? new Set(_categoriesArg.slice("--categories=".length).split(",").map(c=>c.trim()).filter(Boolean))
73
+ : null;
74
 
75
  // ── Colors ────────────────────────────────────────────────────────────────────
76
  const G="\x1b[32m",R="\x1b[31m",Y="\x1b[33m",B="\x1b[34m",
 
2005
  ccTask,
2006
  ];
2007
 
2008
+ const allTasks = [...codingTasks,...[rsTask,daTask,twTask,ryTask,sqlTask,cwTask,mmluTask],...[orTask,mcTask,rcTask,rbTask,avTask]];
2009
  let selected;
2010
+ if (TARGET_CATEGORIES) {
2011
+ const known = new Set(allTasks.map(task => task.category));
2012
+ const unknown = [...TARGET_CATEGORIES].filter(category => !known.has(category));
2013
+ if (unknown.length) throw new Error(`Categorie benchmark non valide: ${unknown.join(", ")}`);
2014
+ selected = allTasks.filter(task => TARGET_CATEGORIES.has(task.category));
2015
+ if (!selected.length) throw new Error("Nessuna categoria benchmark selezionata");
2016
+ } else if(F_CODING){
2017
  selected=rng.shuffle(codingTasks).slice(0,7);
2018
  } else if(F_NONCODE){
2019
  selected=[rsTask,daTask,twTask,ryTask,sqlTask,cwTask,mmluTask];
tests/test_telegram_extended_benchmark.py CHANGED
@@ -50,5 +50,37 @@ class ExtendedBenchmarkHandlerTests(unittest.IsolatedAsyncioTestCase):
50
  self.assertIn("20/20 categorie", final_text)
51
 
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  if __name__ == "__main__":
54
  unittest.main()
 
50
  self.assertIn("20/20 categorie", final_text)
51
 
52
 
53
+ async def test_targeted_weak_runner_uses_only_low_score_categories_and_separate_report(self):
54
+ categories = list(handler._WEAK_CATEGORIES)
55
+ report = {
56
+ "timestamp": "2026-08-15T12:00:00Z",
57
+ "version": "extended-v5",
58
+ "summary": {"avgScore": 31, "avgReplit": 56, "avgCursor": 62, "avgDevin": 68, "avgManus": 71, "gapCount": 8, "verdict": "SOTTO_REPLIT"},
59
+ "tasks": [{"cat": category, "score": 31} for category in categories],
60
+ "gapCards": [],
61
+ }
62
+ replies = AsyncMock()
63
+ with tempfile.TemporaryDirectory() as directory:
64
+ script = Path(directory) / "benchmark-extended.mjs"
65
+ full_output = Path(directory) / "benchmark-v5-latest.json"
66
+ weak_output = Path(directory) / "benchmark-v5-weak-latest.json"
67
+ script.write_text("// runner")
68
+ full_output.write_text(json.dumps({"tasks": []}))
69
+ weak_output.write_text(json.dumps(report))
70
+ with patch.object(handler, "_BENCH_SCRIPT", str(script)), \
71
+ patch.object(handler, "_REPORT_V7", str(full_output)), \
72
+ patch.object(handler, "_REPORT_V7_WEAK", str(weak_output)), \
73
+ patch("asyncio.create_subprocess_exec", AsyncMock(return_value=_Process())) as create_process:
74
+ await handler.run_benchmark_task(123, replies, mode="weak")
75
+
76
+ command = create_process.await_args.args
77
+ self.assertNotIn("--full", command)
78
+ self.assertIn("--categories=" + ",".join(handler._WEAK_CATEGORIES), command)
79
+ self.assertIn("--output=" + str(weak_output), command)
80
+ final_text = replies.await_args_list[-1].args[1]
81
+ self.assertIn("10/10 categorie", final_text)
82
+ self.assertIn("categorie deboli", final_text)
83
+
84
+
85
  if __name__ == "__main__":
86
  unittest.main()