Documentation / Tools

AI Tools

This plugin is a paid add-on. You need to buy Redactor together with AI Tools plugin if you don't have it yet. Or buy the plugin separately in your account if you already have Redactor.

Concept #

The Redactor AI plugin provides an interface for accessing and processing requests to OpenAI API. On your side you need an API key and a small code to process requests on the server side.

This way we don't charge for requests and tokens. These solutions are completely on your side. It seems to us that this is the best option when you can decide which AI model to query, what limits to set, etc.

Why do we need a server-side solution?

Simple, the key to the API must be protected and not publicly available. So it is impossible to do it only using Javascript. That's why Redactor forms a request to the server, so that there in turn the request to the API is sent.

Below you will find an example of setting up and running the editor with the AI plugin and examples of server-side handlers.

Start with AI #

This functionality is seamlessly integrated as a plugin, available for purchase either individually or bundled with Redactor. You can activate the editor with the AI plugin enabled.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        },
        image: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/images/generations',
            model: 'dall-e-3'
        }
    }
});

You can look and try how it works in this example:

Server-side example #

Below is an example of a server-side handler for a request from Redactor and submitting it using the Open AI API. This example is written in PHP. You can modify it according to your server-side environment.


<?php
// Your OpenAI API key
$openaiApiKey = 'YOUR-API-KEY';

// API endpoint
$url = $_POST['url'];

// Data payload
$data = json_decode($_POST['data']);

// Initialize cURL
$ch = curl_init($url);

// Set cURL options
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $openaiApiKey,
]);

// Execute cURL request
$response = curl_exec($ch);

// Check for errors
if (curl_errno($ch)) {
    echo 'cURL error: ' . curl_error($ch);
}

// Close cURL session
curl_close($ch);

// Output response
echo $response;

Server-side stream example #

Below is an example of a server-side stream handler for a request from Redactor and submitting it using the Open AI API. This example is written in PHP. You can modify it according to your server-side environment.


<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

// Your OpenAI API key
$openaiApiKey = 'YOUR-API-KEY';

// API endpoint
$url = $_POST['url'];

// Data payload
$data = json_decode($_POST['data']);

// Set the curl options for the API request
$options = array(
  CURLOPT_URL => $url,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POSTFIELDS => json_encode($data),
  CURLOPT_HTTPHEADER => array(
    'Content-Type: application/json',
    'Authorization: Bearer ' . $openaiApiKey
  ),
  // Process each chunk of data as it arrives
  CURLOPT_WRITEFUNCTION => function($ch, $chunk) {
    echo $chunk;
    return strlen($chunk);
  }
);

// Initialize the curl request
$ch = curl_init();

// Set the curl options specified earlier
curl_setopt_array($ch, $options);

// Execute the curl request and close the connection
curl_exec($ch);
curl_close($ch);

What data Redactor sends to the server? #

Redactor makes a POST request to the server and sends the following data:

  • url — is the endpoint parameter specified in the AI plugin settings. I.e. the address of the request to OpenAI API.
  • data — is a set of JSON parameters that form a request to the API.

Here's an example of what the data created by the editor and sent to the server could look like.

Text request


// post data
{
    "model": "gpt-3.5-turbo",
    "stream": true,
    "messages": [
        {
            "role": "user",
            "content": "Some text..."
        },
        {
            "role": "user",
            "content":"Improve it"
        }
    ]
}

Image request


// post data
{
    "model": "dall-e-3",
    "n": 1,
    "size": "1792x1024",
    "prompt": "Some prompt..."
}

How should the server's response look? #

OpenAI API returns all requests in JSON format. This is exactly what you need for Redactor. So take this into account in your implementation.

In fact, just return the response from OpenAI to the server as it is in JSON format and as described in the OpenAI documentation.

Node.js and Python #

You can find examples of how to implement a request with Node.js or Python to the OpenAI API in the documentation OpenAI.

Open AI has clear and simple SDKs for this. You just need to accept Post data from the editor and send it using libraries to the OpenAI API.

Settings #

stream

Turns off a request to the API as a stream.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: false
        }
    }
});

items

Default

items: {
    improve: { title: 'Improve it', command: 'ai.set', params: { prompt: 'Improve it' } },
    simplify: { title: 'Simplify it', command: 'ai.set', params: { prompt: 'Simplify it' } },
    fix: { title: 'Fix any mistakes', command: 'ai.set', params: { prompt: 'Fix any mistakes' } },
    shorten: { title: 'Make it shorter', command: 'ai.set', params: { prompt: 'Make it shorter' } },
    detailed: { title: 'Make it more detailed', command: 'ai.set', params: { prompt: 'Make it more detailed' } },
    complete: { title: 'Complete sentence', command: 'ai.set', params: { prompt: 'Complete sentence' } },
    tone: { title: 'Change tone', command: 'ai.popupTone' },
    translate: { title: 'Translate', command: 'ai.popupTranslate' }
}

Adds items to the AI dropdown.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        items: {
            turnToBullets: { title: 'Turn prose to bullets', command: 'ai.set', params: { prompt: 'Turn prose to bullets' } }
        },
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        }
    }
});

Replace items in the AI dropdown with your own.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        items: {
            set: true,
            improve: { title: 'Improve it', command: 'ai.set', params: { prompt: 'Improve it' } },
            simplify: { title: 'Simplify it', command: 'ai.set', params: { prompt: 'Simplify it' } },
            fix: { title: 'Fix any mistakes', command: 'ai.set', params: { prompt: 'Fix any mistakes' } }
        },
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        }
    }
});

