SensorflowStudio / tests /test_safety /test_semantic.py
whassan's picture
Deploy Sensorflow Studio
9762da0 verified
Raw History Blame Contribute Delete
3.47 kB
"""Neuro-symbolic semantic mining: deterministic offline ranking with per-stage
explanations, symbolic filters, and hybrid retrieval over containers +
scenario-DB records."""
from __future__ import annotations
from sensorflow.safety import semantic
from sensorflow.safety.scenario_db import ScenarioRecord, get_db
def test_container_search_deterministic_and_explained(mega_env, safety_root):
store, run = mega_env["store"], mega_env["good"]
q = "pedestrian near miss at night in rain"
r1 = semantic.search_containers(store, run, q, k=10, use_llm=False)
r2 = semantic.search_containers(store, run, q, k=10, use_llm=False)
assert r1["results"] == r2["results"] # deterministic offline ranking
assert r1["stage2"]["provider"] == "offline_deterministic"
results = r1["results"]
assert results
scores = [r["score"] for r in results]
assert scores == sorted(scores, reverse=True)
top = results[0]
# concept terms must be reflected in structured evidence
assert top["lighting"] == "night"
assert top["weather"] != "clear"
reasons = top["explanations"]["stage2_reasoning"]
assert reasons and all({"term", "meaning", "evidence"} <= set(m) for m in reasons)
# hybrid retrieval blended embedding similarity
assert r1["hybrid"]["embedding_weight"] > 0
assert top["embedding_similarity"] is not None
def test_container_search_symbolic_filter(mega_env, safety_root):
store, run = mega_env["store"], mega_env["good"]
res = semantic.search_containers(store, run, "risky scenes",
filters={"lighting": "night"}, k=20,
use_llm=False)
assert res["stage1"]["applied_filters"] == {"lighting": ["night"]}
assert res["stage1"]["candidates_after"] < res["stage1"]["candidates_before"]
assert all(r["lighting"] == "night" for r in res["results"])
def test_container_search_fallback_on_unmatched_concept(mega_env, safety_root):
store, run = mega_env["store"], mega_env["good"]
res = semantic.search_containers(store, run, "xylophone zeitgeist", k=5,
use_llm=False)
assert res["results"]
reasons = res["results"][0]["explanations"]["stage2_reasoning"]
assert any("no lexicon term matched" in m["meaning"] for m in reasons)
def test_scenario_search_ranks_matching_odd_tags(fresh_safety_root):
db = get_db()
db.add(ScenarioRecord(scenario_id="n1", scenario_type="near_miss",
source="mined", severity="high",
odd_tags={"weather": "rain", "lighting": "night",
"actor_class": "pedestrian"},
description="pedestrian near miss in night rain"))
db.add(ScenarioRecord(scenario_id="d1", scenario_type="nominal",
source="synthetic", severity="low",
odd_tags={"weather": "clear", "lighting": "day"},
description="clear day nominal drive"))
res = semantic.search_scenarios("pedestrian near miss at night in rain", k=5)
assert res["results"][0]["scenario_id"] == "n1"
assert res["results"][0]["score"] > res["results"][-1]["score"]
assert res["stage2"]["provider"] == "offline_deterministic"
filtered = semantic.search_scenarios("anything", filters={"source": "synthetic"})
assert [r["scenario_id"] for r in filtered["results"]] == ["d1"]