Report an issue

指南将 AI 助手集成到您的应用程序中

本指南将逐步指导您在编辑器集成中运行 AI 助手。它还介绍了可能的配置和定制选项。

这是一个高级功能,您需要在 CKEditor 5 商业许可证之外获得其许可证。 联系我们 以获取满足您需求的报价。

您也可以注册 CKEditor 高级功能 30 天免费试用 来测试此功能。

# 支持的 AI 服务

首先,您需要确定要与哪个 AI 服务提供商集成。CKEditor 本身不提供 AI 模型。相反,此功能依赖于外部服务来提供 AI 生成的响应。

我们支持三个领先的 AI 服务提供平台:OpenAI、Azure OpenAI 和 Amazon Bedrock。

由于此功能依赖于外部提供商,因此响应质量取决于该提供商及其模型。

如果您对可以使用哪些平台没有限制,我们建议与 OpenAI API 集成。它提供更好的质量,并且设置最简单。

如果您希望使用 Amazon Web Services (AWS) 平台,我们建议使用最新的 Claude 模型。它提供比 Amazon Bedrock 上的其他模型更好的质量。

本指南包含有关如何设置支持的 AI 平台的提示。我们预计集成人员了解其选择的平台的工作原理,以及如何配置它以最佳适应其用例。

# 使用代理端点

在进行集成之前,还有另一个主题需要介绍。

此功能与 AI 服务提供商进行通信的两种通用方法是:直接连接或使用您应用程序中的端点。

直接连接设置起来更简单,并且不应涉及对您应用程序后端的更改。它建议用于开发目的。AI 助手支持这一点,因为它让您更轻松地测试此功能,而无需投入时间来设置集成的后端部分。

但是,这种方法会暴露您的私人授权数据,这是一个严重的安全问题。您绝不应在生产环境中使用它。

在最终解决方案中,您的应用程序应提供一个端点,AI 助手将调用该端点,而不是直接调用 AI 服务。此端点的主要目标是将授权数据隐藏在编辑器用户之外。对 AI 服务的请求应从您的后端进行,无需暴露授权凭据。

应用程序端点也是实现其他功能的好地方,例如请求自定义、用户计费或记录统计信息。

# 安装

⚠️ 新的导入路径

版本 42.0.0 开始,我们更改了导入路径的格式。本指南使用新的、更短的格式。如果您使用的是旧版本的 CKEditor 5,请参考 旧版设置中的包 指南。

