优化的前端UI

This commit is contained in:
minghanchen
2026-09-02 11:39:31 +08:00
parent 00c7d6b874
commit ccd64adcfe
10 changed files with 317 additions and 75 deletions
@@ -36,9 +36,9 @@ from cognitive_agent.infrastructure.speech.vocabulary import (
_CLAUSE_SPLIT = re.compile(r"[\s,,;;。!?!?…]+")
_POSITIVE_SPLIT = re.compile(
rf"[\s,,;;]*({'|'.join(map(re.escape, POSITIVE_CONNECTORS))})[\s,,;;]*"
rf"[\s,,;;]*({'|'.join(map(re.escape, sorted(POSITIVE_CONNECTORS, key=len, reverse=True)))})[\s,,;;]*"
)
_COORDINATION_SPLIT = re.compile(r"\s*(?:以及|和|与|及|、)\s*")
_COORDINATION_SPLIT = re.compile(r"\s*(?:还有|以及|和|跟|与|及|、)\s*")
_CORRECTION_PATTERN = re.compile(
rf"[\s,,;;]*({'|'.join(map(re.escape, sorted(CORRECTION_MARKERS, key=len, reverse=True)))}|不[,,]+是)[\s,,;;]*"
)
@@ -62,6 +62,14 @@ _PERCENT = re.compile(r"(-?\d+(?:\.\d+)?)\s*[%%]")
_CHINESE_PERCENT = re.compile(r"百分之([零〇一二两三四五六七八九十百点\d.]+)")
_TERMINAL = re.compile(r"[。!?!?]+$")
_CONTROL_SCAFFOLD = re.compile(r"^(?:把|将|请|给我|帮我)+")
_STRONG_CONTINUATION_ACTION = re.compile(
r"打开|开启|启动|关闭|关掉|关上|停止|调整|调节|设置|设成|设为|设到|"
r"调到|调成|调为|变成|开到|向前|往前|朝前|向后|往后|朝后|"
r"向上|往上|向下|往下|升高|降低"
)
_NON_NUMERIC_ONE = re.compile(
r"(?:一下(?:子)?|一会儿?|一点(?:点|儿)?)(?![零〇一二两三四五六七八九])"
)
@dataclass(frozen=True)
@@ -109,12 +117,7 @@ class UnderstandingTranscriptProcessor:
blocks = [part for part in blocks if part not in POSITIVE_CONNECTORS]
for raw_block in blocks:
block = raw_block
if (
shared_target is not None
and not device_terms_in(block)
and not _CORRECTION_PATTERN.search(block)
and not _CANCELLATION_PATTERN.search(block)
):
if shared_target is not None and self._should_inherit_shared_target(block):
block = self._inherit_shared_target(block, shared_target)
clauses.append(block)
(
@@ -269,7 +272,19 @@ class UnderstandingTranscriptProcessor:
reasons.append("correction_not_resolved")
return active, cancelled, reasons, bool(new.commands), resolution_ms
analyses = [self._analyse_fragment(item) for item in self._plain_fragments(block)]
analyses: list[_FragmentAnalysis] = []
local_shared_target: SpeechCommandIntent | None = None
for item in self._plain_fragments(block):
fragment = item
if (
local_shared_target is not None
and self._should_inherit_shared_target(fragment)
):
fragment = self._inherit_shared_target(fragment, local_shared_target)
analysis = self._analyse_fragment(fragment)
analyses.append(analysis)
if analysis.commands:
local_shared_target = analysis.commands[-1]
resolution_ms += sum(item.resolution_ms for item in analyses)
for index, analysis in enumerate(analyses):
following = analyses[index + 1] if index + 1 < len(analyses) else None
@@ -329,6 +344,8 @@ class UnderstandingTranscriptProcessor:
return application_analysis
devices = device_terms_in(text)
actions = action_terms_in(text)
if devices and not actions and self._has_explicit_set_value(text):
actions = [(0, 0, "set", "implicit_set")]
mode = self.resolver.match_mode(text)
if mode is not None and (devices or actions):
term = (
@@ -738,11 +755,18 @@ class UnderstandingTranscriptProcessor:
def _commands_for(
self, text: str, term: DeviceTerm, action: str, negated: bool
) -> tuple[list[SpeechCommandIntent], list[str], float]:
implicit_driver_temperature = (
term.semantic_key == "hvac.power"
and self._numeric_value(text) is not None
and bool(re.search(r"摄氏度|度|温度", text))
)
default_scope = (
"passenger"
if term.domain == "seat"
else "front_left"
if term.domain == "window"
else "driver"
if term.semantic_key == "hvac.temperature" or implicit_driver_temperature
else "all"
if term.semantic_key == "reading_light.power"
else "vehicle"
@@ -1160,6 +1184,10 @@ class UnderstandingTranscriptProcessor:
def _inherit_shared_target(self, fragment: str, command: SpeechCommandIntent) -> str:
target = self._display_target(command)
if self._has_explicit_scope(fragment):
spoken_scope = str(command.qualifiers.get("spoken_scope", ""))
if spoken_scope and target.startswith(spoken_scope):
target = target[len(spoken_scope) :]
if (
command.domain == "seat"
and not command.qualifiers.get("target_explicit")
@@ -1167,8 +1195,38 @@ class UnderstandingTranscriptProcessor:
):
scope = "主驾" if command.target_scope in {"driver", "front_left"} else "副驾"
target = f"{scope}{target}"
if not action_terms_in(fragment) and self._has_explicit_set_value(fragment):
return f"{target}设置为{fragment}"
return f"{target}{fragment}"
@staticmethod
def _has_explicit_scope(text: str) -> bool:
return any(
alias in text
for aliases in SCOPE_ALIASES.values()
for alias in aliases
)
@classmethod
def _has_explicit_set_value(cls, text: str) -> bool:
if cls._percentage_value(text) is not None or color_in(text) is not None:
return True
return cls._numeric_value(text) is not None and bool(
re.search(r"摄氏度|百分比|度|档|级|[%%]", text)
)
@classmethod
def _should_inherit_shared_target(cls, fragment: str) -> bool:
if (
device_terms_in(fragment)
or _CORRECTION_PATTERN.search(fragment)
or _CANCELLATION_PATTERN.search(fragment)
):
return False
return bool(_STRONG_CONTINUATION_ACTION.search(fragment)) or cls._has_explicit_set_value(
fragment
)
@staticmethod
def _cancel_commands(
commands: Iterable[SpeechCommandIntent], *, negated: bool = False
@@ -1259,6 +1317,7 @@ class UnderstandingTranscriptProcessor:
@staticmethod
def _numeric_value(text: str) -> int | float | None:
text = _NON_NUMERIC_ONE.sub("", text)
match = _NUMBER.search(text)
if match:
value = float(match.group(1))
@@ -44,7 +44,23 @@ DEVICE_TERMS: tuple[DeviceTerm, ...] = (
"seat",
"seat.longitudinal_position",
"seat_longitudinal_motor",
("座椅", "坐椅", "座位"),
(
"座椅",
"坐椅",
"座位",
"驾驶座椅",
"驾驶座",
"驾驶席",
"司机座椅",
"司机座",
"主驾驶座椅",
"主驾驶座",
"乘客座椅",
"乘客座",
"副驾驶座椅",
"副驾驶座",
"副驾驶席",
),
),
DeviceTerm(
"座椅坐垫",
@@ -65,14 +81,42 @@ DEVICE_TERMS: tuple[DeviceTerm, ...] = (
"seat",
"seat.ventilation",
"seat",
("座椅通风", "通风座椅"),
(
"座椅通风",
"通风座椅",
"驾驶座通风",
"驾驶席通风",
"司机座通风",
"司机座椅通风",
"主驾驶座通风",
"主驾驶座椅通风",
"乘客座通风",
"乘客座椅通风",
"副驾驶座通风",
"副驾驶座椅通风",
"副驾驶席通风",
),
),
DeviceTerm(
"座椅加热",
"seat",
"seat.heating",
"seat",
("座椅加热", "加热座椅"),
(
"座椅加热",
"加热座椅",
"驾驶座加热",
"驾驶席加热",
"司机座加热",
"司机座椅加热",
"主驾驶座加热",
"主驾驶座椅加热",
"乘客座加热",
"乘客座椅加热",
"副驾驶座加热",
"副驾驶座椅加热",
"副驾驶席加热",
),
),
DeviceTerm(
"车窗",
@@ -126,8 +170,26 @@ DEVICE_TERMS: tuple[DeviceTerm, ...] = (
)
SCOPE_ALIASES: dict[str, tuple[str, ...]] = {
"driver": ("主驾", "主驾驶", "驾驶位", "司机位", "左前"),
"passenger": ("副驾", "副驾驶", "乘客位", "右前"),
"driver": (
"主驾",
"主驾驶",
"主驾驶座",
"驾驶位",
"驾驶座",
"驾驶席",
"司机位",
"司机座",
"左前",
),
"passenger": (
"副驾",
"副驾驶",
"副驾驶座",
"副驾驶席",
"乘客位",
"乘客座",
"右前",
),
"front_row": ("前排",),
"rear_row": ("后排",),
"rear_left": ("左后", "后排左侧"),
@@ -148,8 +210,12 @@ ACTION_ALIASES: dict[str, tuple[str, ...]] = {
"设置为",
"调到",
"调成",
"调为",
"变成",
"设为",
"设成",
"设到",
"设置",
"开到",
),
"forward": ("向前", "往前", "朝前", "前移", "前倾"),
@@ -176,13 +242,23 @@ CORRECTION_MARKERS: tuple[str, ...] = (
CANCELLATION_MARKERS: tuple[str, ...] = ("算了", "取消", "作废")
POSITIVE_CONNECTORS: tuple[str, ...] = (
"接下来再",
"紧接着",
"再然后",
"接下来",
"然后",
"同时",
"并且",
"接着",
"随后",
"之后",
"而后",
"顺便",
"另外",
"最后",
"再",
"并",
"先",
)
NEGATION_PREFIXES: tuple[str, ...] = ("不要", "别", "不想", "无需", "不必", "禁止")
UNITS: tuple[str, ...] = ("摄氏度", "百分比", "毫米", "厘米", "毫秒", "分钟", "度", "%", "档", "秒")