优化的前端UI
This commit is contained in:
@@ -17,6 +17,9 @@ Provides-Extra: llm
|
||||
Requires-Dist: openai>=1.30; extra == "llm"
|
||||
Provides-Extra: ir
|
||||
Requires-Dist: pyserial<4,>=3.5; extra == "ir"
|
||||
Provides-Extra: speech
|
||||
Requires-Dist: sherpa-onnx==1.13.6; extra == "speech"
|
||||
Requires-Dist: sherpa-onnx-bin==1.13.6; extra == "speech"
|
||||
Provides-Extra: test
|
||||
Requires-Dist: pytest>=8; extra == "test"
|
||||
Requires-Dist: pytest-cov>=5; extra == "test"
|
||||
|
||||
@@ -10,11 +10,14 @@ src/cognitive_agent.egg-info/dependency_links.txt
|
||||
src/cognitive_agent.egg-info/requires.txt
|
||||
src/cognitive_agent.egg-info/top_level.txt
|
||||
src/cognitive_agent/application/capability_registry.py
|
||||
src/cognitive_agent/application/chinese_values.py
|
||||
src/cognitive_agent/application/conversation_state.py
|
||||
src/cognitive_agent/application/direct_can_control.py
|
||||
src/cognitive_agent/application/domain_runtime.py
|
||||
src/cognitive_agent/application/gesture_bridge.py
|
||||
src/cognitive_agent/application/mode_profile.py
|
||||
src/cognitive_agent/application/model_plan_adapter.py
|
||||
src/cognitive_agent/application/mqtt_ota_seat_executor.py
|
||||
src/cognitive_agent/application/native_can_feedback.py
|
||||
src/cognitive_agent/application/native_can_intent.py
|
||||
src/cognitive_agent/application/native_can_relative.py
|
||||
@@ -24,6 +27,7 @@ src/cognitive_agent/application/seat_service.py
|
||||
src/cognitive_agent/application/self_extension.py
|
||||
src/cognitive_agent/application/semantic_ir.py
|
||||
src/cognitive_agent/application/vehicle_profile.py
|
||||
src/cognitive_agent/application/vehicle_state_monitor.py
|
||||
src/cognitive_agent/application/zcan_seat_executor.py
|
||||
src/cognitive_agent/application/calibration/__init__.py
|
||||
src/cognitive_agent/application/calibration/mqtt_client.py
|
||||
@@ -37,11 +41,14 @@ src/cognitive_agent/application/self_repair/healing_model.py
|
||||
src/cognitive_agent/application/self_repair/service.py
|
||||
src/cognitive_agent/application/self_repair/signal_diagnostic.py
|
||||
src/cognitive_agent/application/self_repair/zcan_bridge.py
|
||||
src/cognitive_agent/generated/__init__.py
|
||||
src/cognitive_agent/generated/can_semantic_protocol.py
|
||||
src/cognitive_agent/infrastructure/can/__init__.py
|
||||
src/cognitive_agent/infrastructure/can/access.py
|
||||
src/cognitive_agent/infrastructure/can/gateway.py
|
||||
src/cognitive_agent/infrastructure/can/hardware.py
|
||||
src/cognitive_agent/infrastructure/can/matrix.py
|
||||
src/cognitive_agent/infrastructure/can/mqtt_transport.py
|
||||
src/cognitive_agent/infrastructure/can/zlgcan_bridge.py
|
||||
src/cognitive_agent/infrastructure/can/zlgcan_linux_bridge.py
|
||||
src/cognitive_agent/infrastructure/firmware/__init__.py
|
||||
@@ -50,6 +57,17 @@ src/cognitive_agent/infrastructure/llm/openai_responses.py
|
||||
src/cognitive_agent/infrastructure/nfc/__init__.py
|
||||
src/cognitive_agent/infrastructure/nfc/pn532.py
|
||||
src/cognitive_agent/infrastructure/nfc/reader.py
|
||||
src/cognitive_agent/infrastructure/speech/__init__.py
|
||||
src/cognitive_agent/infrastructure/speech/assembler.py
|
||||
src/cognitive_agent/infrastructure/speech/capability.py
|
||||
src/cognitive_agent/infrastructure/speech/contracts.py
|
||||
src/cognitive_agent/infrastructure/speech/recovery.py
|
||||
src/cognitive_agent/infrastructure/speech/semantic.py
|
||||
src/cognitive_agent/infrastructure/speech/sensevoice.py
|
||||
src/cognitive_agent/infrastructure/speech/tracing.py
|
||||
src/cognitive_agent/infrastructure/speech/understanding.py
|
||||
src/cognitive_agent/infrastructure/speech/vad.py
|
||||
src/cognitive_agent/infrastructure/speech/vocabulary.py
|
||||
src/cognitive_agent/runtime/contracts.py
|
||||
src/cognitive_agent/testing/__init__.py
|
||||
src/cognitive_agent/testing/ch1_hil.py
|
||||
src/cognitive_agent/testing/ch1_hil.py
|
||||
@@ -21,6 +21,10 @@ pyserial<4,>=3.5
|
||||
[llm]
|
||||
openai>=1.30
|
||||
|
||||
[speech]
|
||||
sherpa-onnx==1.13.6
|
||||
sherpa-onnx-bin==1.13.6
|
||||
|
||||
[test]
|
||||
pytest>=8
|
||||
pytest-cov>=5
|
||||
|
||||
@@ -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, ...] = ("摄氏度", "百分比", "毫米", "厘米", "毫秒", "分钟", "度", "%", "档", "秒")
|
||||
|
||||
Reference in New Issue
Block a user