news 2026/5/13 1:16:02

基于Prosemirror与Vercel AI SDK构建开源AI写作编辑器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Prosemirror与Vercel AI SDK构建开源AI写作编辑器

1. 项目概述:一个开箱即用的AI写作编辑器

最近在折腾一些内容创作工具,发现了一个让我眼前一亮的开源项目:steven-tey/novel。这不仅仅是一个简单的文本编辑器,而是一个深度集成了AI能力的“写作副驾驶”。它的核心定位是,为开发者、内容创作者和产品团队提供一个可以快速集成、高度可定制、且具备现代AI写作辅助功能的编辑器组件。

简单来说,Novel 让你能在自己的Web应用中,轻松嵌入一个类似Notion AI或Craft风格的编辑器。用户可以在其中流畅地写作,并随时召唤AI来帮忙续写、改写、总结,甚至是翻译。它基于Vercel的AI SDK构建,底层模型可以灵活切换(比如OpenAI的GPT系列、Anthropic的Claude等),而前端则采用了Prosemirror这个强大的富文本编辑框架,确保了编辑体验的专业性和扩展性。

为什么我会特别关注它?因为在当前这个AI应用爆发的时代,很多团队都想给自己的产品加上“智能写作”功能,但从头开发一个既稳定又好用的编辑器,成本极高。Novel 恰好解决了这个痛点。它不是一个封闭的SaaS服务,而是一个MIT协议的开源项目,这意味着你可以完全掌控代码,根据业务需求进行深度定制,从UI样式到AI提示词(Prompt)工程,一切皆可调整。

2. 核心架构与技术栈拆解

要理解Novel的强大之处,我们需要拆开看看它的“五脏六腑”。它的架构清晰地分为前端编辑器层和后端AI处理层,中间通过清晰的API进行通信。

2.1 前端:基于Prosemirror的现代编辑器

Novel的前端核心是Prosemirror。可能有些朋友对Prosemirror不太熟悉,我简单类比一下:如果说我们常见的富文本编辑器(比如早期的TinyMCE)是一辆组装好的汽车,那么Prosemirror就是一个功能无比强大的汽车底盘和发动机生产线。它不直接提供一个开箱即用的编辑器,而是提供了一套构建编辑器所需的所有底层工具和模块。

选择Prosemirror意味着什么?

  1. 极致的可控性与性能:你可以精确控制编辑器的每一个行为,从按键响应到节点渲染。这避免了使用黑盒编辑器时遇到的种种诡异Bug和性能瓶颈。
  2. 符合现代Web标准:它的数据模型(Schema)和文档状态(State)设计得非常优雅,输出的内容是结构化的JSON,而非杂乱的HTML,这为内容的持久化、协同编辑和AI处理提供了巨大便利。
  3. 丰富的生态系统:社区围绕Prosemirror构建了大量的插件,比如表格、代码块、任务列表等,Novel本身也利用并扩展了这些插件。

Novel在Prosemirror之上,封装了一套自己的UI组件和命令。它实现了几个关键特性:

  • 浮动菜单:选中文字时,会浮现一个格式工具栏(加粗、斜体、链接等)和AI操作菜单。
  • Slash命令:输入“/”会触发一个命令面板,可以快速插入各种元素(标题、引用、代码块)或调用AI功能。
  • AI补全:在写作时,AI可以像幽灵一样在光标处提供续写建议,按Tab键即可采纳。

这些交互模式借鉴了Notion、Craft等优秀产品的设计,经过市场验证,用户体验非常流畅。

2.2 后端:Vercel AI SDK与模型路由

Novel的后端逻辑相对轻量,其核心是Vercel AI SDK。这个SDK是Vercel公司推出的,旨在标准化AI应用(尤其是聊天和补全场景)的开发流程。

它的核心价值在于提供了一个统一的API接口,让你可以轻松切换不同的AI模型提供商。在Novel的配置中,你只需要在环境变量里指定你的API密钥(比如OpenAI的或Anthropic的),然后在代码中调用openai.chat.completions.createanthropic.messages.create,AI SDK会帮你处理好与不同供应商API的通信细节。

更重要的是,Novel利用这个SDK实现了流式响应。当你要求AI“续写这段文字”时,服务器不是等AI生成完整段落再一次性返回,而是像流水一样,一个字一个字地实时推送回前端。前端则将这些token逐个追加到编辑器中,形成了那种“AI正在为你打字”的生动效果。这种体验对用户来说非常直观和吸引人。

