文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载本文聚焦 WaLiOfficeAI Agent 智能办公平台中唯一采用双工具协作的功能——PPT 生成。它拆分为ppt_planLLM 规划大纲与ppt_generateRust 精确渲染两个工具通过 scratchpad 跨工具共享规划数据最终逐页推送生成进度。读完本文你将掌握双工具协作的动机与链路、ppt_plan的 Prompt 设计与大纲 JSON 契约、ppt_generate的三布局渲染与三级 plan 兜底来源以及PptProject持久化与前端产物恢复的完整闭环。一、前言为什么 PPT 是全项目唯一拆成两个工具的功能WaLiOffice 注册了 10 个办公工具详见 docs/md/project/walioffice/part-2/第2-4节工具Trait定义与注册表机制.md其中绝大多数工具都是一步到位——调用一次拿到一个产物。但 PPT 有特殊性内容规划和视觉渲染是两种性质完全不同的工作。规划需要 LLM 发挥创意叙事结构、页数分配、要点提炼。这是语言模型的强项。渲染需要精确的坐标和样式控制每个元素在 13.33 × 7.5 英寸画布上的位置。这是程序逻辑的强项。如果让 LLM 一次干两件事要么规划被渲染细节拖累输出一堆坐标却讲不好故事要么渲染失控自然语言描述不出精确版式。所以 WaLiOffice 的 PPT 功能采用双工具协作模式ppt_plan规划LLM 生成结构化大纲 → 写入 scratchpad只出规划不出页面↓ppt_generate生成读取 scratchpad 大纲 → Rust 代码精确渲染每一页这一模式与意图识别策略一脉相承在 docs/md/project/walioffice/part-2/第2-6节System Prompt工程与意图识别.md 中Ppt意图类型被明确标注为必须两步——ppt_plan → ppt_generate是 14 种意图中唯一强制拆分的流程。代码状态说明ch03-06-ppt-generate分支上ppt_generate.rs已完整实现685 行但ppt_plan.rs在该分支仍是 stub文件头注释完整实现在 3-5 节——ppt_plan 的完整实现213 行随主分支代码呈现本节按完整实现讲解。阅读分支代码时注意这个先后关系。二、本章诉求理解双工具协作模式为什么 PPT 拆两个工具、scratchpad 跨工具数据共享的机制掌握 ppt_plan 的 Prompt 设计大纲 JSON 格式layout 枚举、goal/visual/points 字段、叙事链要求、受众注入掌握 ppt_generate 的渲染逻辑SlidePlan → Slide 的三布局分支、SlideElement 坐标体系、主题色 Palette 轮换理解三级 plan 来源scratchpad 优先 → LLM 实时生成 → fallback_plan 硬编码兜底掌握逐页推送机制project_update 起始帧、每页 slide_update history 追加、最终 ppt artifact理解 PptProject 持久化结构定义、每页循环保存、chat.rs 的产物恢复三、流程设计3.1 双工具协作链路从用户说出需求到 PPT 出现在前端预览面板完整链路如下对应ch03-07分支的ppt_plan.rs与ppt_generate.rs用户帮我做一份电商系统技术方案 PPT ↓ ReAct 循环LLM 决策先调 ppt_plan(topic, audience?) ↓ ppt_planLLM 生成大纲 JSON { title, slides[{title,layout,goal,visual,points}] } ↓ 写入 ctx.scratchpad[ppt_plan] → ToolResult::ok(...).with_data(plan) is_read_onlytrue、produces_artifactfalse对话中不出现产物卡片 ↓ Agent 汇报已规划 N 页大纲 → LLM 继续决策调 ppt_generate(title, theme?) ↓ ppt_generate三级 plan 来源 ① scratchpad 有 → 反序列化 PresentationPlan失败→fallback ② scratchpad 无 → generate_plan_with_llm 实时生成失败→fallback ③ fallback_plan3 页硬编码兜底 ↓ 创建 PptProject → project_update空 slides 起始帧 ↓ for (i, sp) in plan.slides plan_to_slide() 三布局渲染 → push 进 project save_ppt_project() 逐页落库 ctx.send(slide_update) 前端实时看到页面逐张出现 ↓ ToolArtifact { kind: ppt, content: { project_id, slides, history, ... } }这条链路把第三章产物两分法体现得淋漓尽致ppt_plan属于数据产物只写 scratchpad不落盘、不渲染ppt_generate才是文件产物生成 .pptx 并推送到前端预览。可以参考 docs/md/project/walioffice/part-3/第3-5节ECharts图表工具与前端渲染.md 中对文件产物 vs 数据产物的边界分析来理解这种分工。四、ppt_plan只规划不出页面4.1 参数契约与 ToolResult 返回ppt_plan的参数极简参数类型说明topicstring必填PPT 主题如电商系统技术方案audiencestring可选目标受众用于 Prompt 受众注入工具执行完毕后规划结果通过ctx.scratchpad[ppt_plan]写入同时以ToolResult::ok(...).with_data(plan)返回。这里的两个关键标记决定了它在对话中的存在感is_read_onlytrue表示该调用只读取/写入上下文不产生外部副作用produces_artifactfalse对话中不会出现产物卡片用户只看到已规划 N 页大纲的汇报文本。这两个标记是 docs/md/project/walioffice/part-2/第2-4节工具Trait定义与注册表机制.md 中ToolResult规范的落地应用——工具返回的结果既能带回产物也能只传递状态。4.2 Prompt 设计与大纲 JSON 契约ppt_plan的 Prompt 围绕叙事链 结构化大纲构建要求 LLM 输出如下 JSON{ title: 电商系统技术方案, slides: [ { title: 方案概述, layout: title, goal: 让听众快速理解方案定位, visual: 深色背景 金色大标题, points: [背景与目标, 方案价值] }, { title: 总体架构, layout: content, goal: 讲清系统分层与技术选型, visual: 架构分层示意 蓝色主色调, points: [接入层, 应用层, 数据层, 基础设施] } ] }核心字段语义字段说明设计意图titlePPT 总标题作为 PptProject 与最终 artifact 的标题slides[].title每页标题幻灯片标题文本slides[].layout页面布局枚举驱动 ppt_generate 选择渲染分支slides[].goal本页叙事目标让 LLM 每页带着目的写避免凑页数slides[].visual视觉描述给渲染阶段作为样式参考slides[].points上屏要点列表每页的核心内容载体Prompt 的三条硬性要求叙事链要求大纲不是孤立的页面堆叠而是有开场 → 展开 → 收尾的叙事结构每页的 goal 要承接上一页受众注入将audience参数拼入 Prompt例如面向技术评审专家与面向业务领导时页数分配和要点深度应不同布局枚举约束layout 只能取枚举范围内的值见下节保证下游渲染分支可穷举。4.3 只规划不出页面ppt_plan内部不调用任何渲染代码。它的完整流程是① 参数提取与校验topic 不能为空 ② 构建 system_prompt角色 大纲 JSON 格式约束 user_prompttopic audience 注入 叙事链要求 ③ LlmClient.chat() 调用 LLM ④ extract_json 容错解析 → PresentationPlan ⑤ 写入 ctx.scratchpad[ppt_plan] ⑥ ToolResult::ok(plan).with_data(plan)这与 docs/md/project/walioffice/part-3/第3-1节Markdown工具——全链路模板打通.md 中总结的接收参数 → 构建 Prompt → 调 LLM → 解析 JSON → 封装产物工具范式一致只是产物去向从落盘变成了scratchpad。五、ppt_generate把大纲渲染成真幻灯片5.1 三级 plan 来源scratchpad 优先ppt_generate拿到title、theme?参数后第一件事是确定大纲来源采用三级降级策略① scratchpad[ppt_plan] 有 → 反序列化 PresentationPlan └─ 反序列化失败 → 走 ③ fallback_plan ② scratchpad 无 → generate_plan_with_llm(topic) 实时生成 └─ LLM 调用/解析失败 → 走 ③ fallback_plan ③ fallback_plan3 页硬编码兜底这个设计保证了一个关键事实无论前面哪一步出问题用户始终能拿到一份可看的 PPT而不是一串报错。这与项目在视频生成上的FFmpeg 本地兜底见 docs/md/project/walioffice/part-3/第3-11节视频生成——本地ffmpeg兜底机制.md思路一致——远程/智能链路不可用时本地确定性兜底接管。5.2 SlidePlan → Slide三布局渲染分支拿到 plan 后核心渲染函数是plan_to_slide()对每一页SlidePlan根据layout枚举分三支处理layout 值渲染分支典型页面结构title封面布局大标题 副标题 背景装饰content内容布局标题栏 要点列表 卡片容器section章节过渡布局章节标题 视觉装饰条每一分支都在13.33 × 7.5 英寸画布上以 EMUEnglish Metric Units为单位的精确坐标系统布局。每个渲染出来的页面是一组SlideElement包括背景整页底色随主题色轮换卡片承载要点的圆角矩形容器装饰条标题左侧/底部的高亮色条增强版式层次标题文本页面主标题要点列表points数组渲染为带序号的文本行。这种LLM 只出内容结构、Rust 出精确坐标的分工正是前言中渲染需要精确的坐标和样式控制的工程落地——LLM 永远不需要输出坐标数字。5.3 主题色 Palette 轮换theme参数决定整套 PPT 的视觉风格。WaLiOffice 内置 5 套主题配色business / tech / warm / minimal / default渲染时多组色板轮换——即不同页面从当前主题的色板中轮流取色避免整份 PPT 页面颜色完全雷同视觉更丰富。关于PPT 双工具协作的完整场景说明可参见 docs/md/project/walioffice/walioffice.md 的 PPT 章节两阶段 AI 驱动——先ppt_plan自动识别场景产品方案/运营复盘/技术架构等 7 类生成结构化大纲再由ppt_generate将大纲转换为带有真实视觉设计的幻灯片最终由纯 Rust 手写 OOXML 渲染成 .pptx 文件不依赖任何第三方 PPT 库。六、逐页推送与前端实时预览6.1 project_update 起始帧ppt_generate创建PptProject后先通过ctx.send(project_update)推送一个空 slides 的起始帧——前端借此创建项目预览容器进入准备接收页面状态。6.2 每页 slide_update history 追加随后进入逐页渲染循环for (i, sp) in plan.slides { let slide plan_to_slide(sp, palette); // 三布局渲染 project.slides.push(slide); // push 进 project save_ppt_project(project); // 逐页落库 ctx.send(slide_update, slide_index i); // 前端实时看到页面逐张出现 }每一页渲染完成立即推入内存 project → 落库持久化 → 推送 slide_update 事件。用户在前端看到的效果是页面逐张出现——不是等待几十秒后一次性跳出整份 PPT而是实时观察 AI 从规划到成片的生成过程。这与 docs/md/project/walioffice/walioffice.md 中描述的整个过程通过 SSE 逐页推送生成进度完全一致。6.3 最终 ppt artifact所有页面渲染完成后工具封装最终产物ToolArtifact { kind: ppt, content: { project_id, slides, history, ... } }前端收到kind: ppt产物后在右侧产物预览区渲染幻灯片预览对应项目前端 PPT 幻灯片预览器同时产物可下载为 .pptx 文件。七、PptProject 持久化7.1 结构定义PptProject是 PPT 在数据库层的持久化模型核心字段字段说明project_id项目唯一 ID前端产物引用 恢复依据titlePPT 标题来自 plan.titletheme主题配色标识slides已渲染的 Slide 列表history生成历史/状态记录7.2 每页循环保存如前所述save_ppt_project()在每一页渲染完成后立即执行而不是全部渲染完才保存一次。这样即使生成中途中断已渲染的页面也已在库中具备增量恢复能力。7.3 chat.rs 的产物恢复会话恢复链路中chat.rs会在加载历史对话时读取已保存的PptProject将其还原为前端可预览的产物状态——用户重新打开历史会话之前生成的 PPT 页面依然可见、可下载无需重新生成。八、总结双工具协作的设计启示回顾ppt_plan ppt_generate的拆分它回答了 Agent 工具设计中的两个通用问题何时拆工具当任务的子任务在能力性质上根本不同创意叙事 vs 精确渲染、且需要一个中间产物大纲衔接时拆成两个工具并用 scratchpad 共享数据比一个巨型工具更可控、更可降级。如何保证产物稳定三级 plan 来源scratchpad → LLM 实时生成 → 硬编码兜底 逐页落库推送让LLM 可能失败这件事永远不影响用户拿到产物这个底线。这两个思路同样适用于你自建 Agent 平台的其他复杂产物工具规划与执行分离、共享上下文scratchpad传递中间态、确定性兜底托住智能链路正是 WaLiOffice PPT 功能最值得复用的工程经验。相关代码位于ppt_plan.rs主分支 213 行与ppt_generate.rsch03-06-ppt-generate分支 685 行可按 docs/md/project/walioffice/part-3/第3-7节PPT 双工具协作.md 的章节顺序在对应分支上阅读验证。赞分享文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载相关推荐PPTist在线PPT制作工具从零到精通的完整实战指南还在为制作专业PPT而头疼吗PPTist这款基于Vue3.x TypeScript开发的免费在线演示文稿应用让你在浏览器中就能完成从简单编辑到复杂设计的前端企业应用FLUX.1 Kontext 指令式图像编辑实战从一条换 Logo 指令到 TensorRT 加速的完整指南FLUX.1 Kontext 指令式图像编辑实战从一条换 Logo 指令到 TensorRT 加速的完整指南 FLUX.1 Kontext dev 是 Bla人工智能大模型本地部署媒体生成Dify工作流HTML渲染5大实战技巧从零到专业级可视化Dify工作流HTML渲染5大实战技巧从零到专业级可视化 Awesome Dify Workflow作为Dify DSL工作流程的精选集合在HTML渲染方面示例工程上一篇DankMaterialShell核心架构解析Go后端与QML前端的完美结合下一篇Leaflet坐标系与投影一次讲清EPSG3857、墨卡托与Simple CRS到底该怎么选创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考