Tiptap 编辑工作流

构建一个工作流,让 AI 以精准、高效的操作编辑你的 Tiptap 文档。

查看 GitHub 上的源码

技术栈

项目概览

本演示使用 AI 工具包中的 Tiptap 编辑工作流,实时对文档应用编辑操作。该工作流支持替换节点、在节点前插入以及在节点后插入。

安装

创建一个 Next.js 项目:

npx create-next-app@latest tiptap-edit-workflow

安装核心 Tiptap 包和用于 OpenAI 的 Vercel AI SDK

npm install @tiptap/react @tiptap/starter-kit ai @ai-sdk/react @ai-sdk/openai zod uuid

安装 Tiptap AI 工具包:

Pro 软件包

AI 工具包是一个专业版软件包。安装前,请按照 私有注册表指南 配置对私有 NPM 注册表的访问权限。

npm install @tiptap-pro/ai-toolkit @tiptap-pro/ai-toolkit-tool-definitions

服务器设置

创建一个 API 端点,使用 Vercel AI SDK 调用 OpenAI 模型。如果你的后端不是 TypeScript,请参阅 非 TypeScript 后端指南

在该 API 端点中,使用 createTiptapEditWorkflow 函数创建并配置 Tiptap 编辑工作流。该工作流包含一个可直接使用的系统提示,指导 AI 模型如何生成编辑操作。

此外,用户消息中需包含以下两个属性:

  • content: 要编辑的文档内容(从 tiptapRead 获取)
  • task: 由 AI 执行的任务,例如 “使文本更正式”。
  • context: (可选)与任务相关的额外上下文或背景信息。

当 AI 模型生成响应时,API 端点会将操作流式传输给客户端。

// app/api/tiptap-edit-workflow/route.ts
import { openai } from '@ai-sdk/openai'
import { createTiptapEditWorkflow } from '@tiptap-pro/ai-toolkit-tool-definitions'
import { Output, streamText } from 'ai'

export async function POST(req: Request) {
  const { content, task, context } = await req.json()

  // 创建并配置 Tiptap 编辑工作流(默认设置)。
  // 包含可直接使用的系统提示和输出模式。
  const workflow = createTiptapEditWorkflow()

  const result = streamText({
    model: openai('gpt-5.4-mini'),
    // 系统提示
    system: workflow.systemPrompt,
    // 用户消息
    prompt: JSON.stringify({
      content,
      task,
      context,
    }),
    output: Output.object({ schema: workflow.zodOutputSchema }),
  })

  return result.toTextStreamResponse()
}

客户端设置

创建一个 React 组件,渲染编辑器并实时应用编辑。

首先,启动编辑过程时,调用 AI 工具包的 tiptapRead 方法读取文档。该方法返回针对快速、精准编辑优化的内容格式。

接着,调用 API 端点启动工作流。组件通过 Vercel AI SDK 的 useObject hook 处理流式响应,逐步接收结果并实时应用编辑。

每当响应内容更新时,调用 AI 工具包的 tiptapEditWorkflow 方法,将编辑实时应用到文档中。编辑随接收立即生效。

// app/tiptap-edit-workflow/page.tsx
'use client'

import { experimental_useObject as useObject } from '@ai-sdk/react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import {
  AiToolkit,
  type TiptapReadResult,
  getAiToolkit,
  tiptapEditWorkflowOutputSchema,
} from '@tiptap-pro/ai-toolkit'
import { useEffect, useRef, useState } from 'react'
import { v4 as uuid } from 'uuid'

export default function Page() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit, AiToolkit],
    content: `<h1>Document Editor</h1><p>This is a sample document that can be edited by AI.</p>`,
  })

  const [workflowId, setWorkflowId] = useState('')
  const tiptapReadResultRef = useRef<TiptapReadResult | null>(null)
  const [task, setTask] = useState('Make the text more formal and professional')

  const { submit, isLoading, object } = useObject({
    api: '/api/tiptap-edit-workflow',
    schema: tiptapEditWorkflowOutputSchema,
  })

  const operations = object?.operations ?? []

  // 随着分段结果到达实时流式处理
  useEffect(() => {
    if (!editor || !operations) return

    const toolkit = getAiToolkit(editor)
    if (!tiptapReadResultRef.current) return

    toolkit.tiptapEditWorkflow({
      operations,
      workflowId,
      hasFinished: !isLoading,
      tiptapReadResult: tiptapReadResultRef.current,
    })
  }, [operations, workflowId, editor, isLoading])

  if (!editor) return null

  const editDocument = () => {
    const toolkit = getAiToolkit(editor)

    // 获取要编辑的文档内容
    const readResult = toolkit.tiptapRead()
    tiptapReadResultRef.current = readResult

    // 每个工作流必须有唯一 ID
    setWorkflowId(uuid())

    // 调用 API 端点启动工作流
    submit({ content: readResult.content, task })
  }

  return (
    <div>
      <EditorContent editor={editor} />

      <input
        type="text"
        value={task}
        onChange={(e) => setTask(e.target.value)}
        placeholder="输入编辑任务..."
      />

      <button onClick={editDocument} disabled={isLoading}>
        {isLoading ? '正在编辑...' : '编辑文档'}
      </button>
    </div>
  )
}

最终效果

结合额外的 CSS 样式,结果是一个实时 AI 编辑的精致文档编辑应用:

查看 GitHub 上的源码

显示 AI 光标

你可以添加 AiCaret 扩展来显示一个光标,指示 AI 正在编辑文档的位置。这为用户提供了流式编辑时的实时视觉反馈。

import { AiCaret, AiToolkit, getAiToolkit } from '@tiptap-pro/ai-toolkit'

const editor = useEditor({
  extensions: [StarterKit, AiToolkit, AiCaret],
})

有关配置选项和 CSS 样式,请参阅 AI 光标指南

编辑文档的部分内容

要仅编辑文档的子区域,请设置 range 选项。该参数接收一个带有待编辑区域的 Range

例如,要仅编辑选中的内容:

const range = editor.state.selection

// 仅读取文档中选中的部分
const { content } = toolkit.tiptapRead({ range })

const operations = callApi(content)

// 在相同范围内应用操作
toolkit.tiptapEditWorkflow({
  operations,
})

对于大型文档,你可以使用 tiptapReadChunks 方法,将文档拆分为多个块并进行并行处理。每个块都包含其区域范围的 Range

显示复审界面

在审阅界面中显示更改,以便用户接受或拒绝它们。

有两种方法:

  • 使用 Tracked Changes 扩展来渲染审阅界面。更改会作为文档的一部分保留,并对其他用户可见。
  • AI Toolkit suggestions:一种基于装饰的界面,具有临时性,仅对当前文档用户可见。

通过设置 reviewOptions 参数来配置审阅界面。更改将以建议的形式显示,用户可以接受或拒绝。

await toolkit.tiptapEditWorkflow({
  // ... 其他选项

  // 使用 Tracked Changes 显示审阅界面
  reviewOptions: { mode: 'trackedChanges' },

  // 使用 AI Toolkit suggestions 显示审阅界面
  reviewOptions: { mode: 'review' },
})

查看 review changes 指南,了解更多关于审阅界面的信息。

查看 AI Toolkit demos,获取在审阅界面中使用 AI Toolkit 工作流的示例。

相关指南

  • tiptapRead 方法的 API 参考
  • tiptapReadChunks 方法的 API 参考
  • tiptapEditWorkflow 方法的 API 参考
  • 建议:了解如何审阅文档并在编辑器中显示建议。
  • AI Caret:在 AI 插入内容的位置显示光标。