Автор: A.Ankalaev
Cистемный администратор с опытом более 20 лет
Среди специалистов по разработке, особенно тут на Хабре, бытует мнение, что большие языковые модели (LLM) не способны генерировать полноценные приложения «под ключ». Сам работаю с нейросетями со времён GPT, бесконечное количество раз применял их в своей работе для:
обучения персонала безопасности в сетипроектирования концепций
математических вычислений (нагрузка, мощность, распределение)
личного карьерного роста.
Если верить данным в сети:
Запущенный в июне 2022 GitHub Copilot имеет 1,3 миллиона платных пользователей (по состоянию на февраль 2024 года, более свежие данные отсутствуют).
По данным DemandSage, опубликованным 16 апреля 2025 года, ЧатGPT достиг 800 миллионов еженедельных активных пользователей, что подтверждается заявлениями CEO OpenAI Сэма Альтмана на TED 2025
Согласно статье Bloomberg, Cursor AI имеет около 1 миллиона пользователей (по состоянию на апрель 2025 года).
Большой спрос на ИИ, благодаря конкретным способностям, вполне оправдан. Но несмотря на устрашающие возможности, какна деле, так и в нашем сознании, ни один ИИ‑агент, включая крупных игроков, не пишет даже простой проект (15–30 файлов) самостоятельно, даже если скормить ему суперидеальное «ТЗ» и направляющие (аля «назначение роли») во всякие «Rules» подобные механизмы.
Что я только не пробовал подавать на вход, чтоб получить идеальный выход
Назначение роли в Project Rules
Цель проекта в Project Rules
Стек технологий и фреймворков в User Rules
Ограничения и запреты в User Rules
Принципы проектирования в User Rules
Документацию в Docs
Идеальный промпт на 47+ тысяч символов
Не идеальный, но подробный промпт на 10 тысяч символов
Пример почти идеального промпта по моему скромному мнению
# Техническое задание на разработку плагина AIWP-Processor (Часть 1) ## 1. Общая информация Наименование плагина: AIWP-Processor Платформа: WordPress Интеграция: Google Gemini API Назначение: Автоматизация создания и редактирования контента с помощью искусственного интеллекта Документация API: [Google Gemini API FAQ](../doc/gemini-api-faq.md) ## 2. Функциональные требования ### 2.1. Основной функционал 1. Интеграция с Google Gemini API: - Подключение к REST API сервиса Google Gemini. - Настройка и валидация API-ключа. - Получение и сохранение списка доступных моделей. - Выбор модели для для каждого генератора отдельно (Text_Generator
, Image_Generator
).
Взаимодействие с WordPress:
Создание/редактирование заголовков постов
post_title
.Создание/редактирование содержимого постов
post_content
.Генерация и установка изображений
featured_image
.Логирование всех операций и ошибок.
Пользовательский интерфейс:
Метабокс для чат-интерфейса для ввода запросов и получения результатов
metabox-chat.php
.Интеграция метабокса в классический редактор WordPress и в редактор Gutenberg.
Административная панель с вкладками для управления плагином
dashboard.php
.
2.2. Интерфейс метабокса metabox-chat.php
2.2.1. Структура интерфейса
1. Верхняя панель метабокса
<div class="aiwp-metabox-header">
<h3>AI Content Generator</h3>
<div class="aiwp-metabox-controls">
<button title="Clear chat history" class="aiwp-clear-history">
<span class="dashicons dashicons-trash"></span>
</button>
<button title="Show help" class="aiwp-help">
<span class="dashicons dashicons-editor-help"></span>
</button>
</div>
</div>
2. Панель управления генерацией
<div class="aiwp-generation-controls">
<div class="aiwp-options">
<label class="aiwp-checkbox">
<input name="generate_title" id="generate_title" type="checkbox">
<span>Generate Title</span>
</label>
<label class="aiwp-checkbox">
<input name="generate_content" id="generate_content" type="checkbox">
<span>Generate Content</span>
</label>
<label class="aiwp-checkbox">
<input name="generate_image" id="generate_image" type="checkbox">
<span>Generate Featured Image</span>
</label>
</div>
</div>
3. Область чата
<div class="aiwp-chat-container">
<div id="aiwp_chat_messages" class="aiwp-chat-messages">
</div>
<div class="aiwp-chat-input">
<textarea rows="3" placeholder="Enter your prompt here..." id="aiwp_prompt"></textarea>
<button class="button button-primary" id="aiwp_send">
<span class="aiwp-button-text">Send</span>
<span class="aiwp-spinner"></span>
</button>
</div>
</div>
4. Панель результатов
<div class="aiwp-results-panel">
<div class="aiwp-preview">
</div>
<div class="aiwp-actions">
<button data-type="title" class="button aiwp-apply">
Apply Title
</button>
<button data-type="content" class="button aiwp-apply">
Apply Content
</button>
<button data-type="image" class="button aiwp-apply">
Apply Featured Image
</button>
</div>
</div>
2.2.2. Стилизация компонентов
1. Основные размеры и отступы
.aiwp-metabox {
min-height: 400px;
max-height: 800px;
display: flex;
flex-direction: column;
}
.aiwp-chat-container {
flex: 1;
min-height: 300px;
display: flex;
flex-direction: column;
}
.aiwp-chat-messages {
flex: 1;
overflow-y: auto;
padding: 15px;
}
2. Стили сообщений чата
.aiwp-message {
margin-bottom: 15px;
max-width: 85%;
}
.aiwp-message-user {
margin-left: auto;
background: #e9ecef;
border-radius: 15px 15px 0 15px;
}
.aiwp-message-ai {
margin-right: auto;
background: #f8f9fa;
border-radius: 15px 15px 15px 0;
}
3. Стили элементов управления
.aiwp-generation-controls {
padding: 10px;
border-bottom: 1px solid #ddd;
}
.aiwp-checkbox {
display: inline-flex;
align-items: center;
margin-right: 15px;
}
.aiwp-actions {
display: flex;
gap: 10px;
padding: 10px;
border-top: 1px solid #ddd;
}
2.3. Административная панель dashboard.php
2.3.1. Структура административной панели
1. Основной контейнер
<div class="wrap aiwp-dashboard">
<h1>AIWP Processor Dashboard</h1>
<div class="aiwp-container">
<nav class="aiwp-tabs">
<a class="active" href="#dashboard">Dashboard</a>
<a href="#google-api">Google API</a>
<a href="#settings">Settings</a>
<a href="#logs">Logs</a>
</nav>
<div class="aiwp-tab-content">
</div>
</div>
</div>
2. Стилизация панели
.aiwp-dashboard {
max-width: 1200px;
margin: 20px auto;
}
.aiwp-container {
min-height: 700px;
background: #fff;
border: 1px solid #ccd0d4;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
}
.aiwp-tab-content {
padding: 20px;
}
.aiwp-section {
padding: 10px;
margin-bottom: 20px;
}
2.3.2. Содержимое вкладок
1. Dashboard
<div class="aiwp-tab-content" id="dashboard">
<div class="aiwp-section aiwp-status">
<h2>System Status</h2>
<div class="aiwp-grid">
<div class="aiwp-status-item">
<h4>API Connection</h4>
<div class="aiwp-status-indicator"></div>
</div>
</div>
</div>
<div class="aiwp-section aiwp-models">
<h2>Available Models</h2>
<table class="wp-list-table widefat">
</table>
</div>
</div>
2. Google API
<div class="aiwp-tab-content" id="google-api">
<div class="aiwp-section">
<h2>API Configuration</h2>
<form action="options.php" method="post">
<table class="form-table">
<tbody><tr>
<th>API Key</th>
<td>
<input value="<?php echo esc_attr(get_option('aiwp_google_api_key')); ?>" class="regular-text" name="aiwp_google_api_key" type="password">
</td>
</tr>
</tbody></table>
</form>
</div>
</div>
3. Settings
<div class="aiwp-tab-content" id="settings">
<div class="aiwp-section">
<h2>General Settings</h2>
<form action="options.php" method="post">
<table class="form-table">
<tbody><tr>
<th>Email Notifications</th>
<td>
<label>
<input value="1" name="aiwp_email_notifications" type="checkbox">
>
Enable email notifications
</label>
</td>
</tr>
</tbody></table>
</form>
</div>
</div>
4. Logs
<div class="aiwp-tab-content" id="logs">
<div class="aiwp-section">
<div class="aiwp-logs-header">
<h2>Operation Logs</h2>
<div class="aiwp-logs-actions">
<button id="clear_logs" class="button">Clear Logs</button>
<button id="export_logs" class="button">Export Logs</button>
</div>
</div>
<div class="aiwp-logs-table-container">
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>Timestamp</th>
<th>Level</th>
<th>Message</th>
<th>Context</th>
</tr>
</thead>
<tbody id="logs_content">
</tbody>
</table>
</div>
</div>
</div>
3. Особенности поведения
3.1. Логика при работе с новой записью
Стандартный запрос: "You are a content generator. Generate a post with the title: {title} and content: {content}"
При выборе опции "Generate Title": генерация и заполнение поля заголовка
При выборе опции "Generate Content": генерация и заполнение поля содержимого
При выборе опции "Generate Featured Image": "You are a content generator. Make image: {title}"
Применение результатов происходит только после подтверждения пользователем
3.1.1 Детальный процесс обработки новой записи
1. Процесс формирования запроса:
При инициализации метабокса метод
is_new_post()
определяет, что запись новаяКласс
Metabox_Chat
через методformat_prompt()
собирает базовый контекст:$context = [ 'post_type' => get_post_type($post_id), 'category' => get_the_category($post_id), 'tags' => get_the_tags($post_id), 'title' => get_the_title($post_id), 'content' => get_post_field('post_content', $post_id), 'featured_image' => get_post_thumbnail_id($post_id) ];
2. Последовательность обработки при выборе всех опций:
JavaScript формирует начальный запрос:
const requestData = { prompt: userPrompt, options: { generateTitle: true, generateContent: true, generateImage: true } };
На сервере запрос обрабатывается в следующем порядке:
Генерация заголовка (приоритет 1)
Генерация контента с учетом заголовка (приоритет 2)
Генерация изображения на основе заголовка/контента (приоритет 3)
Класс
Google_API_Processor
выполняет запросы последовательно:// 1. Генерация заголовка $title = $api->generate_text([ 'prompt' => "You are a content generator. Generate a post with the title: {title}", 'max_tokens' => 50 ]); // 2. Генерация контента с учетом заголовка $content = $api->generate_text([ 'prompt' => "You are a content generator. Generate a post with the title: {title} and content: {content}", 'max_tokens' => 1000 ]); // 3. Генерация изображения $image = $api->generate_image([ 'prompt' => "You are a content generator. Make image: {title}", 'size' => '1248x1024', 'responseModalities' => ["Text", "Image"] ]);
3. Передача данных между компонентами:
Клиентская часть → Сервер:
metabox-chat.js
→ AJAX запрос →wp_ajax_aiwp_chat_request
Данные передаются в формате JSON через POST запрос
Включается nonce для безопасности
Внутренняя обработка:
Metabox_Chat->handle_ajax_chat_request()
→Google_API_Processor
Результаты сохраняются во временное хранилище через
WP_Session
Логи записываются в
aiwp-logs.json
Сервер → Клиентская часть:
Структурированный JSON-ответ с результатами
WebSocket для real-time обновления статуса генерации
События прогресса для длительных операций 4. Обработка результатов:
Класс
Google_Response_Handler
форматирует и валидирует полученные данныеВременные файлы создаются в защищенной директории
Создаются превью для изображений
Результаты кэшируются для повторного использования
3.2. Логика при работе с существующей записью
При выборе "Generate Title": формирование запроса "You are a content generator. Rewrite the title: {title}"
При выборе "Generate Content": формирование запроса "You are a content generator. Rewrite the content: {content}"
При выборе опции "Generate Featured Image": формирование запроса "You are a content generator. Make image: {title}"
При выборе нескольких опций: комбинированный запрос для редактирования всех выбранных элементов
Все автоматически сформированные запросы можно редактировать перед отправкой
3.2.1 Детальный процесс обработки существующей записи
1. Процесс формирования запроса для существующей записи:
Метод
format_prompt()
собирает текущие данные:$current_data = [ 'title' => get_the_title($post_id), 'content' => get_post_field('post_content', $post_id), 'image' => get_post_thumbnail_id($post_id) ];
2. Последовательность операций при выборе всех опций:
Предварительная обработка:
// Анализ существующего контента $content_analysis = $api->analyze_content([ 'title' => $current_data['title'], 'content' => $current_data['content'], 'maintain_style' => true ]); // Формирование контекста для сохранения стиля $style_context = $content_analysis->extract_style_patterns();
Параллельная обработка запросов:
// Асинхронная генерация всех элементов $promises = [ 'title' => $api->async_generate_text($prompt, $style_context), 'content' => $api->async_generate_text($prompt, $style_context), 'image' => $api->async_generate_image($prompt, [ 'responseModalities' => ["Text", "Image"] ]) ]; // Ожидание выполнения всех запросов $results = Promise\all($promises)->wait();
Пост-обработка результатов:
Сравнение с оригинальным контентом
Сохранение форматирования
Объединение результатов 3. Передача данных между компонентами:
Подготовка данных:
$prepared_data = [ 'original' => $current_data, 'generated' => $results, 'diff' => generate_content_diff($current_data, $results) ];
Система событий:
do_action('aiwp_before_content_update', $prepared_data); update_post_meta($post_id, '_aiwp_generation_history', $prepared_data); do_action('aiwp_after_content_update', $prepared_data);
Клиентское отображение:
Визуальное сравнение версий
Возможность частичного применения изменений
Предпросмотр в реальном времени 4. Обработка специфических случаев:
Сохранение мета-данных:
// Сохранение истории изменений $history = [ 'timestamp' => current_time('mysql'), 'user_id' => get_current_user_id(), 'changes' => $prepared_data['diff'] ]; add_post_meta($post_id, '_aiwp_revision', $history);
Обработка конфликтов:
Проверка наличия несохраненных изменений
Механизм разрешения конфликтов версий
Возможность отката изменений
Валидация результатов:
// Проверка качества генерации $quality_check = [ 'readability_score' => calculate_readability($results['content']), 'seo_score' => analyze_seo_metrics($results), 'similarity_score' => compare_with_original($current_data, $results) ];
4. Требования к безопасности и производительности
Безопасность
Валидация и санитация всех пользовательских входных данных
Безопасное хранение API-ключа
Проверка прав доступа для всех операций
Защита от CSRF-атак
Производительность
Асинхронная обработка запросов к API
Кэширование результатов запросов где возможно
Оптимизация загрузки ресурсов (CSS/JS)
Учет ограничений и квот API Google Gemini
Техническое задание на разработку плагина AIWP-Processor (Часть 2)
5. Архитектура плагина
5.1. Структура файлов и функциональность
| aiwp-processor.php
| uninstall.php
|
+---Backend
| +---Admin
| | class-aiwp-admin.php
| | class-aiwp-ajax-request.php
| | class-aiwp-dashboard.php
| |
| +---API
| | class-google-processor.php
| |
| +---Chat
| | class-metabox-chat.php
| |
| \---Logger
| aiwp-logs.json
| class-aiwp-logger.php
|
+---doc
| development.md
| gemini-api-faq.md
|
\---Frontend
\---assets
+---CSS
| dashboard.css
| metabox.css
|
+---JS
| dashboard.js
| metabox-chat.js
|
\---pages
dashboard.php
metabox-chat.php
aiwp-processor.php # Основной файл плагина
Функции в aiwp-processor.php:
aiwp_activate()
- активация плагина, создание необходимых директорий и файловaiwp_deactivate()
- деактивация плагина, сохранение настроекaiwp_init()
- инициализация плагина при загрузке WordPressaiwp_register_assets()
- регистрация CSS и JavaScript ресурсовaiwp_load_textdomain()
- загрузка файлов локализацииaiwp_plugin_row_meta()
- добавление метаданных плагинаaiwp_check_requirements()
- проверка требований для работы плагинаaiwp_admin_notices()
- отображение административных уведомленийaiwp_add_admin_menu()
- добавление пунктов меню в админ-панель WordPress
uninstall.php # Скрипт удаления плагина
Функции в uninstall.php:
Удаление всех опций и настроек плагина из базы данных
Удаление созданных при установке директорий и файлов
Удаление журналов логирования
Backend/
Admin/
class-aiwp-admin.php # Класс для интеграции с админ-панелью WordPress
Методы класса AIWP_Admin:
__construct()
- конструктор классаinit()
- инициализация классаregister_hooks()
- регистрация хуков WordPressadd_admin_menu()
- добавление административного менюregister_settings()
- регистрация настроек плагинаadmin_enqueue_scripts()
- подключение скриптов и стилей для админ-панелиdisplay_admin_page()
- отображение административной страницы плагинаadd_metaboxes()
- добавление метабокса в классический редактор и Gutenbergadd_metabox_classic()
- добавление метабокса в классический редакторadd_metabox_gutenberg()
- добавление метабокса в редактор Gutenbergsave_metabox_data()
- сохранение данных метабоксаget_plugin_option($option_name)
- получение опции плагинаupdate_plugin_option($option_name, $value)
- обновление опции плагинаdelete_plugin_option($option_name)
- удаление опции плагина
class-aiwp-dashboard.php # Класс для страницы настроек плагина
Методы класса AIWP_Dashboard:
__construct()
- конструктор классаinit()
- инициализация классаregister_hooks()
- регистрация хуков WordPressrender_dashboard_page()
- отображение страницы дашбордаrender_tab_dashboard()
- отображение вкладки Dashboardrender_tab_google_api()
- отображение вкладки Google APIrender_tab_settings()
- отображение вкладки Settingsrender_tab_logs()
- отображение вкладки Logshandle_api_key_update()
- обработка обновления API ключаhandle_model_selection()
- обработка выбора моделей AIhandle_settings_update()
- обработка обновления общих настроекhandle_logs_settings()
- обработка настроек логированияget_available_models()
- получение списка доступных моделейtest_api_connection()
- тестирование соединения с APIclear_logs()
- очистка журнала логовexport_logs()
- экспорт журнала логовprocess_bulk_actions()
- обработка массовых действий
Backend/API/
class-google-processor.php # Класс для работы с Google Gemini API
Методы класса Google_API_Processor:
__construct()
- конструктор классаinit()
- инициализация класса с настройкамиset_api_key($api_key)
- установка API ключаget_api_key()
- получение API ключаvalidate_api_key()
- валидация API ключаget_available_models()
- получение списка доступных моделейget_model_details($model_id)
- получение детальной информации о моделиset_text_model($model_id)
- установка модели для текстового генератораset_image_model($model_id)
- установка модели для генератора изображенийget_text_model()
- получение текущей текстовой моделиget_image_model()
- получение текущей модели изображенийformat_prompt($context, $prompt, $is_new_post = false)
- форматирование запроса с учетом контекстаgenerate_text($prompt, $options = [])
- генерация текста по промптуgenerate_image($prompt, $options = [])
- генерация изображения по промптуasync_generate_text($prompt, $options = [])
- асинхронная генерация текстаasync_generate_image($prompt, $options = [])
- асинхронная генерация изображенияanalyze_content($data)
- анализ существующего контентаrewrite_title($current_title, $prompt)
- переписывание существующего заголовкаrewrite_content($current_content, $prompt)
- переписывание существующего контентаcheck_rate_limits()
- проверка ограничений и квот APIlog_request($request_data)
- логирование запросов к APIlog_response($response_data)
- логирование ответов от APIhandle_api_response($response)
- обработка ответа APIhandle_error($error_code, $error_message)
- обработка ошибок APIsave_api_response($response_data)
- сохранение ответа API для последующего использования
Backend/Chat/
class-metabox-chat.php # Класс для метабокса в редакторе
Методы класса Metabox_Chat:
__construct()
- конструктор классаinit()
- инициализация классаregister_hooks()
- регистрация хуков WordPressenqueue_assets()
- подключение скриптов и стилейadd_metabox()
- добавление метабокса в редакторrender_metabox($post)
- отображение содержимого метабоксаsave_metabox_data($post_id)
- сохранение данных метабоксаgenerate_chat_interface()
- генерация интерфейса чатаhandle_ajax_chat_request()
- обработка AJAX-запроса из чатаformat_prompt($post, $user_prompt, $options)
- форматирование промпта на основе выбранных опцийprocess_api_response($response, $options)
- обработка ответа APIis_new_post($post_id)
- проверка, новая ли записьapply_generated_title($post_id, $title)
- применение сгенерированного заголовкаapply_generated_content($post_id, $content)
- применение сгенерированного содержимогоapply_generated_image($post_id, $image_data)
- применение сгенерированного изображенияsave_chat_history($post_id, $chat_data)
- сохранение истории чата для постаget_chat_history($post_id)
- получение истории чата для постаclear_chat_history($post_id)
- очистка истории чата для постаget_generation_context_from_title($post_id)
- получение контекста для генерацииget_generation_context($post_id)
- получение контекста для генерацииhandle_image_upload()
- обработка загрузки изображенияvalidate_request($post_id, $nonce)
- валидация запроса
Backend/API/
class-google-response-handler.php # Класс для обработки ответов от API
Методы класса Google_Response_Handler:
__construct()
- конструктор классаinit()
- инициализация классаprocess_text_response($response)
- обработка текстового ответаprocess_image_response($response)
- обработка ответа с изображениемextract_title_from_response($response)
- извлечение заголовка из ответаextract_content_from_response($response)
- извлечение содержимого из ответаextract_image_from_response($response)
- извлечение изображения из ответаvalidate_response($response)
- валидация ответаformat_response_for_client($response)
- форматирование ответа для клиентаhandle_error_response($error)
- обработка ошибочного ответаsave_temporary_title($title)
- сохранение временного заголовкаsave_temporary_content($content)
- сохранение временного содержимогоsave_temporary_image($image_data)
- сохранение временного изображенияcleanup_temporary_data()
- очистка временных данных
Backend/Logger/
class-aiwp-logger.php # Класс для логирования операций
Методы класса AIWP_Logger:
__construct()
- конструктор классаinit()
- инициализация классаset_log_file($log_file)
- установка файла для логированияlog($message, $level = 'info', $context = [])
- основной метод логированияlog_info($message, $context = [])
- логирование информационных сообщенийlog_warning($message, $context = [])
- логирование предупрежденийlog_error($message, $context = [])
- логирование ошибокlog_api_request($endpoint, $params)
- логирование API запросовlog_api_response($endpoint, $response)
- логирование ответов APIget_logs($limit = 100, $level = null)
- получение логовget_log_by_id($log_id)
- получение записи лога по IDclear_logs()
- очистка всех логовrotate_logs()
- ротация логов для контроля размера файлаis_logging_enabled()
- проверка, включено ли логированиеset_log_level($level)
- установка уровня детализации логированияget_log_level()
- получение текущего уровня логированияformat_log_entry($message, $level, $context)
- форматирование сообщения лога
aiwp-logs.json # Файл логов
Структура файла логов:
Хранится в формате JSON
Каждая запись содержит:
ID лога
Временная метка
Уровень логирования (info, warning, error)
Сообщение
Контекст (дополнительные данные)
IP-адрес пользователя
Frontend/assets/
CSS/
dashboard.css # Стили для страницы настроек
metabox.css # Стили для метабокса
Техническое задание на разработку плагина AIWP-Processor (Часть 3)
6. Жизненный цикл работы плагина
6.1. Этапы работы плагина
Инициализация
Загрузка основного файла плагина при активации WordPress
Инициализация ключевых классов (Admin, API, Chat, Logger)
Регистрация хуков и фильтров WordPress
Взаимодействие с редактором контента
Отображение метабокса в редакторе записи
Обработка запросов пользователя в интерфейсе метабокса
Отправка данных на сервер через AJAX
Обработка запросов к AI
Валидация и форматирование запроса
Отправка запроса к Google Gemini API
Обработка и форматирование ответа
Логирование результатов операции
Работа с сгенерированными данными
Временное хранение результатов генерации
Применение результатов к записи по запросу пользователя
Сохранение сгенерированных изображений в медиа-библиотеке WordPress
7. Диаграммы взаимодействия компонентов
7.1. Диаграмма взаимодействия при генерации контента
Пользователь → Метабокс чата
Пользователь вводит промпт и выбирает опции генерации
Метабокс чата → AJAX Request → Backend
Отправка запроса с промптом и выбранными опциями на сервер
Backend → Google API Processor
Формирование и отправка запроса к Google Gemini API
Google API Processor → Google Gemini API
Отправка запроса к внешнему API
Google Gemini API → Google API Processor
Получение ответа от внешнего API
Google API Processor → Backend
Обработка ответа и форматирование данных
Backend → Logger
Логирование операции и результата
Backend → AJAX Response → Метабокс чата
Отправка результата обратно клиенту
Метабокс чата → Пользователь
Отображение результата в интерфейсе чата
Пользователь → Метабокс чата → WordPress
Применение результата к записи (по запросу пользователя)
8. Планирование разработки
8.1. Приоритизация задач
Базовая интеграция с WordPress (метабокс, админ-панель)
Подключение к Google Gemini API
Реализация генерации текстового контента
Реализация генерации изображений
Система логирования
Улучшение пользовательского интерфейса
Оптимизация и повышение производительности
8.2. Диаграмма взаимодействия между компонентами
+-------------------+ +-------------------+ +-------------------+
| | | | | |
| WordPress Admin +------>+ AIWP_Admin +------>+ Metabox_Chat |
| | | | | |
+-------------------+ +---------+---------+ +---------+---------+
| |
| |
v v
+---------+---------+ +---------+---------+
| | | |
| AIWP_Dashboard | | Google_API |
| | | _Processor |
+---------+---------+ +---------+---------+
| |
| |
v v
+---------+---------+ +---------+---------+
| | | |
| AIWP_Logger +<------+ Response_Handler |
| | | |
+-------------------+ +-------------------+
9. Детальный процесс работы
9.1. Инициализация плагина
При активации WordPress загружается файл
aiwp-processor.php
Вызывается функция
aiwp_activate()
, которая:Создает необходимые директории для хранения логов и временных файлов
Регистрирует настройки плагина в базе данных WordPress
Инициализирует файл логов в формате JSON
При каждой загрузке WordPress вызывается функция
aiwp_init()
, которая:Создает экземпляры основных классов:
AIWP_Logger
,Google_API_Processor
иAIWP_Admin
Регистрирует все необходимые хуки и фильтры WordPress
Проверяет наличие и валидность API-ключа Google Gemini
Класс
AIWP_Admin
инициализирует административный интерфейс:Регистрирует пункты меню в административной панели WordPress
Подключает JavaScript и CSS ресурсы плагина
Добавляет метабокс в редактор постов (классический и Gutenberg)
9.2. Регистрация пользовательского интерфейса
Класс
AIWP_Admin
через методadd_metaboxes()
определяет тип используемого редактора:Для классического редактора вызывается метод
add_metabox_classic()
Для редактора Gutenberg вызывается метод
add_metabox_gutenberg()
Метабокс регистрируется для всех типов записей, где можно использовать AI-генерацию:
Посты (post)
Страницы (page)
Произвольные типы записей с поддержкой редактора
При рендеринге метабокса вызывается шаблон
metabox-chat.php
, который:Отображает чат-интерфейс с полем ввода промпта
Показывает чекбоксы для выбора типа генерируемого контента
Создает контейнер для вывода истории чата и результатов генерации
Скрипт
metabox-chat.js
инициализируется и привязывает обработчики событий к элементам интерфейса
9.3. Взаимодействие пользователя с метабоксом
Пользователь видит чат-интерфейс в боковой панели или под редактором
Интерфейс содержит:
Поле ввода (textarea) для промпта
Чекбоксы для выбора типа генерации:
"Generate Title" - создать заголовок
"Generate Content" - создать содержимое
"Generate Featured Image" - создать изображение-миниатюру
Кнопку "Send" для отправки запроса
Область истории чата (изначально пустая)
Класс
Metabox_Chat
загружает предыдущую историю чата из метаданных поста, если она существуетМетод
is_new_post()
определяет, является ли пост новым или существующим, для формирования правильного контекста запроса
9.4. Формирование и отправка запроса
Пользователь вводит текст запроса и выбирает нужные опции генерации
При нажатии кнопки "Send" вызывается функция
handlePromptSubmission()
изmetabox-chat.js
, которая:Предотвращает стандартное поведение формы
Добавляет сообщение пользователя в чат-историю
Отображает индикатор загрузки (спиннер)
Собирает данные запроса:
Текст промпта
Выбранные опции генерации (title, content, image)
ID и тип поста
Nonce для безопасности
Отправляет AJAX-запрос к WordPress через
wp_ajax_aiwp_process_chat_request
На стороне сервера запрос перехватывается методом
handle_ajax_chat_request()
классаMetabox_Chat
Метод выполняет:
Проверку безопасности (nonce)
Валидацию входных данных
Определение типа запроса (новый пост или редактирование)
Логирование запроса через класс
AIWP_Logger
9.5. Форматирование оптимизированного промпта
Метод
format_prompt()
классаMetabox_Chat
обрабатывает запрос пользователя:Если пост новый:
При выборе опции "Title" добавляет к промпту: "You are a content generator. Generate a post with the title:"
При выборе опции "Content" добавляет: "Generate post content about:"
При выборе обеих опций формирует комбинированный промпт
Если пост существующий:
При выборе опции "Title" извлекает текущий заголовок и добавляет к промпту: "You are a content generator. Rewrite the title: {current_title}"
При выборе опции "Content" добавляет: "Rewrite the content: {current_content}"
При выборе опции "Featured Image":
Добавляет к промпту: "You are a content generator. Make image: {title_or_prompt}"
Собирает контекст поста для улучшения генерации:
Категории и теги поста
Тип поста и статус
Метаданные (если есть)
9.6. Взаимодействие с Google Gemini API
Метод
handle_ajax_chat_request()
создает экземплярGoogle_API_Processor
В зависимости от выбранных опций вызываются соответствующие методы:
Для генерации текста (заголовок и/или содержимое):
generate_text()
- использует текстовую модель, выбранную в настройках плагинаПередает оптимизированный промпт и дополнительные параметры (температура, максимальная длина и т.д.)
Для генерации изображения:
generate_image()
- использует модель для изображений, выбранную в настройкахПередает промпт для изображения и параметры (разрешение, стиль)
Класс
Google_API_Processor
формирует HTTP-запросы к Google Gemini API:Подготавливает заголовки запроса с API-ключом
Формирует тело запроса в формате JSON
Отправляет запрос через WordPress HTTP API (wp_remote_post)
Получает и декодирует ответ
Обрабатывает возможные ошибки и исключения
Все запросы и ответы логируются через методы
log_request()
иlog_response()
классаAIWP_Logger
9.7. Обработка полученных результатов
Метод
process_api_response()
классаMetabox_Chat
обрабатывает полученные от API данные:При генерации текста:
Извлекает заголовок и содержимое из ответа
Форматирует HTML-структуру содержимого (абзацы, заголовки)
Санитизирует текст для безопасного отображения
При генерации изображения:
Сохраняет изображение во временную директорию
Создает миниатюру для предпросмотра
Подготавливает данные для загрузки в медиа-библиотеку WordPress
Формирует структурированный JSON-ответ, содержащий:
Сгенерированный контент (заголовок, текст, URL изображения)
Статус выполнения (успех или ошибка)
Тип сгенерированного контента
Временные метки
Логирует результат операции через
AIWP_Logger
Подготовленный ответ отправляется обратно клиенту через стандартный механизм AJAX WordPress
9.8. Отображение результатов пользователю
Скрипт
metabox-chat.js
получает ответ и обрабатывает его через функциюhandleResponseActions()
:Скрывает индикатор загрузки
Добавляет ответ от AI в историю чата
Отображает сгенерированный контент с соответствующим форматированием
Для текста: отображает заголовок и содержимое с правильной HTML-структурой
Для изображения: показывает миниатюру изображения
Активирует панель действий с кнопками:
"Apply Title" - если был сгенерирован заголовок
"Apply Content" - если было сгенерировано содержимое
"Apply Featured Image" - если было сгенерировано изображение
Функция
updateChatHistory()
добавляет новые сообщения в чат-интерфейс и прокручивает его внизИстория чата сохраняется в метаданных поста через AJAX-запрос к методу
save_chat_history()
9.9. Применение сгенерированных данных к записи
Пользователь может применить любой из сгенерированных элементов, нажав соответствующую кнопку
При нажатии на кнопку "Apply Title":
Вызывается функция
applyTitleToPost()
вmetabox-chat.js
Отправляется AJAX-запрос к методу
apply_generated_title()
классаMetabox_Chat
Метод обновляет заголовок поста в базе данных
В интерфейсе редактора обновляется поле заголовка
При нажатии на кнопку "Apply Content":
Вызывается функция
applyContentToPost()
вmetabox-chat.js
Отправляется AJAX-запрос к методу
apply_generated_content()
классаMetabox_Chat
Метод обновляет содержимое поста в базе данных
В зависимости от типа редактора:
Для классического редактора: контент вставляется в поле редактора
Для Gutenberg: контент вставляется через API редактора
При нажатии на кнопку "Apply Featured Image":
Вызывается функция
applyFeaturedImageToPost()
вmetabox-chat.js
Отправляется AJAX-запрос к методу
apply_generated_image()
классаMetabox_Chat
Метод:
Загружает временное изображение в медиа-библиотеку WordPress
Создает все необходимые размеры миниатюр
Устанавливает загруженное изображение как миниатюру записи
Обновляет интерфейс с отображением выбранной миниатюры
После каждого применения отображается уведомление об успешном выполнении операции
9.10. Завершение процесса и логирование
Все операции логируются в файле
aiwp-logs.json
через классAIWP_Logger
Метаданные о сеансе генерации сохраняются в посте
Обновляется статистика использования плагина для отображения на странице Dashboard:
Счетчик успешных генераций
Счетчик ошибок
Использованные токены/кредиты API
Временные метки последнего использования
Пользователь может продолжить работу с плагином, генерируя новый контент, или сохранить запись
История чата сохраняется между сеансами редактирования и доступна при повторном открытии записи
10. Цепочка взаимодействия компонентов
10.1. Клиентская часть: Отправка запроса
Нажатие кнопки "Send"
// metabox-chat.js
document.getElementById('aiwp_send').addEventListener('click', function(e) {
e.preventDefault();
handlePromptSubmission();
});
Сбор данных для запроса
// metabox-chat.js
function handlePromptSubmission() {
const prompt = document.getElementById('aiwp_prompt').value;
const generateTitle = document.getElementById('generate_title').checked;
const generateContent = document.getElementById('generate_content').checked;
const generateImage = document.getElementById('generate_image').checked;
const postId = document.getElementById('post_ID').value;
const data = {
action: 'aiwp_process_chat_request',
prompt: prompt,
options: {
generateTitle,
generateContent,
generateImage
},
postId: postId,
_ajax_nonce: aiwpData.nonce
};
sendAjaxRequest(data);
}
Отправка AJAX запроса
// metabox-chat.js
function sendAjaxRequest(data) {
showLoadingSpinner();
addMessageToChat('user', data.prompt);
jQuery.post(ajaxurl, data)
.done(handleResponse)
.fail(handleError)
.always(hideLoadingSpinner);
}
10.2. Серверная часть: Обработка запроса
Перехват AJAX запроса в WordPress
// class-metabox-chat.php
public function register_hooks() {
add_action('wp_ajax_aiwp_process_chat_request', [$this, 'handle_ajax_chat_request']);
}
Начальная обработка запроса
// class-metabox-chat.php
public function handle_ajax_chat_request() {
check_ajax_referer('aiwp_chat_nonce');
$post_id = intval($_POST['postId']);
$prompt = sanitize_textarea_field($_POST['prompt']);
$options = $this->validate_options($_POST['options']);
// Логируем входящий запрос
$this->logger->log_info('Incoming chat request', [
'post_id' => $post_id,
'options' => $options
]);
$this->process_request($post_id, $prompt, $options);
}
Форматирование промпта
// class-metabox-chat.php
private function format_prompt($prompt, $options, $post) {
$formatted_prompt = '';
if ($this->is_new_post($post)) {
if ($options['generateTitle']) {
$formatted_prompt .= "You are a content generator. Generate a post with the title: ";
}
if ($options['generateContent']) {
$formatted_prompt .= "Generate post content about: ";
}
} else {
if ($options['generateTitle']) {
$current_title = get_the_title($post);
$formatted_prompt .= "You are a content generator. Rewrite the title: {$current_title}";
}
if ($options['generateContent']) {
$current_content = get_post_field('post_content', $post);
$formatted_prompt .= "Rewrite the content: {$current_content}";
}
}
if ($options['generateImage']) {
$formatted_prompt .= "Make image: " . ($options['generateTitle'] ? '{title}' : $prompt);
}
return $formatted_prompt . $prompt;
}
10.3. Взаимодействие с API
Создание экземпляра API процессора
// class-metabox-chat.php
private function process_request($post_id, $prompt, $options) {
$api = new Google_API_Processor();
$formatted_prompt = $this->format_prompt($prompt, $options, get_post($post_id));
try {
$response = $this->generate_content($api, $formatted_prompt, $options);
$this->handle_api_response($response, $post_id);
} catch (Exception $e) {
$this->handle_error($e);
}
}
Генерация контента
// class-metabox-chat.php
private function generate_content($api, $prompt, $options) {
$response = [];
if ($options['generateTitle'] || $options['generateContent']) {
$text_model = $api->get_text_model();
$response['text'] = $api->generate_text($prompt, [
'model' => $text_model,
'temperature' => 0.7,
'max_tokens' => 1000
]);
}
if ($options['generateImage']) {
$image_model = $api->get_image_model();
$response['image'] = $api->generate_image($prompt, [
'model' => $image_model,
'size' => '1024x1024',
'quality' => 'hd'
]);
}
return $response;
}
10.4. Обработка ответа API
Парсинг ответа
// class-metabox-chat.php
private function handle_api_response($response, $post_id) {
$processed_response = [
'success' => true,
'data' => []
];
if (isset($response['text'])) {
$text_content = $this->process_text_response($response['text']);
$processed_response['data']['title'] = $text_content['title'] ?? null;
$processed_response['data']['content'] = $text_content['content'] ?? null;
}
if (isset($response['image'])) {
$image_data = $this->process_image_response($response['image'], $post_id);
$processed_response['data']['image'] = $image_data;
}
$this->logger->log_info('API response processed', $processed_response);
wp_send_json_success($processed_response);
}
Обработка текстового контента
// class-metabox-chat.php
private function process_text_response($text_response) {
return [
'title' => wp_strip_all_tags($text_response['title'] ?? ''),
'content' => wp_kses_post($text_response['content'] ?? '')
];
}
Обработка изображения
// class-metabox-chat.php
private function process_image_response($image_response, $post_id) {
$upload_dir = wp_upload_dir();
$temp_file = $upload_dir['path'] . '/temp_' . uniqid() . '.jpg';
file_put_contents($temp_file, base64_decode($image_response['data']));
return [
'temp_path' => $temp_file,
'preview_url' => $upload_dir['url'] . '/' . basename($temp_file)
];
}
10.5. Отправка результата клиенту
Форматирование ответа для клиента
// class-metabox-chat.php
private function format_client_response($processed_data) {
return [
'success' => true,
'data' => $processed_data,
'message' => 'Content generated successfully',
'timestamp' => current_time('mysql')
];
}
JavaScript обработка ответа
// metabox-chat.js
function handleResponse(response) {
if (response.success) {
const data = response.data;
// Добавляем ответ в чат
addMessageToChat('ai', formatAIResponse(data));
// Активируем кнопки применения результатов
if (data.title) enableApplyButton('title');
if (data.content) enableApplyButton('content');
if (data.image) enableApplyButton('image');
// Сохраняем результаты в временное хранилище
storeGeneratedContent(data);
} else {
handleError(response.message);
}
}
10.6. Применение результатов
Обработчики кнопок применения
// metabox-chat.js
function setupApplyButtons() {
document.getElementById('apply_title').addEventListener('click', () => {
const title = getStoredContent('title');
applyTitleToPost(title);
});
document.getElementById('apply_content').addEventListener('click', () => {
const content = getStoredContent('content');
applyContentToPost(content);
});
document.getElementById('apply_image').addEventListener('click', () => {
const image = getStoredContent('image');
applyFeaturedImageToPost(image);
});
}
Применение заголовка
// metabox-chat.js
function applyTitleToPost(title) {
// Для классического редактора
if (document.getElementById('title')) {
document.getElementById('title').value = title;
}
// Для Gutenberg
else if (wp.data && wp.data.select('core/editor')) {
wp.data.dispatch('core/editor').editPost({ title });
}
}
Применение контента
// metabox-chat.js
function applyContentToPost(content) {
// Для классического редактора
if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor) {
tinyMCE.activeEditor.setContent(content);
}
// Для Gutenberg
else if (wp.data && wp.data.select('core/editor')) {
wp.data.dispatch('core/editor').insertBlocks(
wp.blocks.parse(content)
);
}
}
Применение изображения
// metabox-chat.js
function applyFeaturedImageToPost(imageData) {
const data = {
action: 'aiwp_apply_featured_image',
post_id: getCurrentPostId(),
image_data: imageData,
_ajax_nonce: aiwpData.nonce
};
jQuery.post(ajaxurl, data)
.done(response => {
if (response.success) {
updateFeaturedImagePreview(response.data.attachment_url);
}
})
.fail(handleError);
}
Почему так происходит? Давайте разберёмся вместе!
👉 Мнение лично моё, и может служить как ответом для интересующихся, так и поводом для рассуждения, для более продвинутых персон. К некоторым тут на Хабре, испытываю большую симпатию, уважение и белую зависть, за знания и умение грамотно излагать, свой опыт и мысли в текст. Прошу не бросать в меня помидоры, пишу впервые😊🙏
Нейрон - начало
Я называю его «нейроном-сперматозоидом», который в процессе своей короткой жизни должен обработать всю цепочку от «килограммового промпта» до «ответа», а ещё после (смерти) ответа, помнить мой промпт. Проблема начинается именно здесь. Хочется писать максимально просто, чтобы о проблеме могли рассуждать не только посвящённые в тонкости читатели.
В больших LLM, до получения ответа "промпт" проходит примерно такой коридор:
1. Tokenization
2. Embedding
3. Transformer layers
4. Logits
5. Softmax
6. Sampling
7. Autoregression
(Кому интересны подробности выражений, могут спросить нейросеть😊)
Всем этим процессом оперирует один «нейрон», который после присвоения определённого количества токенов нашему промпту, преобразует их в эмбеддинг, который затем проходит через N слоёв трансформера. И вот здесь наш «нейрон-сперматозоид» активирует сотни других нейронов в слоях внимания. Именно тут начинает работать концепция «цепочки мыслей» (chain-of-thought) ответ, который почти у любой LLM будет примерно таким:
- Отлично! Я напишу структурированный базовый WordPress плагин для автоматизации публикаций в соцсети.
Одну минуту?!
Неужели я ввёл такой супер-мега-крутой промпт, который ответил бы на все вопросы рядового программиста?
Представьте:
Настоящий разработчик, получив письмо по электронной почте с просьбой: «Напиши мне базовый WordPress-плагин для автоматизации публикаций в соцсети», станет сразу писать код заказчика, не собрав данные, требования и ограничения, без анализа объема информации для выполнения задачи.
Именно так отвечают почти все LLM, если не учиться правильно ими оперировать. Да, сегодня нужно именно учиться и пробовать разные методы, чтобы ИИ выполнял то, что вы задумали, ведь ваша мысль - это уже план, а она осталась у вас в голове. Ваш промпт, это даже не половина вашего желания, а уж тем более мысли. Любая нейросеть, даже рассуждающая, спешит исполнить ваше желание как простую математическую задачку, на которую она уже заранее знает ответ, ведь сухих данных у неё в памяти хоть отбавляй.
Как уже было сказано, даже самые продвинутые нейросети, получив на вход промпт, не работают над конечным продуктом вашего (промпта) желания, в первую очередь потому, что в большинстве случаев «промпт» содержит недостаточно входных данных, чтобы получить желаемо детализированный ответ. По сути, ИИ просто отвечает на мой «промпт» на уровне уровнения. Ведь при отсутствии, явно нужных данных, нейросеть в лучшем случае , будет заполнять код абстрактными для нас данными, которые она получала во время своего обучения. Поэтому писать проект за меня, будет проблематично, как в техническом, так и в идеологическом плане.
Задумайтесь только, ведь наша "идея" может состоять из огромного количества факторов. Но даже наша мысль, которую мы сами не обдумали в пух и прах, во всех мельчайших деталях, не сможет быть реализована и восполнена кем-то вместо нас, даже если это супернейросеть. И только после того, как мы всё соберём, и промпт будет содержать достаточно входных данных, я бы сказал: «Абсолютных Данных», по которым человек - программист, сможет выполнить проект самостоятельно.
Опираясь на сухие цифры: модель Gemini 2.5 Pro имеет входной контекст в 1 миллион токенов, но на выход только 64 тысячи. А вот модель от Anthropic (Sonnet 3.7 Think) вполне могла бы склеить всю цепочку действий почти идеально, если бы вывод не упирался в размер окна, которое тут составляет 128 тысяч токенов.
Нейрон - Один за всех, и все за одного.
Один "нейрон" вместо команды. Сегодня LLM - это один «запускающий и выполняющий всю цепочку действий элемент», и проблема заключается в том, что пока один «нейрон» вынужден быть: Архитектором и исполнителем, тестировщиком, и даже заказчиком, мы не получим того самого магического результата - готового и продуманного до мелочей проекта. Всё потому, что на текущем этапе развития LLM, количество входных и выходных токенов всё ещё ограничено. Даже если подать на вход идеальный промпт на 200 тысяч токенов, ИИ сможет составить план на 500 тысяч, но для реализации этого плана ему потребуется ещё хотя бы полмиллиона токенов на выход. А если где-то не хватит данных, увы, уточнить у меня что же я имел в виду, он уже не сможет.
Агенты - решат все проблемы?
Возможно, всё изменится, когда появятся модели-агенты, способные оперировать миллионами токенов на вход и на выход. Тогда один агент сможет создать детальный план, разложить всё по полочкам, и что важно, управлять другими агентами: назначить первого архитектором, второго — FullTask-программистом, третьего — QA-тестировщиком, четвёртого — менеджером по кофе. И вот тогда, при условии, что я всё-таки напишу в промпте исчерпывающие детали будущего проекта, может и увижу, тот самый долгожданный момент, когда ИИ напишет и протестирует проект за меня.
А может и не увижу, потому что, как показывает практика, чем совершеннее становится инструмент, тем сложнее становятся наши желания. Ну а пока продолжаем писать промпты, мечтать о будущем и с лёгкой иронией наблюдать за тем, как нейросети снова и снова предлагают нам «структурированный базовый WordPress-плагин»
Всем спасибо за внимание! Жду комментариев 😊