Если вы когда-либо в спешке вставляли отрывок из статьи в метаописание посреди ночи, вы знаете проблему: он повторяется, часто слишком длинный и иногда отклоняется от темы. Автоматические аннотации, с другой стороны, могут быть надежными… при условии, что они правильно связаны с… WordPress 6.9.4, с кэшированием, средствами защиты и без открытых ключей API.
Потребность / Вариант использования
сайт WordPress Главное здесь — содержание. Но читатель бегло просматривает текст. Краткое, лаконичное изложение (2-3 предложения) лучше:
- Страницы категорий (однородный обзор статей).
- информационные бюллетени (Краткие тизеры без необходимости ручного переписывания).
- Страницы «Рекомендуемые» (положить (более читабельно)
- Веб-сайты с несколькими авторами : тот же стиль резюме, та же длина.
В итоге у вас получится система, которая:
- Создает краткое изложение статьи с помощью ИИ при ее сохранении.
- хранить его в цель (в базе данных WordPress)
- Оно кэширует данные (временные данные), чтобы избежать двойной оплаты.
- Отображает его с помощью шорткода (совместим с Divi 5, Elementor, Avada).
- Обрабатывает ошибки (тайм-аут, квота, некорректный JSON) без нарушения работы вашего сайта.
Краткое резюме
- Вы храните ключ API в WP-config.php (никогда не задается жестко в коде).
- Un мю-плагин генерирует сводку посредством wp_remote_post() к API OpenAI.
- Сводка зафиксирована в пост мета (
_ai_summary) и повторно использованы. - Un преходящий Это позволяет избежать повторных звонков и снизить затраты.
- короткий код
[ai_summary]позволяет отображать в Divi 5/Elementor/Avada. - У вас есть режим отладки, чистые журналы и диагностическая панель.
Когда следует использовать ИИ для этого?
Я активирую этот тип автоматического составления сводки, когда сайт соответствует хотя бы одному из следующих условий:
- Много статей (обширные архивы, очень активные категории).
- Несколько редакторов а также необходимость в едином формате.
- Длинный контент (путеводители, файлы, исследования), где часто забывают о роли человека.
- переработка : новостная рассылка, push-уведомления, страницы с «лучшими статьями».
Это также отлично работает для сайтов, использующих Divi 5, Elementor или Avada: мы отображаем краткое содержание с помощью шорткода, не затрагивая конструктор.
Когда НЕ следует использовать ИИ
Не стоит платить за API, если достаточно нативного решения. Типичные примеры:
- У вас уже есть фрагмент кода WordPress. (поле «Извлечь») и ваша команда правильно его заполнит.
- Ваши статьи короткие. (300–500 слов): может быть достаточно сокращенного отрывка.
- У вас действуют строгие правовые ограничения. (Медицинский/юридический контент): резюме, созданное с помощью ИИ, может «интерпретировать» информацию и вносить в нее ошибки.
- Вам нужен на 100% детерминированный сводный отчет? Искусственный интеллект различается даже при строгих параметрах.
Простая альтернатива (без ИИ): отобразить выдержку или сгенерировать «резюме», сократив содержимое (например, wp_trim_words()Это бесплатно, мгновенно и зачастую достаточно.
Предпосылки
Версии и среда
- WordPress : 6.9.4 (апрель 2026 г.) или позже.
- PHP Рекомендуется версия 8.1 и выше. При использовании версии 7.x в современном коде могут возникать фатальные ошибки.
- HTTPS На стороне сайта (настоятельно рекомендуется) это делается во избежание передачи административных сессий в открытом текстовом виде.
API: простое определение (полезно перед написанием кода)
Один API (Интерфейс прикладного программирования) — это сервис, доступный по протоколу HTTP. На практике WordPress отправляет HTTP-запрос (часто в формате JSON) на URL-адрес, сервис отвечает JSON, а ваш код преобразует этот ответ в пригодный для использования текст.
В WordPress это корректно реализуется через HTTP API: wp_remote_post() et wp_remote_get()Официальный источник: HTTP API (developer.wordpress.org).
Ключ API и хранилище (wp-config.php)
Вам потребуется ключ API от поставщика решений в области ИИ. Здесь я показываю OpenAI, поскольку его API стабилен и хорошо документирован, но структура будет аналогичной для Anthropic/Mistral/Google.
- Создайте ключ: Документация API OpenAI
Далее добавьте ключ к WP-config.php (выше «Вот и всё, прекратите редактировать!»). Никогда не используйте это в плагине, никогда в общем фрагменте кода, никогда в репозитории Git.
define( 'BPCAB_OPENAI_API_KEY', 'sk-votre-cle-ici' );
Обратите внимание на стоимость: Каждое сводное сообщение — это платная услуга. Вы сможете ограничить это за счет кэширования и создания сводных сообщений только при определенных событиях (публикация/обновление).
Куда вставить код
Для такого рода функций я избегаю functions.php (слишком легко сломать при обновлении темы). Два надежных варианта:
- мю-плагин (рекомендуется): файл в
wp-content/mu-plugins/Загружено автоматически. - пользовательские плагины : файл в
wp-content/plugins/, можно включить/выключить.
Я уезжаю мю-плагинПотому что я часто видел, как сайты «теряют» свои сниппеты. после Изменение темы оформления или деактивация плагина сниппетов.
Архитектура решения
Поток (текстовая схема)
Редактор WordPress → сохранение статьи → хук save_post → Получение контента → Проверки (тип, статус, автосохранение) → Временный кэш (во избежание двойных вызовов) → wp_remote_post() → API для ИИ → Парсинг JSON → Санитарная обработка → Хранение метаданных постов _ai_summary → Отображение через шорткод.
Почему именно такой дизайн?
- Хранить в метаданных : сводка является постоянной, индексируемой и многократно используемой без вызова API при каждом отображении.
- преходящий : позволяет избежать многократных вызовов, если вы несколько раз нажмете кнопку «Обновить» или если плагин запустит несколько резервных копий.
- Короткий код Совместимо с Divi 5 / Elementor / Avada без специальной разработки.
Полный код — шаг за шагом
Шаг 1 — Создайте mu-плагин
Создайте папку wp-content/mu-plugins/ Если файл не существует, добавьте его:
wp-content/mu-plugins/ai-auto-summary.php
Вставьте следующую основу:
<?php
/**
* Plugin Name: AI Auto Summary (mu-plugin)
* Description: Génère et stocke un résumé IA des articles WordPress.
* Version: 1.0.0
* Requires at least: 6.9
* Requires PHP: 8.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Шаг 2 — Определите константы и настройки.
Настройки централизованы: длина, модель, время ожидания. Вы можете изменить их, не меняя всю логику.
const BPCAB_AI_SUMMARY_META_KEY = '_ai_summary';
const BPCAB_AI_SUMMARY_MODEL = 'gpt-4.1-mini'; // Modèle “mini” : bon compromis coût/qualité (à ajuster)
const BPCAB_AI_TIMEOUT_SECONDS = 20;
const BPCAB_AI_MAX_INPUT_CHARS = 12000; // Limite simple pour éviter d'envoyer des romans entiers
Шаг 3 — Добавьте хук генерации в нужный момент.
Un крючок является точкой продолжения. А действие Выполняет код в заданный момент времени (например, сохранение сообщения). фильтры изменяет значение (например, содержимое перед отображением). Здесь мы используем действие : save_post.
Классическая ловушка: используйте the_content Для генерации сводки ИИ запускается каждый раз при её отображении. Результат: плата за API и медленная работа сайта. Сводка генерируется в момент сохранения, а не при рендеринге.
add_action( 'save_post', 'bpcab_ai_maybe_generate_summary', 20, 3 );
/**
* Déclenche la génération du résumé lors de l'enregistrement.
*
* @param int $post_id ID du post.
* @param WP_Post $post Objet post.
* @param bool $update True si mise à jour, false si création.
*/
function bpcab_ai_maybe_generate_summary( int $post_id, $post, bool $update ): void {
// 1) Éviter les autosaves/révisions (sinon vous payez pour rien)
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
// 2) Vérifier le type de contenu : ici, uniquement les articles
if ( $post->post_type !== 'post' ) {
return;
}
// 3) Générer seulement quand l'article est publié (ou en passe de l'être)
$status = get_post_status( $post_id );
if ( $status !== 'publish' ) {
return;
}
// 4) Si un résumé existe déjà, ne pas écraser (vous pourrez ajouter un bouton “Regénérer” plus tard)
$existing = get_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, true );
if ( is_string( $existing ) && $existing !== '' ) {
return;
}
// 5) Vérifier la présence de la clé API
if ( ! defined( 'BPCAB_OPENAI_API_KEY' ) || ! is_string( BPCAB_OPENAI_API_KEY ) || BPCAB_OPENAI_API_KEY === '' ) {
error_log( '[AI Summary] Clé API absente. Ajoutez BPCAB_OPENAI_API_KEY dans wp-config.php.' );
return;
}
$content = bpcab_ai_get_post_text_for_summary( $post_id );
if ( $content === '' ) {
return;
}
// 6) Anti double-facturation : transient de verrouillage pendant 10 minutes
$lock_key = 'bpcab_ai_summary_lock_' . $post_id;
if ( get_transient( $lock_key ) ) {
return;
}
set_transient( $lock_key, 1, 10 * MINUTE_IN_SECONDS );
$summary = bpcab_ai_generate_summary_via_openai( $content, get_the_title( $post_id ) );
// En cas d'échec, on libère le lock plus tôt (sinon il expire tout seul)
if ( $summary === '' ) {
delete_transient( $lock_key );
return;
}
// 7) Sanitation : on stocke du texte simple
$summary = sanitize_text_field( $summary );
update_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, $summary );
}
Шаг 4 — Извлеките «чистый» текст из статьи.
Контент WordPress может содержать блоки, HTML-код и шорткоды. Отправка такого необработанного контента искусственному интеллекту часто приводит к странным сводкам (он «обобщает» фрагменты макета). Мы это исправляем:
- удаление шорткодов
- удаление HTML-тегов,
- ограничение по размеру.
/**
* Récupère un texte propre à résumer (sans HTML/shortcodes).
*/
function bpcab_ai_get_post_text_for_summary( int $post_id ): string {
$post = get_post( $post_id );
if ( ! $post instanceof WP_Post ) {
return '';
}
$text = $post->post_content;
// Retirer les shortcodes (souvent présents avec Divi/Avada et certains builders)
$text = strip_shortcodes( $text );
// Retirer le HTML
$text = wp_strip_all_tags( $text );
// Normaliser les espaces
$text = preg_replace( '/s+/', ' ', $text );
$text = trim( (string) $text );
if ( $text === '' ) {
return '';
}
// Limiter la taille envoyée à l'API (simple et efficace)
if ( mb_strlen( $text ) > BPCAB_AI_MAX_INPUT_CHARS ) {
$text = mb_substr( $text, 0, BPCAB_AI_MAX_INPUT_CHARS );
}
return $text;
}
Шаг 5 — Вызов API OpenAI с помощью функции wp_remote_post()
Мы отправляем HTTP POST-запрос к конечной точке "Responses" (современный API). Мы обрабатываем:
- Тайм-аут (в противном случае ваш файл сохранения может оказаться "зависшим").
- HTTP-коды (401, 429, 500…),
- Недопустимый JSON,
- кэш (временный, основанный на хеше содержимого).
/**
* Génère un résumé via l'API OpenAI.
*
* @param string $content Texte à résumer.
* @param string $title Titre de l'article (aide au contexte).
* @return string Résumé ou chaîne vide si échec.
*/
function bpcab_ai_generate_summary_via_openai( string $content, string $title = '' ): string {
// Cache “fonctionnel” : si le contenu est identique, on réutilise le résumé
$hash = hash( 'sha256', $title . '|' . $content );
$cache_key = 'bpcab_ai_summary_' . substr( $hash, 0, 32 );
$cached = get_transient( $cache_key );
if ( is_string( $cached ) && $cached !== '' ) {
return $cached;
}
$endpoint = 'https://api.openai.com/v1/responses';
// Prompt : court, contraint, stable
$instruction = "Vous êtes un assistant de rédaction. Résumez l'article en français en 2 à 3 phrases maximum. " .
"Ton neutre. Pas de listes. Pas de titre. Pas de conclusion. " .
"Ne mentionnez pas que vous êtes une IA.";
$input = "Titre : " . $title . "nnTexte :n" . $content;
$body = array(
'model' => BPCAB_AI_SUMMARY_MODEL,
'input' => array(
array(
'role' => 'system',
'content' => $instruction,
),
array(
'role' => 'user',
'content' => $input,
),
),
// Paramètres de génération : limiter la longueur et la variabilité
'max_output_tokens' => 160,
'temperature' => 0.2,
);
$args = array(
'timeout' => BPCAB_AI_TIMEOUT_SECONDS,
'headers' => array(
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( $body ),
);
$response = wp_remote_post( $endpoint, $args );
if ( is_wp_error( $response ) ) {
error_log( '[AI Summary] wp_remote_post error: ' . $response->get_error_message() );
return '';
}
$code = (int) wp_remote_retrieve_response_code( $response );
$raw = (string) wp_remote_retrieve_body( $response );
if ( $code < 200 || $code >= 300 ) {
error_log( '[AI Summary] HTTP ' . $code . ' - Réponse: ' . $raw );
return '';
}
$data = json_decode( $raw, true );
if ( ! is_array( $data ) ) {
error_log( '[AI Summary] JSON invalide. Body: ' . $raw );
return '';
}
/*
* Parsing : l'API Responses peut renvoyer un tableau "output" avec des items.
* On récupère le texte de sortie de manière prudente, sans supposer un format unique.
*/
$summary = bpcab_ai_extract_text_from_openai_responses( $data );
$summary = trim( (string) $summary );
if ( $summary === '' ) {
error_log( '[AI Summary] Résumé vide. Body: ' . $raw );
return '';
}
// Sanitation côté affichage : on stocke du texte simple, mais on reste prudent
$summary = wp_strip_all_tags( $summary );
// Cache 30 jours : un résumé ne change pas souvent
set_transient( $cache_key, $summary, 30 * DAY_IN_SECONDS );
return $summary;
}
/**
* Extrait le texte depuis la réponse OpenAI "Responses API".
* Cette fonction est volontairement défensive.
*/
function bpcab_ai_extract_text_from_openai_responses( array $data ): string {
// Cas fréquent : output[0].content[0].text
if ( isset( $data['output'] ) && is_array( $data['output'] ) ) {
foreach ( $data['output'] as $output_item ) {
if ( ! is_array( $output_item ) ) {
continue;
}
if ( ! isset( $output_item['content'] ) || ! is_array( $output_item['content'] ) ) {
continue;
}
foreach ( $output_item['content'] as $content_item ) {
if ( is_array( $content_item ) && isset( $content_item['text'] ) && is_string( $content_item['text'] ) ) {
return $content_item['text'];
}
}
}
}
// Fallback : certains formats renvoient "output_text"
if ( isset( $data['output_text'] ) && is_string( $data['output_text'] ) ) {
return $data['output_text'];
}
return '';
}
Шаг 6 — Отобразить сводку (короткий код)
Шорткод — это небольшой фрагмент кода, заключенный в квадратные скобки, который WordPress заменяет контентом. Это самый простой способ интеграции в:
- Дива 5 : Модуль «Код» или «Текст» (в текстовом режиме) с
[ai_summary]. - Elementor : виджет «Шорткод».
- Авада : Элемент «Шорткод» (Fusion Builder).
add_shortcode( 'ai_summary', 'bpcab_ai_summary_shortcode' );
/**
* Shortcode: [ai_summary id="123"]
* Sans id, affiche le résumé du post courant.
*/
function bpcab_ai_summary_shortcode( array $atts ): string {
$atts = shortcode_atts(
array(
'id' => 0,
),
$atts,
'ai_summary'
);
$post_id = (int) $atts['id'];
if ( $post_id <= 0 ) {
$post_id = get_the_ID();
}
if ( ! $post_id ) {
return '';
}
$summary = get_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, true );
if ( ! is_string( $summary ) || $summary === '' ) {
return '';
}
// Affichage : on autorise uniquement du texte (pas de HTML)
$summary = esc_html( $summary );
return '<div class="ai-summary">' . $summary . '</div>';
}
Если вам нужен минимальный HTML-код (например, курсив), не храните необработанный, неконтролируемый HTML-код. Используйте wp_kses_post() на момент отображения и при строгом соблюдении белого списка. Для начинающих я рекомендую: простой текст.
Полный собранный код
Скопируйте и вставьте весь этот файл в wp-content/mu-plugins/ai-auto-summary.phpДалее добавьте константу ключа API в wp-config.php.
<?php
/**
* Plugin Name: AI Auto Summary (mu-plugin)
* Description: Génère et stocke un résumé IA des articles WordPress.
* Version: 1.0.0
* Requires at least: 6.9
* Requires PHP: 8.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
const BPCAB_AI_SUMMARY_META_KEY = '_ai_summary';
const BPCAB_AI_SUMMARY_MODEL = 'gpt-4.1-mini';
const BPCAB_AI_TIMEOUT_SECONDS = 20;
const BPCAB_AI_MAX_INPUT_CHARS = 12000;
add_action( 'save_post', 'bpcab_ai_maybe_generate_summary', 20, 3 );
add_shortcode( 'ai_summary', 'bpcab_ai_summary_shortcode' );
/**
* Déclenche la génération du résumé lors de l'enregistrement.
*
* @param int $post_id ID du post.
* @param WP_Post $post Objet post.
* @param bool $update True si mise à jour, false si création.
*/
function bpcab_ai_maybe_generate_summary( int $post_id, $post, bool $update ): void {
if ( wp_is_post_autosave( $post_id ) || wp_is_post_revision( $post_id ) ) {
return;
}
if ( ! ( $post instanceof WP_Post ) ) {
return;
}
if ( $post->post_type !== 'post' ) {
return;
}
$status = get_post_status( $post_id );
if ( $status !== 'publish' ) {
return;
}
$existing = get_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, true );
if ( is_string( $existing ) && $existing !== '' ) {
return;
}
if ( ! defined( 'BPCAB_OPENAI_API_KEY' ) || ! is_string( BPCAB_OPENAI_API_KEY ) || BPCAB_OPENAI_API_KEY === '' ) {
error_log( '[AI Summary] Clé API absente. Ajoutez BPCAB_OPENAI_API_KEY dans wp-config.php.' );
return;
}
$content = bpcab_ai_get_post_text_for_summary( $post_id );
if ( $content === '' ) {
return;
}
$lock_key = 'bpcab_ai_summary_lock_' . $post_id;
if ( get_transient( $lock_key ) ) {
return;
}
set_transient( $lock_key, 1, 10 * MINUTE_IN_SECONDS );
$summary = bpcab_ai_generate_summary_via_openai( $content, get_the_title( $post_id ) );
if ( $summary === '' ) {
delete_transient( $lock_key );
return;
}
$summary = sanitize_text_field( $summary );
update_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, $summary );
}
/**
* Récupère un texte propre à résumer (sans HTML/shortcodes).
*/
function bpcab_ai_get_post_text_for_summary( int $post_id ): string {
$post = get_post( $post_id );
if ( ! $post instanceof WP_Post ) {
return '';
}
$text = (string) $post->post_content;
$text = strip_shortcodes( $text );
$text = wp_strip_all_tags( $text );
$text = preg_replace( '/s+/', ' ', $text );
$text = trim( (string) $text );
if ( $text === '' ) {
return '';
}
if ( mb_strlen( $text ) > BPCAB_AI_MAX_INPUT_CHARS ) {
$text = mb_substr( $text, 0, BPCAB_AI_MAX_INPUT_CHARS );
}
return $text;
}
/**
* Génère un résumé via l'API OpenAI.
*/
function bpcab_ai_generate_summary_via_openai( string $content, string $title = '' ): string {
$hash = hash( 'sha256', $title . '|' . $content );
$cache_key = 'bpcab_ai_summary_' . substr( $hash, 0, 32 );
$cached = get_transient( $cache_key );
if ( is_string( $cached ) && $cached !== '' ) {
return $cached;
}
$endpoint = 'https://api.openai.com/v1/responses';
$instruction = "Vous êtes un assistant de rédaction. Résumez l'article en français en 2 à 3 phrases maximum. " .
"Ton neutre. Pas de listes. Pas de titre. Pas de conclusion. " .
"Ne mentionnez pas que vous êtes une IA.";
$input = "Titre : " . $title . "nnTexte :n" . $content;
$body = array(
'model' => BPCAB_AI_SUMMARY_MODEL,
'input' => array(
array(
'role' => 'system',
'content' => $instruction,
),
array(
'role' => 'user',
'content' => $input,
),
),
'max_output_tokens' => 160,
'temperature' => 0.2,
);
$args = array(
'timeout' => BPCAB_AI_TIMEOUT_SECONDS,
'headers' => array(
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( $body ),
);
$response = wp_remote_post( $endpoint, $args );
if ( is_wp_error( $response ) ) {
error_log( '[AI Summary] wp_remote_post error: ' . $response->get_error_message() );
return '';
}
$code = (int) wp_remote_retrieve_response_code( $response );
$raw = (string) wp_remote_retrieve_body( $response );
if ( $code < 200 || $code >= 300 ) {
error_log( '[AI Summary] HTTP ' . $code . ' - Réponse: ' . $raw );
return '';
}
$data = json_decode( $raw, true );
if ( ! is_array( $data ) ) {
error_log( '[AI Summary] JSON invalide. Body: ' . $raw );
return '';
}
$summary = bpcab_ai_extract_text_from_openai_responses( $data );
$summary = trim( (string) $summary );
if ( $summary === '' ) {
error_log( '[AI Summary] Résumé vide. Body: ' . $raw );
return '';
}
$summary = wp_strip_all_tags( $summary );
set_transient( $cache_key, $summary, 30 * DAY_IN_SECONDS );
return $summary;
}
/**
* Extrait le texte depuis la réponse OpenAI "Responses API".
*/
function bpcab_ai_extract_text_from_openai_responses( array $data ): string {
if ( isset( $data['output'] ) && is_array( $data['output'] ) ) {
foreach ( $data['output'] as $output_item ) {
if ( ! is_array( $output_item ) ) {
continue;
}
if ( ! isset( $output_item['content'] ) || ! is_array( $output_item['content'] ) ) {
continue;
}
foreach ( $output_item['content'] as $content_item ) {
if ( is_array( $content_item ) && isset( $content_item['text'] ) && is_string( $content_item['text'] ) ) {
return $content_item['text'];
}
}
}
}
if ( isset( $data['output_text'] ) && is_string( $data['output_text'] ) ) {
return $data['output_text'];
}
return '';
}
/**
* Shortcode: [ai_summary id="123"]
*/
function bpcab_ai_summary_shortcode( array $atts ): string {
$atts = shortcode_atts(
array(
'id' => 0,
),
$atts,
'ai_summary'
);
$post_id = (int) $atts['id'];
if ( $post_id <= 0 ) {
$post_id = get_the_ID();
}
if ( ! $post_id ) {
return '';
}
$summary = get_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, true );
if ( ! is_string( $summary ) || $summary === '' ) {
return '';
}
return '<div class="ai-summary">' . esc_html( $summary ) . '</div>';
}
Код Пояснение
Почему используется save_post (а не the_content)?
save_post Он срабатывает, когда WordPress сохраняет контент. Это дает вам «естественный» момент для однократного вызова ИИ, сохранения результата и прекращения его работы.
Я часто встречал обучающие материалы, в которых "на экране" кратко описывается следующее: the_contentНа сайте с отключенным кэшированием или с поисковым роботом вы платите за API по кругу. И читатель может видеть разное резюме при каждой загрузке.
Временная блокировка (защита от двойного вызова)
WordPress позволяет сохранять данные несколько раз (автосохранение, обновления, SEO-плагины). Временные данные bpcab_ai_summary_lock_{ID} предотвращает срабатывание ИИ 3 раза за 30 секунд.
кэш хешей содержимого
Мы вычисляем хеш SHA-256 заголовка и содержимого. Если один и тот же текст повторяется (скопирован, вставлен, восстановлен), мы повторно используем хеш из временного файла. Это приводит к прямой экономии средств.
Санитарная обработка: то, что мы защищаем
sanitize_text_field(): удаляет символы и нормализует простой текст.wp_strip_all_tags(): удаляет все сгенерированные HTML-теги.esc_html()display: предотвращает внедрение HTML/JS-кода.
Реальный риск: если вы отображаете ответ ИИ без возможности экранирования, вы открываете дверь для внедрения кода (редко, но я сталкивался с этим раньше, когда контент «заставлял» ИИ генерировать HTML).
Стоимость и оптимизация API
Цены регулярно меняются. Возьмите за правило проверять официальную страницу перед развертыванием: Цены OpenAI.
Простая оценка (порядок величины)
Краткое изложение в 2-3 предложениях часто выглядит так:
- Вступительный взнос: от 1000 до 3000 токенов (в зависимости от длины статьи).
- Выходные данные: от 80 до 160 токенов.
Пример ежемесячного расчета:
- 200 статей в кратком изложении в месяц
- В среднем 2000 входных токенов + 120 выходных токенов.
Вы умножаете на цену выбранной модели. Ключевой момент: Основная часть затрат приходится на вход.Следовательно, предел BPCAB_AI_MAX_INPUT_CHARS.
Оптимизации, которые действительно работают
- Ограничьте количество отправляемого текста. Зачастую достаточно 8000–12000 символов.
- «Мини» модель Что касается кратких изложений: нет необходимости платить за громоздкий шаблон для трех предложений.
- Генерировать только один раз и хранить в метаданных.
- Ручная регенерация (расширенная опция) вместо повторной генерации при каждом обновлении.
Расширенные варианты и сценарии использования
1) Сгенерируйте краткое содержание заново при обновлении статьи.
По умолчанию код не заменяет существующую сводку. Если вы хотите создавать её заново при каждом обновлении, удалите этот блок:
// 4) Si un résumé existe déjà, ne pas écraser
$existing = get_post_meta( $post_id, BPCAB_AI_SUMMARY_META_KEY, true );
if ( is_string( $existing ) && $existing !== '' ) {
return;
}
Но я так не поступаю на большинстве сайтов: автор может внести 10 мелких исправлений, и вы платите 10 раз больше.
2) Также суммируйте страницы (post_type = page)
Вы можете разрешить page :
if ( ! in_array( $post->post_type, array( 'post', 'page' ), true ) ) {
return;
}
3) Интеграция Divi 5 / Elementor / Avada (практично)
- Дива 5 : добавьте модуль «Код» и поместите
[ai_summary]Если вы используете шаблон Theme Builder, вставьте шорткод в макет статьи. - Elementor : виджет «Шорткод» в шаблоне отдельной записи, затем
[ai_summary]. - Авада : Элемент «Шорткод» в конструкторе или в глобальном шаблоне.
Если ваш конструктор «очищает» шорткод (это происходит в некоторых текстовых модулях), используйте специальный виджет/элемент «Шорткод».
Безопасность и передовой опыт
Никогда не раскрывайте ключ API на стороне клиента.
Не выполняйте вызовы OpenAI из JavaScript в браузере. Даже если вы «скроете» ключ, он в конечном итоге станет видимым. Вызов должен оставаться на стороне сервера (PHP). wp_remote_post().
Ограничение факторов, способных инициировать генерацию
Крючок save_post Запускается при редактировании. В административной панели это уже защищено возможностями WordPress. Если вы позже добавите кнопку «Сгенерировать заново», используйте:
- un нунций (токен защиты от CSRF-атак)
current_user_can( 'edit_post', $post_id ).
ссылка: Одноразовые номера (developer.wordpress.org).
Ограничение тарифов (закон о борьбе со злоупотреблениями / неожиданными платежами)
Если несколько авторов публикуют материалы одновременно, можно ограничить количество сводок до X в час, используя глобальный временный параметр. Например, можно сохранить счетчик и отклонять публикации, превышающие определенный порог. Это простое решение, но оно предотвращает ситуацию, когда «я импортировал 2000 постов и сделал сводку по всем сразу».
GDPR: данные, передаваемые третьей стороне.
Вы отправляете контент внешнему поставщику. В зависимости от вашей ситуации:
- Обновите свою политику конфиденциальности.
- Избегайте отправки ненужных персональных данных.
- Не следует автоматически составлять краткое содержание контента, содержащего конфиденциальную информацию.
Как тестировать и отлаживать
1) Включите ведение журналов WordPress.
В wp-config.php (в тестовой среде) включите:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
Ошибки будут в wp-content/debug.log.
2) Минимальный тест
- Создать новую статью.
- Добавьте 2–3 абзаца текста (а не только заголовок).
- Публиковать.
- Проверьте метаданные
_ai_summary(с помощью плагина типа «Query Monitor» или через редактор, если у вас есть инструмент для работы с метаданными). - добавлять
[ai_summary]В вашем шаблоне или в содержимом проверьте отображение.
3) Проверьте HTTP-запросы
Если у вас возникают проблемы с таймаутом, начните с временного увеличения времени ожидания. BPCAB_AI_TIMEOUT_SECONDS В 30-м шаге проверьте, не блокирует ли ваш хостинг-провайдер исходящие запросы.
Официальная документация по HTTP API WordPress: HTTP API.
Если это не сработает
Диагностическая таблица
| симптом | Причина вероятна | проверка | Решение |
|---|---|---|---|
| Краткое содержание так и не появляется. | Код вставлен не в то место / mu-плагин не загружен | Убедитесь, что файл находится в wp-content/mu-plugins/ |
Переместите файл, проверьте права доступа, перезагрузите панель администратора. |
| ERREUR На момент публикации административные расходы составляли 500 долларов. | Ошибка PHP (отсутствует точка с запятой, скобка) | советоваться wp-content/debug.log |
Исправьте синтаксис или восстановите резервную копию. |
| В логах обнаружена ошибка HTTP 401. | Недействительный ключ API | увидеть debug.log (Ответ API) |
Восстановите ключ, вставьте его. wp-config.php |
| В логах обнаружена ошибка HTTP 429. | Превышена квота / лимит тарифа поставщика | Панель управления поставщика | Подождите, сократите количество звонков, добавьте ограничение скорости и кэширование. |
| Истекло время ожидания / публикация «заблокирована» | Слишком мало времени ожидания, медленный хостинг, исходящий брандмауэр | Увеличьте время ожидания, протестируйте с другого сервера. | Истекло время ожидания (30 секунд), свяжитесь с хостинг-провайдером, авторизуйте конечную точку. |
| Пустое резюме | Контент, который слишком короткий или слишком "конструкторский" (шорткоды) | Проверьте текст после очистки. | Добавить реальный текст, отредактировать текст, резюмировать отрывок. |
| Вы редактируете статью, но аннотация не меняется. | Код не перегенерируется, если метаданные уже существуют. | Проверьте наличие _ai_summary |
Удалите метатег или выполните ручную перегенерацию. |
Реалистичные ошибки, которые я часто вижу (и как их избежать)
- Тестирование в производственной среде без резервного копирования. : Запустите тест на тестовой площадке. Синтаксическая ошибка PHP может заблокировать всю панель администратора.
- Путаница между действием и фильтром. :
save_postЭто действие. Не пытайтесь "вернуть" что-либо, чтобы изменить значение. - Неподходящий зацеп : избегать
the_contentдля дорогостоящей задачи. - плагин кэширования Если вы отображаете сводку с помощью шорткода и используете агрессивный кеш, очистите его после первой генерации.
- PHP слишком устарел. Если ваш хостинг-провайдер использует PHP 7.4, обновитесь до версии 8.1 и выше. Ссылка: Поддерживаемые версии PHP (php.net).
Ресурсы
- HTTP API WordPress (developer.wordpress.org)
- Нонсы и безопасность (developer.wordpress.org)
- API для работы с временными данными (developer.wordpress.org)
- Обзор API OpenAI
- Справочник по API ответов OpenAI
- Зеркало GitHub для разработки WordPress (wordpress-develop)
- WordPress Core Trac (отслеживание заявок)
- Расширение cURL (php.net)
FAQ
1) Работает ли это с Elementor / Divi 5 / Avada?
Да. Короткий код [ai_summary] Это самый простой метод. Используйте виджет/элемент «Шорткод» в своем конструкторе.
2) Почему именно mu-плагин, а не functions.php?
Потому что functions.php Это зависит от темы оформления. При смене темы вы потеряете функциональность. Плагин mu загружается автоматически независимо от темы.
3) Замедлит ли это публикацию статьи?
Да, немного: вы ждете ответа от API во время процесса сохранения (до истечения таймаута). На очень активных сайтах я часто переключаю эту обработку на асинхронную задачу (WP-Cron или Action Scheduler), но это более продвинутый подход.
4) Могу ли я кратко изложить только отрывок (первые 2 абзаца)?
Да. Редактировать bpcab_ai_get_post_text_for_summary() Удалить только первые X символов или разбить на абзацы перед очисткой.
5) Почему данные сохраняются в пост-метатегах, а не пересчитываются при отображении?
Чтобы избежать оплаты API за каждый просмотр страницы и гарантировать стабильное сводное представление данных, вы выполняете быстрое считывание данных из базы данных только при отображении страницы.
6) Можно ли автоматически отображать сводку в архивах (категориях)?
Да. Вы можете добавить шорткод в шаблон архива (или через конструктор, если ваша тема это позволяет). Другой вариант: прикрепить фильтр к the_excerpt Заменить отрывок мета-тегом, но я делаю это только в том случае, если у сайта есть четкая стратегия (иначе это удивит авторов).
7) Навязывает ли WordPress 6.9.4 какой-либо особый способ выполнения HTTP-запросов?
Нет: рекомендуемый подход остается прежним. wp_remote_post() через HTTP API. Он стабилен и совместим со средами, где cURL недоступен напрямую в PHP.
8) Как "принудительно" перезапустить статью, которая уже была кратко изложена?
Удалить метатеги _ai_summary (с помощью мета-инструмента или небольшого административного скрипта), затем обновите статью. Более аккуратный вариант: добавьте кнопку «Перегенерировать» с одноразовым кодом и возможностью обновления.
9) Может ли ИИ искусственно создавать информацию в виде резюме?
Да, это возможно. Снижение температуры помогает, но не гарантирует полного отсутствия ошибок. Для конфиденциального контента рекомендуется проводить проверку вручную или избегать использования ИИ.
10) Почему ограничение BPCAB_AI_MAX_INPUT_CHARS применяется вместо подсчета токенов?
Для точного подсчета токенов требуется специальная библиотека. Для начинающего сайта ограничение количества символов — это простое, надежное решение, которое уже значительно снижает затраты.