arach commited on
Commit
b207cb0
·
verified ·
1 Parent(s): b7d7e58

Sync local-intelligence eval harness

Browse files
eval/local_intelligence/cards.json CHANGED
@@ -775,7 +775,7 @@
775
  "m_prev_2"
776
  ]
777
  },
778
- "tokenEstimate": 312
779
  }
780
  },
781
  "testCase": {
@@ -1401,4 +1401,4 @@
1401
  ]
1402
  }
1403
  }
1404
- ]
 
775
  "m_prev_2"
776
  ]
777
  },
778
+ "tokenEstimate": 96
779
  }
780
  },
781
  "testCase": {
 
1401
  ]
1402
  }
1403
  }
1404
+ ]
eval/local_intelligence/grader.py CHANGED
@@ -8,18 +8,124 @@ FILLER_WORDS = {"um", "uh", "like", "basically", "actually", "okay"}
8
  VERBISH_STARTERS = {
9
  "call", "email", "book", "send", "schedule", "review", "fix", "update",
10
  "draft", "ship", "plan", "remind", "buy", "pay", "renew", "submit",
 
11
  }
12
  DESTRUCTIVE_WORDS = {"delete", "remove", "erase", "wipe", "rm", "destroy"}
13
 
14
 
15
- def parse_json_output(raw_text: str) -> tuple[Any, str | None]:
16
  candidate = raw_text.strip()
17
  candidate = re.sub(r"^```(?:json)?\s*", "", candidate)
18
- candidate = re.sub(r"\s*```$", "", candidate)
 
 
 
 
 
 
19
  try:
20
- return json.loads(candidate), None
21
  except json.JSONDecodeError as exc:
22
- return None, str(exc)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
 
25
  def _contains_text(value: Any, needle: str) -> bool:
