BlockNote Docs特性AIBlockNote AI 参考

AI 参考

AIExtension

使用 AIExtension 创建一个新的 AI 扩展,可以在调用 useCreateBlockNote 时注册到编辑器。

// 用法示例:
useCreateBlockNote({
  // 注册 AI 扩展
  extensions: [AIExtension(options)],
  // 其他编辑器配置
});

type AIExtensionOptions = AIRequestHelpers & {
  /**
   * AI 正在写作时代理光标的名称和颜色
   * @default { name: "AI", color: "#8bc6ff" }
   */
  agentCursor?: { name: string; color: string };
};

type AIRequestHelpers = {
  /**
   * AI SDK 用于向您的后端/LLM 发送请求的传输方式。
   * 实现此项可定制后端 URL 或使用不同的传输方式(例如 websockets)。
   */
  transport?: ChatTransport<UIMessage>;

  /**
   * 使用 ChatProvider 自定义 AI SDK Chat 实例的创建方式。
   * 例如,当您想重用应用程序中其他部分使用的现有 Chat 实例时。
   *
   * @note 不能同时使用 `chatProvider` 和 `transport`。
   */
  chatProvider?: () => Chat<UIMessage>;

  /**
   * 自定义 LLM 可用的流工具。
   */
  streamToolsProvider?: StreamToolsProvider<any, any>;
  // 可在 AIExtension(options) 中提供 `streamToolsProvider`,或通过 InvokeAIOptions 在调用时覆盖。
  // 如果省略,默认使用 `aiDocumentFormats.html.getStreamToolsProvider()`。

  /**
   * 转发给 AI SDK 请求的额外选项(headers/body/metadata)。
   */
  chatRequestOptions?: ChatRequestOptions;

  /**
   * 构建可序列化的文档状态,将转发给后端。
   *
   * @default aiDocumentFormats.html.defaultDocumentStateBuilder
   */
  documentStateBuilder?: DocumentStateBuilder<any>;
};

AIExtension 扩展实例

通过 editor.getExtension(AIExtension) 获得的 AIExtension 扩展实例,暴露状态和方法,用于与 BlockNote 的 AI 功能交互。

type AIExtensionInstance = {
  /**
   * 调用 LLM 并将结果应用到编辑器
   */
  invokeAI(opts: InvokeAIOptions): Promise<void>;

  /**
   * 返回一个只读的 Tanstack Store,包含 AI 菜单的状态
   */
  get store(): Store<{
    aiMenuState:
      | ({
          /**
           * AI 菜单打开时所在块的 ID。
           * 在 AI 修改文档时会发生变化
           */
          blockId: string;
        } & (
          | {
              status: "error";
              error: any;
            }
          | {
              status:
                | "user-input"
                | "thinking"
                | "ai-writing"
                | "user-reviewing";
            }
        ))
      | "closed";
  }>;

  /**
   * 返回包含 AI 扩展全局配置的 Tanstack Store。
   * 调用 {@link invokeAI} 时,默认使用这些配置。
   */
  readonly options: Store<AIRequestHelpers>;

  /** 在特定块打开 AI 菜单 */
  openAIMenuAtBlock(blockID: string): void;
  /** 关闭 AI 菜单 */
  closeAIMenu(): void;
  /** 接受 LLM 所做的更改 */
  acceptChanges(): void;
  /** 拒绝 LLM 所做的更改 */
  rejectChanges(): void;
  /** 重试上一次 LLM 调用(仅当状态为 "error" 时有效) */
  retry(): Promise<void>;
  /** 中止当前的 LLM 请求 */
  abort(reason?: any): Promise<void>;
  /** 高级用法:手动更新 AI 菜单显示的状态 */
  setAIResponseStatus(
    status:
      | "user-input"
      | "thinking"
      | "ai-writing"
      | "user-reviewing"
      | { status: "error"; error: any },
  ): void;
};

InvokeAI

