Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ This [Canonical Plugin](https://make.wordpress.org/core/2022/09/11/canonical-plu
* **[Content Summarization](docs/experiments/summarization.md)** - Summarizes long-form content into digestible overviews.
* **[Excerpt Generation](docs/experiments/excerpt-generation.md)** - Generates excerpt suggestions from content.
* **Experiment Framework** - Opt-in system that lets you enable only the AI features you want to use.
* **[Image Generation and Editing](docs/experiments/image-generation.md)** - Create and edit images from post content in the editor, also via the Media Library.
* **[Image Generation and Editing](docs/features/image-generation.md)** - Create and edit images from post content in the editor, also via the Media Library.
* **[Meta Description Generation](docs/experiments/meta-description.md)** - Generates meta description suggestions and integrates those with various SEO plugins.
* **Multi-Provider Support** - Works with popular AI providers like OpenAI, Google, and Anthropic.
* **[Review Notes](docs/experiments/review-notes.md)** - Reviews post content block-by-block and adds Notes with suggestions for Accessibility, Readability, Grammar, and SEO.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

## Summary

The Image Generation experiment adds AI-powered image generation to the WordPress post editor in two ways: **featured images** (from the featured image panel) and **inline images** (from supported blocks). It provides a "Generate featured image" button in the featured image panel and a "Generate Image" buttons on Image, Cover, Media & Text, and Gallery blocks. The experiment registers three WordPress Abilities (`ai/image-generation`, `ai/image-import`, `ai/image-prompt-generation`) that can be used both through the admin UI and directly via REST API requests.
The Image Generation feature adds AI-powered image generation to the WordPress post editor in two ways: **featured images** (from the featured image panel) and **inline images** (from supported blocks). It provides a "Generate featured image" button in the featured image panel and a "Generate Image" buttons on Image, Cover, Media & Text, and Gallery blocks. The feature registers three WordPress Abilities (`ai/image-generation`, `ai/image-import`, `ai/image-prompt-generation`) that can be used both through the admin UI and directly via REST API requests.

## Overview

### For End Users

When enabled, the Image Generation experiment adds:
When enabled, the Image Generation feature adds:

- **Featured image panel:** A "Generate featured image" button that creates AI images from post content. The image is imported into the media library and set as the featured image. Images are marked with an "AI Generated Featured Image" label.
- **Block buttons:** A "Generate Image" inline and toolbar button on Image, Cover, Media & Text, and Gallery blocks. Clicking it opens a modal where you describe the image, generate it, preview it, optionally refine it (edit with follow-up prompts using the current image as reference), and insert it into the block.
Expand All @@ -29,9 +29,9 @@ When enabled, the Image Generation experiment adds:

### For Developers

The experiment consists of four main components:
The feature consists of four main components:

1. **Experiment Class** (`WordPress\AI\Experiments\Image_Generation\Image_Generation`): Handles registration, asset enqueuing, featured image and inline block editor UI integration, and post meta registration
1. **Feature Class** (`WordPress\AI\Features\Image_Generation\Image_Generation`): Handles registration, asset enqueuing, featured image and inline block editor UI integration, and post meta registration
2. **Generate Image Prompt Ability** (`WordPress\AI\Abilities\Image\Generate_Image_Prompt`): Generates optimized image generation prompts from post content and context
3. **Generate Image Ability** (`WordPress\AI\Abilities\Image\Generate_Image`): Generates base64-encoded images from prompts (and optionally from a reference image for refining) using AI models
4. **Import Image Ability** (`WordPress\AI\Abilities\Image\Import_Base64_Image`): Imports base64-encoded images into the WordPress media library
Expand All @@ -42,7 +42,7 @@ All three abilities can be called directly via REST API, making them useful for

### Key Hooks & Entry Points

- `WordPress\AI\Experiments\Image_Generation\Image_Generation::register()` wires everything once the experiment is enabled:
- `WordPress\AI\Features\Image_Generation\Image_Generation::register()` wires everything once the feature is enabled:
- `register_post_meta()` → registers `ai_generated` post meta for attachment post type
- `wp_abilities_api_init` → registers the `ai/image-generation`, `ai/image-import`, and `ai/image-prompt-generation` abilities
- `admin_enqueue_scripts` → `enqueue_assets()` loads assets on `post.php` and `post-new.php` screens for post types that support featured images
Expand All @@ -51,8 +51,8 @@ All three abilities can be called directly via REST API, making them useful for
### Assets & Data Flow

1. **PHP Side:**
- `enqueue_shared_assets()` (called from `enqueue_assets()` and `enqueue_inline_assets()`) loads `experiments/image-generation` (`src/experiments/image-generation/index.ts`) and localizes `window.aiImageGenerationData` with:
- `enabled`: Whether the experiment is enabled
- `enqueue_shared_assets()` (called from `enqueue_assets()` and `enqueue_inline_assets()`) loads `features/image-generation` (`src/features/image-generation/index.ts`) and localizes `window.aiImageGenerationData` with:
- `enabled`: Whether the feature is enabled
- `altTextEnabled`: Whether the alt text generation experiment is enabled

2. **React Side (Featured Image):**
Expand Down Expand Up @@ -675,7 +675,7 @@ Example error response:
}
```

## Extending the Experiment
## Extending the Feature

### Customizing the Image Prompt Generation System Instruction

Expand Down Expand Up @@ -706,7 +706,7 @@ add_filter( 'wpai_preferred_image_models', function( $models ) {
You can customize what metadata is saved when importing images by modifying the `uploadImage` function in:

```typescript
src/experiments/image-generation/functions/upload-image.ts
src/features/image-generation/functions/upload-image.ts
```

`uploadImage( imageData, options? )` accepts generated image data and an optional `options` object with `onProgress?: ( message: string ) => void` for progress callbacks. When the Alt Text Generation experiment is enabled, it generates alt text via `generateAltText()` before importing; otherwise it uses the image prompt as alt text.
Expand All @@ -715,45 +715,45 @@ You can also filter the input before calling the import ability via REST API.

### Customizing Post Context

The experiment uses `getContext()` to fetch post details (title, type). You can extend this to include additional context by modifying:
The feature uses `getContext()` to fetch post details (title, type). You can extend this to include additional context by modifying:

```typescript
src/experiments/image-generation/functions/get-context.ts
src/features/image-generation/functions/get-context.ts
```

The context is formatted using `formatContext()` which converts key-value pairs into a string format. You can customize this formatting by modifying:

```typescript
src/experiments/image-generation/functions/format-context.ts
src/features/image-generation/functions/format-context.ts
```

### Adding Custom UI Elements

You can extend the React components to add custom UI elements:

1. **Modify the featured image button and progress UI:**
- Edit `src/experiments/image-generation/components/GenerateFeaturedImage.tsx`
- Edit `src/features/image-generation/components/GenerateFeaturedImage.tsx`
- The component renders a button and, while generating, a progress container (`.ai-featured-image__progress`) that displays the current step and a spinner; progress is driven by the `onProgress` callbacks passed to `generateImage()` and `uploadImage()`

2. **Modify the inline generation modal:**
- Edit `src/experiments/image-generation/components/GenerateImageInlineModal.tsx`
- Edit `src/features/image-generation/components/GenerateImageInlineModal.tsx`
- The modal supports idle (prompt input), generating, preview (keep/refine/start over) states
- Customize the flow, UI copy, or add new actions

3. **Add or change supported blocks for inline generation:**
- Edit `inline.tsx` and modify the `TARGET_BLOCKS` array (`core/image`, `core/cover`, `core/media-text`, `core/gallery`)
- To support a new block type, update `insertIntoBlock()` in `src/experiments/image-generation/functions/insert-into-block.ts` with the correct attribute mapping
- To support a new block type, update `insertIntoBlock()` in `src/features/image-generation/functions/insert-into-block.ts` with the correct attribute mapping

4. **Customize the AI label:**
- Edit `src/experiments/image-generation/components/AILabel.tsx`
- Edit `src/features/image-generation/components/AILabel.tsx`

5. **Add custom functions:**
- Create new functions in `src/experiments/image-generation/functions/`
- Create new functions in `src/features/image-generation/functions/`
- Import and use them in the components

6. **Customize the featured image panel:**
- The experiment uses the `editor.PostFeaturedImage` filter to inject into the featured image panel
- You can modify `src/experiments/image-generation/featured-image.tsx` to add additional UI
- The feature uses the `editor.PostFeaturedImage` filter to inject into the featured image panel
- You can modify `src/features/image-generation/featured-image.tsx` to add additional UI

### Customizing Image Processing

Expand All @@ -777,7 +777,7 @@ add_filter( 'wp_generate_attachment_metadata', function( $metadata, $attachment_

### Manual Testing

1. **Enable the experiment:**
1. **Enable the feature:**
- Go to `Settings → AI`
- Toggle **Image Generation** to enabled
- Ensure you have valid AI credentials configured
Expand All @@ -801,7 +801,7 @@ add_filter( 'wp_generate_attachment_metadata', function( $metadata, $attachment_
- Test with each supported block type to ensure correct attribute mapping

4. **Test with different post types:**
- The experiment only loads for post types that support featured images (`post_type_supports( $post_type, 'thumbnail' )`)
- The feature only loads for post types that support featured images (`post_type_supports( $post_type, 'thumbnail' )`)
- Test with posts, pages, and custom post types that have featured image support

5. **Test REST API:**
Expand All @@ -817,7 +817,7 @@ add_filter( 'wp_generate_attachment_metadata', function( $metadata, $attachment_
Unit tests are located in:

- `tests/Integration/Includes/Abilities/Image_GenerationTest.php`
- `tests/Integration/Includes/Experiments/Image_Generation/Image_GenerationTest.php`
- `tests/Integration/Includes/Features/Image_Generation/Image_GenerationTest.php`

Run tests with:

Expand All @@ -829,10 +829,10 @@ npm run test:php

### Requirements

- The experiment requires valid AI credentials to be configured
- The experiment only works for post types that support featured images (`post_type_supports( $post_type, 'thumbnail' )`)
- The feature requires valid AI credentials to be configured
- The feature only works for post types that support featured images (`post_type_supports( $post_type, 'thumbnail' )`)
- Users must have `upload_files` capability
- The experiment requires image generation models to be available (configured via `get_preferred_image_models()`)
- The feature requires image generation models to be available (configured via `get_preferred_image_models()`)

### Performance

Expand All @@ -858,7 +858,7 @@ npm run test:php

### Prompt Generation

- The experiment uses a three-step process:
- The feature uses a three-step process:
1. First, it gets post context (title, type) using the `ai/get-post-details` ability
2. Then, it generates an optimized image generation prompt from post content and context using the `ai/image-prompt-generation` ability
3. Finally, it uses that prompt to generate the actual image
Expand All @@ -883,7 +883,7 @@ npm run test:php
- Images are generated in real-time and not cached
- The ability does not support batch processing (one image per request)
- Generated images are suggestions and should be reviewed before publishing
- The experiment requires JavaScript to be enabled in the admin
- The feature requires JavaScript to be enabled in the admin
- Image generation may fail if AI models are unavailable or rate-limited
- Base64 image data can be very large; ensure adequate server resources

Expand Down
1 change: 0 additions & 1 deletion includes/Experiments/Experiments.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ final class Experiments {
\WordPress\AI\Experiments\Content_Classification\Content_Classification::class,
\WordPress\AI\Experiments\Excerpt_Generation\Excerpt_Generation::class,
\WordPress\AI\Experiments\Alt_Text_Generation\Alt_Text_Generation::class,
\WordPress\AI\Experiments\Image_Generation\Image_Generation::class,
\WordPress\AI\Experiments\Meta_Description\Meta_Description::class,
\WordPress\AI\Experiments\Review_Notes\Review_Notes::class,
\WordPress\AI\Experiments\Summarization\Summarization::class,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
<?php
/**
* Image generation experiment implementation.
* Image generation feature implementation.
*
* @package WordPress\AI
*/

declare( strict_types=1 );

namespace WordPress\AI\Experiments\Image_Generation;
namespace WordPress\AI\Features\Image_Generation;

use WordPress\AI\Abilities\Image\Generate_Image as Image_Generation_Ability;
use WordPress\AI\Abilities\Image\Generate_Image_Prompt as Generate_Image_Prompt_Ability;
use WordPress\AI\Abilities\Image\Import_Base64_Image as Image_Import_Ability;
use WordPress\AI\Abstracts\Abstract_Feature;
use WordPress\AI\Asset_Loader;
use WordPress\AI\Experiments\Alt_Text_Generation\Alt_Text_Generation;
use WordPress\AI\Experiments\Experiment_Category;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Image generation experiment.
* Image generation feature.
*
* @since 0.2.0
*/
Expand All @@ -42,7 +41,7 @@ protected function load_metadata(): array {
return array(
'label' => __( 'Image Generation and Editing', 'ai' ),
'description' => __( 'Generate and edit images using AI', 'ai' ),
'category' => Experiment_Category::EDITOR,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note I removed this category as we currently have that marked as an Experiment Category, and the only place we use this is determining what section a Feature shows within our settings page (this defaults to "Other" if not set).

In #417 we'll start showing stable Features in a new section up top so I don't think categories are needed anymore for stable Features. That said, we can introduce Feature Categories (maybe matching what we have for Experiment Categories, Editor and Admin) if we think that would still be useful to have

'stability' => 'stable',
);
}

Expand Down Expand Up @@ -219,8 +218,8 @@ public function enqueue_inline_assets(): void {
* @since 0.4.0
*/
private function enqueue_shared_assets(): void {
Asset_Loader::enqueue_script( 'image_generation', 'experiments/image-generation' );
Asset_Loader::enqueue_style( 'image_generation', 'experiments/image-generation' );
Asset_Loader::enqueue_script( 'image_generation', 'features/image-generation' );
Asset_Loader::enqueue_style( 'image_generation', 'features/image-generation' );
Asset_Loader::localize_script(
'image_generation',
'ImageGenerationData',
Expand Down
4 changes: 2 additions & 2 deletions includes/Features/Loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function register_features(): void {
*/
private function get_default_features(): array {
$feature_classes = array(
// Features start off as experiments until they pass the requirements to graduate to full features.
\WordPress\AI\Features\Image_Generation\Image_Generation::get_id() => \WordPress\AI\Features\Image_Generation\Image_Generation::class,
);

/**
Expand All @@ -103,7 +103,7 @@ private function get_default_features(): array {
*
* @since 0.6.0
*
* @param array<string, \WordPress\AI\Contracts\Feature|class-string<\WordPress\AI\Contracts\Feature>> $feature_classes Array of feature class names, keyed by ID.
* @param array<string, class-string<\WordPress\AI\Contracts\Feature>> $feature_classes Array of feature class names, keyed by ID.
*/
$items = apply_filters( 'wpai_default_feature_classes', $feature_classes );

Expand Down
8 changes: 4 additions & 4 deletions tests/Integration/Includes/Experiment_LoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ public function test_register_features() {
$this->assertEquals( 'excerpt-generation', $excerpt_experiment->get_id() );
$this->assertEquals( Experiment_Category::EDITOR, $excerpt_experiment->get_category() );

$image_experiment = $this->registry->get_feature( 'image-generation' );
$this->assertNotNull( $image_experiment, 'Image generation experiment should exist' );
$this->assertEquals( 'image-generation', $image_experiment->get_id() );
$this->assertEquals( Experiment_Category::EDITOR, $image_experiment->get_category() );
$image_feature = $this->registry->get_feature( 'image-generation' );
$this->assertNotNull( $image_feature, 'Image generation experiment should exist' );
$this->assertEquals( 'image-generation', $image_feature->get_id() );
$this->assertEquals( Experiment_Category::OTHER, $image_feature->get_category() );

$review_notes_experiment = $this->registry->get_feature( 'review-notes' );
$this->assertNotNull( $review_notes_experiment, 'Review Notes experiment should exist' );
Expand Down
Loading
Loading