在上一章中我们成功搭建了 Next.js Prisma HeroUI 的项目骨架。但此时的项目只是一个空壳缺乏与 AI 交互的灵魂。本章的目标是实现最基础的 AI 对话功能。我们将打通前后端实现流式响应Streaming、Markdown 渲染以及代码高亮让你的应用真正具备“ChatGPT 级别”的交互体验。1. 为什么需要 Streaming流式响应在开始写代码之前我们必须理解一个核心概念为什么 AI 聊天必须是流式的传统请求的痛点在普通的 Web 请求中用户发送消息后需要等待服务端生成完整的回复再一次性返回给前端。对于 LLM 来说生成一段长文本可能需要 5-10 秒。在这期间用户只能面对一个旋转的 Loading 图标体验极其割裂。Streaming 的优势大模型本质上是“逐字Token生成”的。Streaming 技术利用了 Server-Sent Events (SSE) 协议将大模型生成的每一个 Token 实时推送到前端。用户能像看“打字机”一样看到文字逐字出现。这不仅极大地缓解了用户的等待焦虑还让交互感觉更加自然和智能。2. 核心架构与数据流转在 Next.js App Router 中实现 AI Chat我们需要遵循前后端分离的流式架构关键组件解析streamText (AI SDK)核心函数负责与 LLM 通信并将复杂的流式协议转换为标准的 Web 响应。useChat (AI SDK React Hook)前端魔法自动管理消息列表、输入框状态、加载状态并无缝对接后端的 SSE 流。3. 代码实现后端 API Route首先我们在src/app/api/chat/route.ts中创建对话接口。// src/app/api/chat/route.tsimport{streamText}fromai;import{openai}from/lib/ai/config;// 引入上一章配置的 AI SDK 实例// 允许流式响应最长持续 30 秒Vercel 等 Serverless 环境需要exportconstmaxDuration30;exportasyncfunctionPOST(req:Request){const{messages}awaitreq.json();constresultstreamText({model:openai(gpt-4o),// 或 deepseek-chatsystem:你是一个专业的 AI 助手回答请尽量简洁、准确支持 Markdown 格式。,messages,});// 将 AI SDK 的结果转换为标准的流式 HTTP 响应returnresult.toDataStreamResponse();}设计思考为什么不直接返回 JSON因为toDataStreamResponse()内部封装了 Vercel AI SDK 自定义的 Data Stream 协议它不仅传输文本还能传输工具调用状态、错误信息等结构化数据为后续实现 Tool Calling 打下基础。4. 代码实现前端 UI 与 Markdown 渲染4.1 消息气泡组件AI 的回复通常包含代码块和列表我们需要react-markdown配合remark-gfm来渲染。为了美观我们引入react-syntax-highlighter进行代码高亮。npm install react-syntax-highlightertypes/react-syntax-highlighter// src/components/chat/MessageBubble.tsximportReactMarkdownfromreact-markdown;importremarkGfmfromremark-gfm;import{PrismasSyntaxHighlighter}fromreact-syntax-highlighter;import{oneDark}fromreact-syntax-highlighter/dist/esm/styles/prism;exportfunctionMessageBubble({role,content}:{role:string;content:string}){constisUserroleuser;return(div className{flex${isUser?justify-end:justify-start}mb-4}div className{max-w-[80%] p-3 rounded-lg${isUser?bg-blue-500 text-white:bg-gray-100 text-gray-800}}{isUser?(p{content}/p):(ReactMarkdown remarkPlugins{[remarkGfm]}components{{code({node,inline,className,children,...props}){constmatch/language-(\w)/.exec(className||);return!inlinematch?(SyntaxHighlighter style{oneDark}language{match}PreTagdiv{...props}{String(children).replace(/\n$/,)}/SyntaxHighlighter):(code className{className}{...props}{children}/code);}}}{content}/ReactMarkdown)}/div/div);}websourcesource_group_web_1/websource ### 4.2 聊天主页面 使用useChatHook 接管所有状态tsx// src/app/page.tsxuse client;import{useChat}fromai/react;import{MessageBubble}from/components/chat/MessageBubble;import{Input,Button}fromheroui/react;exportdefaultfunctionChatPage(){const{messages,input,handleInputChange,handleSubmit,isLoading}useChat({api:/api/chat,});return(div classNameflex flex-col h-screen max-w-3xl mx-auto p-4h1 classNametext-2xl font-bold mb-4AIAgent Enterprise/h1{/* 消息列表区 */}div classNameflex-1 overflow-y-auto space-y-2 mb-4{messages.map((m)(MessageBubble key{m.id}role{m.role}content{m.content}/))}{isLoadingdiv classNametext-gray-400AI正在思考.../div}/div{/* 输入区 */}form onSubmit{handleSubmit}classNameflex gap-2Input value{input}onChange{handleInputChange}placeholder输入你的问题...classNameflex-1/Button typesubmitcolorprimaryisLoading{isLoading}发送/Button/form/div);}5. 测试验证启动项目 npm run dev打开浏览器。验证清单输入一段包含代码的请求例如“用 Python 写一个快速排序”。观察文字是否像打字机一样逐字流出Streaming 验证。观察代码块是否有语法高亮且排版整齐Markdown 验证。在 AI 回复过程中点击发送按钮检查是否被正确禁用Loading 状态验证。6. 常见问题与踩坑分析问题 1Next.js 报错 Dynamic server usage原因useChat 是一个依赖浏览器 window 和 fetch 的 Hook不能在 Server Component 中使用。解决确保包含 useChat 的页面或组件顶部有 “use client”; 指令。问题 2流式响应中断或报错 maxDuration exceeded原因Serverless 环境如 Vercel Hobby 计划默认限制函数执行时间为 10 秒。解决在 API Route 中显式声明export const maxDuration 30;并确保你的 AI 提供商套餐支持长连接。问题 3代码高亮样式丢原因react-syntax-highlighter的样式在 SSR 时可能无法正确注入。解决确保在 Client Component 中引入样式或者改用 shikiNext.js 官方推荐的高亮库对 SSR 更友好。本章总结我们理解了 Streaming 对于 AI 应用体验的决定性作用。实现了基于 Vercel AI SDK 的 streamText 后端流式接口。利用 useChat Hook 在前端实现了零样板代码的状态管理。集成了 react-markdown 与 react-syntax-highlighter实现了生产级的富文本渲染。至此你的项目已经具备了与 ChatGPT 媲美基础对话能力。但这仅仅是开始。目前的 AI 还是一个“只会说不会做”的大脑。从下一章开始我们将赋予它“手脚”——实现 Tool Calling工具调用让它能够真正执行任务。