API Key Overwrite

If you have multiple API keys for the same service and would like to rotate between them (round robin), there is an addon specifically designed for that: Dynamic Keys.

If you want your user to use their own API keys you will need to write the code to allow them to write their own API Key somewhere. For example, you could let them add it directly into their WordPress Profile.

As for AI Engine, you can inject this API Key in many different ways. In the Filters, pay attention to the mwai_ai_query filter; it’s the one used right before the request is sent to the AI. Here is a simple example:

add_filter( 'mwai_ai_query', function ( $query ) {
  $apiKey = get_user_meta( get_current_user_id(), 'apiKey', true );
  $query->setApiKey( $apiKey );
  return $query;
}, 10, 2 );

Handle error messages

The error messages shown in red in the chat come 90% of the time directly from the AI providers you are using, not from the plugin. If there’s an issue on the plugin side, you might see the error in the PHP error logs instead. These messages sent by the AI service (e.g., when a query couldn’t be processed) might make sense to you as a developer but not to your clients using the chatbot. So, you can override these error messages.

There is a mwai_ai_exception filter that you can hook to, and that takes an argument (the original error message) and you can return whatever message you’d like to return. For example, here is an example if you would like to hide the real error to your visitors:

add_filter( 'mwai_ai_exception', function ( $exception ) {
  try {
    if ( substr( $exception, 0, 26 ) === "Error while calling OpenAI" ) {
      error_log( $exception );
      return "There was an AI system error. Please contact us.";
    }
    return $exception;
  }
  catch ( Exception $e ) {
    error_log( $e->getMessage() );
  }
  return $exception;
} );

Chatbot Takeover

If you need to completely bypass the AI query process and return your own message, you can use the mwai_chatbot_takeover filter. This will send the $takeover value as a reply in the name of the chatbot. This can be used in a lot of different use cases.

Here is an example showing how to respond if the user is asking for the current time. Assuming the AI doesn’t have any context or tool to get this info, we can intervene manually and reply with our own value, bypassing any part of the query process.

add_filter( 'mwai_chatbot_takeover', function( $takeover, $query, $params ) {
    // Check for specific triggers
    if ( strpos( $query->get_message(), 'current time' ) !== false ) {
        return 'The current time is ' . current_time( 'mysql' );
    }
    return $takeover;
}, 10, 3 );

You can also take over the current conversation, not to reply as the chatbot, but to stop the conversation with an error message. Here is an example using the mwai_ai_allowed filter.

add_filter( 'mwai_ai_allowed', function( $allowed, $query, $limits ) {
    // Return true to allow, false to block, or a string error message
    if ( /* some condition */ ) {
        return 'This Query was not allowed!';
    }
    return $allowed;
}, 10, 3 );

Parameters Overwrite

If you would like to set the parameters in the code instead of the shortcode or chatbot settings, you can use the mwai_chatbot_params filter. Here is an example:

add_filter( 'mwai_chatbot_params', function( $params ) {
    // Force specific settings
    $params['temperature'] = 0.7;
    $params['max_tokens'] = 500;
    return $params;
});

Examples

Dynamic Model Change

Seamlessly integrate and switch between language and vision models using the mwai_ai_query filter. The primary goal of this guide is to demonstrate the implementation of a dynamic model-switching mechanism, allowing you to utilize the Vision model only when necessary. By incorporating this approach into your code, you can optimize resource usage and enhance the efficiency of your applications that leverage AI capabilities.

add_filter( 'mwai_ai_query', function ( $query ) {
		// If it's an embbeding request, return the query as is
	  if ( $query->mode == "embedding" ) {
	    return $query;
	  }

    // Check ithe type of uploaded file
    $needVision = ( $query->filePurpose === 'vision' );

    // Switch the model based on the need for vision capabilities
    if ( $needVision ) {
        $query->set_model( 'gpt-4-vision-preview' );
    } else {
        $query->set_model( 'gpt-4-1106-preview' );
    }

    // Log the chosen model to error log for debugging purposes
    error_log("🗒️: " . print_r( $query->model, true ) );
  
    return $query;
}, 10, 2 );

Shortcode Overwrite

If you have a chatbot on your page that you want to display only under certain conditions—such as based on membership, user role, or time of day—you can create your own shortcode with custom logic that conditionally calls the AI Engine chatbot shortcode.

This guide will walk you through the process of creating a shortcode in WordPress that displays content only when specific conditions are met, in this case AI Engine’ chatbot shortcode. We’ll cover 3 scenarios: a site wide post specific chatbot, checking a specific cookie and verifying user rights.

