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 上。

相关推荐
阿里云大数据AI技术2 分钟前
Agent时代“Token炼金术”,阿里云 PAI 推出 TokenWorks:重塑企业专属的高保障SLO推理服务
人工智能·agent
饼饼学习空间智能8 分钟前
2026数字孪生选型避坑指南:如何避免项目沦为3D大屏展示
人工智能·深度学习
SEONIB_Explorer28 分钟前
新手冷启动:如何用 SEONIB + VEONIB 搞定独立站图文与短视频基础产能
人工智能·shopify·seonib·veonib·低成本测试·钩子生成·冷启动 30 天执行计划表
Inhand陈工31 分钟前
数据中心UPS无功补偿与智能化监控方案:基于IG502的Modbus RTU转IEC61850实战
运维·人工智能·物联网·信息与通信
Saniffer_SH39 分钟前
NAND技术(二):从 Channel、Die/LUN、P/E Cycle 到 LDPC,一次讲透 NAND 里那些最容易误解的概念
人工智能·驱动开发·嵌入式硬件·测试工具·fpga开发·计算机外设·压力测试
ChainSafeAI0031 小时前
以太坊利用AI挖掘漏洞成功发现安全缺陷,称人工审核仍不可替代
人工智能·安全
观测云1 小时前
观测云正式发布企业级可观测智能体 AI Agent Teams
人工智能
逐米时代1 小时前
制造企业智能体趋势从单点应用走向协同智能
人工智能
Mark White1 小时前
具身智能论文伴读-第一期
人工智能·深度学习·语言模型
stonewl25991 小时前
2026化工行业 GHS/CLP 国产标签打印软件合规打印方案
大数据·人工智能·物联网