优化后端和前端
This commit is contained in:
@@ -8,6 +8,7 @@ import re
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
from collections.abc import Callable
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from copy import deepcopy
|
||||
from datetime import UTC, datetime
|
||||
@@ -177,7 +178,7 @@ UPDATE_MODE_PROFILE_PREFIX = re.compile(
|
||||
UPDATE_MODE_PROFILE_BA = re.compile(
|
||||
r"^(?:请(?:帮我)?|帮我)?(?:把|将)"
|
||||
r"(?P<name>[^,。,.!!\s]{1,64}?模式)"
|
||||
r"(?:的)?(?P<change>.+)$"
|
||||
r"的(?P<change>.+)$"
|
||||
)
|
||||
RESTORE_MODE_PROFILE_PREFIX = re.compile(
|
||||
r"^(?:请(?:帮我)?|帮我)?(?:恢复|还原|重置|初始化)"
|
||||
@@ -1066,6 +1067,340 @@ class SeatDemoService:
|
||||
return MqttOtaSeatExecutor(executor, resolved_bus_factory)
|
||||
return executor
|
||||
|
||||
def preview_native_can(
|
||||
self,
|
||||
utterance: str,
|
||||
provider: str = "auto",
|
||||
conversation_id: str | None = None,
|
||||
execution_mode: str = "dry_run",
|
||||
approval_token: str | None = None,
|
||||
vehicle_id: str | None = None,
|
||||
simulation_fault: str = "normal",
|
||||
*,
|
||||
hardware_client_id: str | None = None,
|
||||
hardware_access_bypass: bool = True,
|
||||
reasoning_effort: str | None = None,
|
||||
control_transport: str = WIRED_CAN_TRANSPORT,
|
||||
on_commands_validated: Callable[[dict[str, Any]], None] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Validate and execute deterministic controls before hosted parsing."""
|
||||
|
||||
utterance = utterance.strip()
|
||||
if not utterance:
|
||||
raise ValueError("utterance must not be empty")
|
||||
if provider not in {"auto", "openai", "local"}:
|
||||
raise ValueError("provider must be auto, openai, or local")
|
||||
conversation_id = conversation_id or f"conv-{uuid.uuid4().hex}"
|
||||
if not CONVERSATION_ID_PATTERN.fullmatch(conversation_id):
|
||||
raise ValueError(
|
||||
"conversation_id must start with conv- and contain only lowercase letters, numbers, or hyphens"
|
||||
)
|
||||
vehicle_profile = self.vehicle_profiles.get(vehicle_id)
|
||||
control_plane_request = any(
|
||||
matcher(utterance) is not None
|
||||
for matcher in (
|
||||
self._parse_mode_profile_save_name,
|
||||
self._parse_mode_profile_create_name,
|
||||
self._parse_mode_profile_restore_name,
|
||||
self._parse_mode_profile_update,
|
||||
)
|
||||
)
|
||||
if control_plane_request:
|
||||
result = self.process(
|
||||
utterance,
|
||||
provider=provider,
|
||||
conversation_id=conversation_id,
|
||||
execution_mode=execution_mode,
|
||||
approval_token=approval_token,
|
||||
vehicle_id=vehicle_profile.id,
|
||||
simulation_fault=simulation_fault,
|
||||
hardware_client_id=hardware_client_id,
|
||||
hardware_access_bypass=hardware_access_bypass,
|
||||
reasoning_effort=reasoning_effort,
|
||||
control_transport=control_transport,
|
||||
_on_commands_validated=on_commands_validated,
|
||||
)
|
||||
result.update(
|
||||
{
|
||||
"phase": "control_plane_complete",
|
||||
"preview_request_id": result["request_id"],
|
||||
"unresolved_clauses": [],
|
||||
"supplement_required": False,
|
||||
}
|
||||
)
|
||||
self._persist(result)
|
||||
return result
|
||||
context = self._context_for_vehicle(
|
||||
self.conversations.snapshot(conversation_id),
|
||||
vehicle_profile,
|
||||
)
|
||||
clause_results = self._local_clause_results(utterance, context)
|
||||
unresolved_clauses = [
|
||||
clause
|
||||
for clause, _, status in clause_results
|
||||
if status != "complete"
|
||||
]
|
||||
started = time.perf_counter()
|
||||
|
||||
def publish_local_commands(validated: dict[str, Any]) -> None:
|
||||
if on_commands_validated is None:
|
||||
return
|
||||
event = deepcopy(validated)
|
||||
event.update(
|
||||
{
|
||||
"phase": "deterministic_commands_validated",
|
||||
"provider_requested": provider,
|
||||
"unresolved_clauses": unresolved_clauses,
|
||||
"supplement_required": bool(
|
||||
provider != "local" and unresolved_clauses
|
||||
),
|
||||
}
|
||||
)
|
||||
on_commands_validated(event)
|
||||
|
||||
result = self.process(
|
||||
utterance,
|
||||
provider="local",
|
||||
conversation_id=conversation_id,
|
||||
execution_mode=execution_mode,
|
||||
approval_token=approval_token,
|
||||
vehicle_id=vehicle_profile.id,
|
||||
simulation_fault=simulation_fault,
|
||||
hardware_client_id=hardware_client_id,
|
||||
hardware_access_bypass=hardware_access_bypass,
|
||||
reasoning_effort=reasoning_effort,
|
||||
control_transport=control_transport,
|
||||
_local_preview=True,
|
||||
_allow_empty_control_result=True,
|
||||
_on_commands_validated=publish_local_commands,
|
||||
)
|
||||
elapsed_ms = round((time.perf_counter() - started) * 1000, 3)
|
||||
supplement_required = bool(
|
||||
provider != "local" and unresolved_clauses
|
||||
)
|
||||
result.update(
|
||||
{
|
||||
"phase": "deterministic_preview",
|
||||
"provider_requested": provider,
|
||||
"preview_request_id": result["request_id"],
|
||||
"preview_elapsed_ms": elapsed_ms,
|
||||
"unresolved_clauses": unresolved_clauses,
|
||||
"supplement_required": supplement_required,
|
||||
}
|
||||
)
|
||||
result["decision_summary"] = [
|
||||
*result.get("decision_summary", []),
|
||||
(
|
||||
"本地规则阶段已完成白名单校验并先行处理 "
|
||||
f"{sum(len((config.get('spec') or {}).get('operations', [])) for config in result.get('function_configs', {}).values())} 条 CAN 控制指令。"
|
||||
),
|
||||
]
|
||||
self._persist(result)
|
||||
manifest = {
|
||||
"version": 1,
|
||||
"preview_request_id": result["request_id"],
|
||||
"utterance": utterance,
|
||||
"provider": provider,
|
||||
"conversation_id": conversation_id,
|
||||
"execution_mode": execution_mode,
|
||||
"vehicle_id": vehicle_profile.id,
|
||||
"simulation_fault": simulation_fault,
|
||||
"hardware_client_id": hardware_client_id,
|
||||
"reasoning_effort": reasoning_effort,
|
||||
"control_transport": control_transport,
|
||||
"unresolved_clauses": unresolved_clauses,
|
||||
"preview_control_signatures": result.get(
|
||||
"parsed_control_signatures", []
|
||||
),
|
||||
}
|
||||
self._atomic_write(
|
||||
self.artifact_root / result["request_id"] / "preview.json",
|
||||
json.dumps(manifest, ensure_ascii=False, indent=2) + "\n",
|
||||
)
|
||||
return result
|
||||
|
||||
def supplement_native_can(
|
||||
self,
|
||||
preview_request_id: str,
|
||||
*,
|
||||
provider: str | None = None,
|
||||
approval_token: str | None = None,
|
||||
hardware_client_id: str | None = None,
|
||||
hardware_access_bypass: bool = True,
|
||||
reasoning_effort: str | None = None,
|
||||
on_commands_validated: Callable[[dict[str, Any]], None] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Parse only unresolved clauses and merge them with the local result."""
|
||||
|
||||
if not MODE_EDITOR_REQUEST_ID_PATTERN.fullmatch(preview_request_id):
|
||||
raise ValueError("invalid preview request id")
|
||||
preview_dir = self.artifact_root / preview_request_id
|
||||
try:
|
||||
manifest = json.loads(
|
||||
(preview_dir / "preview.json").read_text(encoding="utf-8")
|
||||
)
|
||||
preview = json.loads(
|
||||
(preview_dir / "result.json").read_text(encoding="utf-8")
|
||||
)
|
||||
except (OSError, json.JSONDecodeError) as exc:
|
||||
raise ValueError("native CAN preview not found") from exc
|
||||
if (
|
||||
not isinstance(manifest, dict)
|
||||
or manifest.get("version") != 1
|
||||
or manifest.get("preview_request_id") != preview_request_id
|
||||
or not isinstance(preview, dict)
|
||||
or preview.get("request_id") != preview_request_id
|
||||
):
|
||||
raise ValueError("invalid native CAN preview manifest")
|
||||
selected_provider = str(manifest.get("provider") or "auto")
|
||||
if provider is not None and provider != selected_provider:
|
||||
raise ValueError("supplement provider does not match preview")
|
||||
selected_effort = manifest.get("reasoning_effort")
|
||||
if reasoning_effort is not None and reasoning_effort != selected_effort:
|
||||
raise ValueError("supplement reasoning effort does not match preview")
|
||||
expected_client_id = manifest.get("hardware_client_id")
|
||||
if hardware_client_id != expected_client_id:
|
||||
raise ValueError("supplement hardware client does not match preview")
|
||||
unresolved_clauses = [
|
||||
str(item).strip()
|
||||
for item in manifest.get("unresolved_clauses", [])
|
||||
if str(item).strip()
|
||||
]
|
||||
if not unresolved_clauses:
|
||||
raise ValueError("native CAN preview has no unresolved clauses")
|
||||
excluded_signatures = {
|
||||
tuple(item)
|
||||
for item in manifest.get("preview_control_signatures", [])
|
||||
if isinstance(item, list)
|
||||
}
|
||||
|
||||
def publish_cloud_commands(validated: dict[str, Any]) -> None:
|
||||
if on_commands_validated is None:
|
||||
return
|
||||
event = self._merge_native_can_phases(preview, validated)
|
||||
event.update(
|
||||
{
|
||||
"phase": "supplement_commands_validated",
|
||||
"preview_request_id": preview_request_id,
|
||||
"supplement_of": preview_request_id,
|
||||
"supplement_required": False,
|
||||
}
|
||||
)
|
||||
on_commands_validated(event)
|
||||
|
||||
supplement = self.process(
|
||||
",".join(unresolved_clauses),
|
||||
provider=selected_provider,
|
||||
conversation_id=str(manifest["conversation_id"]),
|
||||
execution_mode=str(manifest.get("execution_mode") or "dry_run"),
|
||||
approval_token=approval_token,
|
||||
vehicle_id=str(manifest["vehicle_id"]),
|
||||
simulation_fault=str(manifest.get("simulation_fault") or "normal"),
|
||||
hardware_client_id=hardware_client_id,
|
||||
hardware_access_bypass=hardware_access_bypass,
|
||||
reasoning_effort=(
|
||||
str(selected_effort) if selected_effort is not None else None
|
||||
),
|
||||
control_transport=str(
|
||||
manifest.get("control_transport") or WIRED_CAN_TRANSPORT
|
||||
),
|
||||
_excluded_control_signatures=excluded_signatures,
|
||||
_model_parse_source="cloud_supplement",
|
||||
_allow_empty_control_result=True,
|
||||
_on_commands_validated=publish_cloud_commands,
|
||||
)
|
||||
merged = self._merge_native_can_phases(preview, supplement)
|
||||
merged.update(
|
||||
{
|
||||
"phase": "two_stage_complete",
|
||||
"utterance": str(manifest["utterance"]),
|
||||
"provider_requested": selected_provider,
|
||||
"preview_request_id": preview_request_id,
|
||||
"supplement_of": preview_request_id,
|
||||
"supplement_request_id": supplement["request_id"],
|
||||
"supplement_required": False,
|
||||
"unresolved_clauses": unresolved_clauses,
|
||||
}
|
||||
)
|
||||
self._persist(merged)
|
||||
return merged
|
||||
|
||||
@staticmethod
|
||||
def _merge_native_can_phases(
|
||||
preview: dict[str, Any],
|
||||
supplement: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Create one durable result without collapsing same-domain phases."""
|
||||
|
||||
merged = deepcopy(supplement)
|
||||
|
||||
def phase_documents(
|
||||
local_documents: dict[str, Any] | None,
|
||||
cloud_documents: dict[str, Any] | None,
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
**{
|
||||
f"local_{key}": deepcopy(value)
|
||||
for key, value in (local_documents or {}).items()
|
||||
},
|
||||
**{
|
||||
f"cloud_{key}": deepcopy(value)
|
||||
for key, value in (cloud_documents or {}).items()
|
||||
},
|
||||
}
|
||||
|
||||
configs = phase_documents(
|
||||
preview.get("function_configs"),
|
||||
supplement.get("function_configs"),
|
||||
)
|
||||
plans = phase_documents(
|
||||
preview.get("command_plans"),
|
||||
supplement.get("command_plans"),
|
||||
)
|
||||
merged["function_configs"] = configs
|
||||
merged["command_plans"] = plans
|
||||
merged["function_config"] = next(iter(configs.values()), None)
|
||||
merged["command_plan"] = next(iter(plans.values()), None)
|
||||
merged["decision_summary"] = [
|
||||
*preview.get("decision_summary", []),
|
||||
*supplement.get("decision_summary", []),
|
||||
]
|
||||
merged["trace_events"] = [
|
||||
*preview.get("trace_events", []),
|
||||
*supplement.get("trace_events", []),
|
||||
]
|
||||
merged["validation"] = [
|
||||
*preview.get("validation", []),
|
||||
*supplement.get("validation", []),
|
||||
]
|
||||
merged["parsed_control_signatures"] = [
|
||||
*preview.get("parsed_control_signatures", []),
|
||||
*supplement.get("parsed_control_signatures", []),
|
||||
]
|
||||
merged["phase_execution_reports"] = {
|
||||
"local_rule": deepcopy(preview.get("execution_report")),
|
||||
"cloud_supplement": deepcopy(supplement.get("execution_report")),
|
||||
}
|
||||
if supplement.get("execution_report") is None:
|
||||
merged["execution_report"] = deepcopy(preview.get("execution_report"))
|
||||
successful = {"succeeded", "partially_succeeded", "no_action"}
|
||||
preview_ok = preview.get("status") in successful
|
||||
supplement_ok = supplement.get("status") in successful
|
||||
has_any_commands = bool(configs and plans)
|
||||
if preview_ok and supplement_ok:
|
||||
merged["status"] = "succeeded" if has_any_commands else "no_action"
|
||||
elif preview_ok and preview.get("function_configs"):
|
||||
merged["status"] = "partially_succeeded"
|
||||
merged["local_preview"] = {
|
||||
"request_id": preview.get("request_id"),
|
||||
"elapsed_ms": preview.get("preview_elapsed_ms"),
|
||||
"command_count": sum(
|
||||
len((config.get("spec") or {}).get("operations", []))
|
||||
for config in preview.get("function_configs", {}).values()
|
||||
),
|
||||
}
|
||||
return merged
|
||||
|
||||
def process(
|
||||
self,
|
||||
utterance: str,
|
||||
@@ -1080,6 +1415,11 @@ class SeatDemoService:
|
||||
hardware_access_bypass: bool = True,
|
||||
reasoning_effort: str | None = None,
|
||||
control_transport: str = WIRED_CAN_TRANSPORT,
|
||||
_local_preview: bool = False,
|
||||
_excluded_control_signatures: set[tuple[Any, ...]] | None = None,
|
||||
_model_parse_source: str = "cloud_model",
|
||||
_allow_empty_control_result: bool = False,
|
||||
_on_commands_validated: Callable[[dict[str, Any]], None] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
control_transport = self._validate_control_transport(control_transport)
|
||||
# Creating a reusable scene is a configuration workflow. Synthesize
|
||||
@@ -1099,6 +1439,11 @@ class SeatDemoService:
|
||||
simulation_fault,
|
||||
reasoning_effort,
|
||||
control_transport,
|
||||
_local_preview,
|
||||
_excluded_control_signatures,
|
||||
_model_parse_source,
|
||||
_allow_empty_control_result,
|
||||
_on_commands_validated,
|
||||
)
|
||||
if hardware_access_bypass or self._driver_only_vehicle_execution_active(
|
||||
control_transport
|
||||
@@ -1114,6 +1459,11 @@ class SeatDemoService:
|
||||
simulation_fault,
|
||||
reasoning_effort,
|
||||
control_transport,
|
||||
_local_preview,
|
||||
_excluded_control_signatures,
|
||||
_model_parse_source,
|
||||
_allow_empty_control_result,
|
||||
_on_commands_validated,
|
||||
)
|
||||
authorized_client_id = self.hardware_access.ensure_authorized(hardware_client_id)
|
||||
with self.hardware_execution.reserve():
|
||||
@@ -1128,6 +1478,11 @@ class SeatDemoService:
|
||||
simulation_fault,
|
||||
reasoning_effort,
|
||||
control_transport,
|
||||
_local_preview,
|
||||
_excluded_control_signatures,
|
||||
_model_parse_source,
|
||||
_allow_empty_control_result,
|
||||
_on_commands_validated,
|
||||
)
|
||||
|
||||
def _process_once(
|
||||
@@ -1141,6 +1496,11 @@ class SeatDemoService:
|
||||
simulation_fault: str = "normal",
|
||||
reasoning_effort: str | None = None,
|
||||
control_transport: str = WIRED_CAN_TRANSPORT,
|
||||
local_preview: bool = False,
|
||||
excluded_control_signatures: set[tuple[Any, ...]] | None = None,
|
||||
model_parse_source: str = "cloud_model",
|
||||
allow_empty_control_result: bool = False,
|
||||
on_commands_validated: Callable[[dict[str, Any]], None] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
control_transport = self._validate_control_transport(control_transport)
|
||||
utterance = utterance.strip()
|
||||
@@ -1298,6 +1658,8 @@ class SeatDemoService:
|
||||
context,
|
||||
vehicle_profile,
|
||||
reasoning_effort=reasoning_effort,
|
||||
local_preview=local_preview,
|
||||
model_parse_source=model_parse_source,
|
||||
)
|
||||
if self._is_dynamic_mode_stop_request(utterance):
|
||||
parsed = self._apply_dynamic_mode_stop_request(parsed, utterance)
|
||||
@@ -1305,6 +1667,7 @@ class SeatDemoService:
|
||||
parsed = self._apply_mode_profiles(
|
||||
parsed, matched_modes, context, vehicle_profile
|
||||
)
|
||||
parsed = self._mark_control_parse_source(parsed, "local_rule")
|
||||
relative_resolution = (
|
||||
self.native_can_relative_resolver.resolve(utterance, context)
|
||||
if self.native_can_relative_resolver.matches(utterance)
|
||||
@@ -1323,6 +1686,15 @@ class SeatDemoService:
|
||||
relative_resolution.claimed_controls if relative_resolution else None
|
||||
),
|
||||
)
|
||||
if local_preview:
|
||||
parsed["ambiguities"] = []
|
||||
parsed["unresolved_spans"] = []
|
||||
parsed["model_requests"] = []
|
||||
if excluded_control_signatures:
|
||||
parsed = self._filter_excluded_controls(
|
||||
parsed,
|
||||
excluded_control_signatures,
|
||||
)
|
||||
parsed = apply_language_safety_guards(parsed, utterance)
|
||||
parsed = self._partition_native_actions(
|
||||
parsed,
|
||||
@@ -1335,6 +1707,47 @@ class SeatDemoService:
|
||||
)
|
||||
),
|
||||
)
|
||||
result["parsed_control_signatures"] = [
|
||||
list(self._control_signature(action))
|
||||
for action in [
|
||||
*parsed.get("actions", []),
|
||||
*parsed.get("domain_actions", []),
|
||||
*parsed.get("native_can_actions", []),
|
||||
]
|
||||
]
|
||||
has_control = any(
|
||||
parsed.get(key)
|
||||
for key in ("actions", "domain_actions", "native_can_actions")
|
||||
)
|
||||
if allow_empty_control_result and not has_control:
|
||||
result["provider_used"] = provider_used
|
||||
result["decision_summary"] = [
|
||||
*parsed.get("decision_summary", []),
|
||||
"当前阶段没有新增的已验证 CAN 控制指令。",
|
||||
]
|
||||
result["deferred_requests"] = parsed.get("deferred_requests", [])
|
||||
result["model_requests"] = parsed.get("model_requests", [])
|
||||
result["intent_ir"] = build_intent_ir(
|
||||
parsed,
|
||||
utterance,
|
||||
request_id,
|
||||
provider_used,
|
||||
self.semantic_capability_metadata,
|
||||
)
|
||||
result["validation"] = self.contracts.validate(result["intent_ir"])
|
||||
result["status"] = "no_action"
|
||||
self._trace(
|
||||
traces,
|
||||
request_id,
|
||||
"intent_parse",
|
||||
"succeeded",
|
||||
"当前阶段未产生新的白名单控制动作。",
|
||||
started,
|
||||
{"provider": provider_used, "control_count": 0},
|
||||
domain="orchestration",
|
||||
)
|
||||
self._persist(result)
|
||||
return result
|
||||
if hardware_request and not control_plane_request:
|
||||
if (
|
||||
control_transport == WIRELESS_MQTT_TRANSPORT
|
||||
@@ -1505,6 +1918,7 @@ class SeatDemoService:
|
||||
simulation_fault=simulation_fault,
|
||||
vehicle_profile=vehicle_profile,
|
||||
control_transport=control_transport,
|
||||
on_commands_validated=on_commands_validated,
|
||||
)
|
||||
|
||||
intent_ir = build_intent_ir(
|
||||
@@ -1776,6 +2190,8 @@ class SeatDemoService:
|
||||
self._persist(result)
|
||||
return result
|
||||
|
||||
self._emit_validated_commands(result, on_commands_validated)
|
||||
|
||||
safety_started = time.perf_counter()
|
||||
self._trace(
|
||||
traces,
|
||||
@@ -3395,6 +3811,21 @@ class SeatDemoService:
|
||||
result["deferred_requests"] = deferred_requests
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def _emit_validated_commands(
|
||||
result: dict[str, Any],
|
||||
callback: Callable[[dict[str, Any]], None] | None,
|
||||
) -> None:
|
||||
"""Expose fully compiled commands before physical execution begins."""
|
||||
|
||||
if callback is None:
|
||||
return
|
||||
event = deepcopy(result)
|
||||
event["status"] = "processing"
|
||||
event["phase"] = "commands_validated"
|
||||
event["execution_report"] = None
|
||||
callback(event)
|
||||
|
||||
def _process_orchestrated(
|
||||
self,
|
||||
utterance: str,
|
||||
@@ -3411,6 +3842,7 @@ class SeatDemoService:
|
||||
simulation_fault: str = "normal",
|
||||
vehicle_profile: VehicleProfile | None = None,
|
||||
control_transport: str = WIRED_CAN_TRANSPORT,
|
||||
on_commands_validated: Callable[[dict[str, Any]], None] | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Run isolated adapters under the selected physical-bus policy."""
|
||||
vehicle_profile = vehicle_profile or self.vehicle_profiles.default()
|
||||
@@ -3669,6 +4101,8 @@ class SeatDemoService:
|
||||
self._persist(result)
|
||||
return result
|
||||
|
||||
self._emit_validated_commands(result, on_commands_validated)
|
||||
|
||||
self._trace(
|
||||
traces,
|
||||
request_id,
|
||||
@@ -3842,7 +4276,7 @@ class SeatDemoService:
|
||||
"execute",
|
||||
"succeeded" if execution_succeeded and not report_issues else "failed",
|
||||
(
|
||||
"无线 MQTT 白名单控制帧已发布;车辆实际状态以状态话题回读为准。"
|
||||
"无线 MQTT 白名单控制帧已提交;车辆实际状态以状态话题回读为准。"
|
||||
if (
|
||||
hardware_request
|
||||
and control_transport == WIRELESS_MQTT_TRANSPORT
|
||||
@@ -4385,16 +4819,29 @@ class SeatDemoService:
|
||||
)
|
||||
return merged
|
||||
|
||||
def _interpret(
|
||||
@staticmethod
|
||||
def _mark_control_parse_source(
|
||||
parsed: dict[str, Any],
|
||||
source: str,
|
||||
*,
|
||||
overwrite: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""Attach per-control provenance without changing semantic content."""
|
||||
|
||||
marked = deepcopy(parsed)
|
||||
for key in ("actions", "domain_actions", "native_can_actions"):
|
||||
for action in marked.get(key, []):
|
||||
if overwrite or not action.get("parse_source"):
|
||||
action["parse_source"] = source
|
||||
return marked
|
||||
|
||||
def _local_clause_results(
|
||||
self,
|
||||
utterance: str,
|
||||
provider: str,
|
||||
context: dict[str, Any],
|
||||
vehicle_profile: VehicleProfile | None = None,
|
||||
*,
|
||||
reasoning_effort: str | None = None,
|
||||
) -> tuple[dict[str, Any], str, str | None]:
|
||||
vehicle_profile = vehicle_profile or self.vehicle_profiles.default()
|
||||
) -> list[tuple[str, dict[str, Any], str]]:
|
||||
"""Parse each clause deterministically and preserve inherited seat scope."""
|
||||
|
||||
clause_results: list[tuple[str, dict[str, Any], str]] = []
|
||||
|
||||
def parse_clause(clause: str) -> dict[str, Any]:
|
||||
@@ -4413,7 +4860,7 @@ class SeatDemoService:
|
||||
relative.claimed_controls if relative else None
|
||||
),
|
||||
)
|
||||
return local
|
||||
return self._mark_control_parse_source(local, "local_rule")
|
||||
|
||||
def has_seat_domain(parsed: dict[str, Any]) -> bool:
|
||||
if parsed.get("actions") or "seat" in parsed.get("detected_domains", []):
|
||||
@@ -4441,12 +4888,6 @@ class SeatDemoService:
|
||||
if clause_has_seat and explicit_driver != explicit_passenger:
|
||||
inherited_seat_scope = "driver" if explicit_driver else "passenger"
|
||||
elif clause_has_seat and inherited_seat_scope:
|
||||
# Chinese compound controls commonly state the seat once and
|
||||
# then list axes or thermal functions after commas. Carry the
|
||||
# last explicit seat scope only into later seat clauses; this
|
||||
# prevents a passenger request from silently falling through
|
||||
# to the CH1 driver default while leaving climate/door/window
|
||||
# clauses untouched.
|
||||
scope_label = (
|
||||
"主驾座椅"
|
||||
if inherited_seat_scope == "driver"
|
||||
@@ -4457,10 +4898,59 @@ class SeatDemoService:
|
||||
clause_results.append(
|
||||
(clause, local, self._local_clause_status(local, clause))
|
||||
)
|
||||
return clause_results
|
||||
|
||||
@classmethod
|
||||
def _trusted_local_preview(
|
||||
cls,
|
||||
clause_results: list[tuple[str, dict[str, Any], str]],
|
||||
) -> dict[str, Any]:
|
||||
"""Keep deterministic controls while deferring incomplete text to GPT."""
|
||||
|
||||
trusted = cls._merge_parsed_results(
|
||||
[parsed for _, parsed, status in clause_results if status != "unparsed"]
|
||||
)
|
||||
# Ambiguities and unresolved spans belong to the supplement phase. A
|
||||
# deterministic action still goes through the normal schema, compiler,
|
||||
# whitelist and physical execution gates before it can be sent.
|
||||
trusted["ambiguities"] = []
|
||||
trusted["unresolved_spans"] = []
|
||||
trusted["model_requests"] = []
|
||||
return trusted
|
||||
|
||||
@classmethod
|
||||
def _filter_excluded_controls(
|
||||
cls,
|
||||
parsed: dict[str, Any],
|
||||
excluded: set[tuple[Any, ...]],
|
||||
) -> dict[str, Any]:
|
||||
filtered = deepcopy(parsed)
|
||||
for key in ("actions", "domain_actions", "native_can_actions"):
|
||||
filtered[key] = [
|
||||
action
|
||||
for action in filtered.get(key, [])
|
||||
if cls._control_signature(action) not in excluded
|
||||
]
|
||||
return filtered
|
||||
|
||||
def _interpret(
|
||||
self,
|
||||
utterance: str,
|
||||
provider: str,
|
||||
context: dict[str, Any],
|
||||
vehicle_profile: VehicleProfile | None = None,
|
||||
*,
|
||||
reasoning_effort: str | None = None,
|
||||
local_preview: bool = False,
|
||||
model_parse_source: str = "cloud_model",
|
||||
) -> tuple[dict[str, Any], str, str | None]:
|
||||
vehicle_profile = vehicle_profile or self.vehicle_profiles.default()
|
||||
clause_results = self._local_clause_results(utterance, context)
|
||||
|
||||
trusted_local = self._merge_parsed_results(
|
||||
[parsed for _, parsed, status in clause_results if status != "unparsed"]
|
||||
)
|
||||
preview_local = self._trusted_local_preview(clause_results)
|
||||
all_local = self._merge_parsed_results(
|
||||
[parsed for _, parsed, _ in clause_results]
|
||||
)
|
||||
@@ -4474,7 +4964,13 @@ class SeatDemoService:
|
||||
safe_fallback = trusted_local if trusted_controls else all_local
|
||||
if provider == "local" or not fallback_clauses:
|
||||
return (
|
||||
all_local if provider == "local" else trusted_local,
|
||||
(
|
||||
preview_local
|
||||
if provider == "local" and local_preview
|
||||
else all_local
|
||||
if provider == "local"
|
||||
else trusted_local
|
||||
),
|
||||
"local_rules",
|
||||
None,
|
||||
)
|
||||
@@ -4505,6 +5001,11 @@ class SeatDemoService:
|
||||
vehicle_profile,
|
||||
utterance=fallback_utterance,
|
||||
)
|
||||
model = self._mark_control_parse_source(
|
||||
model,
|
||||
model_parse_source,
|
||||
overwrite=True,
|
||||
)
|
||||
return (
|
||||
self._merge_local_and_model_intent(trusted_local, model),
|
||||
f"local_rules+openai:{self.openai.model}",
|
||||
|
||||
Reference in New Issue
Block a user