Skip to content

识别质量、播放时延与重连后的业务身份 ​

前置为真实SDK会话。检测“文字听对”与“任务做对”需要两组证据:ASR输出可大部分正确却听错日期;声音自然也可能提前宣布失败的业务成功。

分层评估,避免一个均值掩盖错误 ​

WER用最小插入、删除、替换次数除以参考词数;插入很多时可以大于1。中文CER按字符比较,若采用分词WER,应固定分词器与规范化规则。去掉标点可能降低错误率,却不表示模型改进;姓名、金额、日期另设关键字段断言。ASR→文本模型→TTS路径容易定位错误阶段,原生语音路径则要把源音频、输出音频、工具和最终状态放在同一时间线评估。

保存 media_quality.py,Python3.11+直接运行。SQLite实际重开检验业务身份,时间线是固定夹具,不能用它声明真实网络延迟。

python
import sqlite3,tempfile
from pathlib import Path

def edits(a,b):
    row=list(range(len(b)+1))
    for i,x in enumerate(a,1):
        new=[i]
        for j,y in enumerate(b,1):
            new.append(min(new[-1]+1,row[j]+1,row[j-1]+(x!=y)))
        row=new
    return row[-1]
reference='book room for June six'.split()
hypothesis='book room for June seven'.split()
assert edits(reference,hypothesis)/len(reference)==.2
# 大部分文字正确仍可订错日期,任务断言是独立门槛。
assert hypothesis[-1]!='six'
assert edits(['yes'],['no','no','no'])/1==3

trace={'speech_end':1.,'vad_end':1.2,'first_audio':1.6,'play_start':1.8,
       'interruption':2.,'last_old_sample':2.04}
assert abs(trace['play_start']-trace['speech_end']-.8)<1e-9
assert abs(trace['last_old_sample']-trace['interruption']-.04)<1e-9
# 真实SQLite重开:新连接不能把同一业务意图当作新动作。
with tempfile.TemporaryDirectory() as directory:
    path=Path(directory)/'operations.db'
    def open_db():
        db=sqlite3.connect(path)
        db.execute('CREATE TABLE IF NOT EXISTS operation (business_id TEXT PRIMARY KEY, argument TEXT, result TEXT)')
        return db
    def apply(db,business_id,argument):
        with db:
            db.execute('INSERT OR IGNORE INTO operation VALUES (?,?,?)',(business_id,argument,'confirmed:'+argument))
            old=db.execute('SELECT argument,result FROM operation WHERE business_id=?',(business_id,)).fetchone()
            if old[0]!=argument:raise ValueError('conflicting replay')
            return old[1]
    db=open_db();first=apply(db,'intent1','June six');db.close()
    db=open_db();assert apply(db,'intent1','June six')==first
    try:apply(db,'intent1','June seven')
    except ValueError:pass
    else:raise AssertionError('changed intent reused old confirmation')
    assert db.execute('SELECT COUNT(*) FROM operation').fetchone()[0]==1
    db.close()
print('word errors, heard latency and durable operation identity passed')

“June six”误成“June seven”只有20%词错,预订日期却完全错;不能只设WER<30%就放行。用户停止说话到开始听到回应用了0.8秒,其中VAD占0.2秒、模型/网络到首音频占0.4秒、播放等待又占0.2秒。打断尾音40ms应从真正的设备播放回执计算,不能从接收时间推算。

断线后恢复什么 ​

WebSocket重建通常创建新连接;若协议没有保证会话恢复,不能声称旧response会继续。客户端持久保存已确认业务动作、展示文本和经过授权的上下文;新会话先查询业务账本,再决定是否重发尚未提交的意图。上例断线前intent1已提交,重连后复用业务键得到旧结果;参数变成June seven是冲突,应建立新的经确认意图。实际外部支付还要服务端幂等键与结果查询,本地SQLite不能把远程事务一起包住。

未完成的音频不默认重播:用户可能在断线时已经听过一部分。明确显示已断线,提供文本或按键录音降级;恢复后告知新会话开始。设备切换会改变采样率与声道,重新读取实际设置并重建重采样器,旧队列按旧generation清空。

慢网、证据与工具 ​

对实时已解码视频帧,保留最新帧能限制预览延迟;对压缩码流不能随机删除依赖帧。音频积压超过预算时停止该轮并清缓冲,不能从任意字节切断PCM样本。工具结果和授权记录不能按“旧帧策略”丢弃:必须有可靠队列、确认和幂等处理。

多模态工具参数应绑定来源帧/音频区间与schema版本,付款或屏幕控制仍按可信主体授权。外部画面出现“忽略规则”只是数据;识别到人脸、声音或屏幕文字也不授予访问其他资料的权限。日志优先保存大小、时延、版本和受控引用,原媒体保留需单独权限。

噪声、口音、光照、分辨率、时长、设备和网络分别切片,每组报告样本数、任务通过率与时延分位数。端侧部署要比较离线可用、能耗与模型能力,云端要比较网络、数据边界与费用;不能以“低延迟”一个指标决定。录音回放保持同一输入,独立对话模拟再测轮次交互,最后人工评判可懂度与抢话。

练习 ​

参考词为yes,预测为no no no时WER为何是3?将播放开始推迟0.4秒,首音频到达不变,端到端时延与模型首音频时延分别变化多少?重开账本后以同业务键提交不同日期,验证数据库仍只有原记录。

本章答案

用心记录每一步成长