auto-sync 2026-07-02T20:07:13Z workspace (part 9)
Browse files
workspace/tests/test_tangent_cvae.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from dovla_cil.generation.tangent_cvae import (
|
| 4 |
+
build_tangent_cvae_rows,
|
| 5 |
+
condition_vector,
|
| 6 |
+
hash_bow,
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def _target(group_id: str, label: str, value: float) -> dict:
|
| 11 |
+
return {
|
| 12 |
+
"group_id": group_id,
|
| 13 |
+
"task_id": "PickCube-v1",
|
| 14 |
+
"instruction": "Pick up the cube.",
|
| 15 |
+
"observation_inline": {"features": [0.1, 0.2, 0.3]},
|
| 16 |
+
"candidate_type": "near_miss",
|
| 17 |
+
"tangent_label": label,
|
| 18 |
+
"delta_utility": 1.0 if label == "positive" else -1.0,
|
| 19 |
+
"delta_action": [[value, 0.0], [value, 0.0]],
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def test_hash_bow_is_unit_scaled_and_deterministic() -> None:
|
| 24 |
+
left = hash_bow("Pick up the cube", 16)
|
| 25 |
+
right = hash_bow("Pick up the cube", 16)
|
| 26 |
+
|
| 27 |
+
assert left == right
|
| 28 |
+
assert len(left) == 16
|
| 29 |
+
assert 0.99 <= sum(value * value for value in left) <= 1.01
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def test_condition_vector_includes_observation_text_and_task() -> None:
|
| 33 |
+
task_to_index = {"PickCube-v1": 0, "StackCube-v1": 1}
|
| 34 |
+
vector = condition_vector(
|
| 35 |
+
_target("g0", "positive", 0.1),
|
| 36 |
+
task_to_index=task_to_index,
|
| 37 |
+
obs_dim=4,
|
| 38 |
+
text_dim=8,
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
assert len(vector) == 14
|
| 42 |
+
assert vector[:4] == [0.1, 0.2, 0.3, 0.0]
|
| 43 |
+
assert vector[-2:] == [1.0, 0.0]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def test_build_tangent_cvae_rows_preserves_labels_and_action_dim() -> None:
|
| 47 |
+
rows, tasks, action_dim = build_tangent_cvae_rows(
|
| 48 |
+
[
|
| 49 |
+
_target("g0", "positive", 0.1),
|
| 50 |
+
_target("g1", "negative", -0.2),
|
| 51 |
+
],
|
| 52 |
+
obs_dim=4,
|
| 53 |
+
text_dim=8,
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
assert tasks == ["PickCube-v1"]
|
| 57 |
+
assert action_dim == 4
|
| 58 |
+
assert [row.example.tangent_label for row in rows] == ["positive", "negative"]
|
| 59 |
+
assert rows[0].delta == [0.1, 0.0, 0.1, 0.0]
|
workspace/tests/test_tangent_memory.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from dovla_cil.generation.tangent_memory import (
|
| 4 |
+
TangentExample,
|
| 5 |
+
evaluate_tangent_memory_generator,
|
| 6 |
+
)
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def _example(
|
| 10 |
+
group_id: str,
|
| 11 |
+
label: str,
|
| 12 |
+
value: float,
|
| 13 |
+
*,
|
| 14 |
+
task_id: str = "TaskA",
|
| 15 |
+
utility: float = 1.0,
|
| 16 |
+
) -> TangentExample:
|
| 17 |
+
return TangentExample(
|
| 18 |
+
group_id=group_id,
|
| 19 |
+
task_id=task_id,
|
| 20 |
+
candidate_type="near_miss" if label == "positive" else "random_negative",
|
| 21 |
+
tangent_label=label,
|
| 22 |
+
delta_utility=utility if label == "positive" else -utility,
|
| 23 |
+
delta_action=[[value, 0.0], [value, 0.0]],
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def test_positive_tangent_memory_reports_support_recall_proxy() -> None:
|
| 28 |
+
examples = [
|
| 29 |
+
_example("train-a", "positive", 0.1),
|
| 30 |
+
_example("train-b", "positive", 0.4),
|
| 31 |
+
_example("val-a", "positive", 0.11),
|
| 32 |
+
_example("val-a", "negative", -0.6),
|
| 33 |
+
_example("val-b", "positive", 0.39),
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
report = evaluate_tangent_memory_generator(
|
| 37 |
+
examples,
|
| 38 |
+
k_values=(1, 2),
|
| 39 |
+
thresholds=(0.05,),
|
| 40 |
+
val_fraction=0.5,
|
| 41 |
+
seed=4,
|
| 42 |
+
diversity_weight=0.0,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
assert report["overall"]["num_groups"] >= 1
|
| 46 |
+
assert 0.0 <= report["overall"]["ptr_proxy_at_2_thr_0p05"] <= 1.0
|
| 47 |
+
assert report["proposal_count_by_task"]["TaskA"] == 2
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def test_positive_tangent_memory_uses_train_positive_prototypes_only() -> None:
|
| 51 |
+
examples = [
|
| 52 |
+
_example("train-b", "positive", 10.0, utility=1.0),
|
| 53 |
+
_example("val-a", "positive", 0.0, utility=100.0),
|
| 54 |
+
_example("val-a", "negative", 10.0, utility=1.0),
|
| 55 |
+
]
|
| 56 |
+
|
| 57 |
+
report = evaluate_tangent_memory_generator(
|
| 58 |
+
examples,
|
| 59 |
+
k_values=(1,),
|
| 60 |
+
thresholds=(0.1,),
|
| 61 |
+
val_fraction=0.5,
|
| 62 |
+
seed=0,
|
| 63 |
+
diversity_weight=0.0,
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
assert report["train_positive_by_task"]["TaskA"] == 1
|
| 67 |
+
assert report["proposal_count_by_task"]["TaskA"] == 1
|
| 68 |
+
assert report["overall"]["ptr_proxy_at_1_thr_0p1"] == 0.0
|
| 69 |
+
assert report["groups"][0]["positive_min_rms_l2_at_1"] > 1.0
|