fix(realtime): preserve aligned long-segment partials (#3589)

Signed-off-by: LauraGPT <[email protected]>
Co-authored-by: LauraGPT <[email protected]>
This commit is contained in:
zhifu gao
2026-08-31 12:42:04 +08:00
committed by GitHub
co-authored by LauraGPT
parent 8cd758c0ce
commit 2b6294d69e
2 changed files with 59 additions and 9 deletions
+17 -9
View File
@@ -13,6 +13,7 @@ Features:
import asyncio
from collections import deque
import copy
from difflib import SequenceMatcher
import json
import logging
import os
@@ -1104,24 +1105,31 @@ class RealtimeASRSession:
):
final_cmp = _normalize_transcript(final_text)
recent_cmp = _normalize_transcript(recent_partial)
common_prefix_len = 0
for final_char, partial_char in zip(final_cmp, recent_cmp):
if final_char != partial_char:
break
common_prefix_len += 1
diverged = common_prefix_len < min(len(final_cmp), len(recent_cmp))
matcher = SequenceMatcher(None, final_cmp, recent_cmp, autojunk=False)
matching_blocks = matcher.get_matching_blocks()
matched_chars = sum(block.size for block in matching_blocks)
final_coverage = matched_chars / max(1, len(final_cmp))
first_match = next(
(block for block in matching_blocks if block.size), None
)
starts_aligned = bool(
first_match and first_match.a <= 1 and first_match.b <= 2
)
diverged = final_cmp != recent_cmp
catastrophically_short = (
diverged
and len(final_cmp) >= 2
and len(final_cmp) >= 1
and len(recent_cmp) >= 24
and len(recent_cmp) >= len(final_cmp) * 3
and common_prefix_len >= max(1, len(final_cmp) // 2)
and starts_aligned
and matched_chars >= max(1, len(final_cmp) // 2)
)
tail_regressed = (
diverged
and len(final_cmp) >= 16
and len(recent_cmp) - len(final_cmp) >= 4
and common_prefix_len >= max(12, (len(final_cmp) * 3) // 4)
and starts_aligned
and final_coverage >= 0.75
)
if catastrophically_short or tail_regressed:
partial_text = recent_partial
+42
View File
@@ -550,6 +550,48 @@ def test_long_segment_recovers_from_catastrophically_short_final():
assert text == partial
def test_long_segment_recovers_from_single_character_final():
module = load_service_module()
partial = (
"哎,不好意思,上午高雄交通比较混乱一点,我们不晓得我们有点。"
"胡总,各位长官。"
)
session = make_reported_long_segment_reconciliation_session(
module, partial, partial_end_ms=35328
)
text = session._reconcile_completed_segment_text(
"哎",
[2920, 36260],
decode_succeeded=True,
)
assert text == partial
def test_long_segment_recovers_when_an_early_partial_correction_hides_tail_regression():
module = load_service_module()
partial = (
"哇,哎,不好意思,上午杭高雄的交通比较混乱一点,我们不晓得我们有点。"
"哎,好嘞,胡总各位长官。"
)
final = (
"哇,不好意思,上午高雄的交通比较混乱一点,我们不晓得我们有点。"
"哎,好嘞,"
)
session = make_reported_long_segment_reconciliation_session(
module, partial, partial_end_ms=14336
)
text = session._reconcile_completed_segment_text(
final,
[2920, 14420],
decode_succeeded=True,
)
assert text == partial
def test_long_segment_keeps_distinct_short_final_without_prefix_alignment():
module = load_service_module()
partial = "会议取消,稍后另行通知,请各位等待后续的完整安排和确认消息。"