1023 lines
39 KiB
Python
Executable File
1023 lines
39 KiB
Python
Executable File
from __future__ import annotations
|
|
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from cognitive_agent.application.domain_runtime import ConfiguredDomainRuntime
|
|
from cognitive_agent.application.mode_profile import ModeProfileRegistry
|
|
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
|
|
from cognitive_agent.infrastructure.can.hardware import HardwareSafetyError
|
|
|
|
|
|
class ConfiguredDomainRuntimeTests(unittest.TestCase):
|
|
def test_matrix_backed_domain_frames(self) -> None:
|
|
cases = {
|
|
"climate": (
|
|
[
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_temperature",
|
|
"target": "driver",
|
|
"parameters": {"temperature_c": 22},
|
|
"operation": "set",
|
|
"reason": "test",
|
|
},
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_fan_level",
|
|
"target": "vehicle",
|
|
"parameters": {"level": 3},
|
|
"operation": "set",
|
|
"reason": "test",
|
|
},
|
|
],
|
|
["05 16 00 00 00 00 00 00", "04 04 00 00 00 00 00 00"],
|
|
),
|
|
"roof": (
|
|
[
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target": "vehicle",
|
|
"parameters": {"transmittance_pct": 30},
|
|
"operation": "set",
|
|
"reason": "test",
|
|
},
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_shade_position",
|
|
"target": "vehicle",
|
|
"parameters": {"position_pct": 60},
|
|
"operation": "set",
|
|
"reason": "test",
|
|
},
|
|
],
|
|
["13 00 1E 00", "04 00 00 00 3C"],
|
|
),
|
|
"ambient_light": (
|
|
[
|
|
{
|
|
"domain": "ambient_light",
|
|
"capability": "ambient_light.set_illumination",
|
|
"target": "vehicle",
|
|
"parameters": {
|
|
"color_hex": "#FF8040",
|
|
"brightness_pct": 60,
|
|
},
|
|
"operation": "set",
|
|
"reason": "test",
|
|
}
|
|
],
|
|
["2B FF 80 40 3C"],
|
|
),
|
|
}
|
|
for domain, (actions, expected_frames) in cases.items():
|
|
with self.subTest(domain=domain):
|
|
runtime = ConfiguredDomainRuntime(REPOSITORY_ROOT, domain)
|
|
config = runtime.build_function_config(
|
|
actions, "req-test-domain-frame", "test"
|
|
)
|
|
plan = runtime.compile(config)
|
|
report = runtime.execute(plan, config)
|
|
frames = [
|
|
item["telemetry"]["command_frame"]["data_hex"]
|
|
for item in report["spec"]["results"]
|
|
]
|
|
self.assertEqual(frames, expected_frames)
|
|
|
|
|
|
class MultiDomainServiceTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.service = SeatDemoService(REPOSITORY_ROOT)
|
|
self.service.openai.api_key = "test-key"
|
|
self.temporary_directory = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.temporary_directory.cleanup)
|
|
self.service.artifact_root = Path(self.temporary_directory.name)
|
|
|
|
def test_driver_massage_mode_and_strength_continuations_compile_locally(
|
|
self,
|
|
) -> None:
|
|
result = self.service.preview_native_can(
|
|
"打开主驾座椅按摩,模式切换为脉冲模式,强度调到最大",
|
|
provider="auto",
|
|
conversation_id="conv-driver-massage-pulse-strong",
|
|
execution_mode="dry_run",
|
|
)
|
|
self.assertEqual(result["unresolved_clauses"], [])
|
|
self.assertFalse(result["supplement_required"])
|
|
commands = [
|
|
command
|
|
for plan in result.get("command_plans", {}).values()
|
|
for command in plan.get("spec", {}).get("commands", [])
|
|
]
|
|
self.assertEqual(
|
|
[command["signals"]["debug_command"] for command in commands],
|
|
[
|
|
"seat driver massage mode pulse",
|
|
"seat driver massage strength strong",
|
|
],
|
|
)
|
|
self.assertEqual(
|
|
[command["signals"]["data_hex"] for command in commands],
|
|
[
|
|
"12 00 00 03 00 00 00 00",
|
|
"12 03 00 00 00 00 00 00",
|
|
],
|
|
)
|
|
self.assertTrue(
|
|
all(
|
|
operation["parse_source"] == "local_rule"
|
|
for config in result.get("function_configs", {}).values()
|
|
for operation in config.get("spec", {}).get("operations", [])
|
|
)
|
|
)
|
|
|
|
def test_four_domain_scene_is_generated_executed_and_persisted(self) -> None:
|
|
model_output = {
|
|
"detected_domains": ["seat", "climate", "roof", "ambient_light"],
|
|
"requests": [
|
|
{
|
|
"domain": "seat",
|
|
"capability": "seat.set_backrest_recline",
|
|
"target_scope": "passenger",
|
|
"operation": "set",
|
|
"parameters": [{"name": "position_pct", "value": 55}],
|
|
"reason": "comfortable viewing posture",
|
|
},
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_temperature",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "temperature_c", "value": 24}],
|
|
"reason": "comfortable cabin",
|
|
},
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 20}],
|
|
"reason": "reduce glare",
|
|
},
|
|
{
|
|
"domain": "ambient_light",
|
|
"capability": "ambient_light.set_illumination",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [
|
|
{"name": "color_hex", "value": "#FF8040"},
|
|
{"name": "brightness_pct", "value": 35},
|
|
],
|
|
"reason": "warm cinema lighting",
|
|
},
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["生成四域观影目标。"],
|
|
"confidence": 0.95,
|
|
}
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
result = self.service.process(
|
|
"进入观影状态",
|
|
"openai",
|
|
"conv-four-domain-test",
|
|
)
|
|
|
|
self.assertEqual(result["status"], "succeeded")
|
|
self.assertEqual(
|
|
set(result["function_configs"]),
|
|
{"seat", "climate", "roof", "ambient_light"},
|
|
)
|
|
self.assertEqual(len(result["scene_config"]["spec"]["function_refs"]), 4)
|
|
self.assertEqual(
|
|
{item["domain"] for item in result["execution_report"]["spec"]["results"]},
|
|
{"seat", "climate", "roof", "ambient_light"},
|
|
)
|
|
self.assertEqual(result["domain_state"]["roof"]["transmittance_pct"], 20)
|
|
self.assertEqual(
|
|
result["domain_state"]["ambient_light"]["color_hex"], "#FF8040"
|
|
)
|
|
run_path = self.service.artifact_root / result["request_id"]
|
|
self.assertTrue((run_path / "scene.yaml").is_file())
|
|
for domain in ("seat", "climate", "roof", "ambient_light"):
|
|
self.assertTrue((run_path / "functions" / f"{domain}.yaml").is_file())
|
|
self.assertTrue(
|
|
(run_path / "command-plans" / f"{domain}.yaml").is_file()
|
|
)
|
|
|
|
def test_domain_state_is_supplied_to_follow_up_model_turn(self) -> None:
|
|
first_plan = {
|
|
"detected_domains": ["roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 30}],
|
|
"reason": "initial target",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["天幕透光率设为30%。"],
|
|
"confidence": 0.96,
|
|
}
|
|
second_plan = {
|
|
**first_plan,
|
|
"requests": [
|
|
{
|
|
**first_plan["requests"][0],
|
|
"operation": "decrease",
|
|
"parameters": [{"name": "transmittance_pct", "value": 20}],
|
|
"reason": "resolved relative to current 30 percent",
|
|
}
|
|
],
|
|
"decision_summary": ["基于当前30%继续调暗到20%。"],
|
|
}
|
|
with patch.object(
|
|
self.service.openai,
|
|
"interpret",
|
|
side_effect=[first_plan, second_plan],
|
|
) as interpret:
|
|
self.service.process(
|
|
"天幕透光率调到30%",
|
|
"openai",
|
|
"conv-roof-follow-up",
|
|
)
|
|
result = self.service.process(
|
|
"再暗一点",
|
|
"openai",
|
|
"conv-roof-follow-up",
|
|
)
|
|
|
|
second_context = interpret.call_args_list[1].args[1]
|
|
self.assertEqual(
|
|
second_context["domain_devices"]["roof"]["transmittance_pct"], 30
|
|
)
|
|
self.assertEqual(result["domain_state"]["roof"]["transmittance_pct"], 20)
|
|
self.assertEqual(result["conversation_turn"], 2)
|
|
|
|
def test_named_mode_profile_executes_without_model_expansion(self) -> None:
|
|
model_output = {
|
|
"detected_domains": ["seat"],
|
|
"requests": [],
|
|
"ambiguities": [],
|
|
"decision_summary": ["用户要求调用已有零重力模式。"],
|
|
"confidence": 0.94,
|
|
}
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
result = self.service.process(
|
|
"副驾驶进入零重力模式",
|
|
"openai",
|
|
"conv-zero-gravity-mode",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(result["status"], "succeeded")
|
|
self.assertEqual(result["matched_modes"][0]["id"], "zero_gravity")
|
|
operations = result["function_config"]["spec"]["operations"]
|
|
by_capability = {item["capability"]: item for item in operations}
|
|
self.assertEqual(
|
|
by_capability["seat.set_longitudinal_position"]["parameters"],
|
|
{"position_pct": 100},
|
|
)
|
|
self.assertEqual(
|
|
by_capability["seat.set_cushion_tilt"]["parameters"],
|
|
{"position_pct": 100},
|
|
)
|
|
self.assertEqual(
|
|
by_capability["seat.set_backrest_recline"]["parameters"],
|
|
{"position_pct": 81, "angle_deg": 150},
|
|
)
|
|
self.assertEqual(
|
|
by_capability["seat.set_legrest_height"]["parameters"],
|
|
{"position_pct": 94, "angle_deg": 163},
|
|
)
|
|
|
|
def test_named_mode_profile_suppresses_generic_local_parser_ambiguity(self) -> None:
|
|
result = self.service.process(
|
|
"副驾进入零重力模式",
|
|
"local",
|
|
"conv-zero-gravity-local-mode",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(result["status"], "succeeded")
|
|
self.assertEqual(result["matched_modes"][0]["id"], "zero_gravity")
|
|
self.assertFalse(
|
|
any(
|
|
issue.get("code") == "AMBIGUOUS_INTENT"
|
|
for issue in result["validation"]
|
|
)
|
|
)
|
|
|
|
def test_named_mode_profile_combines_with_temporary_roof_request(self) -> None:
|
|
model_output = {
|
|
"detected_domains": ["roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 20}],
|
|
"reason": "用户同时要求天幕调暗。",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["零重力之外还需设置天幕。"],
|
|
"confidence": 0.96,
|
|
}
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
result = self.service.process(
|
|
"副驾零重力模式,天幕透光率调到20%",
|
|
"openai",
|
|
"conv-mode-plus-roof",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(result["status"], "succeeded")
|
|
self.assertEqual(set(result["function_configs"]), {"seat", "roof"})
|
|
self.assertEqual(result["scene_config"]["kind"], "SceneConfig")
|
|
self.assertEqual(result["domain_state"]["roof"]["transmittance_pct"], 20)
|
|
self.assertIn(
|
|
"seat.set_backrest_recline",
|
|
{
|
|
item["capability"]
|
|
for item in result["function_configs"]["seat"]["spec"]["operations"]
|
|
},
|
|
)
|
|
|
|
def test_hardware_orchestration_rejects_ch0_seat_and_virtual_roof_before_send(
|
|
self,
|
|
) -> None:
|
|
model_output = {
|
|
"detected_domains": ["seat", "roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "seat",
|
|
"capability": "seat.set_backrest_recline",
|
|
"target_scope": "passenger",
|
|
"operation": "set",
|
|
"parameters": [{"name": "position_pct", "value": 55}],
|
|
"reason": "调整副驾靠背。",
|
|
},
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 20}],
|
|
"reason": "降低天幕透光率。",
|
|
},
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["执行副驾与天幕联合模式。"],
|
|
"confidence": 0.96,
|
|
}
|
|
hardware_executor = MagicMock()
|
|
with (
|
|
patch.object(self.service.openai, "interpret", return_value=model_output),
|
|
patch.object(
|
|
self.service,
|
|
"_new_hardware_executor",
|
|
return_value=hardware_executor,
|
|
) as executor_factory,
|
|
):
|
|
with self.assertRaisesRegex(
|
|
HardwareSafetyError,
|
|
"hardware mode refuses virtual or unverified vehicle actions",
|
|
):
|
|
self.service.process(
|
|
"副驾靠背调到55%,天幕透光率调到20%",
|
|
"openai",
|
|
"conv-mixed-hardware-success",
|
|
execution_mode="hardware",
|
|
approval_token="test-token",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
executor_factory.assert_not_called()
|
|
hardware_executor.execute.assert_not_called()
|
|
|
|
def test_hardware_orchestration_rejects_ch0_motion_before_executor_creation(
|
|
self,
|
|
) -> None:
|
|
model_output = {
|
|
"detected_domains": ["seat", "roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "seat",
|
|
"capability": "seat.set_longitudinal_position",
|
|
"target_scope": "passenger",
|
|
"operation": "set",
|
|
"parameters": [{"name": "position_pct", "value": 100}],
|
|
"reason": "移动副驾。",
|
|
},
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 20}],
|
|
"reason": "降低天幕透光率。",
|
|
},
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["执行副驾与天幕联合模式。"],
|
|
"confidence": 0.96,
|
|
}
|
|
hardware_executor = MagicMock()
|
|
with (
|
|
patch.object(self.service.openai, "interpret", return_value=model_output),
|
|
patch.object(
|
|
self.service,
|
|
"_new_hardware_executor",
|
|
return_value=hardware_executor,
|
|
) as executor_factory,
|
|
):
|
|
with self.assertRaisesRegex(
|
|
HardwareSafetyError,
|
|
"hardware mode refuses virtual or unverified vehicle actions",
|
|
):
|
|
self.service.process(
|
|
"副驾水平移到100%,天幕透光率调到20%",
|
|
"openai",
|
|
"conv-mixed-hardware-failure",
|
|
execution_mode="hardware",
|
|
approval_token="test-token",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
executor_factory.assert_not_called()
|
|
hardware_executor.execute.assert_not_called()
|
|
|
|
def test_reference_mode_library_modes_execute_for_denza(self) -> None:
|
|
model_output = {
|
|
"detected_domains": ["seat"],
|
|
"requests": [],
|
|
"ambiguities": [],
|
|
"decision_summary": ["用户要求调用已有长期模式。"],
|
|
"confidence": 0.95,
|
|
}
|
|
utterances = [
|
|
"副驾驶进入零重力模式",
|
|
"副驾驶进入巡航沙发模式",
|
|
"副驾驶进入休闲躺椅模式",
|
|
"副驾驶进入小憩模式",
|
|
"副驾驶进入轻松进出模式",
|
|
"副驾驶进入宝宝午睡模式",
|
|
"副驾驶进入办公模式",
|
|
"副驾驶进入冥想空间模式",
|
|
"副驾驶进入电感沙滩椅",
|
|
"副驾驶进入女王副驾模式",
|
|
"副驾驶进入小腿解压悬浮模式",
|
|
]
|
|
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
for index, utterance in enumerate(utterances):
|
|
with self.subTest(utterance=utterance):
|
|
result = self.service.process(
|
|
utterance,
|
|
"openai",
|
|
f"conv-reference-mode-{index}",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(result["status"], "succeeded")
|
|
self.assertTrue(result["matched_modes"])
|
|
self.assertTrue(
|
|
result["function_config"] or result["function_configs"]
|
|
)
|
|
|
|
def test_save_recent_successful_actions_as_long_term_mode_profile(self) -> None:
|
|
self.service.mode_profiles = ModeProfileRegistry(
|
|
self.service.artifact_root / "modes"
|
|
)
|
|
model_output = {
|
|
"detected_domains": ["roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 35}],
|
|
"reason": "保存前先形成一个可复用动作。",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["天幕透光率设为35%。"],
|
|
"confidence": 0.96,
|
|
}
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
first = self.service.process(
|
|
"天幕透光率调到35%",
|
|
"openai",
|
|
"conv-save-mode-profile",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
saved = self.service.process(
|
|
"这个模式不错,固化为露营模式",
|
|
"local",
|
|
"conv-save-mode-profile",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(first["status"], "succeeded")
|
|
self.assertEqual(saved["status"], "succeeded")
|
|
self.assertIsNone(saved["command_plan"])
|
|
self.assertEqual(saved["mode_profile"]["name"], "露营模式")
|
|
telemetry = saved["execution_report"]["spec"]["results"][0]["telemetry"]
|
|
self.assertEqual(telemetry["operation"], "save_mode_profile")
|
|
self.assertFalse(telemetry["can_command_emitted"])
|
|
|
|
registry = ModeProfileRegistry(self.service.artifact_root / "modes")
|
|
matched = registry.match_text("进入露营模式", vehicle_id="denza_n7")
|
|
requests = registry.requests_for_profiles(matched)
|
|
self.assertEqual(requests[0]["capability"], "roof.set_transmittance")
|
|
self.assertEqual(
|
|
requests[0]["parameters"],
|
|
[{"name": "transmittance_pct", "value": 35}],
|
|
)
|
|
self.assertEqual(
|
|
registry.match_text("进入露营模式", vehicle_id="other_vehicle"),
|
|
[],
|
|
)
|
|
|
|
def test_mode_card_editor_persists_only_server_generated_command_flow(self) -> None:
|
|
mode_root = Path(self.temporary_directory.name) / "mode-card-presets"
|
|
user_root = Path(self.temporary_directory.name) / "mode-card-user"
|
|
preset = mode_root / "vehicles" / "denza_n7" / "office.yaml"
|
|
preset.parent.mkdir(parents=True)
|
|
preset.write_text(
|
|
"""
|
|
id: office
|
|
name: 办公模式
|
|
icon: briefcase
|
|
scope:
|
|
vehicle_ids: [denza_n7]
|
|
operations:
|
|
- domain: climate
|
|
capability: climate.set_temperature
|
|
target_scope: passenger
|
|
parameters:
|
|
temperature_c: 24
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
self.service.mode_profiles = ModeProfileRegistry(
|
|
mode_root, user_root=user_root
|
|
)
|
|
model_output = {
|
|
"detected_domains": ["climate"],
|
|
"requests": [
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_temperature",
|
|
"target_scope": "passenger",
|
|
"operation": "set",
|
|
"parameters": [{"name": "temperature_c", "value": 24}],
|
|
"reason": "办公温度。",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["副驾温度设置为24度。"],
|
|
"confidence": 0.97,
|
|
}
|
|
instruction = "副驾空调温度设置为24度"
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
generated = self.service.process(
|
|
instruction,
|
|
"openai",
|
|
"conv-mode-card-editor",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
saved = self.service.save_mode_profile_card(
|
|
"office",
|
|
"专注办公模式",
|
|
instruction,
|
|
generated["request_id"],
|
|
"denza_n7",
|
|
)
|
|
|
|
self.assertEqual(saved["status"], "succeeded")
|
|
self.assertEqual(saved["storage"], "persistent_yaml")
|
|
self.assertEqual(saved["mode_profile"]["origin"], "customized")
|
|
self.assertEqual(saved["mode_profile"]["instruction"], instruction)
|
|
self.assertTrue(saved["mode_profile"]["command_flow"]["plans"])
|
|
self.assertTrue(
|
|
saved["mode_profile"]["command_flow"]["function_configs"]
|
|
)
|
|
reloaded = ModeProfileRegistry(mode_root, user_root=user_root)
|
|
persisted = next(
|
|
item
|
|
for item in reloaded.public_modes("denza_n7")
|
|
if item["id"] == "office"
|
|
)
|
|
self.assertEqual(persisted["name"], "专注办公模式")
|
|
created = self.service.create_mode_profile_card(
|
|
"自然舒享模式",
|
|
instruction,
|
|
generated["request_id"],
|
|
"denza_n7",
|
|
)
|
|
self.assertEqual(created["status"], "succeeded")
|
|
self.assertEqual(created["mode_profile"]["origin"], "user")
|
|
self.assertEqual(created["mode_profile"]["instruction"], instruction)
|
|
self.assertNotEqual(created["mode_profile"]["id"], "office")
|
|
self.assertTrue(
|
|
(
|
|
user_root
|
|
/ "vehicles"
|
|
/ "denza_n7"
|
|
/ "user"
|
|
/ f"{created['mode_profile']['id']}.yaml"
|
|
).is_file()
|
|
)
|
|
with self.assertRaisesRegex(ValueError, "生成指令"):
|
|
self.service.save_mode_profile_card(
|
|
"office",
|
|
"专注办公模式",
|
|
"副驾空调温度设置为25度",
|
|
generated["request_id"],
|
|
"denza_n7",
|
|
)
|
|
|
|
def test_saved_mode_card_executes_without_reinterpreting_instruction(self) -> None:
|
|
mode_root = Path(self.temporary_directory.name) / "direct-mode-presets"
|
|
user_root = Path(self.temporary_directory.name) / "direct-mode-user"
|
|
preset = mode_root / "vehicles" / "denza_n7" / "office.yaml"
|
|
preset.parent.mkdir(parents=True)
|
|
preset.write_text(
|
|
"""
|
|
id: office
|
|
name: 办公模式
|
|
icon: briefcase
|
|
scope:
|
|
vehicle_ids: [denza_n7]
|
|
operations:
|
|
- domain: climate
|
|
capability: climate.set_temperature
|
|
target_scope: driver
|
|
parameters:
|
|
temperature_c: 24
|
|
""".strip()
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
self.service.mode_profiles = ModeProfileRegistry(
|
|
mode_root, user_root=user_root
|
|
)
|
|
instruction = "空调温度设置为25度,风速设置为1档"
|
|
generated = self.service.preview_native_can(
|
|
instruction,
|
|
provider="local",
|
|
conversation_id="conv-generate-office-card",
|
|
execution_mode="dry_run",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
saved = self.service.save_mode_profile_card(
|
|
"office",
|
|
"办公模式",
|
|
instruction,
|
|
generated["request_id"],
|
|
"denza_n7",
|
|
)
|
|
|
|
with patch.object(
|
|
self.service,
|
|
"_interpret",
|
|
side_effect=AssertionError("saved mode must not reinterpret natural language"),
|
|
):
|
|
executed = self.service.execute_mode_profile_card(
|
|
"office",
|
|
conversation_id="conv-execute-office-card",
|
|
execution_mode="dry_run",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
operations = [
|
|
operation
|
|
for config in executed.get("function_configs", {}).values()
|
|
for operation in config.get("spec", {}).get("operations", [])
|
|
]
|
|
self.assertEqual(executed["status"], "succeeded")
|
|
self.assertEqual(executed["utterance"], "办公模式")
|
|
self.assertEqual(executed["provider_used"], "saved_mode_command_flow")
|
|
self.assertEqual(executed["orchestration_route"], "saved_mode_command_flow")
|
|
self.assertEqual(
|
|
[
|
|
(
|
|
operation["capability"],
|
|
operation["target"]["zone"],
|
|
operation["parameters"],
|
|
operation["parse_source"],
|
|
)
|
|
for operation in operations
|
|
],
|
|
[
|
|
(
|
|
"climate.set_temperature",
|
|
"driver",
|
|
{"temperature_c": 25},
|
|
"saved_mode_command_flow",
|
|
),
|
|
(
|
|
"climate.set_fan_level",
|
|
"vehicle",
|
|
{"level": 1},
|
|
"saved_mode_command_flow",
|
|
),
|
|
],
|
|
)
|
|
self.assertEqual(
|
|
saved["mode_profile"]["command_flow"]["execution_steps"], []
|
|
)
|
|
|
|
def test_saved_mode_card_replays_front_right_dynamic_target_as_passenger(
|
|
self,
|
|
) -> None:
|
|
mode_root = Path(self.temporary_directory.name) / "dynamic-mode-presets"
|
|
user_root = Path(self.temporary_directory.name) / "dynamic-mode-user"
|
|
self.service.mode_profiles = ModeProfileRegistry(
|
|
mode_root,
|
|
user_root=user_root,
|
|
)
|
|
self.service.mode_profiles.save_mode(
|
|
"小憩模式",
|
|
[
|
|
{
|
|
"domain": "seat",
|
|
"capability": "seat.start_dynamic_mode",
|
|
"target_scope": "front_right",
|
|
"parameters": {"mode_id": 2},
|
|
},
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_power",
|
|
"target_scope": "vehicle",
|
|
"parameters": {"state": "on"},
|
|
},
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_shade_motion",
|
|
"target_scope": "vehicle",
|
|
"parameters": {"motion": "open"},
|
|
},
|
|
],
|
|
mode_id="nap",
|
|
vehicle_id="denza_n7",
|
|
instruction="打开摇篮模式,开启空调",
|
|
command_flow={
|
|
"schema": "cognitive-agent-mode-command-flow/v1",
|
|
"source_request_id": "req-saved-dynamic-mode",
|
|
"plans": {
|
|
"local_seat": {
|
|
"spec": {
|
|
"commands": [
|
|
{
|
|
"message": "Seat_Dynamic_Mode_Virtual",
|
|
"signals": {"Dynamic_Mode_ID": 2},
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
},
|
|
)
|
|
|
|
with patch.object(
|
|
self.service,
|
|
"_interpret",
|
|
side_effect=AssertionError("saved mode must not reinterpret natural language"),
|
|
):
|
|
executed = self.service.execute_mode_profile_card(
|
|
"nap",
|
|
conversation_id="conv-execute-saved-dynamic-card",
|
|
execution_mode="dry_run",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(executed["status"], "succeeded")
|
|
self.assertEqual(executed["utterance"], "小憩模式")
|
|
self.assertEqual(executed["provider_used"], "saved_mode_command_flow")
|
|
self.assertFalse(
|
|
[item for item in executed.get("validation", []) if item["severity"] == "error"]
|
|
)
|
|
dynamic_request = next(
|
|
item
|
|
for item in executed["model_requests"]
|
|
if item["capability"] == "seat.start_dynamic_mode"
|
|
)
|
|
self.assertEqual(dynamic_request["target_scope"], "passenger")
|
|
self.assertTrue(executed["command_plans"])
|
|
replayed_capabilities = {
|
|
operation["capability"]
|
|
for config in executed["function_configs"].values()
|
|
for operation in config["spec"]["operations"]
|
|
}
|
|
self.assertIn("roof.set_shade_motion", replayed_capabilities)
|
|
|
|
def test_build_named_mode_executes_and_persists_in_one_turn(self) -> None:
|
|
mode_root = Path(self.temporary_directory.name) / "modes"
|
|
self.service.mode_profiles = ModeProfileRegistry(mode_root)
|
|
model_output = {
|
|
"detected_domains": ["ambient_light", "climate"],
|
|
"requests": [
|
|
{
|
|
"domain": "ambient_light",
|
|
"capability": "ambient_light.set_illumination",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [
|
|
{"name": "color_hex", "value": "#B040FF"},
|
|
{"name": "brightness_pct", "value": 60},
|
|
],
|
|
"reason": "营造K歌氛围。",
|
|
},
|
|
{
|
|
"domain": "climate",
|
|
"capability": "climate.set_temperature",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "temperature_c", "value": 24}],
|
|
"reason": "保持K歌时的座舱舒适度。",
|
|
},
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["已构建K歌场景。"],
|
|
"confidence": 0.94,
|
|
}
|
|
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
built = self.service.process(
|
|
"构建一个K歌模式",
|
|
"openai",
|
|
"conv-build-karaoke-mode",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(built["status"], "succeeded")
|
|
self.assertEqual(built["mode_profile"]["name"], "K歌模式")
|
|
self.assertEqual(built["mode_creation"]["source_status"], "succeeded")
|
|
self.assertEqual(built["mode_creation"]["operation_count"], 2)
|
|
self.assertIn(
|
|
"K歌模式",
|
|
{
|
|
mode["name"]
|
|
for mode in self.service.runtime_info()["modes"]
|
|
},
|
|
)
|
|
matched = self.service.mode_profiles.match_text(
|
|
"进入K歌模式", vehicle_id="denza_n7"
|
|
)
|
|
self.assertEqual([profile.name for profile in matched], ["K歌模式"])
|
|
self.assertTrue(Path(built["mode_profile"]["source"]).is_file())
|
|
|
|
def test_build_named_mode_is_always_a_dry_run_configuration_workflow(self) -> None:
|
|
mode_root = Path(self.temporary_directory.name) / "hardware-modes"
|
|
self.service.mode_profiles = ModeProfileRegistry(mode_root)
|
|
model_output = {
|
|
"detected_domains": ["ambient_light"],
|
|
"requests": [
|
|
{
|
|
"domain": "ambient_light",
|
|
"capability": "ambient_light.set_illumination",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [
|
|
{"name": "color_hex", "value": "#B040FF"},
|
|
{"name": "brightness_pct", "value": 60},
|
|
],
|
|
"reason": "构建K歌氛围。",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["构建K歌灯光。"],
|
|
"confidence": 0.95,
|
|
}
|
|
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
built = self.service.process(
|
|
"构建一个K歌模式",
|
|
"openai",
|
|
"conv-build-karaoke-hardware-mode",
|
|
execution_mode="hardware",
|
|
vehicle_id="denza_n7",
|
|
hardware_access_bypass=False,
|
|
)
|
|
|
|
self.assertEqual(built["status"], "succeeded")
|
|
self.assertEqual(built["execution_mode"], "dry_run")
|
|
self.assertFalse(built["hardware_execution_allowed"])
|
|
self.assertEqual(built["mode_profile"]["name"], "K歌模式")
|
|
|
|
def test_create_mode_language_does_not_match_ordinary_mode_execution(self) -> None:
|
|
self.assertEqual(
|
|
self.service._parse_mode_profile_create_name("创建一个K歌模式"),
|
|
"K歌模式",
|
|
)
|
|
self.assertEqual(
|
|
self.service._parse_mode_profile_create_name("新增冥想空间模式"),
|
|
"冥想空间模式",
|
|
)
|
|
self.assertIsNone(
|
|
self.service._parse_mode_profile_create_name("进入K歌模式")
|
|
)
|
|
|
|
def test_update_and_restore_long_term_mode_profile_are_control_plane_only(self) -> None:
|
|
self.service.mode_profiles = ModeProfileRegistry(
|
|
self.service.artifact_root / "modes"
|
|
)
|
|
profile = self.service.mode_profiles.save_mode(
|
|
"露营模式",
|
|
[
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": {"transmittance_pct": 20},
|
|
"reason": "原始天幕目标。",
|
|
}
|
|
],
|
|
vehicle_id="denza_n7",
|
|
)
|
|
model_output = {
|
|
"detected_domains": ["roof"],
|
|
"requests": [
|
|
{
|
|
"domain": "roof",
|
|
"capability": "roof.set_transmittance",
|
|
"target_scope": "vehicle",
|
|
"operation": "set",
|
|
"parameters": [{"name": "transmittance_pct", "value": 50}],
|
|
"reason": "用户修改长期模式天幕目标。",
|
|
}
|
|
],
|
|
"ambiguities": [],
|
|
"decision_summary": ["修改露营模式天幕目标。"],
|
|
"confidence": 0.96,
|
|
}
|
|
|
|
with patch.object(self.service.openai, "interpret", return_value=model_output):
|
|
updated = self.service.process(
|
|
"修改露营模式,天幕透光率改到50%",
|
|
"openai",
|
|
"conv-update-mode-profile",
|
|
execution_mode="hardware",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(updated["status"], "succeeded")
|
|
self.assertIsNone(updated["command_plan"])
|
|
update_telemetry = updated["execution_report"]["spec"]["results"][0][
|
|
"telemetry"
|
|
]
|
|
self.assertEqual(update_telemetry["operation"], "update_mode_profile")
|
|
self.assertFalse(update_telemetry["can_command_emitted"])
|
|
self.assertTrue(Path(profile.source).with_suffix(".yaml.initial.bak").is_file())
|
|
|
|
registry = ModeProfileRegistry(self.service.artifact_root / "modes")
|
|
requests = registry.requests_for_profiles(
|
|
registry.match_text("进入露营模式", vehicle_id="denza_n7")
|
|
)
|
|
self.assertEqual(
|
|
requests[0]["parameters"],
|
|
[{"name": "transmittance_pct", "value": 50}],
|
|
)
|
|
|
|
restored = self.service.process(
|
|
"恢复露营模式初始配置",
|
|
"local",
|
|
"conv-update-mode-profile",
|
|
execution_mode="hardware",
|
|
vehicle_id="denza_n7",
|
|
)
|
|
|
|
self.assertEqual(restored["status"], "succeeded")
|
|
self.assertIsNone(restored["command_plan"])
|
|
restore_telemetry = restored["execution_report"]["spec"]["results"][0][
|
|
"telemetry"
|
|
]
|
|
self.assertEqual(restore_telemetry["operation"], "restore_mode_profile")
|
|
self.assertFalse(restore_telemetry["can_command_emitted"])
|
|
restored_registry = ModeProfileRegistry(self.service.artifact_root / "modes")
|
|
restored_requests = restored_registry.requests_for_profiles(
|
|
restored_registry.match_text("进入露营模式", vehicle_id="denza_n7")
|
|
)
|
|
self.assertEqual(
|
|
restored_requests[0]["parameters"],
|
|
[{"name": "transmittance_pct", "value": 20}],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|