anhtld commited on
Commit
1121493
·
verified ·
1 Parent(s): 9844154

add context learned dominance diagnostics

Browse files
workspace/scripts/eval_learned_dominance_selector.py CHANGED
@@ -2,6 +2,7 @@
2
  from __future__ import annotations
3
 
4
  import argparse
 
5
  import json
6
  import math
7
  import re
@@ -34,6 +35,7 @@ BASIC_FEATURE_NAMES = [
34
  "num_candidates",
35
  ]
36
  FEATURE_NAMES = BASIC_FEATURE_NAMES
 
37
 
38
 
39
  def main(argv: list[str] | None = None) -> int:
@@ -56,7 +58,7 @@ def main(argv: list[str] | None = None) -> int:
56
  parser.add_argument("--ridge-lambdas", default="0,0.01,0.1,1,10,100")
57
  parser.add_argument(
58
  "--feature-set",
59
- choices=("basic", "tangent"),
60
  default="basic",
61
  help="Deployment-visible feature family for candidate-level dominance fitting.",
62
  )
@@ -218,6 +220,7 @@ def _candidate_dataset(
218
  successes = [float(bool(value)) for value in row.get("candidate_success", [])[:k]]
219
  tangents = row.get("generated_tangents", [])[:k]
220
  candidate_types = row.get("candidate_types", [])[:k]
 
221
  if not scores or len(scores) != len(utilities):
222
  continue
223
  score_mean = sum(scores) / len(scores)
@@ -234,6 +237,13 @@ def _candidate_dataset(
234
  score_std=score_std,
235
  candidate_index=candidate_index,
236
  candidate_type=candidate_types[candidate_index] if candidate_index < len(candidate_types) else "",
 
 
 
 
 
 
 
237
  tangent=tangent,
238
  num_candidates=len(scores),
239
  feature_set=feature_set,
@@ -276,12 +286,24 @@ def _candidate_dataset(
276
  def _feature_names(feature_set: str) -> list[str]:
277
  if feature_set == "basic":
278
  return list(BASIC_FEATURE_NAMES)
 
 
 
 
 
 
 
 
 
 
 
 
279
  if feature_set == "tangent":
280
- return [
281
- *BASIC_FEATURE_NAMES,
282
- *[f"tangent_{index:02d}" for index in range(21)],
283
- *[f"abs_tangent_{index:02d}" for index in range(21)],
284
- ]
285
  raise ValueError(f"unknown feature_set: {feature_set}")
286
 
287
 
@@ -296,6 +318,7 @@ def _candidate_feature(
296
  tangent: np.ndarray,
297
  num_candidates: int,
298
  feature_set: str,
 
299
  ) -> np.ndarray:
300
  tangent = np.asarray(tangent, dtype=float).reshape(-1)
301
  if tangent.size < 21:
@@ -323,9 +346,42 @@ def _candidate_feature(
323
  return basic
324
  if feature_set == "tangent":
325
  return np.concatenate([basic, tangent.astype(float), np.abs(tangent).astype(float)])
 
 
 
 
 
 
 
 
 
 
 
326
  raise ValueError(f"unknown feature_set: {feature_set}")
327
 
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  def _target_value(
330
  target: str,
331
  *,
 
2
  from __future__ import annotations
3
 
4
  import argparse
5
+ import hashlib
6
  import json
7
  import math
8
  import re
 
35
  "num_candidates",
36
  ]
37
  FEATURE_NAMES = BASIC_FEATURE_NAMES
38
+ CONTEXT_HASH_WIDTH = 8
39
 
40
 
41
  def main(argv: list[str] | None = None) -> int:
 
58
  parser.add_argument("--ridge-lambdas", default="0,0.01,0.1,1,10,100")
59
  parser.add_argument(
60
  "--feature-set",
61
+ choices=("basic", "tangent", "context", "context_tangent"),
62
  default="basic",
63
  help="Deployment-visible feature family for candidate-level dominance fitting.",
64
  )
 
220
  successes = [float(bool(value)) for value in row.get("candidate_success", [])[:k]]
221
  tangents = row.get("generated_tangents", [])[:k]
222
  candidate_types = row.get("candidate_types", [])[:k]
223
+ source_task_ids = row.get("candidate_source_task_ids", [])[:k]
224
  if not scores or len(scores) != len(utilities):
225
  continue
226
  score_mean = sum(scores) / len(scores)
 
237
  score_std=score_std,
238
  candidate_index=candidate_index,
239
  candidate_type=candidate_types[candidate_index] if candidate_index < len(candidate_types) else "",
240
+ context={
241
+ "target_task_id": row.get("task_id", ""),
242
+ "instruction": row.get("instruction", ""),
243
+ "source_task_id": source_task_ids[candidate_index]
244
+ if candidate_index < len(source_task_ids)
245
+ else "",
246
+ },
247
  tangent=tangent,
248
  num_candidates=len(scores),
249
  feature_set=feature_set,
 
286
  def _feature_names(feature_set: str) -> list[str]:
287
  if feature_set == "basic":
288
  return list(BASIC_FEATURE_NAMES)
289
+ context_names = [
290
+ *[f"target_task_hash_{index:02d}" for index in range(CONTEXT_HASH_WIDTH)],
291
+ *[f"source_task_hash_{index:02d}" for index in range(CONTEXT_HASH_WIDTH)],
292
+ *[f"instruction_hash_{index:02d}" for index in range(CONTEXT_HASH_WIDTH)],
293
+ "source_target_same_task",
294
+ "instruction_chars_per_128",
295
+ "instruction_words_per_32",
296
+ ]
297
+ tangent_names = [
298
+ *[f"tangent_{index:02d}" for index in range(21)],
299
+ *[f"abs_tangent_{index:02d}" for index in range(21)],
300
+ ]
301
  if feature_set == "tangent":
302
+ return [*BASIC_FEATURE_NAMES, *tangent_names]
303
+ if feature_set == "context":
304
+ return [*BASIC_FEATURE_NAMES, *context_names]
305
+ if feature_set == "context_tangent":
306
+ return [*BASIC_FEATURE_NAMES, *context_names, *tangent_names]
307
  raise ValueError(f"unknown feature_set: {feature_set}")
308
 
309
 
 
318
  tangent: np.ndarray,
319
  num_candidates: int,
320
  feature_set: str,
321
+ context: dict[str, Any] | None = None,
322
  ) -> np.ndarray:
323
  tangent = np.asarray(tangent, dtype=float).reshape(-1)
324
  if tangent.size < 21:
 
346
  return basic
347
  if feature_set == "tangent":
348
  return np.concatenate([basic, tangent.astype(float), np.abs(tangent).astype(float)])
349
+ if feature_set == "context":
350
+ return np.concatenate([basic, _context_feature(context or {})])
351
+ if feature_set == "context_tangent":
352
+ return np.concatenate(
353
+ [
354
+ basic,
355
+ _context_feature(context or {}),
356
+ tangent.astype(float),
357
+ np.abs(tangent).astype(float),
358
+ ]
359
+ )
360
  raise ValueError(f"unknown feature_set: {feature_set}")
361
 
362
 
363
+ def _context_feature(context: dict[str, Any]) -> np.ndarray:
364
+ target_task = str(context.get("target_task_id", ""))
365
+ source_task = str(context.get("source_task_id", ""))
366
+ instruction = str(context.get("instruction", ""))
367
+ return np.asarray(
368
+ [
369
+ *_stable_hash_features(target_task, CONTEXT_HASH_WIDTH),
370
+ *_stable_hash_features(source_task, CONTEXT_HASH_WIDTH),
371
+ *_stable_hash_features(instruction.lower(), CONTEXT_HASH_WIDTH),
372
+ float(bool(target_task) and target_task == source_task),
373
+ min(len(instruction) / 128.0, 4.0),
374
+ min(len(instruction.split()) / 32.0, 4.0),
375
+ ],
376
+ dtype=float,
377
+ )
378
+
379
+
380
+ def _stable_hash_features(text: str, width: int) -> list[float]:
381
+ digest = hashlib.sha256(text.encode("utf-8")).digest()
382
+ return [((digest[index] / 127.5) - 1.0) for index in range(width)]
383
+
384
+
385
  def _target_value(
386
  target: str,
387
  *,