BlockNote AI 参考
createAIExtension
使用 createAIExtension
来创建一个新的 AI 扩展,该扩展可以在调用 useCreateBlockNote
时注册到编辑器。
// 用法:
const aiExtension = createAIExtension(opts: AIExtensionOptions);
// 定义:
function createAIExtension(options: AIExtensionOptions): (editor: BlockNoteEditor) => AIExtension;
type AIExtensionOptions = {
/**
* 用于调用大语言模型的默认语言模型
*/
model: LanguageModel;
/**
* 是否对大语言模型的响应进行流式传输
* @default true
*/
stream?: boolean;
/**
* 用于调用大语言模型的默认数据格式
* 推荐使用 html 格式,其他格式为实验性支持
* @default llmFormats.html
*/
dataFormat?: LLMFormat;
/**
* 用于自定义发送给大语言模型的提示函数
* @default 选定 {@link dataFormat} 的默认提示构建器
*/
promptBuilder?: PromptBuilder;
/**
* AI 书写时代理光标的名称和颜色
*
* @default { name: "AI", color: "#8bc6ff" }
*/
agentCursor?: { name: string; color: string };
};
getAIExtension
使用 getAIExtension
来获取注册到编辑器的 AI 扩展实例:
function getAIExtension(editor: BlockNoteEditor): AIExtension;
AIExtension
AIExtension
类是 AI 扩展的主类。它暴露状态和方法以便与 BlockNote 的 AI 功能交互。
class AIExtension {
/**
* 执行对大语言模型的调用并将结果应用到编辑器中
*/
callLLM(
opts: MakeOptional<LLMRequestOptions, "model">,
): Promise<LLMResponse | undefined>;
/**
* 返回一个只读的 zustand 存储,包含 AI 菜单的状态
*/
get store(): ReadonlyStoreApi<{
aiMenuState:
| ({
/**
* AI 菜单打开所在区块的 ID。
* 当 AI 正在修改文档时会发生变化
*/
blockId: string;
} & (
| {
status: "error";
error: any;
}
| {
status:
| "user-input"
| "thinking"
| "ai-writing"
| "user-reviewing";
}
))
| "closed";
/**
* 大语言模型的上一次响应,用于多步调用
*/
llmResponse?: LLMResponse;
}>;
/**
* 返回 zustand 存储,包含 AI 扩展的全局配置,
* 这些选项在所有调用 {@link callLLM} 的大语言模型请求中作为默认值
*/
readonly options: StoreApi<{
model: LanguageModel;
dataFormat: LLMFormat;
stream: boolean;
promptBuilder?: PromptBuilder;
}>;
/**
* 在指定区块打开 AI 菜单
*/
openAIMenuAtBlock(blockID: string): void;
/**
* 关闭 AI 菜单
*/
closeAIMenu(): void;
/**
* 接受大语言模型所做的更改
*/
acceptChanges(): void;
/**
* 拒绝大语言模型所做的更改
*/
rejectChanges(): void;
/**
* 重试上一次大语言模型调用。
*
* 仅当当前状态为 "error" 时有效
*/
retry(): Promise<void>;
/**
* 更新大语言模型调用的状态
*
* @warning 该方法通常仅用于高级用例,
* 如果您想要实现大语言模型调用的执行方式。
* 通常应使用 {@link callLLM},其会自动处理状态更新。
*/
setAIResponseStatus(
status:
| "user-input"
| "thinking"
| "ai-writing"
| "user-reviewing"
| {
status: "error";
error: any;
},
): void;
}
LLMRequestOptions
对大语言模型的请求由 AIExtension
对象的 callLLM
调用发起。
该方法接受一个 LLMRequestOptions
对象作为参数。
type LLMRequestOptions = {
/**
* 用于调用大语言模型的语言模型 (AI SDK)
*
* (通过 `AIExtension` 调用 `callLLM` 时,默认使用 `AIExtension` 配置中的模型)
*/
model: LanguageModelV1;
/**
* 用于大语言模型调用的用户提示
*/
userPrompt: string;
/**
* 大语言模型之前的响应,用于多步调用
*
* (通过 `AIExtension` 类调用 `callLLM` 时自动填充)
*/
previousResponse?: LLMResponse;
/**
* 用于调用大语言模型的默认数据格式
* 推荐使用 "html",其他格式为实验性支持
* @default html 格式(`llm.html`)
*/
dataFormat?: LLMFormat;
/**
* 用于调用大语言模型的 `PromptBuilder`
*
* (PromptBuilder 是一个函数,接受 BlockNoteEditor 和用户提示的详细信息,
* 生成一个 AI SDK 的 `CoreMessage` 数组传入大语言模型)
*
* @default 由格式提供 (例如 `llm.html.defaultPromptBuilder`)
*/
promptBuilder?: PromptBuilder;
/**
* 大语言模型调用的最大重试次数
*
* @default 2
*/
maxRetries?: number;
/**
* 是否使用编辑器选择范围作为大语言模型调用的上下文
*
* @default true
*/
useSelection?: boolean;
/**
* 定义大语言模型是否允许添加、更新或删除区块
*
* @default { add: true, update: true, delete: true }
*/
defaultStreamTools?: {
/** 是否启用添加工具(默认:true) */
add?: boolean;
/** 是否启用更新工具(默认:true) */
update?: boolean;
/** 是否启用删除工具(默认:true) */
delete?: boolean;
};
/**
* 是否对大语言模型响应进行流式传输
*
* 流式时,使用 AI SDK 的 `streamObject` 函数;
* 非流式时,使用 AI SDK 的 `generateObject` 函数。
*
* @default true
*/
stream?: boolean;
/**
* 如果用户光标位于空段落,当 AI 开始书写时自动删除该段落
*
* (用于用户在空白块内输入 `/ai` 命令时)
*
* @default true
*/
deleteEmptyCursorBlock?: boolean;
/**
* 当大语言模型更新特定区块时的回调
*
* (由 `AIExtension` 使用,用于更新 `AIMenu` 位置)
*/
onBlockUpdate?: (blockId: string) => void;
/**
* 当 AI 代理开始书写时的回调
*/
onStart?: () => void;
/**
* 是否在文本更新操作之间添加延迟,使 AI 模拟人类打字
*
* @default true
*/
withDelays?: boolean;
/**
* 传递给 AI SDK `generateObject` 函数的附加选项
* (仅在 `stream` 为 false 时使用)
*/
_generateObjectOptions?: Partial<Parameters<typeof generateObject<any>>[0]>;
/**
* 传递给 AI SDK `streamObject` 函数的附加选项
* (仅在 `stream` 为 true 时使用)
*/
_streamObjectOptions?: Partial<Parameters<typeof streamObject<any>>[0]>;
};
doLLMRequest
(高级)
callLLM
函数会自动将 AIExtension
中设置的默认选项传递给大语言模型请求。
它还会处理大语言模型响应并相应地更新 AI 菜单的状态。
对于高级用例,您也可以直接使用底层的 doLLMRequest
函数直接发起大语言模型请求,
此时需要您手动处理响应。
/**
* 执行一次大语言模型调用
*
* @param editor - 需要操作的大语言模型的 BlockNoteEditor
* @param opts - 大语言模型调用的选项(@link {CallLLMOptions})
* @returns 一个包含大语言模型响应的 `LLMResponse` 对象,可应用到编辑器
*/
function doLLMRequest(
editor: BlockNoteEditor<any, any, any>,
opts: LLMRequestOptions,
): Promise<LLMResponse>;
调用 LLMResponse
对象的 execute
方法可以将变化应用到编辑器。
PromptBuilder(高级)
PromptBuilder
是一个函数,接受一个 BlockNoteEditor 和用户提示相关的详细信息,
将其转换为一组 CoreMessage(AI SDK)数组传递给大语言模型。
提供自定义的 PromptBuilder
可以精细控制发送给大语言模型的指令。
可以使用 LLM 格式中提供的 promptHelpers
来实现自定义的 PromptBuilder
。
建议参考 默认 PromptBuilder (opens in a new tab) 实现来着手定制属于自己的。
/**
* PromptBuilder 是一个函数,接受 BlockNoteEditor 和用户提示相关信息,
* 并将其构造成一组 CoreMessage (AI SDK),传给大语言模型。
*/
type PromptBuilder = (
editor: BlockNoteEditor<any, any, any>,
opts: PromptBuilderInput,
) => Promise<Array<CoreMessage>>;
/**
* 传递给 PromptBuilder 的输入参数
*/
type PromptBuilderInput = {
/**
* 用户的提示内容
*/
userPrompt: string;
/**
* 大语言模型应针对的编辑器所选区块
*/
selectedBlocks?: Block<any, any, any>[];
/**
* 应排除在提示之外的区块 ID
* (例如:如果 LLMRequest 中设置了 `deleteEmptyCursorBlock` 为 true,
* 这里会包含要忽略的区块 ID)
*/
excludeBlockIds?: string[];
/**
* 在多步骤对话或前次出现错误修复时,
* 之前发送给大语言模型的信息列表
*/
previousMessages?: Array<CoreMessage>;
};
格式
调用大语言模型时,大语言模型需要解析文档并执行操作来修改文档。 不同的模型可能更好地理解不同的数据格式。 默认情况下,BlockNote 和大语言模型采用基于 HTML 的格式进行交互。同时我们还提供实验性的 JSON 和 Markdown 格式。
type LLMFormat = {
/**
* 获取该格式特定的流式操作工具列表,大语言模型可以选择调用
*/
getStreamTools: (
editor: BlockNoteEditor<any, any, any>,
withDelays: boolean,
defaultStreamTools?: {
add?: boolean;
update?: boolean;
delete?: boolean;
},
selectionInfo?: {
from: number;
to: number;
},
onBlockUpdate?: (blockId: string) => void,
) => StreamTool<any>[];
/**
* 默认的 PromptBuilder,用于将用户提示转换为一组大语言模型消息 (CoreMessage[])
*/
defaultPromptBuilder: PromptBuilder;
/**
* 实现自定义 PromptBuilder 时可用的辅助函数。
* 函数签名依赖于具体格式
*/
promptHelpers: any;
};
// 默认的 LLMFormat 导出为 `llmFormats`:
export const llmFormats = {
_experimental_json,
_experimental_markdown,
html,
};