Example 1: Different Chatbot for each Page

Let’s create a WordPress shortcode that displays a different AI Engine chatbot on each page depending on the page’s slug, and ensure this shortcode is executed in the footer of every page, so this way we don’t have to manually go and place our custom shortcode on each post manually.

// Create our custom shortcode
function page_slug_chatbot_shortcode_callback($atts) {
    // Get the global post object
    global $post;

    if (!$post) {
        return ''; // No post context
    }

    // Get the page slug
    $slug = $post->post_name;

    // Use the slug as the chatbot ID (or map to specific values if needed)
    $chatbot_id = esc_attr($slug); // ensure safety

    // You can also define a fallback default bot if needed
    $default_id = 'default_bot';

    // Optionally, define custom mappings
    $custom_bots = [
        'home' => 'homepage_bot',
        'contact' => 'contact_bot',
        'about-us' => 'about_bot',
        'blog' => 'blog_assistant'
    ];

    // Use mapped ID if defined, else fallback to slug or default
    $chatbot_id = $custom_bots[$slug] ?? $chatbot_id ?? $default_id;

    return do_shortcode('[mwai_chatbot custom_id="' . $chatbot_id . '"]');
}
add_shortcode('slug_mwai_chatbot', 'page_slug_chatbot_shortcode_callback');

// Add the shortcode on every posts
function insert_chatbot_shortcode_in_footer() {
    echo do_shortcode('[slug_mwai_chatbot]');
}
add_action('wp_footer', 'insert_chatbot_shortcode_in_footer');
function custom_cookie_chatbot_shortcode_callback($atts) {
    // Check if the custom_cookie is set
    if (isset($_COOKIE['custom_cookie'])) {
        // Render the mwai_chatbot_v2 shortcode content here
        return do_shortcode('[mwai_chatbot]');
    } else {
        // Optionally, provide a message or alternative content
        return 'Custom cookie not set, chatbot shortcode not rendered';
    }
}
add_shortcode('cookie_mwai_chatbot', 'custom_cookie_chatbot_shortcode_callback');

Add the [cookie_mwai_chatbot] shortcode to your WordPress post or page. The enclosed content will only display if the ‘custom_cookie’ is set.

Example 3: Check User Rights

function user_rights_chatbot_shortcode_callback($atts) {
    // Check if the user has specific rights (e.g., 'manage_options')
    if (current_user_can('manage_options')) {
        // Render the mwai_chatbot_v2 shortcode content here
        return do_shortcode('[mwai_chatbot id="manager_bot"]');
    } else {
        // Optionally, return the default chatbot
        return do_shortcode('[mwai_chatbot]');
    }
}
add_shortcode('rights_mwai_chatbot', 'user_rights_chatbot_shortcode_callback');

Add the [rights_mwai_chatbot] shortcode to your WordPress post or page. Users who have the rights to manage options will experience a specific chatbot tailored for them, while regular users will see your default chatbot in the same location.

The possibilities are endless; you can even create a customized “mwai” shortcode with parameters based on users’ preferences if needed. You can add custom logic, retrieve data from an external API, and the conditions can be tailored to virtually anything.


Example 4: Display Chatbot Only Between 8 AM and 8 PM

If your server is in a different timezone than your intended audience, use date_default_timezone_set() to ensure accuracy.

You could expand this logic to display different bots for different times (e.g., daytime vs. nighttime assistant), or include logic for weekends, holidays, or even integrate with an external calendar API.

function time_restricted_chatbot_shortcode_callback($atts) {
    // Set your desired timezone
    date_default_timezone_set('UTC'); // Adjust to your local timezone if needed, e.g., 'Europe/Paris'

    // Get the current hour (24-hour format)
    $current_hour = (int) date('G'); // Returns 0–23

    // Define start and end hour for chatbot display
    $start_hour = 8;
    $end_hour = 20;

    if ($current_hour >= $start_hour && $current_hour < $end_hour) {
        // Within allowed time range
        return do_shortcode('[mwai_chatbot]');
    } else {
        // Outside allowed time range
        return 'The chatbot is available between 8:00 AM and 8:00 PM.';
    }
}
add_shortcode('time_mwai_chatbot', 'time_restricted_chatbot_shortcode_callback');

Update OpenAI Models

We always update the available OpenAI models when a new version of AI Engine is released. However, if you can’t wait to try out the latest model that was released just two hours ago, you can manually add it to the OpenAI model list in AI Engine.

