AI 助手首字延迟优化
AI 助手场景下首字延迟(TTFT)的全链路排查与优化,覆盖前端到模型的 12 个关键节点。
#tech / ai
#type / howto
#status / growing
[!info] related notes
- 相关概念: AI 对话前端性能优化, AI 对话与流式界面, SSE
- 相关 MOC: 前端工程化 MOC
AI 助手首字延迟优化
目标
在不更换底层大模型的前提下,定位和优化 AI 助手每次提问后首字响应延迟(TTFT, Time To First Token)。
前置条件
- 有全链路可观测性(至少能在关键节点打点)
- 能区分网络延迟和服务端处理延迟
步骤
1. 全链路节点拆解
首字延迟 = 以下 12 个节点的总和:
- 前端点击到请求发出(事件处理、状态更新)
- DNS 解析
- TCP 连接 / TLS 握手
- 网关 / 鉴权 / 限流
- 后端参数校验
- 上下文组装(历史消息、system prompt)
- RAG 检索(向量搜索、文档召回)
- Tool Calling 前置判断
- 模型 API 请求排队
- 模型 TTFT(从请求到第一个 token)
- SSE flush / 代理层缓冲
- 前端渲染第一个 token
2. 每个节点打点
const timestamps = {
request_created_at: Date.now(),
dns_resolved_at: null,
tcp_connected_at: null,
gateway_processed_at: null,
param_validated_at: null,
context_assembled_at: null,
rag_completed_at: null,
llm_request_sent_at: null,
first_token_received_at: null,
sse_flushed_at: null,
frontend_rendered_at: null,
};
3. 定位瓶颈
- 控制台 Network 面板查看 TTFB(Time To First Byte)
- 后端日志记录每个阶段耗时
- 如果网络延迟占比大 → 优化 DNS/TLS/CDN
- 如果服务端处理占比大 → 优化上下文组装、RAG 并行化
- 如果模型 TTFT 占比大 → prompt 压缩、减少 context 长度
4. 常见优化手段
| 节点 | 优化方式 |
|---|---|
| DNS/TCP/TLS | 连接复用、HTTP/2、预连接 |
| 网关 | 减少中间件、异步鉴权 |
| 上下文组装 | 历史消息裁剪、system prompt 压缩 |
| RAG 检索 | 并行化、缓存高频查询、top-k 减少 |
| 模型排队 | 多实例负载均衡、优先级队列 |
| 模型 TTFT | prompt 压缩、减少 max_tokens、流式输出 |
| SSE flush | 关闭 nginx buffering(proxy_buffering off) |
| 代理层 | res.flushHeaders()、避免中间件阻塞 |
| 前端渲染 | 先发 thinking 占位事件、减少首 token 的 DOM 操作 |
5. 关键配置
nginx SSE 配置:
location /api/chat {
proxy_buffering off;
proxy_cache off;
proxy_set_header Connection '';
chunked_transfer_encoding off;
}
Node.js 流式响应:
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});
res.flushHeaders(); // 立即发送 headers,不等第一个 chunk
验证
- 对比优化前后的 TTFT(用浏览器 Performance 面板或后端日志)
- 确认每个节点的耗时分布
- 监控线上 P50/P95/P99 延迟
常见问题
- Q: 为什么本地很快但线上很慢?
A: 通常是 nginx 代理缓冲或 TLS 握手导致,检查
proxy_buffering和连接复用配置。 - Q: RAG 检索很慢怎么办? A: 并行化多个检索源、缓存高频查询结果、减少召回数量。