v0.9.0: Runware FLUX.1 schnell as default image provider
New Runware image backend at ~$0.0006/image (FLUX.1 schnell) — 65× cheaper than Gemini 2.5 Flash Image. Provider mirrors OpenRouter's split: interface + provider + support + pricing + batch, all under the 300-line cap. Batch class uses curl_multi for true parallel A/B dispatch — wall-clock drops to the slowest single image instead of the sum. Changes: - Add PRAutoBlogger_Runware_Image_Provider + Pricing + Support + Batch - Flip PRAUTOBLOGGER_DEFAULT_IMAGE_PROVIDER/MODEL to runware:100@1 - Add prautoblogger_runware_api_key settings field (encrypted at rest) - v0.9.0 one-time migration flips legacy default model + re-derives provider - Wire runware branch into Image_Pipeline::create_default_provider() - Add runware:100@1 and runware:101@1 to Image_Model_Registry (defaults top) - Update image prompt builder: no more anthropomorphized molecules; prefer concrete human-scale scenes (gym bros, doctors, scientists) - ARCHITECTURE.md + CHANGELOG.md updated with new integration + decision - Unit tests for pricing, support, provider; update model registry test Cost impact at 100 images/day (50 articles × A/B): - Before (Gemini via OpenRouter): $3.90/day ≈ $117/mo - After (FLUX schnell via Runware): $0.06/day ≈ $1.80/mo Net saving: ~$115/mo
This commit is contained in:
@@ -231,7 +231,7 @@ class PRAutoBlogger_Admin_Page {
|
||||
$option_name = substr( $filter, strlen( 'sanitize_option_' ) );
|
||||
}
|
||||
|
||||
$encrypted = [ 'prautoblogger_openrouter_api_key', 'prautoblogger_ga4_credentials_json', 'prautoblogger_cloudflare_ai_token' ];
|
||||
$encrypted = [ 'prautoblogger_openrouter_api_key', 'prautoblogger_ga4_credentials_json', 'prautoblogger_cloudflare_ai_token', 'prautoblogger_runware_api_key' ];
|
||||
if ( in_array( $option_name, $encrypted, true ) ) {
|
||||
// Empty value means password field wasn't touched — keep existing.
|
||||
if ( '' === $value ) {
|
||||
|
||||
@@ -6,12 +6,13 @@ declare(strict_types=1);
|
||||
*
|
||||
* What: Returns a hardcoded list of image models for the admin model picker.
|
||||
* No API discovery — updated manually when providers add/remove models.
|
||||
* Who calls it: PRAutoBlogger_Admin_Page (model picker UI) and
|
||||
* PRAutoBlogger_Image_Pipeline (model validation).
|
||||
* Who calls it: PRAutoBlogger_Admin_Page (model picker UI + save-time provider
|
||||
* derivation) and PRAutoBlogger_Image_Pipeline (provider lookup).
|
||||
* Dependencies: None.
|
||||
*
|
||||
* @see admin/class-settings-fields-extended.php — Image settings reference this registry.
|
||||
* @see core/class-image-pipeline.php — Validates selected model against this list.
|
||||
* @see core/class-image-pipeline.php — Derives provider from picked model.
|
||||
* @see providers/class-runware-image-provider.php — Runware FLUX backend.
|
||||
*/
|
||||
class PRAutoBlogger_Image_Model_Registry {
|
||||
|
||||
@@ -21,22 +22,41 @@ class PRAutoBlogger_Image_Model_Registry {
|
||||
* Each entry contains:
|
||||
* - id: Model identifier used in API calls.
|
||||
* - name: Human-readable display name.
|
||||
* - provider: 'openrouter' or 'cloudflare'.
|
||||
* - provider: 'runware' | 'openrouter' | 'cloudflare'.
|
||||
* - cost_per_image: Estimated USD cost per generation.
|
||||
* - capabilities: Array of capability tags.
|
||||
* - description: Short description for the admin UI.
|
||||
*
|
||||
* Ordered cheapest-to-most-expensive within each provider, with the
|
||||
* recommended default (Runware schnell) at the top.
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public static function get_models(): array {
|
||||
return [
|
||||
[
|
||||
'id' => 'runware:100@1',
|
||||
'name' => 'FLUX.1 schnell (Runware)',
|
||||
'provider' => 'runware',
|
||||
'cost_per_image' => 0.0006,
|
||||
'capabilities' => [ 'image_generation' ],
|
||||
'description' => __( 'Default. Fast, very cheap, comic-friendly fidelity.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'runware:101@1',
|
||||
'name' => 'FLUX.1 dev (Runware)',
|
||||
'provider' => 'runware',
|
||||
'cost_per_image' => 0.02,
|
||||
'capabilities' => [ 'image_generation' ],
|
||||
'description' => __( 'Higher fidelity FLUX. ~30x schnell cost.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'google/gemini-2.5-flash-image',
|
||||
'name' => 'Gemini 2.5 Flash Image (Nano Banana)',
|
||||
'provider' => 'openrouter',
|
||||
'cost_per_image' => 0.005,
|
||||
'capabilities' => [ 'image_generation' ],
|
||||
'description' => __( 'Good quality, low cost. Recommended.', 'prautoblogger' ),
|
||||
'description' => __( 'Mid-tier quality, proven.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'google/gemini-3.1-flash-image-preview',
|
||||
@@ -76,7 +96,7 @@ class PRAutoBlogger_Image_Model_Registry {
|
||||
'provider' => 'cloudflare',
|
||||
'cost_per_image' => 0.0007,
|
||||
'capabilities' => [ 'image_generation' ],
|
||||
'description' => __( 'Cheapest. Low quality, 4-step.', 'prautoblogger' ),
|
||||
'description' => __( 'Legacy Cloudflare fallback. Use Runware FLUX instead.', 'prautoblogger' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -86,7 +106,7 @@ class PRAutoBlogger_Image_Model_Registry {
|
||||
* model id is not in the registry.
|
||||
*
|
||||
* @param string $model_id Model slug from the admin UI.
|
||||
* @return string Provider id ('openrouter' | 'cloudflare' | '').
|
||||
* @return string Provider id ('runware' | 'openrouter' | 'cloudflare' | '').
|
||||
*/
|
||||
public static function provider_for( string $model_id ): string {
|
||||
foreach ( self::get_models() as $model ) {
|
||||
|
||||
@@ -240,6 +240,14 @@ class PRAutoBlogger_Settings_Fields_Extended {
|
||||
'default' => '',
|
||||
'description' => __( 'Only needed if using Cloudflare provider.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'prautoblogger_runware_api_key',
|
||||
'label' => __( 'Runware API Key', 'prautoblogger' ),
|
||||
'type' => 'password',
|
||||
'section' => 'prautoblogger_images',
|
||||
'description' => __( 'Required when using a Runware FLUX model. Get your key at runware.ai/signup.', 'prautoblogger' ),
|
||||
'icon' => '🔑',
|
||||
],
|
||||
[
|
||||
'id' => 'prautoblogger_image_style_suffix',
|
||||
'label' => __( 'Style Suffix', 'prautoblogger' ),
|
||||
|
||||
Reference in New Issue
Block a user