通过调用 AIExtension 实例的 invokeAI 发起对 LLM 的请求。该方法接受一个 InvokeAIOptions 对象作为参数。

type InvokeAIOptions = {
  /** 用户提示 */
  userPrompt: string;

  /** 是否使用编辑器选区作为 LLM 调用内容(默认:true) */
  useSelection?: boolean;

  /**
   * 如果用户光标处在一个空段落,当 AI 开始写作时自动删除该段落。
   * 用于在空块中输入 `/ai` 时。(默认:true)
   */
  deleteEmptyCursorBlock?: boolean;
} & AIRequestHelpers; // 可在每次调用时覆盖助手选项

因为 InvokeAIOptions 继承自 AIRequestHelpers,您可以在每次调用时单独覆盖这些选项,而不改变全局的扩展配置。

getStreamToolsProvider

调用 LLM 时,需要解析文档并调用操作以修改文档。使用格式的 getStreamToolsProvider 获取 LLM 编辑时可能调用的工具。通常使用 aiDocumentFormats.html.getStreamToolsProvider(...)

/** 返回供 LLM 使用的流工具提供者 */
type getStreamToolsProvider = (
  // 是否在文档编辑间添加人工延迟
  // 或者直接按 LLM 流式传入的数据立即应用,无延迟
  // (默认:true)
  withDelays: boolean,
  // 使用的流工具,分别用于添加、更新和删除块
  // (默认:{ add: true, update: true, delete: true })
  defaultStreamTools?: {
    add?: boolean;
    update?: boolean;
    delete?: boolean;
  },
) => StreamToolsProvider;

文档状态构建器(高级)

当 BlockNote AI 发送请求时,也会转发编辑器的序列化快照。LLM 使用该文档状态来理解文档、光标位置和选区。DocumentStateBuilder 类型定义了该快照的生成方式:

type DocumentStateBuilder<T> = (
  aiRequest: Omit<AIRequest, "documentState">,
) => Promise<
  | {
      selection: false;
      blocks: BlocksWithCursor<T>[];
      isEmptyDocument: boolean;
    }
  | {
      selection: true;
      selectedBlocks: { id: string; block: T }[];
      blocks: { block: T }[];
      isEmptyDocument: boolean;
    }
>;

默认使用 aiDocumentFormats.html.defaultDocumentStateBuilder

AIRequest(高级)

buildAIRequest 返回执行 AI 调用所需的所有内容:

type AIRequest = {
  editor: BlockNoteEditor;
  selectedBlocks?: Block[];
  emptyCursorBlockToDelete?: string;
  streamTools: StreamTool<any>[];
  documentState: DocumentState<any>;
  onStart: () => void;
};

sendMessageWithAIRequest(高级)

需要手动调用 LLM 且不更新 BlockNote AI 菜单状态时,使用 sendMessageWithAIRequest。 例如,从不同上下文(如聊天窗口)提交 LLM 请求时。 sendMessageWithAIRequest 类似于 chat.sendMessages,但它会将 documentState 附加到发出的消息元数据中,配置工具流式传输,并将工具定义(JSON Schema)转发到后端。

async function sendMessageWithAIRequest(
  chat: Chat<UIMessage>,
  aiRequest: AIRequest,
  message?: Parameters<Chat<UIMessage>["sendMessage"]>[0],
  options?: Parameters<Chat<UIMessage>["sendMessage"]>[1],
): Promise<Result<void>>;

buildAIRequest(高级)

如果绕过 invokeAI 直接调用 sendMessageWithAIRequest,使用 buildAIRequest 从编辑器状态组装 AIRequest

async function buildAIRequest(opts: {
  editor: BlockNoteEditor;
  useSelection?: boolean;
  deleteEmptyCursorBlock?: boolean;
  streamToolsProvider?: StreamToolsProvider<any, any>;
  documentStateBuilder?: DocumentStateBuilder<any>;
  onBlockUpdated?: (blockId: string) => void;
  onStart?: () => void;
}): Promise<AIRequest>;