2.3 数据流与状态管理

整个应用的数据流非常清晰:

  1. 用户在编辑器中触发一个AI动作(如选中文本后点击“改写”)。
  2. 前端将当前选中的文本、光标位置以及动作类型(如“rewrite”)封装成一个请求,发送到Next.js应用的一个API路由(例如/api/generate)。
  3. API路由根据动作类型,构造不同的系统提示词(System Prompt)和用户消息(User Message),然后通过AI SDK调用对应的模型。
  4. AI模型开始流式返回结果,API路由将这些结果以Server-Sent Events (SSE) 的形式推回前端。
  5. 前端Prosemirror编辑器接收到数据流,实时插入到文档的指定位置。

这个过程中,编辑器的状态(文档内容、选择范围)由Prosemirror管理,AI请求的状态(是否加载中、流式内容)由React组件状态管理,两者通过自定义的Hook(如useAI)优雅地结合。

3. 从零开始部署与深度配置实战

纸上谈兵终觉浅,我们来实际动手,把一个基础的Novel编辑器集成到自己的Next.js项目中,并完成一些关键配置。

3.1 基础环境搭建与项目初始化

假设你已经有了一个Next.js 14+(App Router)的项目。如果没有,可以快速创建一个:

npx create-next-app@latest my-ai-editor --typescript --tailwind --app cd my-ai-editor

接下来,安装Novel的核心依赖:

npm install novel

这个命令会安装novel包本身以及它的核心Peer Dependencies:prosemirror相关的一系列包和@uiw/react-codemirror等。

然后,我们需要安装AI SDK和对应的模型提供商包。以使用OpenAI GPT-4为例:

npm install ai openai

如果你计划使用Anthropic Claude,则需要安装@anthropic-ai/sdk

3.2 核心组件集成与基础渲染

Novel提供了一个高度封装的主组件Editor。在你的应用页面(例如app/page.tsx)中,你可以这样引入:

import { Editor } from 'novel'; export default function Home() { return ( <div className="container mx-auto max-w-4xl p-8"> <h1 className="text-3xl font-bold mb-6">我的AI写作助手</h1> <Editor /> </div> ); }

就这么简单,一个功能完整的、带AI能力的编辑器就渲染出来了。你可以尝试输入文字,输入“/”调出命令菜单,或者选中文字看看浮出的AI菜单。

注意:此时AI功能还不可用,因为缺少关键的API配置。点击AI按钮会报错。我们接下来就解决这个问题。

3.3 配置AI后端与API路由