tone

Default

tone: [
    'Academic',
    'Assertive',
    'Casual',
    'Confident',
    'Constructive',
    'Empathetic',
    'Exciting',
    'Fluent',
    'Formal',
    'Friendly',
    'Inspirational',
    'Professional'
]

Creates your own set of writing tone.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        tone: [
            'Academic',
            'Fluent',
            'Professional'
        ],
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        }
    }
});

style

Default

style: [
    '3d model',
    'Digital art',
    'Isometric',
    'Line art',
    'Photorealistic',
    'Pixel art'
]

Creates your own set of image styling tone.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        style: [
            'Photorealistic',
            'Pixel art'
        ],
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        },
        image: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/images/generations',
            model: 'dall-e-3'
        }
    }
});

translate

Default

translate: [
    'Arabic',
    'Chinese',
    'English',
    'French',
    'German',
    'Greek',
    'Italian',
    'Japanese',
    'Korean',
    'Portuguese',
    'Russian',
    'Spanish',
    'Swedish',
    'Ukrainian'
]

Creates your own set of translate languages.


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        translate: [
            'English',
            'Finnish',
            'Swedish'
        ],
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        }
    }
});

Events #

AI Tools plugin has several events, for example, ai.before.send event that sends xhr. This can be useful if you want to add your headers to the request.


Redactor('#entry', {
    plugins: ['ai'],
    text: {
        url: '/path-to-server-side/',
        endpoint: 'https://api.openai.com/v1/chat/completions',
        model: 'gpt-3.5-turbo',
        stream: true
    },
    subscribe: {
        'ai.before.send': function(event) {
            let xhr = event.get('xhr');
            xhr.setRequestHeader('X-CSRF-Token', 'your-token-value');
        }
    }
});

See more about AI Tools events.

Translations #

AI plugin by default, contains the following object with language variables:


translations: {
    en: {
        "ai": {
            "placeholder-image": "Describe the image you want to generate.",
            "placeholder-text": "Tell me what you want to write.",
            "send": "Send",
            "stop": "Stop",
            "discard": "Discard",
            "insert": "Insert",
            "prompt": "Prompt",
            "image-style": "Image style",
            "change-tone": "Change tone"
        }
    }
}

You can change the language values to your own, for example when you start the editor like this:


Redactor('#entry', {
    plugins: ['ai'],
    lang: 'sv',
    text: {
        url: '/path-to-server-side/',
        endpoint: 'https://api.openai.com/v1/chat/completions',
        model: 'gpt-3.5-turbo',
        stream: true
    },
    translations: {
        sv: {
            "ai": {
                "placeholder-image": "Beskriv bilden du vill generera.",
                "placeholder-text": "Berätta vad du vill skriva.",
                "send": "Skicka",
                "stop": "Stoppa",
                "discard": "Kassera",
                "insert": "Infoga",
                "prompt": "Uppmaning",
                "image-style": "Bildstil",
                "change-tone": "Ändra ton"
            }
        }
    }
});

This example shows running Redactor with Swedish and with the plugin translated into Swedish.

See more details on how to customize the languages.

Translate prompts #

Also you can run the editor with all the plugin settings override them and in those settings specify text phrases in the language you want. This is what it might look like:


Redactor('#entry', {
    plugins: ['ai'],
    ai: {
        items: {
            improve: { title: 'Improve it', command: 'ai.set', params: { prompt: 'Improve it' } },
            simplify: { title: 'Simplify it', command: 'ai.set', params: { prompt: 'Simplify it' } },
            fix: { title: 'Fix any mistakes', command: 'ai.set', params: { prompt: 'Fix any mistakes' } },
            shorten: { title: 'Make it shorter', command: 'ai.set', params: { prompt: 'Make it shorter' } },
            detailed: { title: 'Make it more detailed', command: 'ai.set', params: { prompt: 'Make it more detailed' } },
            complete: { title: 'Complete sentence', command: 'ai.set', params: { prompt: 'Complete sentence' } },
            tone: { title: 'Change tone', command: 'ai.popupTone' },
            translate: { title: 'Translate', command: 'ai.popupTranslate' }
        },
        tone: [
            'Academic',
            'Assertive',
            'Casual',
            'Confident',
            'Constructive',
            'Empathetic',
            'Exciting',
            'Fluent',
            'Formal',
            'Friendly',
            'Inspirational',
            'Professional'
        ],
        style: [
            '3d model',
            'Digital art',
            'Isometric',
            'Line art',
            'Photorealistic',
            'Pixel art'
        ],
        translate: [
            'Arabic',
            'Chinese',
            'English',
            'French',
            'German',
            'Greek',
            'Italian',
            'Japanese',
            'Korean',
            'Portuguese',
            'Russian',
            'Spanish',
            'Swedish',
            'Ukrainian'
        ],
        size: {
            '1792x1024': 'Landscape',
            '1024x1792': 'Portrait',
            '1024x1024': 'Square'
        },
        makeit: 'Make it',
        translateto: 'Translate to',
        text: {
            url: '/path-to-server-side/',
            endpoint: 'https://api.openai.com/v1/chat/completions',
            model: 'gpt-3.5-turbo',
            stream: true
        }
    }
});

Just replace the English text with your own, it should work.