175 lines
6.4 KiB
Python
Executable File
175 lines
6.4 KiB
Python
Executable File
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from seat_domain.intent import parse_local_intent
|
|
|
|
|
|
class LocalIntentParserTests(unittest.TestCase):
|
|
@staticmethod
|
|
def context(level: int = 0) -> dict:
|
|
return {
|
|
"last_target": "passenger" if level else None,
|
|
"devices": {
|
|
"driver": {
|
|
"ventilation": {"state": "off", "level": 0},
|
|
"heating": {"state": "off", "level": 0},
|
|
},
|
|
"passenger": {
|
|
"ventilation": {"state": "on" if level else "off", "level": level},
|
|
"heating": {"state": "off", "level": 0},
|
|
},
|
|
},
|
|
}
|
|
|
|
def test_parses_passenger_ventilation_on(self) -> None:
|
|
result = parse_local_intent("打开副驾座椅通风")
|
|
|
|
self.assertEqual(
|
|
result["actions"],
|
|
[
|
|
{
|
|
"target": "passenger",
|
|
"function": "ventilation",
|
|
"state": "on",
|
|
"requested_level": None,
|
|
}
|
|
],
|
|
)
|
|
self.assertEqual(result["ambiguities"], [])
|
|
|
|
def test_rejects_scope_that_includes_driver(self) -> None:
|
|
result = parse_local_intent("主副驾座椅通风都打开")
|
|
|
|
self.assertEqual(result["actions"], [])
|
|
self.assertEqual(result["ambiguities"][0]["field"], "target")
|
|
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
|
|
|
|
def test_keeps_requested_level_for_safety_validation(self) -> None:
|
|
result = parse_local_intent("副驾座椅加热开到三档")
|
|
|
|
self.assertEqual(result["actions"][0]["requested_level"], 3)
|
|
|
|
def test_defaults_missing_target_to_passenger(self) -> None:
|
|
result = parse_local_intent("打开座椅通风")
|
|
|
|
self.assertEqual(result["actions"][0]["target"], "passenger")
|
|
self.assertEqual(result["ambiguities"], [])
|
|
|
|
def test_parses_four_axis_zero_for_passenger(self) -> None:
|
|
result = parse_local_intent("把水平、坐盆、靠背、腿托四轴归零")
|
|
|
|
self.assertEqual(result["ambiguities"], [])
|
|
self.assertEqual(
|
|
[(action["axis"], action["position_pct"]) for action in result["actions"]],
|
|
[
|
|
("longitudinal", 0),
|
|
("cushion_tilt", 0),
|
|
("backrest_recline", 0),
|
|
("legrest_height", 0),
|
|
],
|
|
)
|
|
self.assertTrue(
|
|
all(action["target"] == "passenger" for action in result["actions"])
|
|
)
|
|
|
|
def test_parses_explicit_motion_percentages(self) -> None:
|
|
result = parse_local_intent("副驾水平移到63%,靠背调到54%")
|
|
|
|
self.assertEqual(result["ambiguities"], [])
|
|
self.assertEqual(
|
|
[(action["axis"], action["position_pct"]) for action in result["actions"]],
|
|
[("longitudinal", 63), ("backrest_recline", 54)],
|
|
)
|
|
|
|
def test_rejects_driver_four_axis_zero(self) -> None:
|
|
result = parse_local_intent("把主驾座椅四轴归零")
|
|
|
|
self.assertEqual(result["actions"], [])
|
|
self.assertEqual(result["ambiguities"][0]["field"], "target")
|
|
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
|
|
|
|
def test_maps_mild_hot_and_stuffy_feedback_to_level_one(self) -> None:
|
|
result = parse_local_intent("副驾有点热,有点闷", self.context())
|
|
|
|
self.assertEqual(
|
|
result["actions"],
|
|
[
|
|
{
|
|
"target": "passenger",
|
|
"function": "ventilation",
|
|
"state": "on",
|
|
"requested_level": 1,
|
|
}
|
|
],
|
|
)
|
|
self.assertIn("热、闷", "".join(result["decision_summary"]))
|
|
|
|
def test_increments_active_level_for_continuing_discomfort(self) -> None:
|
|
result = parse_local_intent("还有点闷", self.context(level=1))
|
|
|
|
self.assertEqual(result["actions"][0]["requested_level"], 2)
|
|
self.assertEqual(result["actions"][0]["target"], "passenger")
|
|
self.assertIn("提升到2档", "".join(result["decision_summary"]))
|
|
|
|
def test_cold_feedback_reduces_active_ventilation_before_heating(self) -> None:
|
|
result = parse_local_intent("我有点冷", self.context(level=1))
|
|
|
|
self.assertEqual(
|
|
result["actions"],
|
|
[
|
|
{
|
|
"target": "passenger",
|
|
"function": "ventilation",
|
|
"state": "off",
|
|
"requested_level": None,
|
|
}
|
|
],
|
|
)
|
|
self.assertIn("不立即开启加热", "".join(result["decision_summary"]))
|
|
|
|
def test_airflow_cause_targets_ventilation_not_heating(self) -> None:
|
|
context = self.context()
|
|
context["devices"]["passenger"]["ventilation"] = {"state": "on", "level": 2}
|
|
result = parse_local_intent("副驾吹的我有点冷", context)
|
|
|
|
self.assertEqual(
|
|
result["actions"],
|
|
[
|
|
{
|
|
"target": "passenger",
|
|
"function": "ventilation",
|
|
"state": "on",
|
|
"requested_level": 1,
|
|
}
|
|
],
|
|
)
|
|
self.assertNotIn("heating", {action["function"] for action in result["actions"]})
|
|
self.assertIn("致冷来源", "".join(result["decision_summary"]))
|
|
|
|
def test_cold_and_stuffy_are_independent_comfort_dimensions(self) -> None:
|
|
result = parse_local_intent("副驾有点冷、有点闷", self.context())
|
|
|
|
self.assertEqual(
|
|
{
|
|
(action["function"], action["state"], action["requested_level"])
|
|
for action in result["actions"]
|
|
},
|
|
{("heating", "on", 1), ("ventilation", "on", 1)},
|
|
)
|
|
self.assertEqual(result["ambiguities"], [])
|
|
self.assertIn("不将其判定为语义冲突", "".join(result["decision_summary"]))
|
|
|
|
def test_vehicle_scope_does_not_inherit_a_seat_target(self) -> None:
|
|
result = parse_local_intent("车上太闷了", self.context(level=1))
|
|
|
|
self.assertEqual(result["actions"], [])
|
|
self.assertEqual(result["ambiguities"][0]["field"], "domain")
|
|
self.assertEqual(result["detected_domains"], ["climate"])
|
|
self.assertEqual(result["scope"], "vehicle")
|
|
self.assertIn("整车舱范围", "".join(result["decision_summary"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|