Next.js接大模型流式SSE实操踩坑

先把结论甩出来:Next.js App Router 里做大模型流式输出,服务端用 Route Handler 直接返回一个 ReadableStream,把模型 SSE 透传给浏览器;前端别急着上 EventSource(它只支持 GET,传不了 body),用 fetch + response.body.getReader() 自己读流就行。整套打通其实就两个文件的事,难点都在那些没人提的细节里。

事情起因是上周我给自己那个内部小工具加了个对话框。之前一次性等模型把几百字吐完再渲染,白屏五六秒,我自己都嫌卡。改成流式,逐字蹦出来,体感立刻不一样了。

服务端:route handler 把流透传出去

app/api/chat/route.ts 长这样:

javascript 复制代码
export const runtime = 'edge' // node 也行,edge 冷启动快点

export async function POST(req: Request) {
  const { messages } = await req.json()

  const upstream = await fetch('https://你的模型网关/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.LLM_KEY}`,
    },
    body: JSON.stringify({ model: 'xxx', messages, stream: true }),
  })

  // 直接把上游的 SSE 流当成自己的响应体往下游灌
  return new Response(upstream.body, {
    headers: {
      'Content-Type': 'text/event-stream; charset=utf-8',
      'Cache-Control': 'no-cache, no-transform',
      Connection: 'keep-alive',
    },
  })
}

注意 no-transform 那一行,别省。我一开始没写,本地好好的,一上 Nginx 反代就变成等全部生成完才一次性返回------代理把流给缓冲了,排查了快一个钟头才反应过来是这破玩意儿。

如果上游格式跟你前端想要的对不上,就别裸透传,用 TransformStream 中间拆一道 data: 行再重新拼,逻辑也就十几行,这里不展开了。

前端:fetch 读流,逐字渲染

javascript 复制代码
const res = await fetch('/api/chat', {
  method: 'POST',
  body: JSON.stringify({ messages }),
})

const reader = res.body!.getReader()
const decoder = new TextDecoder()
let buf = ''

while (true) {
  const { done, value } = await reader.read()
  if (done) break
  buf += decoder.decode(value, { stream: true })

  // SSE 一条条 \n\n 切,注意半截 chunk 要留着下一轮拼
  const lines = buf.split('\n\n')
  buf = lines.pop() ?? ''
  for (const line of lines) {
    if (!line.startsWith('data:')) continue
    const data = line.slice(5).trim()
    if (data === '[DONE]') return
    const delta = JSON.parse(data).choices[0].delta.content ?? ''
    setText((t) => t + delta) // 蹦字
  }
}

那个 buf.pop() 留半截的细节是真容易翻车------一个 chunk 不保证正好切在 \n\n 上,UTF-8 中文还可能被切两半,TextDecoder{ stream: true } 帮你兜住后半个问题,前半个得自己用 buffer 接。

一点题外的取舍

代码不长,但调通那天我顺手干了件偷懒的事。模型这块我没自己折腾,挂了个零代码就能配智能体的平台------拖一拖把提示词、知识库配好,发布成一个 API,我前端这边只管 fetch 那个地址。说实话第一版我让那小助手当客服答疑,回答干巴巴像背说明书,回去把知识库文档喂细了点、温度调低,第二版才像样。它也就帮我省了搭后端和调模型的活,前端流式这套该写还得写,逐字渲染的边界问题它一个都不替你扛。

学习曲线倒不算陡,但配 RAG 那块文档分块策略我摸了大半天才找到手感,不是点两下就完美。

模型/API 我走的讯飞 MaaS,现成调,没自己部署算力,省了一台 GPU 机器钱。

你们接流式踩过哪些代理缓冲、中文截断的坑?评论区聊聊,我赌一半人栽在 no-transform 上。

相关推荐
Shockang12 分钟前
AI 编码智能体生产化工程
人工智能
jay神2 小时前
深度学习确定baseline之后怎么做改进?
人工智能·深度学习·yolo·计算机视觉·分类
acrel72 小时前
安科瑞Acrel-1000变电站综合自动化系统在合肥某新材料公司35kV综合自动化项目中的应用分析
大数据·人工智能
UWA2 小时前
隐藏视频变“常驻刺客”,VideoPlayer与“N/A”纹理该怎么查
人工智能·性能优化·音视频·memory·cpu·游戏开发
V哥AI增长2 小时前
小红书笔记在生成式AI引擎中的可见性机制解析:从抓取原理到GEO工程化实践
大数据·人工智能·笔记
ajassi20002 小时前
AI语音智能体开发日记(十二)GX8006 固件定制指南——从双唤醒词到 UART 音频传输
人工智能·ai·ai编程
大模型momo2 小时前
告别单体 Agent:多智能体设计模式(Multi-Agent Patterns)深度实战手册
人工智能·agent·multi-agent·多agent
DisonTangor2 小时前
【SeeDream开源平替】MiniMax H3 重磅开源:全模态视频生成新标杆,2K 画质 + 原生立体声,15 秒大片一键生成!
人工智能·ai作画·开源·aigc·音视频
很楠爱上3 小时前
(附上相关学习资源)适合新手做的第一个agent项目*ovo*Dify Agent 全栈实战:从智能选车顾问到新能源汽车之家的端到端开发
人工智能·汽车·agent·项目·开发笔记
IT智慧客07313 小时前
2026年7月前端面试高频考点与趋势分析(面20个前端后的总结)
人工智能