vla / tests /test_cil_schema.py
anhtld's picture
Initial commit: DoVLA-CIL codebase (h=16 breakthrough) (part 2)
20c251e verified
Raw
History Blame Contribute Delete
3.38 kB
from __future__ import annotations
import pytest
from dovla_cil.data.schema import (
CIL_VERSION,
ActionChunk,
CILGroup,
CILRecord,
FailureInfo,
RewardInfo,
StructuredEffect,
compute_regret_and_ranks,
compute_state_hash,
make_record_id,
validate_group,
)
def make_record(
group_id: str, action_id: str, progress: float, *, state_hash: str = "s"
) -> CILRecord:
return CILRecord(
version=CIL_VERSION,
record_id=make_record_id(group_id, action_id, seed=7),
group_id=group_id,
state_hash=state_hash,
task_id="task",
scene_id=None,
instruction="move the mug",
instruction_family={"family": "place"},
observation_ref=None,
observation_inline={"symbolic": True},
action_chunk=ActionChunk(
action_id=action_id,
representation="delta_xy",
horizon=1,
values=[[progress, 0.0]],
skill_type="push",
),
next_observation_ref=None,
next_observation_inline={"symbolic": True, "next": True},
structured_effect=StructuredEffect(
object_pose_delta={"mug": [progress, 0.0, 0.0]},
relation_before={"inside(mug,bowl)": False},
relation_after={"inside(mug,bowl)": progress > 0.5},
moved_objects=["mug"] if progress else [],
symbolic_before={"objects": {"mug": {"position": [0, 0, 0]}}},
symbolic_after={"objects": {"mug": {"position": [progress, 0, 0]}}},
),
reward=RewardInfo(
progress=progress,
success=progress > 0.5,
terminal_success=progress > 0.5,
dense_components={"progress": progress},
),
regret=None,
rank_within_group=None,
candidate_type="sampled",
failure=None
if progress > 0
else FailureInfo(type="no_motion", symbolic_reason="object did not move"),
)
def test_schema_roundtrip() -> None:
record = make_record("g", "a", 1.0)
record.validate()
assert CILRecord.from_dict(record.to_dict()) == record
group = CILGroup.from_records([record])
assert group.group_id == "g"
def test_group_validation() -> None:
records = [make_record("g", "a", 0.0), make_record("g", "b", 1.0)]
validate_group(records)
with pytest.raises(ValueError):
validate_group([make_record("g", "a", 0.0), make_record("other", "b", 1.0)])
with pytest.raises(ValueError):
validate_group([make_record("g", "a", 0.0), make_record("g", "b", 1.0, state_hash="x")])
def test_regret_and_rank_computation() -> None:
ranked = compute_regret_and_ranks(
[make_record("g", "low", 0.0), make_record("g", "high", 1.0)]
)
by_action = {record.action_chunk.action_id: record for record in ranked}
assert by_action["high"].rank_within_group == 0
assert by_action["high"].regret == 0.0
assert by_action["low"].rank_within_group == 1
assert by_action["low"].regret == 2.0
def test_deterministic_record_ids_and_state_hashes() -> None:
assert make_record_id("g", "a", 1) == make_record_id("g", "a", 1)
assert make_record_id("g", "a", 1) != make_record_id("g", "a", 2)
assert compute_state_hash(b"state") == compute_state_hash(b"state")
assert compute_state_hash(b"state") != compute_state_hash(b"other")