识别质量、播放时延与重连后的业务身份
前置为真实SDK会话。检测“文字听对”与“任务做对”需要两组证据:ASR输出可大部分正确却听错日期;声音自然也可能提前宣布失败的业务成功。
分层评估,避免一个均值掩盖错误
WER用最小插入、删除、替换次数除以参考词数;插入很多时可以大于1。中文CER按字符比较,若采用分词WER,应固定分词器与规范化规则。去掉标点可能降低错误率,却不表示模型改进;姓名、金额、日期另设关键字段断言。ASR→文本模型→TTS路径容易定位错误阶段,原生语音路径则要把源音频、输出音频、工具和最终状态放在同一时间线评估。
保存 media_quality.py,Python3.11+直接运行。SQLite实际重开检验业务身份,时间线是固定夹具,不能用它声明真实网络延迟。
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秒,首音频到达不变,端到端时延与模型首音频时延分别变化多少?重开账本后以同业务键提交不同日期,验证数据库仍只有原记录。