本文根据 Felix Arntz 于 2026 年 5 月 14 日发表于 WordPress Developer Blog 的文章整理并中文化。原文标题:How to build an image generation plugin with the WordPress AI Client。原文作者在文末感谢 @psykro、@juanmaguitar 与 @bph 参与审阅和校对。
- 原文:https://developer.wordpress.org/news/2026/05/how-to-build-an-image-generation-plugin-with-the-wordpress-ai-client/
- 分类:WordPress 运维
- 原文示例插件:AI Client ImageGen
- 原文图片说明:文章展示媒体库中的“Generate Image”弹窗、提示词输入、生成图片预览和保存界面;此处保留文字说明,未附图。
- 许可说明:原文示例插件头和 package.json 标注 GPL-2.0-or-later。原文未为文章文字单独注明转载许可。
目标与前提
本教程要在 WordPress 媒体库中加入一个“Generate Image File”按钮。用户点击后输入提示词,插件通过 WordPress AI Client 请求图像生成,先在界面预览结果,再由用户决定是否将图片保存为新的媒体附件。生成和保存拆成两个 REST API 操作,使用户能先检查图片再入库。
WordPress AI Client 的关键价值,是插件不直接绑定某一家模型服务。站点所有者在 WordPress 后台的 Settings > Connectors 中配置服务和凭据;插件只声明需要图像生成能力,由 WordPress 将请求路由给可用的提供方和模型。原文举例提到 Anthropic、Google、OpenAI 等服务。新增提供方或模型时,已有插件通常不必为每个厂商维护独立代码路径。
开始前需要:
- WordPress 7.0 或更高版本;
- 在 Settings > Connectors 配置了支持图像生成的 AI 提供方和模型;
- Node.js 20 或更高版本,用于构建前端资源;
- 基本的 WordPress 插件、REST API 和 PHP 开发经验。
使用文章所示 @wordpress/env 本地环境还需要 Docker,也可换用其他 WordPress 开发环境。
理解 AI Client 的调用方式
从提示构造器开始
每次调用从 wp_ai_client_prompt() 开始。它返回一个流式构造器,方法采用 WordPress 的 snake_case 命名,并封装底层 php-ai-client 库。
$builder = wp_ai_client_prompt()
->with_text( 'Summarize the benefits of caching in WordPress' )
->using_temperature( 0.7 );
$result = $builder->generate_text_result();
with_text() 设置提示内容;using_temperature() 是可选参数,用来调整输出随机性。调用生成方法后会得到 GenerativeAiResult 对象,其中包含生成内容,以及处理请求的提供方和模型等元数据。该对象可序列化,也可以直接交给 rest_ensure_response(),用于 REST API 响应。图像生成使用同一构造器模式,之后再配置输出格式、方向等选项。
偏好模型,不把模型写成硬依赖
插件可使用 using_model_preference() 按顺序提出首选模型。AI Client 会先尝试首选项;若都不可用,则回退到任何支持所需能力的模型。这样用户能用偏好模型,但不会因为站点没有该模型就无法使用插件。
$builder = wp_ai_client_prompt()
->with_text( 'Summarize the benefits of caching in WordPress' )
->using_temperature( 0.7 )
->using_model_preference( 'gpt-5.4', 'gemini-3.1-pro-preview', 'claude-opus-4.6' );
模型偏好不是强制要求。不要把插件设计成只能与某个特定厂商或型号配合;只有当某个模型特别适合用例时,才把它列为偏好,同时保留其他兼容模型的使用空间。
暴露功能前检查能力
并非每个站点都配置了 AI 提供方,也不是每个模型都支持所有能力。显示按钮或加载界面前,可以调用 is_supported_for_image_generation():
$is_available = wp_ai_client_prompt()
->with_text( 'test' )
->is_supported_for_image_generation();
该方法会根据构造器选项和可用模型声明的能力,判断站点是否有模型支持图像生成。它不发起外部 API 请求、不执行推理,也不分析提示词,因此不会产生推理成本。这个检查适合用于决定是否加载 UI,或在功能不可用时提示管理员去 Connectors 配置服务。仅安装 WordPress 7.0 并不意味着已配置可用的 AI 功能。
插件结构与入口
原文采用如下目录布局:
ai-client-imagegen/
├── plugin.php
├── includes/
│ ├── prompt.php
│ ├── rest-api.php
│ └── admin.php
├── src/
│ └── index.ts
├── build/
│ ├── index.js
│ └── index.asset.php
├── package.json
└── composer.json
- plugin.php:入口文件,加载实现并注册钩子;
- includes/prompt.php:统一构造 AI Client 图像提示;
- includes/rest-api.php:生成图像和保存到媒体库的 REST 路由;
- includes/admin.php:注册脚本,并在媒体库页面按条件加载;
- src/index.ts:前端弹窗、API 调用与保存操作;
- build/:由 @wordpress/scripts 生成的 JavaScript 和依赖清单。
文章中的一些代码片段为突出重点而从实际插件代码中略作删减。完整插件链接见原文所列 GitHub 项目:https://github.com/wptrainingteam/ai-client-imagegen 。原文没有逐行讲解前端约 590 行 TypeScript,而是建议将该项目中的 src/index.ts 放入本地对应目录。
入口文件声明插件信息,确认 WordPress 环境存在,并在 AI Client 函数不存在时提前退出。随后加载实现文件并注册钩子:
<?php
/**
* Plugin Name: AI Client ImageGen
* Plugin URI: https://github.com/wptrainingteam/ai-client-imagegen
* Description: Generates images in the WordPress Media Library using the built-in AI Client.
* Requires at least: 7.0
* Requires PHP: 7.4
* Version: 1.0.0
* Author: Your Name
* License: GPL-2.0-or-later
* Text Domain: ai-client-imagegen
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'wp_ai_client_prompt' ) ) {
return;
}
require_once __DIR__ . '/includes/prompt.php';
require_once __DIR__ . '/includes/rest-api.php';
require_once __DIR__ . '/includes/admin.php';
add_action( 'rest_api_init', 'aicig_register_rest_routes' );
add_action( 'init', 'aicig_register_assets' );
add_action( 'admin_enqueue_scripts', 'aicig_enqueue_media_assets' );
Requires at least: 7.0 用于声明最低 WordPress 版本;function_exists() 则是运行时保护。原文代码中的 Author: Your Name 是示例占位文本,实际插件应填写作者信息。
复用图像提示构造器
在 includes/prompt.php 中,将提示文本和图像输出选项集中到一个函数。可选方向值用于提示期望的媒体比例;未指定时不设置方向。FileTypeEnum::inline() 要求结果以可内嵌数据形式返回,便于前端预览。
<?php
use WordPress\AiClient\Files\Enums\FileTypeEnum;
use WordPress\AiClient\Files\Enums\MediaOrientationEnum;
function aicig_get_image_generation_prompt( string $prompt, string $orientation = '' ): WP_AI_Client_Prompt_Builder {
$builder = wp_ai_client_prompt()
->with_text( $prompt )
->as_output_file_type( FileTypeEnum::inline() );
if ( $orientation ) {
$builder->as_output_media_orientation( MediaOrientationEnum::from( $orientation ) );
}
return $builder;
}
该函数返回构造器而不是立即执行请求。REST 回调之后调用 generate_image_result();管理员界面则复用同一函数做能力检查。提示构造不指定服务商或模型,路由由 AI Client 处理。MediaOrientationEnum::from() 接收 square、landscape 或 portrait 等方向值。
注册 REST API
插件将两个端点放在 ai-client-imagegen/v1 命名空间下:
- POST /generate-image:接收提示词和可选方向,生成图像并返回 AI Client 结果;
- POST /upload-image:接收 Base64 图像、文件名和可选 MIME 类型,将图片保存为媒体附件。
两个端点都使用 current_user_can( ‘upload_files’ ) 作为权限检查。原文将路由注册和处理逻辑拆开说明;下面把文章中的片段放在一起,展示彼此之间的调用关系。
生成图像
生成路由要求 prompt 为字符串,方向可选且限定为 square、landscape 或 portrait。处理器从请求读取参数,调用共享提示构造器,再由 generate_image_result() 执行请求。
function aicig_register_rest_routes(): void {
register_rest_route(
'ai-client-imagegen/v1',
'/generate-image',
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => 'aicig_rest_generate_image',
'permission_callback' => static function () {
return current_user_can( 'upload_files' );
},
'args' => array(
'prompt' => array(
'type' => 'string',
'required' => true,
),
'orientation' => array(
'type' => 'string',
'required' => false,
'enum' => array( 'square', 'landscape', 'portrait' ),
),
),
)
);
}
function aicig_rest_generate_image( WP_REST_Request $request ) {
$prompt = $request->get_param( 'prompt' );
$orientation = $request->get_param( 'orientation' );
$builder = aicig_get_image_generation_prompt(
$prompt,
$orientation ?? ''
);
return rest_ensure_response(
$builder->generate_image_result()
);
}
GenerativeAiResult 可以序列化,因此 rest_ensure_response() 能直接将结果转换为 JSON 响应,其中包含图像数据和提供方、模型等元数据。若发生错误,generate_image_result() 返回的 WP_Error 也可作为 REST 响应处理。
保存到媒体库
用户确认预览后,前端把图像的 Base64 数据、文件名和 MIME 类型发送给保存端点。回调严格解码 Base64;无效数据返回 400 错误。文件写入失败时返回 500 错误。写入成功后,创建附件、生成缩略图和元数据,最终响应附件 ID 与 URL。
function aicig_register_rest_routes(): void {
// Other REST route registration for generating an image.
register_rest_route(
'ai-client-imagegen/v1',
'/upload-image',
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => 'aicig_rest_upload_image',
'permission_callback' => static function () {
return current_user_can( 'upload_files' );
},
'args' => array(
'image_base64' => array(
'type' => 'string',
'required' => true,
),
'file_name' => array(
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_file_name',
),
'mime_type' => array(
'type' => 'string',
'required' => false,
'default' => 'image/png',
'sanitize_callback' => 'sanitize_mime_type',
),
),
)
);
}
function aicig_rest_upload_image( WP_REST_Request $request ) {
$image_base64 = $request->get_param( 'image_base64' );
$file_name = $request->get_param( 'file_name' );
$mime_type = $request->get_param( 'mime_type' );
$decoded = base64_decode( $image_base64, true );
if ( false === $decoded ) {
return new WP_Error(
'invalid_image_data',
__( 'The provided image data is not valid base64.', 'ai-client-imagegen' ),
array( 'status' => 400 )
);
}
$upload = wp_upload_bits( $file_name, null, $decoded );
if ( ! empty( $upload['error'] ) ) {
return new WP_Error(
'upload_failed',
$upload['error'],
array( 'status' => 500 )
);
}
$attachment_data = array(
'post_mime_type' => $mime_type,
'post_title' => sanitize_file_name(
pathinfo( $file_name, PATHINFO_FILENAME )
),
'post_status' => 'inherit',
);
$attachment_id = wp_insert_attachment(
$attachment_data,
$upload['file']
);
if ( is_wp_error( $attachment_id ) ) {
return $attachment_id;
}
require_once ABSPATH . 'wp-admin/includes/image.php';
$metadata = wp_generate_attachment_metadata(
$attachment_id,
$upload['file']
);
wp_update_attachment_metadata( $attachment_id, $metadata );
return rest_ensure_response(
array(
'id' => $attachment_id,
'url' => wp_get_attachment_url( $attachment_id ),
)
);
}
文件名和 MIME 类型分别通过 sanitize_file_name()、sanitize_mime_type() 清理。创建媒体附件是标准 WordPress 流程:wp_upload_bits() 写文件,wp_insert_attachment() 创建记录,wp_generate_attachment_metadata() 与 wp_update_attachment_metadata() 保存尺寸等元数据。原文把两个路由示例分开展示;在实际文件中,应将两个 register_rest_route() 调用合并到同一个 aicig_register_rest_routes() 定义中,而不是重复定义同名函数。
后台脚本注册与按需加载
在 includes/admin.php 中,先注册打包后的脚本。index.asset.php 由 @wordpress/scripts 自动生成,包含依赖和基于内容的版本标识;若文件暂时不存在,原文示例提供空依赖和 1.0.0 版本的回退值。
function aicig_register_assets(): void {
$asset_file = plugin_dir_path( __DIR__ ) . 'build/index.asset.php';
if ( file_exists( $asset_file ) ) {
$asset = require $asset_file;
} else {
$asset = array(
'dependencies' => array(),
'version' => '1.0.0',
);
}
wp_register_script(
'aicig-imagegen',
plugins_url( 'build/index.js', __DIR__ ),
$asset['dependencies'],
$asset['version'],
array( 'strategy' => 'defer' )
);
}
然后仅在媒体库、且当前用户有上传权限、且站点存在图像生成能力时,加载前端脚本:
function aicig_enqueue_media_assets( string $hook_suffix ): void {
if ( 'upload.php' !== $hook_suffix ) {
return;
}
if ( ! current_user_can( 'upload_files' ) ) {
return;
}
if ( ! aicig_get_image_generation_prompt( 'test' )->is_supported_for_image_generation() ) {
// Show an admin notice, or handle the unsupported case in another way.
return;
}
wp_enqueue_script( 'aicig-imagegen' );
}
三道条件依次是:
- 页面必须是媒体库(upload.php);
- 用户必须有 upload_files 权限;
- AI Client 必须报告存在可用的图像生成模型。
前两道检查与 REST API 的权限条件一致,避免出现界面可见、操作却无权完成的情况。第三道检查复用提示构造函数;传入 test 只是满足构造器输入,支持检查不会分析提示词,也不会真正生成图像。若没有可用模型,可在提前返回的位置显示提示,引导管理员检查 Connectors 设置。
前端界面
前端文件是约 590 行 TypeScript,原文没有逐行展开。它使用原生 DOM 操作创建弹窗,通过 @wordpress/api-fetch 发送请求、用 @wordpress/i18n 支持国际化,显示图像预览以及提供方和模型信息,并处理保存到媒体库的操作。用户点击保存前可以检查结果,保存时还可以定制文件名。
原文选择轻量的原生 DOM 写法,是因为这个独立弹窗不需要额外框架;界面更复杂时,可考虑使用 WordPress 内置的 React。前端完整实现应从原文提供的项目源码取得:https://github.com/wptrainingteam/ai-client-imagegen/blob/main/src/index.ts 。这篇教程没有包含该文件的完整代码,因此此处不补写未展示的实现细节。
构建与本地运行
在项目根目录添加 package.json,声明前端运行时依赖和构建工具:
{
"name": "ai-client-imagegen",
"private": true,
"license": "GPL-2.0-or-later",
"dependencies": {
"@wordpress/api-fetch": "^7.41.0",
"@wordpress/i18n": "^6.14.0"
},
"devDependencies": {
"@wordpress/env": "^10.27.0",
"@wordpress/scripts": "^31.0.0",
"typescript": "^5.8.2"
},
"scripts": {
"build": "wp-scripts build",
"wp-env": "wp-env"
}
}
再添加 .wp-env.json,使用 WordPress 7.0 并将当前目录作为启用的插件:
{
"core": "https://wordpress.org/wordpress-7.0.zip",
"plugins": [ "." ]
}
安装依赖并生成前端构建文件:
npm install
npm run build
@wordpress/scripts 会把 src/index.ts 编译为 build/index.js,并生成 build/index.asset.php 依赖清单。PHP 部分不需要单独构建,因为 AI Client 随 WordPress Core 提供。
若用 @wordpress/env 启动本地开发站点:
npm run wp-env start
该环境基于 Docker,默认在 http://localhost:8888 提供站点;原文给出的默认登录凭据是 admin / password。启动后按以下顺序操作:
- 在 Settings > Connectors 配置支持图像生成的服务;
- 打开 Media > Library;
- 点击“Generate Image File”,输入提示词并生成图片;
- 检查预览,满意后点击保存按钮,并可修改文件名。
如果看到的是提示而非生成按钮,说明当前已配置的提供方不支持图像生成,应检查 Connectors 设置。以上是原文的运行步骤;本文没有实际运行插件或验证生成结果。
后续扩展:把现有图片交给 AI 编辑
原文指出,图像编辑可沿用几乎相同的提示构造方式,只需额外把既有图像作为 File DTO 输入:
use WordPress\AiClient\Files\DTO\File;
use WordPress\AiClient\Files\Enums\FileTypeEnum;
use WordPress\AiClient\Files\Enums\MediaOrientationEnum;
function aicig_get_image_editing_prompt( string $prompt, File $image_file, string $orientation = '' ): WP_AI_Client_Prompt_Builder {
$builder = wp_ai_client_prompt()
->with_text( $prompt )
->with_file( $image_file )
->as_output_file_type( FileTypeEnum::inline() );
if ( $orientation ) {
$builder->as_output_media_orientation( MediaOrientationEnum::from( $orientation ) );
}
return $builder;
}
with_file() 将源图片传给 AI Client,再由 Client 路由到支持图像编辑的提供方和模型。可以在生成端点增加可选图片参数,并按参数有无选择生成或编辑提示构造函数;前端则需要相应设计编辑入口和交互。
原文还提出几种延伸方向:
- 为一个提示词生成多张变体,让用户挑选;
- 利用文本生成功能,根据图片内容自动生成更有描述性的文件名;
- 从媒体库选择已有图片,输入指令后请求 AI 编辑。
小结
这个示例中,真正负责 AI 接入的部分很小:一个统一构造提示的函数,以及调用 generate_image_result() 的 REST 处理器。其余工作仍是熟悉的 WordPress 插件开发,包括路由注册、媒体附件创建、权限判断和后台脚本加载。AI Client 接管服务商通信、认证、模型选择与结果规范化,使插件能把注意力放在媒体库中的用户流程上。
wp_ai_client_prompt() 提供统一入口;模型偏好让插件表达理想选项而不强制绑定;is_supported_for_image_generation() 能在不发起推理请求的前提下确认能力;拆分“生成预览”和“保存媒体”则把最终入库的决定留给用户。基于同一结构,还可以继续探索图片编辑、变体生成与智能命名。
来源信息
- 原文作者:Felix Arntz
- 原文标题:How to build an image generation plugin with the WordPress AI Client
- 原文日期:2026 年 5 月 14 日
- 原文地址:https://developer.wordpress.org/news/2026/05/how-to-build-an-image-generation-plugin-with-the-wordpress-ai-client/
- 原文致谢:@psykro、@juanmaguitar、@bph(审阅与校对)











暂无评论内容