这是让编辑器“智能”起来的关键一步。Novel期望你在项目中创建一个特定的API路由来处理AI请求。

  1. 设置环境变量:在项目根目录创建.env.local文件,填入你的OpenAI API密钥。

    OPENAI_API_KEY=sk-your-secret-key-here

    安全提醒:永远不要将API密钥提交到Git仓库!确保.env.local.gitignore中。

  2. 创建API路由文件:在app/api/目录下,创建generate/route.ts。这是Novel默认会调用的端点。

    // app/api/generate/route.ts import { OpenAI } from "openai"; import { OpenAIStream, StreamingTextResponse } from "ai"; // 创建一个OpenAI客户端实例。注意Edge Runtime的限制。 const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY || "", }); // 设置运行时为Edge,以获得更快的流式响应 export const runtime = "edge"; export async function POST(req: Request) { // 解析前端发送的请求体 const { prompt, context } = await req.json(); // 调用OpenAI API,请求流式响应 const response = await openai.chat.completions.create({ model: "gpt-4-turbo-preview", // 可根据需要更换模型,如 gpt-3.5-turbo messages: [ { role: "system", // 这是核心的系统提示词,定义了AI的“角色”和行为准则 content: `你是一位资深的写作助手。根据用户的指令和提供的文本上下文,完成续写、改写、扩写、总结或翻译等任务。保持语言风格与上下文一致,输出高质量、流畅的文本。`, }, { role: "user", content: prompt, // 前端传来的具体指令,如“将这段文字改写得更加正式:{选中文本}” }, ], stream: true, // 开启流式输出 temperature: 0.7, // 控制创造性,越高越随机,越低越确定 }); // 将OpenAI的响应流转换为标准的文本流 const stream = OpenAIStream(response); // 返回流式响应给前端 return new StreamingTextResponse(stream); }

    这个API路由做了几件事:接收前端请求,用系统提示词和用户指令构造消息,调用OpenAI接口,并将流式结果返回。

  3. 连接编辑器与后端:现在,我们需要告诉编辑器这个API的存在。修改Editor组件的使用方式:

    import { Editor } from 'novel'; export default function Home() { return ( <Editor // 覆盖默认的AI补全处理函数 completionApi="/api/generate" // 可以在这里传入初始内容 defaultValue={{ type: "doc", content: [/* 你的初始文档JSON */] }} /> ); }

    completionApi属性设置为你的API路由地址。现在,刷新页面,选中一段文字,点击“AI”菜单中的“续写”或“改写”,你应该能看到AI开始流式生成内容了!

3.4 深度定制:样式、提示词与行为

基础功能跑通后,我们就可以根据产品需求进行深度定制了。Novel的开放性在这里体现得淋漓尽致。

1. 自定义样式与主题Novel的UI完全由你自己的Tailwind CSS控制。你可以通过覆盖CSS变量或直接修改组件类名来改变外观。

<Editor className="min-h-[500px] border border-gray-300 rounded-lg shadow-inner" // 容器样式 editorProps={{ attributes: { class: "prose prose-lg max-w-none focus:outline-none p-4", // 编辑器内部样式,这里用了Tailwind Typography插件 }, }} />

你甚至可以替换掉Novel自带的图标、按钮组件,实现完全的品牌化。

2. 定制AI提示词与行为这是让AI输出符合你业务需求的关键。我们回到app/api/generate/route.ts。系统提示词(systemrole)是AI的“宪法”。

  • 针对不同任务优化:你可以根据前端传来的context或自定义参数,动态切换提示词。
    const { prompt, context, action } = await req.json(); // 假设前端传了action类型 let systemPrompt = `你是一位写作助手。`; if (action === 'rewrite') { systemPrompt = `你是一位专业的文案润色专家。请将用户提供的文本改写得更加优美、流畅,并保持原意。`; } else if (action === 'summarize') { systemPrompt = `你是一位总结高手。请用最精炼的语言概括用户文本的核心内容,不超过3句话。`; } // ... 将 systemPrompt 用于 messages
  • 控制输出格式:如果你希望AI生成特定格式(如Markdown标题、列表),可以在提示词中明确要求。
    content: `${prompt}\n\n请用Markdown格式输出。`

3. 扩展编辑器功能(添加自定义Slash命令)Novel允许你注入自己的“扩展”(Extensions)。比如,你想添加一个自定义的“插入当前日期”的Slash命令。

// 首先,你需要创建一个Prosemirror插件或节点(这需要深入Prosemirror知识)。 // 更简单的方式是利用Novel提供的钩子或模仿其现有扩展的写法。 // 这里是一个概念性示例,实际代码更复杂: import { Extension } from "novel"; const insertDateExtension = Extension.create({ name: "insertDate", addCommands() { return { insertDate: () => ({ state, dispatch }) => { const date = new Date().toLocaleDateString(); const { tr, selection } = state; tr.insertText(date, selection.from); if (dispatch) dispatch(tr); return true; }, }; }, }); // 然后在Editor组件中传入 <Editor extensions={[insertDateExtension, ...defaultExtensions]} />

对于大多数需求,Novel内置的扩展(图片上传、代码高亮、任务列表等)已经足够。深度自定义需要你对Prosemirror有较好的理解。

4. 生产环境部署与性能优化指南

当你想把集成了Novel的应用部署到生产环境时,有几个关键点需要特别注意。

4.1 部署平台选择与配置

Novel是一个前端组件,其部署和任何Next.js应用一样。Vercel是最无缝的选择,特别是考虑到Novel本身就由Vercel的员工作为个人项目发起。

  1. 在Vercel上部署

    • 将你的代码推送到GitHub/GitLab。
    • 在Vercel控制台导入项目。
    • 在项目设置的“Environment Variables”中,添加OPENAI_API_KEY
    • 部署即可。Vercel会自动识别Next.js项目并优化构建。
  2. 在其他平台部署(如Netlify、AWS Amplify、自有服务器):

    • 确保平台支持Next.js 14的App Router和Edge Runtime(如果你的API路由用了runtime = 'edge')。
    • 在构建命令中,使用next build
    • 同样,在平台的环境变量设置中配置好你的AI API密钥。

4.2 安全性考量

AI应用涉及API密钥和用户数据,安全至关重要。

  1. API密钥保护

    • 绝对前端保密:永远不要在前端代码或浏览器中硬编码或暴露API密钥。所有AI调用必须通过你自己的后端API路由(我们之前创建的/api/generate)进行中转。
    • 使用环境变量:如上所述,将密钥存储在服务器的环境变量中。
    • 考虑使用密钥管理服务:对于大型应用,可以使用Vercel Secrets、AWS Secrets Manager等服务来更安全地管理密钥。
  2. 用户输入净化与限流

    • 提示词注入防护:用户输入的文本会被拼接到提示词中。虽然风险较低,但理论上存在用户通过精心构造的输入让AI执行意外操作的可能。可以在后端对用户输入的prompt进行基本的检查和过滤。
    • 设置API速率限制:防止恶意用户刷你的API,导致高昂的AI调用费用。你可以在Next.js API路由中集成类似@upstash/ratelimit这样的库,基于用户IP或会话进行限流。
    // 示例:使用Upstash Redis进行限流 import { Ratelimit } from "@upstash/ratelimit"; import { Redis } from "@upstash/redis"; const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, "10 s"), // 10秒内最多10次请求 }); export async function POST(req: Request) { const ip = req.headers.get("x-forwarded-for") ?? "127.0.0.1"; const { success } = await ratelimit.limit(ip); if (!success) { return new Response("请求过于频繁,请稍后再试", { status: 429 }); } // ... 原有的AI处理逻辑 }

4.3 性能优化与监控

  1. 利用Edge Runtime:我们的API路由设置了runtime: "edge"。这会将函数部署到全球分布的边缘网络,能显著降低AI请求的延迟,提升用户体验。确保你的部署平台支持Next.js Edge Functions。

  2. 模型选择与成本平衡

    • GPT-3.5-Turbo vs GPT-4:GPT-3.5-Turbo速度更快、成本极低,对于大多数文本润色、续写任务已经足够好用。GPT-4质量更高,但速度慢、成本高,适合对质量要求极高的场景。可以在API中根据任务类型动态选择模型。
    • 设置最大Token数:在调用AI API时,设置max_tokens参数,防止生成过长的内容,控制单次调用成本。
    const response = await openai.chat.completions.create({ model: model, // 动态选择的模型 messages: [...], stream: true, max_tokens: 500, // 限制生成长度 });
  3. 监控与日志

    • 记录AI调用的次数、消耗的Token数以及可能的错误。这有助于分析使用情况和成本。
    • 可以考虑集成像LogtailSentry这样的日志服务到你的Next.js应用中。

5. 常见问题排查与实战心得

在实际集成和使用Novel的过程中,我遇到了一些典型问题,这里总结出来,希望能帮你避坑。

5.1 AI功能不工作或报错

这是最常见的问题,排查思路如下:

  1. 检查API密钥:确保.env.local文件中的OPENAI_API_KEY正确无误,且已重启开发服务器。在Vercel等部署平台,确认环境变量已正确设置。
  2. 检查API路由:访问/api/generate看是否能正常响应(可能会要求POST方法)。可以在路由中暂时去掉AI调用,先返回一个简单的测试文本,看看前后端通信是否正常。
  3. 查看浏览器控制台网络请求:打开开发者工具,点击AI按钮,查看对/api/generate的请求和响应。关注请求载荷(Payload)是否正确,响应状态码是否为200,响应数据是否是流式文本。
  4. 模型可用性:确认你API账户是否有权限调用你所选的模型(例如,GPT-4可能需单独申请)。
  5. 跨域问题(CORS):如果你将前端和后端分离部署,可能会遇到CORS问题。Next.js的API路由和前端同源,通常不会有此问题。如果遇到,需要在API路由响应头中添加CORS头。

5.2 编辑器样式异常或交互卡顿

  1. Tailwind CSS冲突:如果你项目中的Tailwind版本或配置与Novel有冲突,可能导致样式错乱。确保使用兼容的版本,并检查是否有全局CSS覆盖了Prosemirror的类名。
  2. 扩展冲突:如果你添加了自定义的Prosemirror插件或Novel扩展,可能会与现有扩展产生冲突。尝试逐个禁用扩展来定位问题。
  3. 大型文档性能:Prosemirror处理大型文档性能很好,但极端情况下(数万字以上)的复杂操作可能变慢。确保你没有在每次渲染时都创建新的编辑器实例或扩展。

5.3 流式响应中断或显示不完整

  1. 网络环境:流式响应对网络稳定性要求较高。不稳定的网络可能导致流中断。可以考虑添加重试逻辑或更友好的错误提示。
  2. Edge Runtime超时:Vercel的Edge Function有执行时间限制(约30秒)。如果AI生成内容非常长且慢,可能超时。对于长文生成任务,考虑切换到标准的Serverless Function(runtime: 'nodejs'),它有更长的超时时间,或者提示用户分步操作。
  3. 前端处理逻辑:检查Novel版本。早期版本在流式接收和处理上可能有Bug,更新到最新版本通常能解决。

5.4 我的实战心得与建议

  1. 从小功能开始:不要试图一次性把所有AI功能都做完美。先从一两个核心功能(如“续写”和“改写”)开始,打磨好用户体验和提示词,再逐步扩展。
  2. 提示词工程是核心:AI输出的质量,80%取决于你的提示词。多花时间调试系统提示词。让它明确角色、任务、输出格式和风格。可以准备不同的提示词模板用于不同场景。
  3. 为用户提供“撤销”安全感:AI生成的内容可能不总是用户想要的。确保任何AI操作(替换、插入)都可以通过标准的Ctrl+Z撤销。这能极大降低用户的使用焦虑。
  4. 考虑“无AI”的降级方案:不是所有用户都愿意或能够使用AI功能。确保编辑器的基础文本编辑功能(加粗、列表、标题等)在无网络或AI服务不可用时依然完美工作。可以把AI功能视为一个强大的增强插件,而非核心依赖。
  5. 关注内容结构化存储:Novel编辑器产生的文档是Prosemirror的JSON结构。相比于存储HTML,这给了你巨大的灵活性。你可以把这个JSON存到数据库,未来可以轻松地重新渲染、做内容分析,或者转换为其他格式(如Markdown、PDF)。在设计数据库时,为这个JSON字段留好位置。

集成像Novel这样的工具,最终目的是提升产品的核心价值。它不是一个炫技的玩具,而是一个能够切实帮助用户提升写作效率和质量的功能点。通过合理的定制和打磨,它完全可以成为你产品中一个亮眼的差异化特性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/13 1:15:11

【收藏】2026测试人必看!再不学大模型AI,真的要被行业淘汰了

最近和身边做测试的朋友闲聊&#xff0c;发现大家的焦虑感比往年更重了——有人做了3年功能测试&#xff0c;跳槽面试连初筛都过不了&#xff1b;有人深耕性能测试5年&#xff0c;薪资原地踏步&#xff0c;反而被刚入行、懂AI测试的新人弯道超车。 从ChatGPT横空出世引爆AI行业…

作者头像 李华
网站建设 2026/5/13 1:04:08

车载AR交互技术:POI选择优化与多模态融合方案

1. 车载AR交互技术的现状与挑战在过去的五年里&#xff0c;车载增强现实(AR)技术已经从概念验证阶段逐步走向实际应用。根据最新市场调研数据&#xff0c;预计到2025年全球车载AR市场规模将达到47亿美元&#xff0c;年复合增长率高达35%。这种快速增长背后反映的是用户对更智能…

作者头像 李华
网站建设 2026/5/13 1:02:18

Windows端口转发终极指南:PortProxyGUI图形化管理工具完整教程

Windows端口转发终极指南&#xff1a;PortProxyGUI图形化管理工具完整教程 【免费下载链接】PortProxyGUI A manager of netsh interface portproxy which is to evaluate TCP/IP port redirect on windows. 项目地址: https://gitcode.com/gh_mirrors/po/PortProxyGUI …

作者头像 李华
网站建设 2026/5/13 1:02:09

IT30--制造业数字化转型的破局与重构

在2026年的今天&#xff0c;当AI大模型开始重构各行各业的底层逻辑&#xff0c;一家深耕珠宝领域的企业——A公司&#xff0c;正站在传统与未来的十字路口。这不仅是关于技术的升级&#xff0c;更是一场关于生存与发展的“投名状”。 基于A公司详尽的数字化规划蓝图&#xff0c…

作者头像 李华