$new_models = array([
	"model" => "GPT 4.1",
	"name" => "gpt-4.1",
	"family" => "gpt4.1",
	"price" => [
		"in" => 2.00,
		"out" => 8.00,
	],
	"type" => "token",
	"unit" => 1 / 1000000,
	"maxCompletionTokens" => 16384,
	"maxContextualTokens" => 128000,
	"finetune" => false,
	"tags" => ['core', 'chat', 'vision', 'functions', 'json', 'finetune']
]);

add_filter('mwai_openai_models', function ($models) use ($new_models) {
	return array_merge($models, $new_models);
});

Sell your Add-on

Since June 2024, the AI Engine has begun supporting add-ons, which are plugins related to AI Engine. We believe this approach helps to avoid clutter in the WordPress Admin and conveniently organizes everything. Therefore, all plugins related to the AI Engine are located in the Add-ons section.

If you are a developer, you can build your own plugin that extends AI Engine—for example, a plugin that adds settings to customize cache behavior—and sell it to your clients. To make things clearer and easier for them, you can register your plugin as an AI Engine addon so it’s visible and easily accessible within the AI Engine interface.

How to insert your Add-on

It’s quite straightforward. You just need to add a filter on mwai_addons and register your own add-on. The placement of the add-on settings within the WP Admin is entirely at your discretion. If you plan to sell an add-on, it’s your responsibility to implement a licensing system. For a free add-on, it’s advisable to host it on the WordPress repository, if possible, for easy updates. If that’s not feasible, you’ll need to construct your own system.

add_filter( 'mwai_addons', array( $this, 'refresh_addons' ), 1 );

function refresh_addons( $addons ) {
	$addons[] = [
			'slug' => "your-addon",
			'name' => "Your Add-on",
			'icon_url' => 'https://yoursite.com/favicon.png', // Useless for now
			'description' => "This add-on does this and that.",
			'install_url' => "https://yoursite.com", // This link will show up if the plugin is disabled.
			'settings_url' => null, // This link will be used by the button "Settings".
			'enabled' => true // If the add-on is installed (probably always true).
		];
	return $addons;
}

Add AI Engine logs

If you want your Add-on to log messages, you don’t have to build your own logger or use the PHP error logs. There is a built in class Meow_MWAI_Logging with static functions you can call from anywhere. This will add your logs directly in the AI Engine Dev Tools console reader.

Meow_MWAI_Logging::warn( "..." );
Meow_MWAI_Logging::error( "..." );
Meow_MWAI_Logging::log( "..." );
Meow_MWAI_Logging::deprecated( "..." );

Meow_MWAI_Logging::clear();

Modify a Query

If you want your chatbot to be aware of certain information that might change (such as time, events, last news, etc.) or that might differ from user to user (such as name, location, interests, etc.) dynamically, then you can use the mwai_ai_query filter. This filter allows you to modify the query before it’s sent, which is basically the opposite of what we did when modifying the reply.

This lets us modify the instructions, the user’s message, and the model context, and run processes before the query is handled by the AI.

For instance, we could use placeholders in our instructions and modify them based on the current situation.

add_filter( 'mwai_ai_query', function ( $query ) {

  // Check if the $query object is an instance of Meow_MWAI_Query_Text
  if ( $query instanceof Meow_MWAI_Query_Text ) {
    // Replace the {CLIENT_NAME} placeholder with the user's name
    $name = get_user_meta( get_current_user_id(), 'name', true );
    $query->set_instructions( str_replace( '{CLIENT_NAME}', $name, $query->instructions ) );

    // Replace the {CLIENT_LOCATION} placeholder with the user's location
    $location = get_user_meta( get_current_user_id(), 'location', true );
    $query->set_instructions( str_replace( '{CLIENT_LOCATION}', $location, $query->instructions ) );

    // Replace the {CLIENT_LAST_DELIVERY} placeholder with the user's last delivery
    $last_delivery = get_user_meta( get_current_user_id(), 'last_delivery', true );
    $query->set_instructions( str_replace( '{CLIENT_LAST_DELIVERY}', $last_delivery, $query->instructions ) );

    // Call a weather API to replace {WEATHER} with current weather
    $api_url = 'https://api.weather.com/current?location=' . urlencode($location);
    $response = wp_remote_get( $api_url );

    if ( is_array( $response ) && ! is_wp_error( $response ) ) {
      $weather_data = json_decode( wp_remote_retrieve_body( $response ) );
      $current_weather = $weather_data->current->temperature;

      // Replace the {WEATHER} placeholder with the current weather
      $query->set_instructions( str_replace( '{WEATHER}', $current_weather . '°C', $query->instructions ) );
    }
  }

  return $query;
}, 10, 2 );