docs(12B): 延迟验收暂定结论 + 建立项目文档索引
ci / server (push) Failing after 10s
ci / design-tokens (push) Failing after 10s

- doc/latency-acceptance-12b.html:延迟分解、#23/#24 修复记录、暂定新目标
  (first_partial P95<1.2s;release_to_commit ≤3s 会话<300ms / 长会话<600ms)、
  paraformer 切换待 eval 对比决策、复测方法
- doc/index.html:项目文档单一入口(按规范补建,登记现有 4 份文档)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-10 20:02:16 +08:00
parent d22e02fa2e
commit 2979bdd2a3
2 changed files with 258 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dudu 文档索引</title>
<style>
:root {
--accent: #4F6EF7;
--accent-text: #3D58DB;
--accent-soft: #EEF1FE;
--bg: #F6F7FA;
--card: #FFFFFF;
--text-1: #1B1E26;
--text-2: #5A6072;
--text-3: #A6ABB8;
--border-1: #E4E6EB;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
background: var(--bg); color: var(--text-1); line-height: 1.75;
}
.container { max-width: 980px; margin: 0 auto; padding: 0 24px 80px; }
header.hero { background: var(--accent); color: #fff; padding: 48px 24px 40px; text-align: center; }
header.hero h1 { margin: 0 0 6px; font-size: 30px; }
header.hero p { margin: 0; opacity: .85; font-size: 15px; }
section.card {
background: var(--card); border: 1px solid var(--border-1); border-radius: 14px;
padding: 28px 32px; margin-top: 24px; box-shadow: 0 1px 3px rgba(17,19,26,.05);
}
h2 { font-size: 21px; margin: 0 0 14px; padding-bottom: 8px; border-bottom: 2px solid var(--accent); display: inline-block; }
ul { padding-left: 22px; }
li { margin: 8px 0; }
a { color: var(--accent-text); text-decoration: none; font-weight: 600; }
a:hover { text-decoration: underline; }
.desc { color: var(--text-2); font-size: 13.5px; font-weight: 400; }
footer { text-align: center; color: var(--text-3); font-size: 13px; margin-top: 44px; }
</style>
</head>
<body>
<header class="hero">
<h1>dudu 文档索引</h1>
<p>五端付费语音输入法 · 全部设计 / 计划 / 调研 / 排障文档单一入口</p>
</header>
<div class="container">
<section class="card">
<h2>设计方案</h2>
<ul>
<li><a href="frontend-design.html">前端交互与界面设计</a> <span class="desc">— 五端交互流、界面规格与设计系统对接(v1.1)</span></li>
<li><a href="backend-architecture.html">后端与数据架构</a> <span class="desc">— API、WS 流式协议、时长账本计费、Redis/PG 设计(v1.1</span></li>
</ul>
</section>
<section class="card">
<h2>实现计划</h2>
<ul>
<li><a href="plan/design.html">MVP 实现计划(阅读版)</a> <span class="desc">— 全端任务拆解与依赖关系</span></li>
</ul>
</section>
<section class="card">
<h2>知识库调研 / 验收报告</h2>
<ul>
<li><a href="latency-acceptance-12b.html">12B 延迟验收结论(暂定)</a> <span class="desc">— 2026-07-10 · 全链路延迟分解、#23/#24 修复、暂定新目标与 paraformer 待决策</span></li>
</ul>
</section>
<footer>dudu · 文档索引 · 新增文档须同时登记到本页</footer>
</div>
</body>
</html>
+181
View File
@@ -0,0 +1,181 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dudu 12B 延迟验收结论(暂定)</title>
<style>
:root {
--accent: #4F6EF7;
--accent-text: #3D58DB;
--accent-soft: #EEF1FE;
--bg: #F6F7FA;
--card: #FFFFFF;
--text-1: #1B1E26;
--text-2: #5A6072;
--text-3: #A6ABB8;
--border-1: #E4E6EB;
--positive: #16A34A;
--warning: #E8890C;
--danger: #DC2626;
--code-bg: #1B1E26;
--code-text: #D6DCEA;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
background: var(--bg); color: var(--text-1); line-height: 1.75;
}
.container { max-width: 980px; margin: 0 auto; padding: 0 24px 80px; }
header.hero { background: var(--accent); color: #fff; padding: 48px 24px 40px; text-align: center; }
header.hero h1 { margin: 0 0 6px; font-size: 30px; }
header.hero p { margin: 0; opacity: .85; font-size: 15px; }
.chips { margin-top: 16px; }
.chip { display: inline-block; padding: 3px 14px; margin: 3px; background: rgba(255,255,255,.16); border-radius: 999px; font-size: 13px; }
section.card {
background: var(--card); border: 1px solid var(--border-1); border-radius: 14px;
padding: 28px 32px; margin-top: 24px; box-shadow: 0 1px 3px rgba(17,19,26,.05);
}
h2 { font-size: 21px; margin: 0 0 14px; padding-bottom: 8px; border-bottom: 2px solid var(--accent); display: inline-block; }
h3 { font-size: 16px; margin: 22px 0 8px; color: var(--accent-text); }
table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13.5px; }
th, td { border: 1px solid var(--border-1); padding: 7px 11px; text-align: left; vertical-align: top; }
th { background: #F0F1F4; font-weight: 600; }
tr:nth-child(even) td { background: #FCFCFD; }
pre.code, pre.diagram {
background: var(--code-bg); color: var(--code-text); padding: 16px 18px; border-radius: 10px;
overflow-x: auto; font-family: "SF Mono", Menlo, Consolas, monospace; font-size: 12.5px; line-height: 1.55;
}
code.inline { background: var(--accent-soft); color: var(--accent-text); padding: 1px 6px; border-radius: 4px; font-family: "SF Mono", Menlo, monospace; font-size: 12.5px; }
.callout { border-left: 4px solid var(--accent); background: var(--accent-soft); padding: 11px 16px; border-radius: 0 8px 8px 0; margin: 12px 0; font-size: 13.5px; }
.callout.warn { border-color: var(--warning); background: #FCEFD7; }
.tag { display: inline-block; font-size: 12px; padding: 1px 10px; border-radius: 999px; margin-right: 6px; font-weight: 600; }
.tag.green { background: #DCFCE7; color: var(--positive); }
.tag.orange { background: #FCEFD7; color: var(--warning); }
.tag.red { background: #FEE2E2; color: var(--danger); }
.tag.blue { background: var(--accent-soft); color: var(--accent-text); }
ul, ol { padding-left: 22px; }
li { margin: 3px 0; }
footer { text-align: center; color: var(--text-3); font-size: 13px; margin-top: 44px; }
</style>
</head>
<body>
<header class="hero">
<h1>12B 延迟验收结论(暂定)</h1>
<p>网关全链路实测 · 延迟分解 · 修复与调优 · 暂定新目标</p>
<div class="chips">
<span class="chip">2026-07-10</span>
<span class="chip">工具:server/cmd/latencyprobe</span>
<span class="chip">分支:feat/12b-latency-probe</span>
<span class="chip">providergummy-realtime-v1(真实)</span>
</div>
</header>
<div class="container">
<section class="card">
<h2>一、暂定结论(TL;DR</h2>
<table>
<tr><th>指标</th><th>原目标 P95</th><th>实测(预连接后)</th><th>暂定新目标</th></tr>
<tr>
<td><code class="inline">first_partial</code>(按键→首字)</td>
<td>&lt;500ms</td>
<td><span class="tag green">P50 942ms · P95 950ms</span>(极稳定)</td>
<td><strong>P95 &lt; 1.2s</strong></td>
</tr>
<tr>
<td><code class="inline">release_to_commit</code>(松键→上屏)</td>
<td>&lt;300ms</td>
<td>短句 ~170ms · 8s 会话 350~500ms</td>
<td><strong>≤3s 会话 &lt;300ms;长会话 &lt;600ms</strong></td>
</tr>
</table>
<div class="callout">
<strong>为什么 500ms 结构性不可达:</strong>first_partial = max(握手, DashScope 音频块阈值 ~850ms) + 推理 ~90ms。
地板是 DashScope 的<strong>音频块阈值</strong>,与网关代码无关(直连同样 ~1s)。要破地板只能换模型(见第四节)。
</div>
<div class="callout">
<strong>体感修正:</strong>前导静音实验证明阈值按「音频量」而非「语音量」计——400ms 静音只使 first_partial 推迟 ~100ms。
用户按键后自然停顿 ~300ms 再开口时,<strong>从开口算的首字延迟仅 ~640ms</strong>,体感优于指标数字。
</div>
</section>
<section class="card">
<h2>二、延迟分解(实测)</h2>
<table>
<tr><th>环节</th><th>耗时</th><th>处置</th></tr>
<tr><td>网关预检(限流 / 配额 / 设备槽)</td><td>~10ms</td><td>无需优化</td></tr>
<tr><td>DashScope dial + task-started 握手</td><td>暖 ~130ms · <span class="tag red">抖动 60ms~3.7s</span></td><td><span class="tag green">已消除</span> spare 预连接(#24</td></tr>
<tr><td>DashScope 音频块阈值</td><td><strong>~850ms(地板)</strong></td><td><span class="tag orange">换模型才能降</span>paraformer ~520ms</td></tr>
<tr><td>推理 + 回传</td><td>~90ms</td><td>无手段</td></tr>
<tr><td>final flush(松键后)</td><td>短句 ~170ms · 8s 会话 350~540ms</td><td>随内容量增长,属 provider 物理时间</td></tr>
</table>
<h3>测量口径(对齐桌面端 dictation.rs</h3>
<ul>
<li><code class="inline">first_partial</code>start 帧发出 → 首个 partial(不含麦克风启动,桌面另有 <code class="inline">audio.start_ms</code></li>
<li><code class="inline">release_to_commit</code>stop 帧发出 → 尾部 final(不含注入耗时 &lt;10ms</li>
<li>工具:<code class="inline">go run ./cmd/latencyprobe -wav xx.wav -n 12</code>(单持久连接 + 100ms/帧实时推流,复刻桌面行为)</li>
</ul>
</section>
<section class="card">
<h2>三、本轮落地的修复与优化</h2>
<h3>#23 stop 后周期 usage 帧抢跑尾部 final(已修,服务端根治)</h3>
<ul>
<li><strong>症状:</strong>8s 会话 4/4 复现 usage 先于尾部 final 到达,客户端以 partial 文本提前上屏、丢失 final 修正(iOS 21A 修过客户端侧,桌面端仍暴露)</li>
<li><strong>根因:</strong>finish 等尾部 final 期间(最长 3susageLoop 仍在 tick</li>
<li><strong>修复:</strong>finish 先冻结会话并停 usageLoop 再 flush——stop 后唯一的 usage 是结算帧且必在全部 final 之后,<strong>五端客户端「final 或 usage 即提交」逻辑自动变安全</strong>,无协议改动。修复后 6/6 归零</li>
<li>桌面端收尾兜底 350ms → 800msfinal flush 实测 350~540ms350ms 会截丢尾 final</li>
</ul>
<h3>#24 gummy spare 预连接(已实现)</h3>
<ul>
<li>常备一条已完成 run-task 握手的 DashScope 会话,start 直取、异步补位、40s 定期换新</li>
<li>依据:DashScope 空闲 <strong>60s 存活、120s 报 Idle timeout</strong>(实测),留余量 45s</li>
<li>效果:网关 start 处理 <strong>120~670ms → 3~4ms</strong>dial 抖动(60ms~3.7s)移出关键路径,否则 P95 可达 1.5~4.5s</li>
</ul>
<h3>顺手修复</h3>
<ul>
<li>滑动窗口 Lua「只查不记」与实现不符:val=0 的检查不再写入 0 值成员污染窗口 ZSET</li>
<li>gummycheck 增加 <code class="inline">-model / -pace / -idle</code> 参数,支持模型对比与闲置存活实验</li>
</ul>
</section>
<section class="card">
<h2>四、待决策:要不要换 paraformer</h2>
<table>
<tr><th></th><th>gummy-realtime-v1(现用)</th><th>paraformer-realtime-v2</th></tr>
<tr><td>音频块阈值(首字地板)</td><td>~850ms</td><td><span class="tag green">~520ms</span></td></tr>
<tr><td>partial 刷新节奏</td><td>~1s / 次</td><td><span class="tag green">~500ms / 次(更跟手)</span></td></tr>
<tr><td>识别质量(单样本 TTS 实测)</td><td><span class="tag green">全对</span></td><td><span class="tag red">「各自模块的进度汇报」→「各字文案者进入汇报」</span></td></tr>
<tr><td>partial 时间戳(计量交叉校验用)</td><td>每条带 end_time</td><td>仅 final 带</td></tr>
</table>
<div class="callout warn">
<strong>决策前置条件:</strong>用 eval 框架(<code class="inline">eval/</code>)跑真实数据集对比两模型 WER,再决定是否为 ~300ms 首字收益换质量。
切换成本低:<code class="inline">GummyProvider.Model</code> 一行配置。
</div>
</section>
<section class="card">
<h2>五、复测方法</h2>
<pre class="code"># 起服务端(pg/redis 容器已在跑)
cd server && ./run-dev.sh
# 全链路延迟实测(另开终端)
go run ./cmd/latencyprobe -wav /path/to/16k-mono.wav -n 12
# 直连模型对比 / 闲置存活实验
rbw get dashscope-api-key | go run ./cmd/gummycheck -wav xx.wav -pace 100 -model paraformer-realtime-v2
rbw get dashscope-api-key | go run ./cmd/gummycheck -wav xx.wav -pace 100 -idle 60</pre>
<ul>
<li>注意设备 30 分钟滑动窗口上限 30 次会话,probe 换 <code class="inline">-device</code> 规避</li>
<li>观测日志:<code class="inline">gummy: session ready</code>dial/task-started 耗时)、<code class="inline">gummy: session from spare</code><code class="inline">gateway: start handled</code></li>
</ul>
</section>
<footer>dudu · 12B 延迟验收(暂定结论)· 2026-07-10 · 数据与工具见 feat/12b-latency-probe</footer>
</div>
</body>
</html>