安装编辑器 后,将该功能添加到您的插件列表和工具栏配置中

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        // Load the plugin.
        plugins: [ AIAssistant, /* ... */ ],

        // Provide the license key.
        licenseKey: '<YOUR_LICENSE_KEY>',

        // Add the "AI commands" and "AI Assistant" buttons to the toolbar.
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        // AI configuration will land here:
        ai: {
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

详细了解 安装插件工具栏配置

# 集成

在下一步中,您需要设置您选择的 AI 服务,并集成编辑器以使用它

# OpenAI 集成

本节介绍如何将 AI 助手与 OpenAI 平台 集成。

# 设置帐户

创建 一个 OpenAI 帐户,并获取您的 OpenAI API 密钥。

# 建立连接

要连接到 OpenAI 服务,您需要向编辑器添加一个连接适配器插件。该适配器负责以正确的格式发出请求并处理响应。

ckeditor5-ai 包中导入 OpenAITextAdapter 插件,并将其添加到插件列表中。

然后,将 OpenAI 密钥添加到编辑器配置中。

您应在请求的“Authorization”标头中发送密钥。您可以使用 config.ai.openAI.requestHeaders 配置属性来设置请求标头。

以下代码段展示了所述更改。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, OpenAITextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            openAI: {
                requestHeaders: {
                    // Paste your OpenAI API key in place of YOUR_OPENAI_API_KEY:
                    Authorization: 'Bearer YOUR_OPENAI_API_KEY'
                }
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

这是启动 AI 助理所需的最小设置。你现在可以测试它了。

# 请求参数

你可以使用 config.ai.openAI.requestParameters 选项进一步配置 OpenAI 适配器的工作方式。

  • 选择要使用的确切 OpenAI 模型。
  • 设置响应是否应该被流式传输(模拟“写作”体验)或一次性返回。
  • 微调模型行为。

查看 OpenAI 参考 以了解你可以使用哪些参数以及它们如何影响响应。

# 支持的模型

默认情况下,OpenAI 适配器将使用“默认”(最新的稳定版)GPT-3.5 模型。

CKEditor 5 支持所有最新的 GPT-3.5 和 GPT-4 模型,以及旧版模型(版本 0613)。

你可以在 OpenAI 文档 中找到有关提供模型的更多信息。

# 与代理端点集成

正如 前面所述,在转入生产环境之前,你应该创建一个端点来与 OpenAI 服务通信,而不是直接连接并暴露你的 OpenAI API 密钥。

对于 OpenAI 集成,你可以将端点(以其最简单的形式)实现为一个透明的代理服务。该服务将从编辑器获取请求,向其中添加授权标头,并将它们传递给 AI 服务。然后,你应该将所有响应传递回编辑器。

实现端点后,使用 config.ai.openAI.apiUrl 选项将 URL 设置为你的端点。另外,请记住从配置中删除 OpenAI 密钥。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, OpenAITextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            openAI: {
                apiUrl: 'https://url.to.your.application/ai'
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

现在,所有请求都被重定向到 'https://url.to.your.application/ai'

# 其他授权和自定义标头

根据你的应用程序,可能需要在将请求发送到你的应用程序端点之前对其进行预授权。一种常见的模式是使用 JSON Web Token (JWT) 授权。

此模式以及类似情况可以通过 config.ai.openAI.requestHeaders 选项得到支持。你可以将其设置为一个对象或一个解析为对象的异步函数。该对象随后被设置为请求标头。

你可以将 config.ai.openAI.requestHeaders 设置为一个函数,该函数查询授权 API 并将返回的 JWT 设置在授权标头中。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, OpenAITextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            openAI: {
                apiUrl: 'https://url.to.your.application/ai',
                requestHeaders: async () => {
                    const jwt = await fetch( 'https://url.to.your.auth.endpoint/' );

                    return {
                        Authorization: 'Bearer ' + jwt
                    };
                }
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

你可以将 actionId 参数传递给 requestHeaders 函数。它标识用户执行的操作。这允许你在你的端点进行进一步的自定义。

{
    requestHeaders: async ( actionId ) => {
        const jwt = await fetch( 'https://url.to.your.auth.endpoint/?actionId=' + actionId );

        return {
            Authorization: 'Bearer ' + jwt
        };
    }
}

# 高级定制

应用请求处理定制的最灵活的地方是你的应用程序端点。但是,如果由于任何原因你无法在应用程序的后端定制请求,你可以考虑在编辑器端使用以下扩展点。

动态请求标头。

如前所述,你可以将 config.ai.openAI.requestHeaders 作为异步函数提供,该函数可以调用你的应用程序。你可以使用 actionId 参数进行进一步的定制。

动态请求参数。

与请求标头类似,你可以将 config.ai.openAI.requestParameters 作为异步函数提供。该函数也会传递 actionId。你可以根据它返回不同的参数。例如,你可以对不同的操作使用不同的模型。

定制 请求消息

传递给 OpenAI 服务的请求消息是根据用户使用该功能的方式构建的:选择的内容和提供的查询。

你可以重载 OpenAITextAdapter#prepareMessages() 方法来定制请求消息或提供自定义逻辑来创建请求消息。

例如

  • 你可以对特定(或自定义)预定义命令微调系统消息。
  • 你可以预先查询你的应用程序以获取额外的上下文信息并将其添加为额外的消息。
  • 你可以从编辑器、文档数据或你的自定义功能中获取额外的上下文或数据。
  • 你可以在将 context 发送到服务之前更改或删除其部分内容。
import { OpenAITextAdapter } from 'ckeditor5-premium-features';

class CustomOpenAITextAdapter extends OpenAITextAdapter {
    public async prepareMessages( query, context, actionId ) {
        const messages = super.prepareMessages( query, context, actionId );

        // Customize `messages` based on your requirements.
        // You can use `actionId` to target only specific actions.
        // You can make a call to your backend since `prepareMessages` is an asynchronous function.
        // You can use `this.editor` to get access to the editor API.

        return messages;
    }
}

请记住将 CustomOpenAITextAdapter 添加到插件列表中,而不是 OpenAITextAdapter

更改 AI 服务响应

发送请求的每个功能都提供 onData() 回调。每次适配器从 AI 服务接收数据时,都会执行该回调。你可以装饰此回调来定制响应。

这将需要重载 OpenAITextAdapter#sendRequest() 方法并更改 requestData.onData 参数。

import { OpenAITextAdapter } from 'ckeditor5-premium-features';

class CustomOpenAITextAdapter extends OpenAITextAdapter {
    public async sendRequest( requestData ) {
        const originalOnData = requestData.onData;

        requestData.onData = ( content ) => {
            // Customize `content` based on your requirements.
            // You can use `requestData.actionId` to target only specific actions.
            // ...
            // Then call the original callback with the modified `content`.
            originalOnData( content );
        };

        return super.sendRequest( requestData );
    }
}

如果适配器在流式模式下工作,content 将包含一个部分的、累积的响应。这可能会给你的自定义处理带来一些额外的复杂性。

请记住将 CustomOpenAITextAdapter 添加到插件列表中,而不是 OpenAITextAdapter

重载 sendRequest() 方法。

你可以重载 sendRequest() 方法,在进行调用之前或之后添加一些处理。

import { OpenAITextAdapter } from 'ckeditor5-premium-features';

class CustomOpenAITextAdapter extends OpenAITextAdapter {
    public async sendRequest( requestData ) {
        // Do something before making the actual request.

        return super.sendRequest( requestData ).then( () => {
            // Do something after the request has finished.
        } );
    }
}

请记住将 CustomOpenAITextAdapter 添加到插件列表中,而不是 OpenAITextAdapter

# Azure OpenAI 集成

本节介绍如何将 AI 助理与 Azure OpenAI 服务 集成。

微软的 Azure 平台提供了许多与 AI 相关的服务。AI 助理仅支持 OpenAI 模型。

# 设置服务

首先,如果你还没有,你需要创建一个 Azure 帐户。

你需要按照以下步骤来设置 AI 助理

  • 登录你的 Azure 帐户。
  • 创建一个“Azure OpenAI”资源。
  • 转到“Azure OpenAI”资源并打开“密钥和端点”以找到你的 API 密钥。
  • 转到“模型部署”,然后创建一个部署。选择你想要使用的模型和名称。
  • 你将需要资源名称、API 密钥和部署名称来配置 AI 助理。

# 建立连接

要连接到 Azure OpenAI 服务,你需要向编辑器添加一个连接适配器插件。该适配器负责以正确的格式发出请求并处理响应。

ckeditor5-ai 包中导入 OpenAITextAdapter 插件,并将其添加到插件列表中。

然后,你需要配置 AI 助理,使其使用你的数据连接到 Azure OpenAI 服务。

  • Azure OpenAI 参考 中所述的请求 URL(它将包含你的部署名称和 API 版本)。
    • 我们使用 2023-12-01-preview API 版本测试了 AI 助理。
  • 你需要在请求 api-key 标头中传递 API 密钥。

以下代码段展示了所述更改。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, OpenAITextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            openAI: {
                // Paste your resource name, deployment name, and API version
                // in place of YOUR_RESORCE_NAME, YOUR_DEPLOYMENT_NAME, and YOUR_API_VERSION:
                apiUrl: 'https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/chat/completions?api-version=YOUR_API_VERSION',
                requestHeaders: {
                    'api-key': 'YOUR_AZURE_OPEN_AI_API_KEY'
                }
            }
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

这是启动 AI 助理所需的最小设置。你现在可以测试它了。

# 请求参数

你可以使用 config.ai.openAI.requestParameters 选项进一步配置 OpenAI 适配器的工作方式。

  • 设置响应是否应该被流式传输(模拟“写作”体验)或一次性返回。
  • 微调模型行为。

查看 Azure OpenAI 参考 以了解你可以使用哪些参数以及它们如何影响响应。

你也可以将 requestParameters 设置为异步函数。在这种情况下,它应该解析为包含参数的对象。该函数接收 actionId 作为参数,它标识用户执行的操作。这允许你在你的端点进行进一步的自定义。

# 支持的模型和 API 版本

CKEditor 5 支持所有最新的 GPT-3.5 和 GPT-4 模型,以及旧版模型(版本 0613)。

你可以在 Azure OpenAI 文档 中找到有关提供模型的更多信息。

测试过的最新 API 版本是 2023-12-01-preview

# 与代理端点集成

正如 前面所述,在转入生产环境之前,你应该创建一个端点来与 OpenAI 服务通信,而不是直接连接并暴露你的 OpenAI API 密钥。

请参阅 “与代理端点集成”部分,了解 OpenAI 集成,因为这两个平台的过程相同。

# 高级定制

应用请求处理定制的最灵活的地方是你的应用程序端点。但是,如果由于任何原因你无法在应用程序的后端定制请求,你可以扩展 OpenAITextAdapter。有很多扩展点可以考虑。

请参阅 “高级定制”部分,了解 OpenAI 集成,因为它对这两个平台都是一样的。

# Amazon Bedrock 集成

本节介绍如何将 AI 助理与 Amazon Bedrock 服务 集成。Amazon Bedrock 是一个在 AWS 上构建生成式 AI 应用程序的服务。

# 设置帐户

首先,如果你还没有,你需要创建一个 AWS 帐户。

你需要按照以下步骤来设置 AI 助理

  1. 登录你的 AWS 帐户。
  2. 设置 Amazon Bedrock 服务。
  3. 转到 Amazon Bedrock 管理。
  4. 转到“模型访问”»“管理模型访问”。
  5. 请求访问你选择的模型。

# 建立连接

要连接到 Amazon Bedrock 服务,你需要向编辑器添加一个连接适配器插件。该适配器负责以正确的格式发出请求并处理响应。

ckeditor5-ai 包中导入 AWSTextAdapter 插件并将其添加到插件列表中。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, AWSTextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            aws: {
                // ...
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

对于与 Amazon Bedrock 的直接连接,AWSTextAdapter 使用 AWS SDK 库中的 BedrockRuntimeClient

要集成 AI 助理,你需要在 config.ai.aws.bedrockClientConfig 选项中设置适当的授权凭据。

使用 AWS 平台对用户进行身份验证的方法有很多。选择一个方便你的方法。从集成的角度来看,唯一必要的步骤是在 config.ai.aws.bedrockClientConfig 选项中设置正确的参数。来自此选项的值将传递给 BedrockRuntimeClient 构造函数。

以下代码段展示了所述更改。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, AWSTextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            aws: {
                bedrockClientConfig: {
                    // Fill in your service region, for example, 'us-west-2'.
                    region: 'YOUR_SERVICE_REGION',
                    credentials: {
                        // Paste your credentials in place of YOUR_ACCESS_KEY_ID and YOUR_SECRET_ACCESS_KEY.
                        accessKeyId: 'YOUR_ACCESS_KEY_ID',
                        secretAccessKey: 'YOUR_SECRET_ACCESS_KEY'
                    }
                }
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

这是启动 AI 助理所需的最小设置。你现在可以测试它了。

# 请求参数

你可以使用 config.ai.aws.requestParameters 选项进一步配置 Amazon Bedrock 适配器的工作方式。

查看 Amazon Bedrock 模型参数参考 以了解更多信息。

不同的模型支持不同的参数集。

# 支持的模型

AWS 文本适配器支持通过 Amazon Bedrock 提供的许多模型。

但是,在撰写本指南时,我们建议使用 Claude 系列的模型,因为它们提供了最佳的结果。其他模型往往会返回更差的、非格式化的答案,无法执行指令,不支持流式传输,而且稳定性差得多。

我们使用以下模型测试了适配器

  • Anthropic 的 Claude
    • 'anthropic.claude-v2'
    • 'anthropic.claude-instant-v1'
  • Meta 的 Llama 2
    • 'meta.llama2-70b-chat-v1'(以及 13b
  • Cohere 的 Command
    • 'cohere.command-text-v14'
    • 'cohere.command-light-text-v14'
  • AI21 的 Jurassic-2
    • 'ai21.j2-mid-v1'

# 与代理端点集成

正如 前面所述,在转入生产环境之前,可能需要在应用程序的后端创建一个端点。它将与 Amazon Bedrock 服务通信。

如果你的集成的前端授权是安全的,不会导致暴露你的秘密授权凭据,则无需这样做。但是,提供一个端点可能是有益的,因为它可以让你增强请求,收集统计数据或控制服务使用情况。

我们建议使用 AWS SDK 来实现端点。它在许多流行的编程语言中都有提供。

当您切换到使用端点时,AI 助手执行的所有请求都将传递到您的端点,而不是 AWS 端点。有效负载将包含所有必要的数据,以便您对 AWS 端点进行实际请求。

作为响应,适配器将期望得到一个包含完整数据(如果非流式)的 JSON 对象,或多个数据部分(如果流式)。

例如,如果 Claude 模型以三个更新流式传输了 '<p>This is a test.</p>',则适配器应该收到三个响应,类似于以下

Response 1: '{ "completion": "<p>Thi" }\n'
Response 2: '{ "completion": "s is a " }\n'
Response 3: '{ "completion": "test</p>" }\n'

您必须用换行符 (\n) 分隔 JSON 字符串,以便适配器能够将它们解析为单独的 JSON 对象。

不同的模型将返回不同的 JSON 结构。您的端点应始终以相同的结构响应。

但是,这对您的端点实现应该是透明的。Amazon Bedrock 将以已经具有正确结构的更新块进行响应。您应该在将这些块响应给适配器之前对其进行解码(从字节表示形式转换为字符串)。

实现端点后,使用 config.ai.aws.apiUrl 选项将 URL 设置为您的端点。此外,请记住删除 BedrockRuntimeClient 的配置。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, AWSTextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            aws: {
                apiUrl: 'https://url.to.your.application/ai'
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

现在,所有请求都被重定向到 'https://url.to.your.application/ai'

# 附加授权和自定义标头

根据你的应用程序,可能需要在将请求发送到你的应用程序端点之前对其进行预授权。一种常见的模式是使用 JSON Web Token (JWT) 授权。

这,以及类似的案例,可以通过 config.ai.aws.requestHeaders 选项来支持。您可以将其设置为对象或解析为对象的异步函数。该对象随后将被设置为请求标头。

您可以将 config.ai.aws.requestHeaders 设置为一个函数,该函数查询授权 API 并将返回的 JWT 设置在授权标头中。

import { ClassicEditor } from 'ckeditor5';
import { AIAssistant, OpenAITextAdapter } from 'ckeditor5-premium-features';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ AIAssistant, OpenAITextAdapter, /* ... */ ],
        licenseKey: '<YOUR_LICENSE_KEY>',
        toolbar: [ 'aiCommands', 'aiAssistant', /* ... */ ],

        ai: {
            openAI: {
                apiUrl: 'https://url.to.your.application/ai',
                requestHeaders: async () => {
                    const jwt = await fetch( 'https://url.to.your.auth.endpoint/' );

                    return {
                        Authorization: 'Bearer ' + jwt
                    };
                }
            }
            // ...
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

你可以将 actionId 参数传递给 requestHeaders 函数。它标识用户执行的操作。这允许你在你的端点进行进一步的自定义。

{
    requestHeaders: async ( actionId ) => {
        const jwt = await fetch( 'https://url.to.your.auth.endpoint/?actionId=' + actionId );

        return {
            Authorization: 'Bearer ' + jwt
        };
    }
}

# 高级定制

应用请求处理定制的最灵活的地方是你的应用程序端点。但是,如果由于任何原因你无法在应用程序的后端定制请求,你可以考虑在编辑器端使用以下扩展点。

动态请求标头。

如前所述,您可以提供 config.ai.aws.requestHeaders 作为异步函数,该函数可以调用您的应用程序。您可以使用 actionId 参数进行进一步的自定义。

动态请求参数。

与请求标头类似,您也可以提供 config.ai.aws.requestParameters 作为异步函数。该函数也传递了 actionId。您可以根据它返回不同的参数。例如,您可以使用不同的模型来处理不同的操作。

自定义请求提示。

传递给 AI 模型的请求提示是根据用户使用该功能的方式构建的:所选内容和提供的查询。

您可以重载 AWSTextAdapter#preparePrompt() 方法来自定义发送给 AI 模型的提示。

例如

  • 您可以针对特定(或您自定义的)预定义命令微调提示。
  • 您可以预先查询您的应用程序以获取额外的上下文信息并将其添加到提示中。
  • 您可以从编辑器、文档数据或自定义功能中获取额外的上下文或数据。
  • 你可以在将 context 发送到服务之前更改或删除其部分内容。
  • 您可以根据所用模型更改提示。

不同的模型可能需要特定的提示格式。

import { AWSTextAdapter } from 'ckeditor5-premium-features';

class CustomAWSTextAdapter extends AWSTextAdapter {
    public async preparePrompt( query, context, model, actionId ) {
        // Customize `query` and `context` based on your requirements.
        // You can use `actionId` to target only specific actions.
        // Then, call the method in the parent class.
        // Alternatively, you can generate the full prompt on your own.
        // Keep in mind that various models may require a specific prompt format.
        // You can make a call to your backend since `preparePrompt` is an asynchronous function.
        // You can use `this.editor` to get access to the editor API.

        return super.preparePrompt( query, context, model, actionId );
    }
}

请记住将 CustomAWSTextAdapter 添加到插件列表中,而不是 AWSTextAdapter

更改 AI 服务响应

发送请求的每个功能都提供 onData() 回调。每次适配器从 AI 服务接收数据时,都会执行该回调。你可以装饰此回调来定制响应。

这将需要重载 AWSTextAdapter#sendRequest() 方法并更改 requestData.onData 参数

import { AWSTextAdapter } from 'ckeditor5-premium-features';

class CustomAWSTextAdapter extends AWSTextAdapter {
    public async sendRequest( requestData ) {
        const originalOnData = requestData.onData;

        requestData.onData = ( content ) => {
            // Customize `content` based on your requirements.
            // You can use `requestData.actionId` to target only specific actions.
            // ...
            // Then call the original callback with the modified `content`.
            originalOnData( content );
        };

        return super.sendRequest( requestData );
    }
}

如果适配器在流式模式下工作,content 将包含部分的、累积的响应。这可能会给您的自定义处理带来一些额外的复杂性。

请记住将 CustomAWSTextAdapter 添加到插件列表中,而不是 AWSTextAdapter

重载 sendRequest() 方法。

你可以重载 sendRequest() 方法,在进行调用之前或之后添加一些处理。

import { AWSTextAdapter } from 'ckeditor5-premium-features';

class CustomAWSTextAdapter extends AWSTextAdapter {
    public async sendRequest( requestData ) {
        // Do something before making the actual request.

        return super.sendRequest( requestData ).then( () => {
            // Do something after the request has finished.
        } );
    }
}

请记住将 CustomAWSTextAdapter 添加到插件列表中,而不是 AWSTextAdapter

# 自定义模型

您可以将 AI 助手与您选择的任何服务以及您的自定义模型集成在一起。

# 使用 OpenAI 适配器并调整 AI 服务响应

支持不同 AI 模型或服务的一种简单方法是使用 OpenAI 集成,然后 在您的应用程序中提供一个端点,该端点将查询所选模型或服务。您需要确保传递给适配器的响应与 OpenAI API 响应格式相同。

最终,适配器对您连接的端点保持无动于衷。它的作用是创建请求数据并处理响应。只要响应格式与 OpenAI API 使用的格式相同,它就会工作。

# 实现自定义适配器

支持不同模型的另一种方法是提供 AITextAdapter 插件的自定义实现。

这将使您在创建请求和处理响应方面拥有更大的灵活性。完整的实现将取决于所选 AI 模型设定的要求。

首先定义您的自定义适配器类

import { AITextAdapter } from 'ckeditor5-premium-features';

class CustomAITextAdapter extends AITextAdapter {}

从编辑器的角度来看,您需要实现 sendRequest() 方法

import { AITextAdapter } from 'ckeditor5-premium-features';

class CustomAITextAdapter extends AITextAdapter {
    public async sendRequest( requestData ) {}
}

这是您应该处理请求的地方。 requestData 参数包含该功能(例如 AI 助手)在调用适配器时提供的数据。

API 文档描述了 requestData 的每个部分。为了更好地理解它,以下是对使用 AI 助手作为示例的细分

  • query – 用户提供的预定义命令查询或自定义查询。AI 模型的指令。
  • context – 用户发出请求时在编辑器中选择的 HTML 内容。它可能是空的。
  • actionId – 对于 AI 助手,这可能是 aiAssistant:customaiAssistant:command:<commandId>。您可以使用它来以不同的方式处理各种用户操作。
  • onData – 对于 AI 助手,它会更新 UI(响应区域)并将更新的响应保存在该功能的内部结构中。您应该在适配器从 AI 服务获得更新时每次调用它。

简而言之,您应该使用 querycontext(以及可选的 actionId)来为 AI 服务构建提示。然后在您收到响应时调用 onData()。这可能发生一次(非流式)或多次(流式)。对流的支持取决于 AI 服务。

import { AITextAdapter } from 'ckeditor5-premium-features';

class CustomAITextAdapter extends AITextAdapter {
    public async sendRequest( requestData ) {
        const prompt = requestData.query + '\n\n' + requestData.context;
        const response = await fetch( `http://url.to.ai.serivce.endpoint/?prompt=${ prompt }` );
        const responseText = await response.text();

        requestData.onData( responseText );
    }
}

或者,您可以将 querycontextactionId 传递到您应用程序端点的请求中,并在后端进行处理。

如果您的适配器由于某种原因失败,您应该抛出 AIRequestError。该错误将由该功能处理。在 AI 助手的情况下,它将在红色通知框中显示。

import { AITextAdapter, AIRequestError } from 'ckeditor5-premium-features';

class CustomAITextAdapter extends AITextAdapter {
    public async sendRequest( requestData ) {
        const prompt = requestData.query + '\n\n' + requestData.context;
        const response = await fetch( `http://url.to.ai.serivce.endpoint/?prompt=${ prompt }` );

        if ( !response.ok ) {
            throw AIRequestError( 'The request failed for unknown reason.' );
        }

        const responseText = await response.text();

        requestData.onData( responseText );
    }
}

最后,将 CustomAITextAdapter 添加到编辑器插件列表中。请注意,您无需添加任何其他适配器

ClassicEditor
    .create( element, {
        plugins: [ AIAssistant, CustomAITextAdapter, /* ... */ ],
        /* .. */
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

如果自定义 AI 模型支持流式传输,您将以多个小块的形式收到响应。确保每次调用 onData() 回调时,传递给它的值都包含完整的响应。它需要是当前更新和所有先前接收到的响应的总和。

# 配置和样式

# 将 AI 命令添加到列表中

“AI 命令” 按钮 AI 命令 允许快速访问最常见的 AI 助手命令。您可以扩展 默认命令列表 或定义您的列表。

使用 config.ai.aiAssistant.extraCommandGroups 配置选项扩展默认命令列表

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        ai: {
            // AI Assistant feature configuration.
            aiAssistant: {
                // Extend the default commands configuration.
                extraCommandGroups: [
                    // Add a command to an existing group:
                    {
                        groupId: 'translate',
                        commands: [
                            {
                                id: 'translatePolish',
                                label: 'Translate to Polish',
                                prompt: 'Translate to Polish language.'
                            }
                        ]
                    },
                    // Create a new AI commands group:
                    {
                        groupId: 'transformations',
                        groupLabel: 'Transformations',
                        commands: [
                            {
                                id: 'addEmojis',
                                label: 'Add emojis',
                                prompt: 'Analyze each sentence of this text. After each sentence add an emoji that summarizes the sentence.'
                            },
                            // ...
                        ]
                    },
                ]
            }
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

使用 config.ai.aiAssistant.commands 配置选项从头开始创建命令列表

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        ai: {
            // AI Assistant feature configuration.
            aiAssistant: {
                // Define the commands list from scratch.
                commands: [
                    // Command groups keep them organized on the list.
                    {
                        groupId: 'customGroupId',
                        groupLabel: 'My group of commands',
                        commands: [
                            {
                                id: 'translateSpanish',
                                label: 'Translate to Spanish',
                                prompt: 'Translate this text to Spanish.'
                            },
                            {
                                id: 'explainFive',
                                label: 'Explain like I\'m five',
                                prompt: 'Explain this like I\'m five years old.'
                            },
                            // ...
                        ]
                    },
                    // You can add more command groups here.
                ]
            }
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

请注意,您可以通过将命令定义直接传递给 ai.aiAssistant.commands 配置键来避免创建命令组。这将导致用户界面中的扁平列表。

# 从列表中删除默认命令

您可以使用 config.ai.aiAssistant.removeCommands 配置从列表中删除一些 默认命令

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        ai: {
            // AI Assistant feature configuration.
            aiAssistant: {
                // Remove some of the default commands.
                removeCommands: [
                    'improveWriting',
                    // ...
                ]
            }
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

# 从 UI 中删除紫色色调

默认情况下,UI 的某些部分带有紫色色调,以将 AI 助手与 CKEditor 5 其他功能区分开来。如果您不希望在集成中使用这种样式,可以通过将 config.ai.useTheme 配置设置为 false 来将其删除

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        ai: {
            // Remove the default feature's theme.
            useTheme: false
        }
    } )
    .then( /* ... */ )
    .catch( /* ... */ );

此编辑器中的 AI 助手与 UI 的其他部分共享颜色。

# 使用自定义颜色为 UI 设置样式

您可以使用 CSS 自定义属性自定义 AI 助手 UI 的外观。以下是您可以设置的 CSS 变量的完整列表。

例如,您可以使用以下 CSS 代码段将色调颜色更改为红色

.ck-ai-assistant-ui_theme {
    --ck-color-button-default-hover-background: hsl(0, 100%, 96%);
    --ck-color-button-default-active-background: hsl(0,100%,96.3%);
    --ck-color-button-on-background: hsl(0,100%,96.3%);
    --ck-color-button-on-hover-background: hsl(0,60%,92.2%);
    --ck-color-button-on-active-background: hsl(0,100%,96.3%);
    --ck-color-button-on-disabled-background: hsl(0,100%,96.3%);
    --ck-color-button-on-color: hsl(0,59.2%,52%);
    --ck-color-button-action-background: hsl(0,59.2%,52%);
    --ck-color-button-action-hover-background: hsl(0,58.9%,49.6%);
    --ck-color-button-action-active-background: hsl(0,58.9%,49.6%);
    --ck-color-button-action-disabled-background: hsl(0,59.3%,75.9%);
    --ck-color-list-button-hover-background: hsl(0,100%,96.3%);
    --ck-color-ai-selection: hsl(0,60%,90%);
}

此编辑器中的 AI 助手 UI 使用配置的红色。

如果您将 config.aiAssistant.useTheme 设置为 false删除默认颜色主题.ck-ai-assistant-ui_theme 类将不再可用。但是,您仍然可以通过 .ck-ai-assistant-ui CSS 类应用自定义样式,该类无论配置如何都会保留。

# 更改对话框的宽度

使用以下 CSS 代码段来加宽 AI 助手弹出式对话框

.ck.ck-ai-form {
    --ck-ai-form-view-width: 800px;
}

# 更改响应区域的高度

使用以下 CSS 代码段来增加响应内容区域的 max-height CSS 属性,并将更多内容显示给用户

.ck.ck-ai-form {
    --ck-ai-form-content-height: 500px;
}

# 为 AI 响应区域设置样式

默认情况下,AI 助手的响应内容区域带有 .ck-content CSS 类。这使得用户能够看到与主编辑器内容相同样式的响应(在 内容样式 指南中了解有关此内容的更多信息)。

但是,如果您的集成在 .ck-content 类范围之外使用自定义样式,并且您希望将它们应用于助手的响应内容区域,您可以使用 config.ai.aiAssistant.contentAreaCssClass 并指定元素的附加类名(或类名)。

还可以通过 .ck.ck-ai-form .ck.ck-ai-form__content-field 选择器为 AI 助手的响应内容区域设置样式

.ck.ck-ai-form .ck.ck-ai-form__content-field h2 {
    /* Custom <h2> styles. */
}