hello 大家好,我是张XX,这篇文章打算跟大家聊聊如何用 AI 生成 RevealJS Html 演示文稿代码并预览。如果大家有任何问题,欢迎私信我。
最近 claude 非常火,聊天就能帮你写代码,而且可以直接预览代码生成的效果,在前端圈掀起了不小的波澜。
本文将教会你如何仿照 claude 基于对话创建代码的效果,来实现对话生成 RevealJS 的 HTML 代码并预览的功能。
项目的 Demo 效果如下:
项目源码地址见:ai-ppt
你将学到以下内容:
- 如何构建 AI 聊天组件
- 如何预览生成的 html 代码
本文的内容将基于 gemini flash 模型。
0. 前置准备
本教程需要 React 的基本知识。
你还需要在 Google 的 Gemini 平台上拥有一个帐户。 你可以在这里创建一个
1. 项目初始化
首先创建 next 项目:
npx create-next-app@latest revealjs-ai-tutorial
进入目录
cd revealjs-ai-tutorial
2. 实现 chat 组件
2.1 Message UI 组件
首先实现 Message UI 组件,新建文件 /components/chat.tsx
, 截取部分组件代码如下:
export default function Chat() {
return (
<div id="chat-container">
{messages.map((message, index) => (
<div className="py-2 px-4 shadow-sm whitespace-pre-wrap" key={index}>
{message.content.map((content, id) => {
if (content.type === 'text') {
return <p key={content.text} className="flex-1">{content.text}</p>
}
})}
{message.meta &&
<div className="mt-4 flex justify-start items-start border rounded-md">
<div className="p-2 self-stretch border-r w-14 flex items-center justify-center">
<Terminal strokeWidth={2} className="text-[#FF8800]"/>
</div>
<div className="p-2 flex flex-col space-y-1 justify-start items-start min-w-[100px]">
<span className="font-bold font-sans text-sm text-primary">{message.meta.title}</span>
<span className="font-sans text-sm">{message.meta.description}</span>
</div>
</div>
}
</div>
))}
</div>
)
}
组件效果如下图所示:
可以发现,组件是基于 message
这个数据的内容渲染的,而这个 message
正是大模型提供的数据结构,因此下一步我们需要实现访问大模型的接口,也是整个核心所在。
2.2 创建 Chat API
首先我们在 app
目录下新建 api/chat/route.ts
目录,新建 /api/chat
接口:
export async function POST(req: Request) {
const { messages } = await req.json() as Req
// todo: 此处需实现调用 Gemini 模型
}
我们创建了 /api/chat
接口,接下来就是要在接口中实现对 Gemini 模型的调用。
在这里我们需要用到一个 npm 库 ai-sdk
, 它为开发者封装了各种 AI 服务(如语言模型,生成式AI, 图像识别等), 极大的简化的 AI 模型的集成流程,使开发者能够快速的将 AI 功能嵌入应用中。
ai-sdk
目前支持多个主流的 AI 服务,如 OpenAI, Anthropic(Claude模型), Google Gemini 等。
接下来我们就使用 ai-sdk
来访问 Google Gemini模型。
我们来看一下具体的 ai-sdk
使用示例:
import { createGoogleGenerativeAI } from '@ai-sdk/google';
export async function POST(req) {
const { messages } = await req.json()
// 创建 Google Generative AI 客户端,使用的 google 模型为 gemini-1.5-flash, 这是一个免费模型
const client = createGoogleGenerativeAI({ apiKey: process.env.GEMINI_API_KEY})
('models/gemini-1.5-flash-latest')
const stream = await streamObject({
model: client,
schema: artifactSchema,
system: `
Generate a visually appealing reveal.js presentation in HTML.
The presentation should include the following slides: appealing cover, bullet points with links, conclusion and end page.
more than 6 slides.
use the template: ${htmlTemplate}
`,
messages
})
return stream.toTextStreamResponse()
}
代码中的 streamObject
是一个函数,用于创建AI 生成内容的流式对象,这个流会从 Google Generative AI 模型中获取生成结果。
该函数接受一个对象作为参数,其中包含以下关键项:
-
model: 将前面创建的 client 传递给 model 参数,这个模型将用于生成文本或处理自然语言任务。
-
schema:是为生成的演示文稿设定的格式规范。具体包括commentary(描述生成步骤),title(对生成结果的简短标题), description(对生成内容的描述), code(生成的 html 内容)。 这些字段信息将携带在返回的字段 中。
-
system: 是传递给 AI 模型的系统提示(prompt)
-
messages:用户输入的上下文信息,这些消息将作为输入帮助模型生成合适的内容。
最后通过 stream.toTextStreamResponse()
返回流处理式响应。因为响应是以流的形式传输的,客户端可以在逐步接收数据时逐步处理,而不需要等待整个响应完成。这种流式处理方式的好处是能够处理大段文本输出,适合生成较大内容、需要持续响应或有实时更新需求的场景。
2.3 调用 Chat API
在 2.1 章节中我们实现了 Chat 组件的 UI 部分,但 message
数据如何获取,数据结构是什么,都尚未交代,本章就来说明这部分内容。
import { experimental_useObject as useObject } from 'ai/react'
export default function Chat() {
const [messages, setMessages] = useState<ChatMessage[]>([])
const { object, submit } = useObject({
api: '/api/chat'
})
useEffect(() => {
if (object) {
setMessages([
...message, {
content: [{
type: 'text',
text: object.commentary
}, {
type: 'code',
text: object.code
}],
meta: {
title: object.title,
description: object.description
}
}
])
}, [object])
const handleSubmit = () => {
submit({
messages: addMessage({role: 'user', content}),
})
}
return (
// ...
)
}
从 ai/react
模块导入 experimental_useObject
,并将其重命名为 useObject
。这个 hook 用于与后端进行交互。
调用 useObject
hook
, 其中 api 字段指向后端的 /api/chat
接口。并返回 object
和 submit
函数。
- object 是从后端 API 获取的对象,包含聊天的响应内容
- submit 用于提交用户问题时,向后端发送请求。
使用 useEffect hook
,当 object 发生变化时执行该副作用。如果 object 存在,将聊天响应的内容添加到 messages
数组中。
至此,我们实现了调用 api/chat
接口,访问大模型,并将返回的字段渲染到 UI 上。接下来就是如何预览生成的 html 代码。
3. 预览生成的 RevealJS HTML
预览的容器是一个 iframe
, 在这里利用了 iframe 的 dataURI 属性,这个 URI 允许浏览器将一段 HTML 内容直接嵌入到页面中。
export function Preview({
result,
}) {
if (!result) return null
const encodedHTML = encodeURIComponent(result);
const dataURI = `data:text/html;charset=utf-8,${encodedHTML}`;
return (
<div className="w-full h-full">
<iframe
className="h-full w-full"
loading="lazy"
src= {dataURI}
/>
</div>
)
}
总结
我们学习了如何基于 ai-sdk 实现聊天对话,并将生成的 RevealJS Html 进行预览。 感谢大家对本文的支持~欢迎点赞收藏,在评论区留下你的高见 🌹🌹🌹