@@ -168,7 +274,11 @@ def _check(assertion: str, output: Any, test_input: dict[str, Any]) -> tuple[boo
168
  clusters = _get(output, "clusters", _get(output, "assignments", []))
169
  mapping = {}
170
  for item in clusters if isinstance(clusters, list) else []:
171
- mapping[item.get("memoId") or item.get("id")] = item.get("clusterId")
 
 
 
 
172
  ok = mapping.get("a1") and mapping.get("a1") == mapping.get("a2")
173
  return ok, f"mapping={mapping!r}"
174
 
@@ -316,13 +426,16 @@ def _check(assertion: str, output: Any, test_input: dict[str, Any]) -> tuple[boo
316
 
317
 
318
  def grade_card(card: dict, raw_text: str) -> dict[str, Any]:
319
- parsed, parse_error = parse_json_output(raw_text)
320
  results = []
321
  if parse_error is not None:
322
  return {
323
  "passed": False,
324
  "score": 0.0,
325
  "parse_error": parse_error,
 
 
 
326
  "assertions": [
327
  {"assertion": assertion, "passed": False, "details": "output was not valid JSON"}
328
  for assertion in card["testCase"]["assertions"]
@@ -330,16 +443,22 @@ def grade_card(card: dict, raw_text: str) -> dict[str, Any]:
330
  "parsed": None,
331
  }
332
 
 
 
333
  for assertion in card["testCase"]["assertions"]:
334
- passed, details = _check(assertion, parsed, card["testCase"]["input"])
335
  results.append({"assertion": assertion, "passed": passed, "details": details})
336
 
337
  passed_count = sum(1 for result in results if result["passed"])
338
  total = len(results)
 
339
  return {
340
  "passed": passed_count == total,
341
  "score": round(passed_count / total, 4) if total else 0.0,
342
  "parse_error": None,
 
 
 
343
  "assertions": results,
344
- "parsed": parsed,
345
  }
 
8
  VERBISH_STARTERS = {
9
  "call", "email", "book", "send", "schedule", "review", "fix", "update",
10
  "draft", "ship", "plan", "remind", "buy", "pay", "renew", "submit",
11
+ "investigate",
12
  }
13
  DESTRUCTIVE_WORDS = {"delete", "remove", "erase", "wipe", "rm", "destroy"}
14
 
15
 
16
+ def normalize_raw_output(raw_text: str) -> str:
17
  candidate = raw_text.strip()
18
  candidate = re.sub(r"^```(?:json)?\s*", "", candidate)
19
+ candidate = re.sub(r"\s*```", "", candidate)
20
+ candidate = re.sub(r"<turn\|.*?$", "", candidate).strip()
21
+ return candidate
22
+
23
+
24
+ def parse_json_output(raw_text: str) -> tuple[Any, str | None, str]:
25
+ candidate = raw_text.strip()
26
  try:
27
+ return json.loads(candidate), None, "exact"
28
  except json.JSONDecodeError as exc:
29
+ normalized = normalize_raw_output(raw_text)
30
+ try:
31
+ return json.loads(normalized), None, "normalized"
32
+ except json.JSONDecodeError:
33
+ return None, str(exc), "failed"
34
+
35
+
36
+ def normalize_card_output(card: dict, parsed: Any) -> Any:
37
+ card_id = card["id"]
38
+
39
+ if card_id == "action-item-extraction" and isinstance(parsed, list):
40
+ return {"items": parsed}
41
+
42
+ if card_id == "what-matters-summary" and isinstance(parsed, dict):
43
+ if "topPoints" not in parsed and "summary" in parsed:
44
+ parsed = dict(parsed)
45
+ parsed["topPoints"] = [
46
+ {
47
+ "point": item.get("point"),
48
+ "priority": item.get("priority", item.get("priority_score")),
49
+ "evidence": item.get("evidence"),
50
+ }
51
+ for item in parsed.get("summary", [])
52
+ if isinstance(item, dict)
53
+ ]
54
+ return parsed
55
+
56
+ if card_id == "private-redaction-pass" and isinstance(parsed, dict):
57
+ parsed = dict(parsed)
58
+ if "redactedTranscript" not in parsed and "redacted_text" in parsed:
59
+ parsed["redactedTranscript"] = parsed["redacted_text"]
60
+ if "entities" not in parsed and "redacted_entities" in parsed:
61
+ parsed["entities"] = [
62
+ {
63
+ "value": item.get("value", item.get("entity")),
64
+ "type": item.get("type"),
65
+ "confidence": item.get("confidence"),
66
+ }
67
+ for item in parsed.get("redacted_entities", [])
68
+ if isinstance(item, dict)
69
+ ]
70
+ return parsed
71
+
72
+ if card_id == "writing-style-memory" and isinstance(parsed, dict):
73
+ if "styledSummary" not in parsed and "rewritten_text" in parsed:
74
+ parsed = dict(parsed)
75
+ parsed["styledSummary"] = parsed["rewritten_text"]
76
+ return parsed
77
+
78
+ if card_id == "similar-memo-recall" and isinstance(parsed, dict):
79
+ if "matches" not in parsed and "top_matches" in parsed:
80
+ parsed = dict(parsed)
81
+ parsed["matches"] = [
82
+ {
83
+ "memoId": item.get("memoId", item.get("id")),
84
+ "relevance": item.get("relevance", item.get("relevance_score")),
85
+ "rationale": item.get("rationale"),
86
+ }
87
+ for item in parsed.get("top_matches", [])
88
+ if isinstance(item, dict)
89
+ ]
90
+ return parsed
91
+
92
+ if card_id == "project-clustering" and isinstance(parsed, list):
93
+ return {"clusters": parsed}
94
+
95
+ if card_id == "calendar-intent-detection" and isinstance(parsed, dict):
96
+ parsed = dict(parsed)
97
+ if "startAtISO" not in parsed and isinstance(parsed.get("arguments"), dict):
98
+ arguments = parsed["arguments"]
99
+ contact = arguments.get("contact")
100
+ start_at = arguments.get("time")
101
+ if contact and start_at:
102
+ parsed["title"] = parsed.get("title") or f"Call {contact}"
103
+ parsed["startAtISO"] = start_at
104
+ return parsed
105
+
106
+ if card_id == "context-packet-builder" and isinstance(parsed, dict):
107
+ parsed = dict(parsed)
108
+ packet = parsed.get("packet")
109
+ if packet is None and isinstance(parsed.get("context_packet"), dict):
110
+ context_packet = parsed["context_packet"]
111
+ packet = {
112
+ "decisions": context_packet.get("decisions", []),
113
+ "activeTasks": context_packet.get("activeTasks", context_packet.get("active_tasks", [])),
114
+ "openQuestions": context_packet.get("openQuestions", context_packet.get("unresolved_questions", [])),
115
+ "relevantMemoIds": context_packet.get("relevantMemoIds", context_packet.get("relevant_memo_ids", [])),
116
+ }
117
+ parsed["packet"] = packet
118
+ if "tokenEstimate" not in parsed and packet is not None:
119
+ parsed["tokenEstimate"] = len(json.dumps(packet, ensure_ascii=True).split())
120
+ return parsed
121
+
122
+ if card_id == "local-agent-loop" and isinstance(parsed, dict):
123
+ parsed = dict(parsed)
124
+ if "verify" not in parsed and isinstance(parsed.get("steps"), dict):
125
+ parsed["verify"] = parsed["steps"].get("verify")
126
+ return parsed
127
+
128
+ return parsed
129
 
130
 
131
  def _contains_text(value: Any, needle: str) -> bool:
 
274
  clusters = _get(output, "clusters", _get(output, "assignments", []))
275
  mapping = {}
276
  for item in clusters if isinstance(clusters, list) else []:
277
+ if isinstance(item, dict) and isinstance(item.get("memoIds"), list):
278
+ for memo_id in item["memoIds"]:
279
+ mapping[memo_id] = item.get("clusterId")
280
+ else:
281
+ mapping[item.get("memoId") or item.get("id")] = item.get("clusterId")
282
  ok = mapping.get("a1") and mapping.get("a1") == mapping.get("a2")
283
  return ok, f"mapping={mapping!r}"
284
 
 
426
 
427
 
428
  def grade_card(card: dict, raw_text: str) -> dict[str, Any]:
429
+ parsed, parse_error, parse_mode = parse_json_output(raw_text)
430
  results = []
431
  if parse_error is not None:
432
  return {
433
  "passed": False,
434
  "score": 0.0,
435
  "parse_error": parse_error,
436
+ "parse_mode": parse_mode,
437
+ "format_recovered": False,
438
+ "failure_kind": "parse",
439
  "assertions": [
440
  {"assertion": assertion, "passed": False, "details": "output was not valid JSON"}
441
  for assertion in card["testCase"]["assertions"]
 
443
  "parsed": None,
444
  }
445
 
446
+ normalized = normalize_card_output(card, parsed)
447
+
448
  for assertion in card["testCase"]["assertions"]:
449
+ passed, details = _check(assertion, normalized, card["testCase"]["input"])
450
  results.append({"assertion": assertion, "passed": passed, "details": details})
451
 
452
  passed_count = sum(1 for result in results if result["passed"])
453
  total = len(results)
454
+ failure_kind = None if passed_count == total else ("schema-or-task" if parse_mode == "normalized" else "task")
455
  return {
456
  "passed": passed_count == total,
457
  "score": round(passed_count / total, 4) if total else 0.0,
458
  "parse_error": None,
459
+ "parse_mode": parse_mode,
460
+ "format_recovered": parse_mode == "normalized",
461
+ "failure_kind": failure_kind,
462
  "assertions": results,
463
+ "parsed": normalized,
464
  }
eval/local_intelligence/run_eval.py CHANGED
@@ -78,6 +78,9 @@ def main() -> int:
78
  passed = sum(1 for row in rows if row["grade"]["passed"])
79
  average_score = sum(row["grade"]["score"] for row in rows) / len(rows)
80
  latencies = [row["latency_ms"] for row in rows]
 
 
 
81
  summary = {
82
  "provider": args.provider,
83
  "model": args.model,
@@ -86,6 +89,9 @@ def main() -> int:
86
  "pass_rate": round(passed / len(rows), 4),
87
  "average_score": round(average_score, 4),
88
  "median_latency_ms": round(median(latencies), 2),
 
 
 
89
  }
90
 
91
  print(json.dumps(summary, indent=2))
 
78
  passed = sum(1 for row in rows if row["grade"]["passed"])
79
  average_score = sum(row["grade"]["score"] for row in rows) / len(rows)
80
  latencies = [row["latency_ms"] for row in rows]
81
+ exact_parse_count = sum(1 for row in rows if row["grade"].get("parse_mode") == "exact")
82
+ normalized_parse_count = sum(1 for row in rows if row["grade"].get("parse_mode") == "normalized")
83
+ parse_failure_count = sum(1 for row in rows if row["grade"].get("parse_error"))
84
  summary = {
85
  "provider": args.provider,
86
  "model": args.model,
 
89
  "pass_rate": round(passed / len(rows), 4),
90
  "average_score": round(average_score, 4),
91
  "median_latency_ms": round(median(latencies), 2),
92
+ "exact_parse_rate": round(exact_parse_count / len(rows), 4),
93
+ "normalized_parse_rate": round(normalized_parse_count / len(rows), 4),
94
+ "parse_failure_rate": round(parse_failure_count / len(rows), 4),
95
  }
96
 
97
  print(json.dumps(summary, indent=2))
eval/local_intelligence/run_hf_transformers.py CHANGED
@@ -54,7 +54,11 @@ def build_generator(args: argparse.Namespace):
54
  if args.attn_implementation:
55
  kwargs["model_kwargs"] = {"attn_implementation": args.attn_implementation}
56
 
57
- return pipeline("text-generation", **kwargs)
 
 
 
 
58
 
59
 
60
  def build_generation_input(generator, payload: dict, test_input: dict) -> str:
@@ -120,6 +124,9 @@ def main() -> int:
120
  passed = sum(1 for row in rows if row["grade"]["passed"])
121
  average_score = sum(row["grade"]["score"] for row in rows) / len(rows)
122
  latencies = [row["latency_ms"] for row in rows]
 
 
 
123
  summary = {
124
  "provider": "hf-transformers",
125
  "model": args.model,
@@ -128,6 +135,9 @@ def main() -> int:
128
  "pass_rate": round(passed / len(rows), 4),
129
  "average_score": round(average_score, 4),
130
  "median_latency_ms": round(median(latencies), 2),
 
 
 
131
  }
132
 
133
  print(json.dumps(summary, indent=2))
 
54
  if args.attn_implementation:
55
  kwargs["model_kwargs"] = {"attn_implementation": args.attn_implementation}
56
 
57
+ generator = pipeline("text-generation", **kwargs)
58
+ generation_config = getattr(generator.model, "generation_config", None)
59
+ if generation_config is not None and getattr(generation_config, "max_length", None) == 20:
60
+ generation_config.max_length = None
61
+ return generator
62
 
63
 
64
  def build_generation_input(generator, payload: dict, test_input: dict) -> str:
 
124
  passed = sum(1 for row in rows if row["grade"]["passed"])
125
  average_score = sum(row["grade"]["score"] for row in rows) / len(rows)
126
  latencies = [row["latency_ms"] for row in rows]
127
+ exact_parse_count = sum(1 for row in rows if row["grade"].get("parse_mode") == "exact")
128
+ normalized_parse_count = sum(1 for row in rows if row["grade"].get("parse_mode") == "normalized")
129
+ parse_failure_count = sum(1 for row in rows if row["grade"].get("parse_error"))
130
  summary = {
131
  "provider": "hf-transformers",
132
  "model": args.model,
 
135
  "pass_rate": round(passed / len(rows), 4),
136
  "average_score": round(average_score, 4),
137
  "median_latency_ms": round(median(latencies), 2),
138
+ "exact_parse_rate": round(exact_parse_count / len(rows), 4),
139
+ "normalized_parse_rate": round(normalized_parse_count / len(rows), 4),
140
+ "parse_failure_rate": round(parse_failure_count / len(rows), 4),
141
  }
142
 
143
  print(json.dumps(summary, indent=2))