集成你的自定义后端和大语言模型(LLMs)
默认情况下,AI 建议扩展使用 Tiptap 内容 AI 云来生成内容建议。这让你以最少的配置享受其功能。不过,你也可以集成自己的后端和大语言模型来生成建议。
自定义大语言模型演示
我们为成长版和企业版客户提供详细的自定义大语言模型演示。它包含客户端和服务器端代码,以及如何运行和部署的说明。见 套餐与定价。
AI 建议扩展支持不同程度的自定义。你可以:
- 使用 Tiptap 内容 AI 云,但自定义 OpenAI 模型。
- 替换用于获取建议数据的 API 端点,使用你自己的大语言模型和后端,但让扩展处理建议的展示和应用。这是大多数用例的推荐方式,因为我们会帮你处理大部分复杂性:比较编辑器旧内容和新内容,以友好的方式展示差异,以及处理冲突。
- 完全实现你自己的解析器函数。这可以让你完全自由决定建议如何在编辑器中展示,仅推荐进阶场景使用。
在 Tiptap 云中自定义 OpenAI 模型
你可以通过 model 选项配置用于生成建议的 OpenAI 模型。默认模型是 gpt-4o-mini,它在速度、成本和准确性间取得良好平衡。
如果你想提升建议质量,可以使用更大的模型,如 gpt-4o。但请注意,更大的模型通常更昂贵,速度更慢且延迟更高。
AiSuggestion.configure({
// 用于生成建议的模型。默认为 "gpt-4o-mini"
model: 'gpt-4o',
})替换 API 端点(推荐)
如需使用你自己的后端和大语言模型生成建议,可以提供自定义的 apiResolver 函数。该函数应调用你的后端并根据编辑器内容和规则返回建议数组。
AiSuggestion.configure({
async resolver({ defaultResolver, ...options }) {
const suggestions = defaultResolver({
...options,
apiResolver: async ({ html, htmlChunks, rules }) => {
// 调用自定义后端和大语言模型生成响应
const response = await claudeSonnetApi({ html, htmlChunks, rules })
// 以正确格式返回响应(详情见下文)
return { format: 'replacements', content: response }
},
})
return suggestions
},
})为提供最大灵活性,apiResolver 可接受两种响应格式:
replacements 格式(推荐)
响应为一组替换项,将应用于编辑器内容。适用于建议修改文档中特定部分。这是我们在 Tiptap 内容 AI 云内部使用的格式,效果最佳。
它包含以下属性:
items:建议列表。每条建议具有以下属性:ruleId:生成该建议的规则 ID。deleteHtml:需从编辑器删除的 HTML 内容。insertHtml:需插入到编辑器的 HTML 内容。chunkId:应应用该建议的内容块 ID。
htmlChunks:编辑器内容中所有 HTML 代码块的列表。每个块包含:id:块的唯一标识符。html:该块的 HTML 内容。generateSuggestions:AI 模型是否针对该块生成了建议。若为false,则建议将从扩展的内部缓存获取。
请确保 htmlChunks 属性包含编辑器内容中的所有 HTML 代码块,否则缓存机制无法正常工作。
你可通过读取 apiResolver 函数的 htmlChunks 参数轻松获得该属性值。
以下是一个使用 replacements 格式的响应示例。
{
"format": "replacements",
"content": {
"htmlChunks": [
{
"id": "1",
"html": "<p>Hello, welcome to our awesome app! We hope you guys will love it. Our aplication offers unique features that enhance your cooking experience. You can explore various cuisines and share your food momentts.</p><p>Hola, estamos emocionados de tenerte aquí. Our app is not just about recipes but also about building a community. We believe this will transform how you cook.</p>",
"generateSuggestions": true
},
{
"id": "2",
"html": "<p>Please check out our cool fetures and enjoy cooking with us. Si tienes dudas, no dudes en preguntar.</p>",
"generateSuggestions": true
}
],
"items": [
{
"ruleId": "1",
"deleteHtml": "Hola, estamos <bold>emocionados</bold> de tenerte aquí.",
"insertHtml": "Hello, we are <bold>excited</bold> to have you here.",
"chunkId": "1"
},
{
"ruleId": "2",
"deleteHtml": "aplication",
"insertHtml": "application",
"chunkId": "1"
},
{
"ruleId": "2",
"deleteHtml": "momentts",
"insertHtml": "moments",
"chunkId": "1"
},
{
"ruleId": "1",
"deleteHtml": "Si tienes dudas, no dudes en preguntar.",
"insertHtml": "If you have any questions, feel free to ask.",
"chunkId": "2"
},
{
"ruleId": "2",
"deleteHtml": "fetures",
"insertHtml": "features",
"chunkId": "2"
}
]
}
}fullHtml 格式
响应为一整段完整的 HTML 字符串,用于替换编辑器内容。适用于你想用建议替换整个内容的情况。我们发现当只有一条规则时此格式表现很好,多条规则时效果稍差。此格式不支持内容分块和缓存。
{
"format": "fullHtml",
"content": {
"items": [
{
"ruleId": "1",
"fullHtml": "<p>Hello, welcome to our awesome app! We hope you guys will love it. Our aplication offers unique features that enhance your cooking experience. You can explore various cuisines and share your food momentts.</p><p>Hello, we are excited to have you here. Our app is not just about recipes but also about building a community. We believe this will transform how you cook.</p><p>Please check out our cool fetures and enjoy cooking with us. If you have doubts, do not hesitate to ask.</p>"
},
{
"ruleId": "2",
"fullHtml": "<p>Hello, welcome to our awesome app! We hope you guys will love it. Our application offers unique features that enhance your cooking experience. You can explore various cuisines and share your food moments.</p><p>Hola, estamos emocionados de tenerte aquí. Our app is not just about recipes but also about building a community. We believe this will transform how you cook.</p><p>Please check out our cool features and enjoy cooking with us. Si tienes dudas, no dudes en preguntar.</p>"
}
]
}
}提高准确率
大语言模型可能出错,导致响应难以符合预期格式。为提升自定义模型准确率,建议遵循以下最佳实践和提示工程技巧:
-
先评估自定义端点响应并测量性能及准确率。推荐使用像 Evalite 这类评估框架,有助于优化和对比提示效果。
-
如使用
replacements格式,利用 OpenAI 结构化输出(或其他 LLM 提供商的同类功能)确保响应为符合特定模式的 JSON 对象。 -
如使用
fullHtml格式,利用 OpenAI 预测输出(或其他 LLM 提供商的同类功能)确保响应不偏离原编辑器内容过多。 -
调整模型的
temperature或top_p参数,以控制输出随机性。 -
不同校对规则适合不同的提示方法和响应格式。你无需只能选择使用
replacements或fullHtml格式——两者皆可!定义一个 API 返回replacements格式的建议,另一个生成fullHtml格式。示例:AiSuggestion.configure({ async resolver({ defaultResolver, rules, ...options }) { // 将规则拆分为两组 const { rulesForFirstApi, rulesForSecondApi, } = splitRules(rules) // 将第一组规则发送给第一个 API 端点 const suggestions1 = await defaultResolver({ ...options, rules: rulesForFirstApiEndpoint apiResolver: async ({ html, htmlChunks, rules }) => { const response = await firstApi({ html, htmlChunks, rules }); return { format: "replacements", content: response }; }, }); // 将第二组规则发送给第二个 API 端点 const suggestions2 = await defaultResolver({ ...options, rules: rulesForSecondApiEndpoint apiResolver: async ({ html, htmlChunks, rules }) => { const response = await secondApi({ html, htmlChunks, rules }); return { format: "fullHtml", content: response }; }, }); // 合并两组建议列表 return [...suggestions1, ...suggestions2] },
提升性能
为提升生成建议时 API 和自定义大语言模型的性能,可参考:
- 选择在准确率、速度和低延迟间平衡的模型。使用如 Artificial Analysis 这类排行榜从多维度对比模型。
- 在改进性能前,测量 API 响应时间。若流程有多个步骤或模型调用,分析每步瓶颈。利用 Evalite 持续迭代提示和效果对比。
- 利用 OpenAI 预测输出(或其他 LLM 提供商的同类功能)提升延迟和处理速度。
- 将编辑器内容分块,分块并行处理,缩短整体处理时间,尤其针对大型文档。利用扩展内建分块缓存机制,仅重新加载变更部分的建议。
- 设计提示时利用完整或部分缓存。不同 LLM 提供商缓存机制差异较大,有的甚至不支持。必要时自行实现缓存机制,复用相同或相似提示的响应。
- 流式响应可以改善 API 体验,特别是大文档,允许在完整响应生成前先展示建议。虽然 AI 建议扩展当前不支持流式,但未来版本可能添加。如你认为此功能有用,欢迎通过 humans@tiptap.dev 联系我们。
完全替换解析器函数(进阶)
若想完全掌控编辑器建议的生成方式,包括明确建议在文档中的具体位置,可提供自定义 resolver 函数。该函数应基于编辑器内容和规则,返回建议数组。
生成有效建议对象需计算编辑器中的具体位置,通常涉及对比编辑器当前内容和大语言模型生成的内容。你可查看扩展源码中的默认解析器函数示例。
更多每条建议对象所需数据详见API 参考。
AiSuggestion.configure({
async resolver({ defaultResolver, ...options }) {
const suggestions = await customResolver(options)
return suggestions
},
})总的来说,自定义解析器实现工作量更大,但灵活性最高。仅推荐用于高级用例。
结合 Tiptap 内容 AI 云和你自己的后端
你无需在使用 Tiptap 内容 AI 云和自定义后端间做选择。可结合两者优点。
AiSuggestion.configure({
async resolver({ defaultResolver, rules, ...options }) {
// 将规则拆分为两组
const { rulesForDefaultSuggestions, rulesForCustomSuggestions } = splitRules(rules)
// 从 Tiptap 内容 AI 云获取建议
const defaultSuggestions = await defaultResolver({
...options,
rules: rulesForDefaultSuggestions,
})
// 从你自己后端获取建议
const customSuggestions = await customResolver({
...options,
rules: rulesForCustomSuggestions,
})
// 合并两个建议列表
return [...defaultSuggestions, ...customSuggestions]
},
})非 AI 方式生成校对建议
生成校对建议不一定要用 AI。你可以将 AI 模型与经典校对技术结合使用。例如,你可检查指定词汇并替换。下面示例展示一个解析器,将单词 “hello” 替换为 “goodbye” 的建议。
AiSuggestion.configure({
rules: [
{
id: '1',
title: '将 hello 替换为 goodbye',
// 由于不使用 LLM 生成建议,本提示不会被使用
prompt: 'Replace hello with goodbye',
color: '#DC143C',
backgroundColor: 'FFE6E6',
},
],
async resolver({ defaultResolver, ...options }) {
const suggestions = await defaultResolver({
...options,
apiResolver: async ({ html, rules }) => {
// 生成响应,无需调用 LLM
return {
format: 'fullHtml',
content: {
items: [
{
ruleId: '1',
// 返回替换所有 "hello" 为 "goodbye" 后的新文档 HTML
fullHtml: html.replaceAll('hello', 'goodbye'),
},
],
},
}
},
})
return suggestions
},
})