尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WaLiOffice 前端对话界面与流式渲染实战:Fetch + ReadableStream 实现 SSE 打字机效果

WaLiOffice 前端对话界面与流式渲染实战:Fetch + ReadableStream 实现 SSE 打字机效果 文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载导读本文以 WaLiOffice —— 小傅哥开源的 Rust React 全栈 AI Agent 智能办公平台为背景深入讲解其前端核心页面 Studio.tsx 中对话 流式渲染的实现方案。通过本文你将掌握前端如何用 Fetch body.getReader()实时读取 SSE 流、如何用EventSourceParser解析 SSE 事件、如何设计handleSend发送流程与事件路由以及如何实现消息打字机渲染、产物面板预览和附件上传三大实战能力。一、为什么前端要区分普通 API和SSE 流式 API在 WaLiOffice 的 第2-7节后端Chat路由与SSE端点 中我们完成了后端的/api/chat/stream流式对话端点Agent 执行是异步多阶段的——思考 → 调工具 → 出结果 → 再思考 → 再调工具每一步都通过 SSE 实时推给前端。用户看到的是前端界面前端就是用户与后端 Agent 之间的桥梁这一节第2-8节要解决的正是这座桥梁的搭建。普通 REST API 是一问一答发请求 → 服务器处理 → 等几秒 → 返回结果 → 结束。而 SSE 流式响应是边想边说发请求后服务器每生成一个 token 就推送一次前端在界面上实时看到 AI 打字。这对前端提出了四项完全不同的要求不能等请求完成必须实时读取响应流不能使用普通axios/fetch的等结果模式流式渲染每个 token 到达后立即追加到消息中实现打字机效果状态管理复杂消息存在正在生成中和已完成两种状态UI 要随状态变化事件分发不同类型的 SSE 事件Thinking、ToolCall、Artifact、Done 等要分发给不同的 UI 组件。WaLiOffice 的前端代码量很大——主界面Studio.tsx达 1565 行。本节重点聚焦其中最核心的三个部分chatApi.streamSSE 客户端——前端如何接收流式响应handleSend发送流程——消息如何发出、状态如何管理ChatPanel流式渲染——打字机效果如何实现。二、前端 SSE 流接收架构与事件分发WaLiOffice 前端接收 SSE 的整体流程如下对应 第2-8节前端对话界面与流式渲染 的 2.1 节用户点击发送或按回车 ↓ handleSend() 构建请求 ↓ fetch(/api/chat/stream, { body: JSON.stringify(req) }) ↓ response.body.getReader().read() 循环读取字节流 ↓ TextDecoder 解码字节 → 字符串 ↓ SSE 事件解析data: event: 行解析 ↓ onEvent(event, data) 事件分发 ↓ ├─ message → 流式追加文本到消息列表打字机效果 ├─ project_update → 初始化 PPT 项目 幻灯片大纲 ├─ slide_update → 逐页更新幻灯片内容 ├─ state_update → 更新状态栏 processLogs ├─ tool_result → processLogs 显示工具结果 ├─ artifact_update → upsertArtifact → 右侧产物面板 ├─ done → 流结束 音效 刷新会话列表 └─ error → 错误提示从流程可以看到前端 SSE 接收的核心链路是发送请求 → 循环读流 → 解码 → 解析事件 → 分发。其中解码和解析是两层独立的处理字节 → 字符串用TextDecoder把getReader().read()读出的Uint8Array字节流解码为字符串。SSE 流按块chunk到达一个事件可能被切分到多个 chunk 中也可能多个事件挤在一个 chunk 里因此解码后还需要做缓冲累积把不完整的行留到下一个 chunk 再拼接。字符串 → 事件SSE 格式约定每个事件由event:行事件类型和data:行事件数据构成用EventSourceParser完成这一解析最终以onEvent(event, data)回调的形式把类型数据二元组交给上层分发。三、chatApi.streamSSE 客户端实现要点前端在frontend/src/api/目录下封装 HTTP 客户端对应 第2-1节工程初始化与项目结构 的目录结构说明其中chatApi.stream就是对话流的 SSE 客户端。它和普通接口的最大区别在于不能等fetchPromise 整体 resolve而是拿到response.body后立刻进入读循环。从文档描述可以还原出它的典型实现骨架关键逻辑const response await fetch(/api/chat/stream, { method: POST, headers: { Content-Type: application/json, /* Authorization: Bearer ... */ }, body: JSON.stringify(req), }); const reader response.body!.getReader(); const decoder new TextDecoder(); let buffer ; while (true) { const { done, value } await reader.read(); if (done) break; buffer decoder.decode(value, { stream: true }); // 按行切分 EventSourceParser 解析 event:/data: 行 // onEvent(event, data) 分发给 handleSend 中的事件处理逻辑 }需要特别留意的工程细节decoder.decode(value, { stream: true })stream: true告诉 TextDecoder 当前是流式输入多字节 UTF-8 字符若被切到两个 chunk 边界会暂存在解码器内部等待下一块补齐避免乱码行缓冲读到的字符串按\n切行末尾不完整的行保留到 buffer下次循环拼接后再处理事件路由解析出的event字段与后端推送的事件类型一一对应进入下面的handleSend分发逻辑。WaLiOffice 后端通过mpscchannel 推送 7 种 AgentEventThinking/ToolCall/ToolResult/Artifact/Message/TurnEnd/Done前端接收端则按 第2-8节 的流程处理 message/project_update/slide_update/state_update/tool_result/artifact_update/done/error 等事件——这组事件协议是整个前后端流式协作的契约可对照 第2-2节LLM客户端与流式SSE实现 中StreamEvent枚举Delta / ToolCallDelta / Done理解其来源。四、handleSend发送流程与状态管理handleSend是前端对话的主控函数承担消息构建 → 状态管理 → 事件路由三个职责消息构建把用户输入可能附带附件组装为ChatRequest追加一条用户消息到消息列表并立即创建一条空的助手消息占位——这条消息的状态是正在生成中后续所有message事件都流式追加到它上面状态管理WaLiOffice 前端使用 Zustand 轻量状态管理对应 walioffice.md 的技术栈说明消息流、会话列表、产物列表都放在全局 store 中。发送中要把正在发送标志置位、禁用发送按钮收到done事件后再复位事件路由把onEvent(event, data)分发的不同类型事件交给不同处理函数事件处理动作落点message流式追加文本到当前助手消息对话区打字机效果project_update初始化 PPT 项目 幻灯片大纲产物面板 / 幻灯片预览slide_update逐页更新幻灯片内容产物面板state_update更新状态栏 processLogs状态栏 / 执行日志tool_result在 processLogs 中显示工具执行结果执行日志artifact_updateupsertArtifact更新或插入产物右侧产物面板done流结束 播放音效 刷新会话列表全局error错误提示全局其中artifact_update走upsertArtifact有则更新、无则插入保证同一份产物如 PPT在多页推送时只维护一个条目而不是重复创建——这是产物面板渐进式刷新的关键。state_update与tool_result都汇入processLogs让用户看到Agent 正在调用 XX 工具 → 工具返回结果的完整执行过程。五、ChatPanel打字机式流式渲染ChatPanel负责消息列表的渲染。打字机效果的本质是消息数据本身是不断增长的字符串UI 只需把最新值渲染出来。从 WaLiOffice 前端的实现思路可以归纳出两个要点增量追加不整体替换每个message事件到达时把新文本append到 store 中对应助手消息的content字段上。React 只 diff 变化的部分视觉上就是文本逐字/逐块出现状态驱动样式消息状态是正在生成中时显示光标闪烁等输入中样式收到done后标记为已完成样式切回静态文本。文档明确指出消息有这两种状态UI 需要相应变化。这里有一个容易被忽视的点由于 SSE 每个 chunk 可能包含多段文本前端应按事件粒度而非字节粒度触发 React 更新。若每个字节都 setState 一次会造成大量重复渲染按事件批量追加则既能保持流畅又不会丢失边生成边显示的体验。六、ArtifactPanel产物预览机制右侧的ArtifactPanel与对话区并行负责展示 Agent 生成的各种产物。WaLiOffice 的产物类型覆盖 PPT / Word / Excel / Draw.io 图表 / ECharts 图表 / 图片 / 视频对应三栏式 Studio 工作台会话列表 / 对话区 / 产物预览中的产物栏详见 walioffice.md。产物渲染遵循类型分派策略每个产物条目都带有类型标记ArtifactPanel根据类型选择对应渲染器PPT 产物 → 幻灯片预览配合project_update/slide_update逐页刷新Markdown / Word → Markdown 文档预览前端渲染表格 → 表格渲染图表 → ECharts 图表图片 / 视频 → 媒体播放组件。配合 第3部分工具集成 等章节可以看到工具端通过 SSE 推送artifact_update前端upsertArtifact后产物面板实时更新同时产物自动导出机制根据 artifact 类型触发 DOCX/XLSX/MD 下载并同步保存到用户文件列表打通了生成 → 预览 → 保存的完整链路。七、附件上传图片压缩 文件解析 OCR 文本提取对话界面还支持附件上传核心诉求是把用户的图片/文件变成 Agent 能理解的输入。WaLiOffice 前端的附件处理包含三个环节图片压缩上传前先压缩目标是最大宽度 1600px、1.8MB 以内的文件——既降低网络传输成本也满足图片理解类 LLM 接口的输入限制该目标参数在 walioffice.md 中明确说明文件解析Office 文档Word/Excel/PPT调用后端extractAPI 提取文本内容后端对应server/src/file_extract.rs附件解析模块支持 PDF/Office/CSV/JSONOCR 文本提取图片内容通过后端image_ocr.rs的 OCR 识别转成文本与图片一并作为多模态输入送给 LLM对应 第2-1节 的模块划分以及后端chat_stream流程中第⑤步save_chat_attachments_to_files的附件落盘处理。附件与文本消息一起组装进请求体后端在 第2-7节 的 Chat 路由中完成附件存储、意图识别含has_image判断后进入 Agent 循环。八、与后端事件协议的呼应本节第2-8节的前端实现与第2-7节的后端 SSE 端点是一体两面的后端以SseReceiverStream返回事件经 tokio 异步任务从AgentEvent转为 SSE Event前端以fetchgetReader消费同一流经EventSourceParser还原为onEvent(event, data)两端通过同一套事件名message、artifact_update、state_update、tool_result、done、project_update、slide_update、error完成语义对齐——这正是 walioffice.md 中通过 SSE 推送 7 种事件前端按 6 种事件解析渲染所描述的协作模式。前端项目结构上frontend/src/下按apiAxios/SSE 客户端、componentsChatPanel/SlidePreview/ArtifactPanel 等、pagesStudio.tsx 主界面、storesZustand 状态管理、types、config、lib、styles分层组织配合 Radix UI 无头组件与 lucide-react 图标体系构成了这套流式对话界面的完整工程底座详见 第2-1节工程初始化与项目结构。九、小结本节围绕 WaLiOffice 前端对话界面讲透了三个核心问题SSE 客户端怎么收fetchbody.getReader()循环读流TextDecoder解码EventSourceParser解析event:/data:行这是与普通 REST 请求最本质的差异发送流程怎么管handleSend完成消息构建、状态管理正在生成/已完成、事件路由8 类事件分发给不同 UI 组件界面怎么渲染ChatPanel增量追加实现打字机效果ArtifactPanel按产物类型分派渲染器附件上传通过图片压缩 文件解析 OCR 把用户输入变成 Agent 可理解的上下文。整套方案的价值在于前后端通过一套流式事件协议解耦——后端只负责把 Agent 的执行过程实时推出来前端只负责把这些事件变成用户能感知的实时打字、实时出产物、实时看工具进度。这套模式可以直接迁移到任何需要长任务实时反馈的 AI 应用智能客服、文档生成、图表创作中复用。相关章节延伸阅读第2-7节后端Chat路由与SSE端点 | 第2-2节LLM客户端与流式SSE实现 | 第2-1节工程初始化与项目结构 | 项目总览 walioffice.md赞分享文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载相关推荐架构革命Box64如何重塑ARM平台上的x86_64程序运行生态架构革命Box64如何重塑ARM平台上的x86_64程序运行生态 在当今多元化的计算架构生态中一个看似不可能的任务正在成为现实在树莓派、安卓设备或RISC文档教程后端Instructor 字段级流式输出实战用 create_partial 把 LLM 结构化结果实时渲染到前端Instructor 字段级流式输出实战用 create_partial 把 LLM 结构化结果实时渲染到前端 本篇技术指南围绕 instructor 的 c人工智能大模型AI 应用《WaLiOffice》LLM 客户端与流式 SSE 实现多 Key 轮询、模型选择与 StreamEvent 事件流设计《WaLiOffice》LLM 客户端与流式 SSE 实现多 Key 轮询、模型选择与 StreamEvent 事件流设计 导读 本文是 WaLiOffice文档教程后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表