文档
参考

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,
};