Files
Cognitive_Agent/tests/unit/test_mode_creation_seat_routing.py
T

187 lines
9.9 KiB
Python

from __future__ import annotations
from copy import deepcopy
from pathlib import Path
import pytest
from cognitive_agent.application.codex_assistant import (
CodexAssistantService,
_catalog_exact_mode_match_count,
_catalog_exact_scene_template_plan,
)
from cognitive_agent.application.mode_profile_intent import (
mode_creation_source_name,
parse_mode_profile_create,
)
from cognitive_agent.application.scene_composer import (
SCENE_COMPOSER_INSTRUCTIONS,
SCHEDULE_COMPOSER_INSTRUCTIONS,
scene_context_for_mode_creation,
)
from cognitive_agent.application.scene_templates import SceneTemplateRegistry
ROOT = Path(__file__).resolve().parents[2]
@pytest.mark.parametrize(("message", "name"), [
("构建主驾阅读模式", "主驾阅读模式"),
("为主驾构建一个阅读模式", "主驾阅读模式"),
("帮我为副驾驶构建一个阅读模式", "副驾阅读模式"),
("给驾驶席创建一个阅读模式", "主驾阅读模式"),
("可以帮我为主驾构建一个阅读模式吗?", "主驾阅读模式"),
("构建一个阅读模式,针对主驾", "主驾阅读模式"),
("构建一个阅读模式,仅联动副驾座椅", "副驾阅读模式"),
("构建一个阅读模式,给主驾使用,先看看", "主驾阅读模式"),
("构建一个主驾驶座椅专属的阅读模式", "主驾阅读模式"),
("构建一个主驾适合看书的功能模式", "主驾看书模式"),
("构建一个适合主驾看书的功能模式", "主驾看书模式"),
("为主驾和副驾创建一个阅读模式", "主副驾阅读模式"),
("构建一个双座阅读模式", "主副驾阅读模式"),
("构建一个阅读模式,针对双座", "主副驾阅读模式"),
])
def test_scoped_creation_keeps_distinct_name_and_fast_template_source(message, name):
assert parse_mode_profile_create(message) == (name, "")
registry = SceneTemplateRegistry(ROOT / "config" / "scene_templates")
template = registry.resolve_exact_name(name)
assert template is not None and template.id == "reading"
@pytest.mark.parametrize(("message", "expected"), [
("为主驾构建一个阅读模式,空调调整到26度", ("主驾阅读模式", "空调调整到26度")),
("构建一个阅读模式,针对主驾,空调调整到26度", ("阅读模式", "针对主驾,空调调整到26度")),
("构建一个主驾阅读模式,靠背向后移动3s", ("主驾阅读模式", "靠背向后移动3s")),
("构建一个名为主驾驶阅读模式", ("主驾驶阅读模式", "")),
("构建一个“阅读模式”,针对主驾", ("阅读模式", "")),
])
def test_explicit_names_and_actual_device_instructions_are_preserved(message, expected):
assert parse_mode_profile_create(message) == expected
@pytest.mark.parametrize("message", [
"不要为主驾构建一个阅读模式", "如何为主驾构建一个阅读模式?",
"为主驾构建一个阅读模式,但不要执行", "引用为主驾构建一个阅读模式",
])
def test_scope_grammar_does_not_bypass_authorization(message):
assert parse_mode_profile_create(message) is None
@pytest.mark.parametrize("name", ["后排阅读模式", "左后排阅读模式", "第三排阅读模式", "未知座位阅读模式"])
def test_unsupported_seats_never_alias_to_front_seat_templates(name):
assert mode_creation_source_name(name) == name
assert SceneTemplateRegistry(ROOT / "config" / "scene_templates").resolve_exact_name(name) is None
@pytest.mark.parametrize(("name", "source", "template_id"), [
("主驾座椅舒适模式", "座椅舒适模式", "seat-comfort"),
("主驾和副驾座椅舒适模式", "座椅舒适模式", "seat-comfort"),
("主副驾座椅动态模式", "座椅动态模式", "seat-dynamic"),
("副驾座椅的动态模式", "座椅的动态模式", "seat-dynamic"),
])
def test_seat_word_is_preserved_when_it_is_the_template_subject(name, source, template_id):
assert mode_creation_source_name(name) == source
template = SceneTemplateRegistry(ROOT / "config" / "scene_templates").resolve_exact_name(name)
assert template is not None and template.id == template_id
def test_catalog_seed_fallback_is_exact_and_preserves_explicit_match_priority():
template = SceneTemplateRegistry(ROOT / "config" / "scene_templates").get_template("reading").public_dict(include_plan=True)
template["assistant_callable"] = True
catalog = {
"source_status": {"scene_templates": "ready", "modes": "ready"},
"scene_templates": [template],
"modes": [{"id": "office", "name": "办公模式"}],
}
assert _catalog_exact_scene_template_plan(catalog, "主驾阅读模式") == template["plan"]
assert _catalog_exact_scene_template_plan(catalog, "后排阅读模式") is None
assert _catalog_exact_mode_match_count(catalog, "主驾办公模式") == 1
catalog["modes"].extend([
{"id": "driver-office-a", "name": "主驾办公模式"},
{"id": "driver-office-b", "name": "主驾办公模式"},
])
assert _catalog_exact_mode_match_count(catalog, "主驾办公模式") == 2
@pytest.mark.parametrize(("message", "expected"), [
("构建一个神游模式", {"passenger"}),
("构建一个主驾神游模式", {"driver", "front_left"}),
("构建一个主副驾神游模式", {"driver", "front_left", "passenger"}),
("构建一个神游模式,主驾空调26度", {"passenger"}),
("构建一个后排神游模式", set()),
])
def test_model_context_scopes_only_seat_capabilities_and_does_not_mutate_source(message, expected):
context = {
"composition_revision": "revision", "vehicle": {"id": "denza_n7"},
"capabilities": [
{"id": "seat.driver", "domain": "seat", "target_scopes": ["driver", "front_left"]},
{"id": "seat.passenger", "domain": "seat", "target_scopes": ["passenger"]},
{"id": "climate.zone", "domain": "climate", "target_scopes": ["driver", "passenger"]},
{"id": "roof.shade", "domain": "roof", "target_scopes": ["vehicle"]},
],
}
original = deepcopy(context)
projected = scene_context_for_mode_creation(context, message)
scopes = {scope for capability in projected["capabilities"] if capability["domain"] == "seat"
for scope in capability["target_scopes"]}
assert scopes == expected
assert [capability for capability in projected["capabilities"] if capability["domain"] != "seat"] == original["capabilities"][2:]
assert context == original
assert projected["seat_scope_policy"]["default_scope"] == "passenger"
def test_static_and_dynamic_prompts_use_one_selected_seat():
assert "defaults to the passenger seat only" in SCENE_COMPOSER_INSTRUCTIONS
assert "retarget a passenger capability to the driver" in SCENE_COMPOSER_INSTRUCTIONS
assert "selected seat scope in every phase" in SCHEDULE_COMPOSER_INSTRUCTIONS
def test_identical_explicit_mode_names_do_not_share_cached_plans_across_seats():
context = {"composition_revision": "revision", "vehicle": {"id": "denza_n7"}, "capabilities": []}
# Explicitly named drafts may intentionally keep the same display name even
# when the outer request selects a different seat.
driver = scene_context_for_mode_creation(context, "为主驾构建一个名为神游模式")
passenger = scene_context_for_mode_creation(context, "为副驾构建一个名为神游模式")
driver_key = CodexAssistantService._scene_cache_key(None, mode_name="神游模式", scene_context=driver)
passenger_key = CodexAssistantService._scene_cache_key(None, mode_name="神游模式", scene_context=passenger)
assert driver_key != passenger_key
@pytest.mark.parametrize("seat", [
"两个座椅", "两张座椅", "两座椅", "两座", "两个座位", "前排两座",
"前排两座椅", "前排两个座椅", "前排两张座椅", "双座", "双座椅",
])
@pytest.mark.parametrize("pattern", ["构建一个{}阅读模式", "为{}构建一个阅读模式", "构建一个阅读模式,针对{}"])
def test_all_two_seat_wordings_have_one_canonical_name(seat, pattern):
message = pattern.format(seat)
assert parse_mode_profile_create(message) == ("主副驾阅读模式", "")
assert mode_creation_source_name(f"{seat}阅读模式") == "阅读模式"
@pytest.mark.parametrize("message", [
"构建一个主驾阅读模式,针对副驾", "构建一个副驾阅读模式,针对主驾",
"为主驾构建一个副驾阅读模式", "为副驾构建一个主驾阅读模式",
"构建一个主副驾阅读模式,只针对主驾", "构建一个主驾阅读模式,针对双座",
"为主驾构建一个名为副驾阅读模式", "构建一个“副驾阅读模式”,针对主驾",
])
def test_conflicting_seat_selection_cannot_silently_become_a_two_seat_creation(message):
assert parse_mode_profile_create(message) is None
@pytest.mark.parametrize(("name", "source"), [
("副驾驶座椅阅读模式", "阅读模式"), ("主驾座椅的阅读模式", "阅读模式"),
("主驾座椅办公模式", "办公模式"), ("副驾座位的观影模式", "观影模式"),
("副驾座椅看书模式", "看书模式"), ("主驾座椅露营模式", "露营模式"),
("主驾座椅舒适模式", "座椅舒适模式"), ("副驾座椅动态模式", "座椅动态模式"),
("乘客座椅舒适模式", "座椅舒适模式"), ("两个座椅的动态模式", "座椅动态模式"),
("两张座椅舒适模式", "座椅舒适模式"), ("前排两座动态模式", "座椅动态模式"),
])
def test_seat_location_wrappers_do_not_hide_generic_scene_sources_or_actual_seat_topics(name, source):
assert mode_creation_source_name(name) == source
@pytest.mark.parametrize("message", [
"构建一个两个座椅的动态模式", "构建一个两张座椅的动态模式", "构建一个前排两座动态模式",
])
def test_double_seat_dynamic_topic_is_not_lost_with_the_scope_qualifier(message):
assert parse_mode_profile_create(message) == ("主副驾座椅动态模式", "")