Agar siz mahsulot tavsifini yozishga 40 daqiqa vaqt sarflab, oxirida iliq versiyasini olgan bo'lsangiz, sizga ushbu ish jarayoni yoqadi: WooCommerce sarlavha, atributlar va bir nechta biznes eslatmalaridan "uzoq" tavsif va "qisqa" parcha yaratadi - va siz tasdiqlash ustidan nazoratni saqlab qolasiz.
Ehtiyoj / Foydalanish holati
WooCommerce kataloglarida kontent yaratish ko'pincha qiyinchilik tug'diradi. Men 300 ta mahsulotga ega do'konlarning shunchaki tavsiflari yo'qligi sababli "kutilayotganini" ko'rdim, garchi fotosuratlar va narxlar tayyor bo'lsa ham. Natija: yomon SEO, konversiya ko'rsatkichlarining keskin pasayishi va jamoaning ishga tushirishni kechiktirishi.
Sun'iy intellekt bu yerda mavjud bo'lgan ma'lumotlardan izchil, tuzilgan va foyda olishga yo'naltirilgan birinchi qoralama yaratish uchun foydalidir. WordPress : sarlavha, kategoriyalar, atributlar, brend, o'lchamlar, material va boshqalar. Maqsad ko'r-ko'rona avtomatlashtirish emas, balki tahririyat nazoratini saqlab qolgan holda har bir mahsulot uchun yozish vaqtini qisqartirishdir.
Oxir-oqibat, qanday amalga oshirishni bilib olasiz:
- Mahsulot muharririda (WooCommerce administratori) "Sun'iy intellekt bilan yaratish" tugmasi.
- AI API orqali qo'ng'iroq qilish
wp_remote_post()(Sans SDK) vaqt tugashi va xatolarni boshqarish bilan. - Xuddi shu avlod uchun qayta to'lovni oldini olish uchun har bir o'tish davri uchun bitta kesh.
- Xavfsiz yangilanish uzoq tavsif et qisqacha tavsif (mahsulotdan parcha).
- Ko'tarilishlarning (va kutilmagan to'lovlarning) oldini olish uchun oddiy stavkalarni cheklash tizimi.
Tez xulosa
- Biz AJAX administrator so'rovini ishga tushiradigan tugma bilan WooCommerce meta qutisini qo'shamiz.
- Server mahsulot ma'lumotlaridan (atributlar, toifalar va boshqalar) so'rov yaratadi.
- Sun'iy intellekt bilan qo'ng'iroq
wp_remote_post(), qisqa vaqt tugashi, cheklangan qayta urinishlar, qayd etilgan xatolar. - Tozalangan javob bilan
wp_kses_post()kiritishdan oldinpost_contentetpost_excerpt. - Hech narsa o'zgarmagan bo'lsa, qayta yaratilmaslik uchun Transients API orqali keshlang.
- API kaliti saqlangan
wp-config.php(hech qachon qattiq kodlanmagan, hech qachon JS tomonida emas).
Buning uchun qachon AI dan foydalanish kerak
Katta hajmdagi ma'lumotlar, ishonchli ma'lumotlar tuzilmasi va izchillik zarurati bo'lganda sun'iy intellektdan foydalaning. Odatda:
- Ko'p sotuvchili do'konlar yozuvlar xom ma'lumotlar (CSV, ERP) shaklida kam matn bilan keladi.
- Variantlarga ega kataloglar (o'lcham/rang), bu yerda siz bir xil tavsiflarni va atributlar tomonidan boshqariladigan farqlarni xohlaysiz.
- SEO "asosiy" : barqaror tuzilishga (paragraflar, ro'yxatlar) ega bo'lgan toza, o'qilishi oson matn yaratish, so'ngra strategik mahsulotlarni takomillashtirish.
- Xalqarolashtirish (kengaytirilgan variant): inson tomonidan tasdiqlash bilan FR bazasidan EN/DE/ES versiyasini yaratish.
Haqiqiy hayot sharoitida yaxshi ishlaydigan narsa mahsulot yaratilganda uni yaratish va keyin faqat ma'lum maydonlar (atributlar, kategoriya, brend) o'zgarganda qayta yaratishdir. Mahsulotning "barmoq izi" asosida keshlash juda yordam beradi.
Qachon AI dan foydalanmaslik kerak
Agar an'anaviy yechim yanada ishonchli yoki kamroq xavfli bo'lsa, sun'iy intellektdan qoching:
- Qat'iy qonuniy tavsiflar (kosmetika, qo'shimchalar, tibbiy): gallyutsinatsiyalar xavfi real. ACF maydonlari/atributlariga ega PHP shablonlarini yoki qonuniy tasdiqlangan ma'lumotlar bazasini afzal ko'ring.
- Yuqori texnologiyali mahsulotlar hatto eng kichik xato ham mijozlarga xizmat ko'rsatish (moslik, standartlar) uchun daromad keltiradigan joyda. Siz hali ham AI dan foydalanishingiz mumkin, lekin faqat majburiy tasdiqlash bilan qulflangan so'rovda.
- Juda qattiq xarajatlar cheklovlariga ega saytlar : agar sizda 20 000 ta mahsulot bo'lsa va siz tez-tez yangilansangiz, keshlash va ommaviy ishlov berishdan foydalanmasangiz, API to'lovi tezda ko'tariladi.
- Manba ma'lumotlaringiz yomon bo'lganda (Noto'g'ri sarlavhalar, bo'sh atributlar). Bo'shliqlarni to'ldirish uchun sun'iy intellekt "ixtiro qiladi". Bu holda, katalogni tozalashdan boshlang.
Odatdagi anti-shablon har bir avtomatik saqlashda avlodni ishga tushirishdir. Gutenberg avtomatik saqlashi, WooCommerce meta teglarini yangilashi va sizning hookingiz kaskadda ishga tushirilishi tufayli bitta mahsulot uchun o'nlab API chaqiruvlariga duch kelasiz.
qo'ymaydi
2026-yil aprel oyiga kelib, kamida quyidagilarga erishishga intiling:
- WordPress 6.9.4 (sizning kontekstingiz) va PHP 8.1 +.
- WooCommerce Yangilangan (2026-yilgi filial). Quyidagi kod mo'rt WooCommerce ichki qismlariga emas, balki barqaror WordPress API-lariga asoslangan.
- Ga kirish
wp-config.php(yoki muhit o'zgaruvchilari) API kalitini saqlash uchun.
API kalitini saqlang (wp-config.php)
Buni qo'shing wp-config.php (ideal holda, xosting provayderingizning sirlarini boshqarish orqali, lekin doimiy yaxshi asos bo'lib qolmoqda).
/**
* Clé API OpenAI (exemple).
* Ne la commitez jamais dans Git. Ne la mettez jamais dans un plugin.
*/
define('BPCAB_OPENAI_API_KEY', 'sk-proj-...');
Agar siz muhit o'zgaruvchilarini afzal ko'rsangiz, quyidagilarni qilishingiz mumkin:
define('BPCAB_OPENAI_API_KEY', getenv('BPCAB_OPENAI_API_KEY') ?: '');
Foydali rasmiy ma'lumotnomalar
- wp_remote_post() (WordPress dasturchi resurslari)
- Nonces (WordPress)
- wp_kses_post() (HTML sanitarizatsiyasi)
- API o'tish davri
- PHPda JSON (php.net)
Yechim arxitekturasi
Oqim (matn sxemasi):
Mahsulot administratori (Generate tugmasi) → AJAX administratori (nonce + imkoniyatlar) → mahsulot ma'lumotlarini olish → xesh hisoblash → vaqtinchalik kesh? → aks holda wp_remote_post() → AI API → JSON tahlili → sanitariya (
wp_kses_post()) → mahsulot yangilanishi (kontent + parcha) → JSON administratorga qaytarildi
Sahna ortida nima bo'lyapti
- Foydalanuvchi interfeysi administratori : tugma + ixtiyoriy "eslatmalar" maydoniga ega meta-quti. JS hech qachon API kalitiga ega bo'lmaydi.
- AJAX so'nggi nuqtasi : nonce + tomonidan himoyalangan
current_user_can('edit_product', $product_id). - tez : ishonchli elementlardan qurilgan (WooCommerce atributlari, toifalari, teglari, agar xohlasangiz narxlar).
- qoplama : ma'lumotlar xeshiga asoslangan vaqtinchalik. Agar hech narsa o'zgarmagan bo'lsa, allaqachon yaratilgan tavsif qaytariladi.
- Sanitarizatsiya Sun'iy intellekt HTML kodini qaytarishi mumkin. Faqat WordPress postda ruxsat bergan narsalarga ruxsat beriladi
wp_kses_post().
To'liq kod - bosqichma-bosqich
Sizga borishingizni maslahat beraman mu-ulash Yangilash paytida bolalar mavzusi yoki parcha plaginining buzilishining oldini olish uchun quyidagilarni yarating: wp-content/mu-plugins/bpcab-ai-woo-descriptions.php.
1) Mahsulot administratorida meta qutisini saqlang
Biz ekrandan foydalanamiz productUshbu meta-quti sizning oldingi quruvchingizdan (Divi/Elementor/Avada) qat'i nazar, mos keladi, chunki u WooCommerce administrator tomonida amalga oshirilmoqda.
<?php
/**
* Plugin Name: BPCAB - IA descriptions produits WooCommerce
* Description: Génère des descriptions produits via IA depuis l'admin WooCommerce (WP 6.9.4+, PHP 8.1+).
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
add_action('add_meta_boxes', function () {
add_meta_box(
'bpcab_ai_product_desc',
'Descriptions IA',
'bpcab_render_ai_metabox',
'product',
'side',
'high'
);
});
function bpcab_render_ai_metabox(WP_Post $post): void {
$product_id = (int) $post->ID;
if (!current_user_can('edit_product', $product_id)) {
echo '<p>Vous n’avez pas les droits pour modifier ce produit.</p>';
return;
}
wp_nonce_field('bpcab_ai_generate_desc', 'bpcab_ai_nonce');
echo '<p>
<label for="bpcab_ai_notes"><strong>Notes internes (optionnel)</strong></label>
<textarea id="bpcab_ai_notes" style="width:100%;min-height:70px;" placeholder="Ex: ton premium, mentionner la garantie 2 ans, éviter les superlatifs..."></textarea>
</p>';
echo '<p>
<button type="button" class="button button-primary" id="bpcab-ai-generate" data-product-id="' . esc_attr((string) $product_id) . '">
Générer avec IA
</button>
</p>';
echo '<div id="bpcab-ai-status" style="margin-top:8px;"></div>';
}
2) JS skriptini faqat mahsulot ekraniga yuklang
Men tez-tez uchraydigan xato - bu skriptni administrator panelining hamma joyiga navbatga qo'yish. Bu keraksiz ravishda ishlarni sekinlashtiradi va boshqa plaginlar bilan ziddiyatlarni keltirib chiqarishi mumkin.
add_action('admin_enqueue_scripts', function (string $hook_suffix) {
// Écrans typiques : post.php (édition), post-new.php (création)
if (!in_array($hook_suffix, ['post.php', 'post-new.php'], true)) {
return;
}
$screen = get_current_screen();
if (!$screen || $screen->post_type !== 'product') {
return;
}
wp_enqueue_script(
'bpcab-ai-woo-admin',
plugins_url('bpcab-ai-woo-admin.js', __FILE__),
['jquery'],
'1.0.0',
true
);
wp_localize_script('bpcab-ai-woo-admin', 'BPCAB_AI', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bpcab_ai_generate_desc'),
]);
});
Keyin, faylni yarating wp-content/mu-plugins/bpcab-ai-woo-admin.jsHa, mu-plagin alohida JS faylini yuklashi mumkin, agar yo'l to'g'ri bo'lsa. Agar infratuzilmangiz buni bloklasa, JSni oddiy plaginga joylashtiring (ko'pincha bu osonroq).
(function ($) {
function setStatus(html) {
$('#bpcab-ai-status').html(html);
}
$(document).on('click', '#bpcab-ai-generate', function () {
var productId = $(this).data('product-id');
var notes = $('#bpcab_ai_notes').val() || '';
setStatus('<p>Génération en cours… (ne fermez pas cet onglet)</p>');
$.ajax({
url: BPCAB_AI.ajaxUrl,
method: 'POST',
dataType: 'json',
data: {
action: 'bpcab_ai_generate_product_desc',
nonce: BPCAB_AI.nonce,
product_id: productId,
notes: notes
}
})
.done(function (resp) {
if (!resp || !resp.success) {
var msg = (resp && resp.data && resp.data.message) ? resp.data.message : 'Erreur inconnue.';
setStatus('<p style="color:#b32d2e;"><strong>Échec:</strong> ' + msg + '</p>');
return;
}
setStatus(
'<p style="color:#1e7e34;"><strong>OK:</strong> Descriptions mises à jour.</p>' +
'<p>Astuce: cliquez sur “Mettre à jour” pour déclencher les hooks habituels de votre stack (cache, SEO, etc.).</p>'
);
})
.fail(function (xhr) {
setStatus('<p style="color:#b32d2e;"><strong>Erreur AJAX:</strong> vérifiez la console et vos logs PHP.</p>');
});
});
})(jQuery);
3) AJAX so'nggi nuqtasini yarating (xavfsizlik + tasdiqlash)
Biz nonce, ruxsatnomalar va mahsulot identifikatorini tekshiramiz. Agar API kaliti sozlanmagan bo'lsa, qo'ng'iroqlarning oldini olamiz.
add_action('wp_ajax_bpcab_ai_generate_product_desc', function () {
// Vérification nonce
$nonce = isset($_POST['nonce']) ? sanitize_text_field((string) $_POST['nonce']) : '';
if (!wp_verify_nonce($nonce, 'bpcab_ai_generate_desc')) {
wp_send_json_error(['message' => 'Nonce invalide. Rechargez la page produit.'], 403);
}
$product_id = isset($_POST['product_id']) ? (int) $_POST['product_id'] : 0;
if ($product_id <= 0) {
wp_send_json_error(['message' => 'ID produit invalide.'], 400);
}
if (!current_user_can('edit_product', $product_id)) {
wp_send_json_error(['message' => 'Droits insuffisants.'], 403);
}
if (!defined('BPCAB_OPENAI_API_KEY') || !BPCAB_OPENAI_API_KEY) {
wp_send_json_error(['message' => 'Clé API manquante. Définissez BPCAB_OPENAI_API_KEY dans wp-config.php.'], 500);
}
$notes = isset($_POST['notes']) ? wp_kses_post((string) $_POST['notes']) : '';
$result = bpcab_ai_generate_and_update_product($product_id, $notes);
if (is_wp_error($result)) {
wp_send_json_error([
'message' => $result->get_error_message(),
'code' => $result->get_error_code(),
], 500);
}
wp_send_json_success(['updated' => true]);
});
4) Mahsulot ma'lumotlarini oling va so'rovni yarating
Agar mavjud bo'lsa, biz WooCommerce-ga tayanamiz; aks holda biz aniq xato qaytaramiz. Buni xato bilan adashtirmang. save_post Oqimni barqarorlashtirmaguningizcha: AJAX oldindan aytib bo'ladigan darajada.
function bpcab_ai_generate_and_update_product(int $product_id, string $notes = '') {
if (!function_exists('wc_get_product')) {
return new WP_Error('woocommerce_missing', 'WooCommerce ne semble pas actif.');
}
$product = wc_get_product($product_id);
if (!$product) {
return new WP_Error('product_missing', 'Produit introuvable.');
}
// Rate limiting basique (par produit + utilisateur) pour éviter les rafales.
$user_id = get_current_user_id();
$rl_key = 'bpcab_ai_rl_' . $user_id . '_' . $product_id;
if (get_transient($rl_key)) {
return new WP_Error('rate_limited', 'Vous générez trop vite. Attendez 30 secondes et réessayez.');
}
set_transient($rl_key, 1, 30);
$payload = bpcab_build_product_payload_for_prompt($product);
// Empreinte: si les données n'ont pas changé, on peut servir depuis cache.
$fingerprint = hash('sha256', wp_json_encode([
'payload' => $payload,
'notes' => $notes,
'v' => '1.0.0', // incrémentez si vous changez la logique de prompt
]));
$cache_key = 'bpcab_ai_desc_' . $product_id . '_' . substr($fingerprint, 0, 12);
$cached = get_transient($cache_key);
if (is_array($cached) && isset($cached['long'], $cached['short'])) {
return bpcab_update_product_descriptions($product_id, $cached['long'], $cached['short']);
}
$prompt = bpcab_build_prompt($payload, $notes);
$ai = bpcab_call_openai_responses_api($prompt);
if (is_wp_error($ai)) {
return $ai;
}
// Sanitation: on autorise un HTML "post" standard, pas de scripts, pas d'iframes.
$long = wp_kses_post($ai['long'] ?? '');
$short = wp_kses_post($ai['short'] ?? '');
// Fallback si l'IA renvoie vide (ça arrive avec des prompts trop stricts).
if (mb_strlen(wp_strip_all_tags($long)) < 80) {
return new WP_Error('ai_empty', 'La réponse IA est trop courte ou vide. Vérifiez vos données produit et le prompt.');
}
if (mb_strlen(wp_strip_all_tags($short)) < 30) {
$short = wp_trim_words(wp_strip_all_tags($long), 35, '…');
}
// Cache 30 jours (vous pouvez réduire si votre catalogue change souvent).
set_transient($cache_key, ['long' => $long, 'short' => $short], 30 * DAY_IN_SECONDS);
return bpcab_update_product_descriptions($product_id, $long, $short);
}
function bpcab_build_product_payload_for_prompt(WC_Product $product): array {
$product_id = $product->get_id();
$cats = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'names']);
$tags = wp_get_post_terms($product_id, 'product_tag', ['fields' => 'names']);
// Attributs WooCommerce (pa_*) et attributs custom.
$attributes_out = [];
foreach ($product->get_attributes() as $attr) {
if ($attr->is_taxonomy()) {
$taxonomy = $attr->get_name();
$label = wc_attribute_label($taxonomy);
$terms = wp_get_post_terms($product_id, $taxonomy, ['fields' => 'names']);
$attributes_out[] = [
'label' => $label,
'values' => array_values(array_filter(array_map('sanitize_text_field', $terms))),
];
} else {
$attributes_out[] = [
'label' => sanitize_text_field($attr->get_name()),
'values' => array_values(array_filter(array_map('sanitize_text_field', $attr->get_options()))),
];
}
}
$sku = (string) $product->get_sku();
$price = $product->get_price();
$regular = $product->get_regular_price();
$sale = $product->get_sale_price();
return [
'title' => sanitize_text_field($product->get_name()),
'sku' => sanitize_text_field($sku),
'categories' => array_values(array_filter(array_map('sanitize_text_field', (array) $cats))),
'tags' => array_values(array_filter(array_map('sanitize_text_field', (array) $tags))),
'attributes' => $attributes_out,
'price' => $price !== '' ? (string) $price : '',
'regular_price' => $regular !== '' ? (string) $regular : '',
'sale_price' => $sale !== '' ? (string) $sale : '',
'short_description_existing' => wp_strip_all_tags((string) $product->get_short_description()),
'description_existing' => wp_strip_all_tags((string) $product->get_description()),
];
}
function bpcab_build_prompt(array $payload, string $notes = ''): string {
$attrs_lines = [];
foreach (($payload['attributes'] ?? []) as $attr) {
$label = $attr['label'] ?? '';
$values = $attr['values'] ?? [];
if (!$label || empty($values)) {
continue;
}
$attrs_lines[] = '- ' . $label . ' : ' . implode(', ', $values);
}
$notes_clean = trim(wp_strip_all_tags($notes));
// Prompt orienté e-commerce: bénéfices, usage, contraintes, pas de promesses non vérifiées.
$prompt = "Vous êtes un rédacteur e-commerce senior. Rédigez pour WooCommerce une description produit en FR.nn";
$prompt .= "Règles STRICTES:n";
$prompt .= "1) N'inventez aucune caractéristique non fournie.n";
$prompt .= "2) Pas de superlatifs gratuits ("le meilleur", "incroyable").n";
$prompt .= "3) Style clair, concret, orienté bénéfices et usages.n";
$prompt .= "4) HTML autorisé: <p>, <ul>, <li>, <strong>, <em>. Pas de titres H1/H2.n";
$prompt .= "5) Retournez STRICTEMENT un JSON valide avec les clés: long_html, short_html.nn";
$prompt .= "Données produit:n";
$prompt .= "- Titre: " . ($payload['title'] ?? '') . "n";
if (!empty($payload['sku'])) {
$prompt .= "- SKU: " . $payload['sku'] . "n";
}
if (!empty($payload['categories'])) {
$prompt .= "- Catégories: " . implode(', ', (array) $payload['categories']) . "n";
}
if (!empty($payload['tags'])) {
$prompt .= "- Tags: " . implode(', ', (array) $payload['tags']) . "n";
}
if (!empty($attrs_lines)) {
$prompt .= "- Attributs:n" . implode("n", $attrs_lines) . "n";
}
// Le prix est optionnel: utile si vous voulez positionnement "entrée de gamme/premium".
if (!empty($payload['price'])) {
$prompt .= "- Prix actuel (indicatif): " . $payload['price'] . "n";
}
if ($notes_clean !== '') {
$prompt .= "nNotes internes:n" . $notes_clean . "n";
}
// Si une description existe déjà, on peut demander une amélioration plutôt qu'une réécriture totale.
$existing = trim((string) ($payload['description_existing'] ?? ''));
if ($existing !== '' && mb_strlen($existing) > 80) {
$prompt .= "nTexte existant (à améliorer sans changer le sens):n" . $existing . "n";
}
$prompt .= "nFormat attendu (exemple):n";
$prompt .= "{"long_html":"<p>...</p>","short_html":"<p>...</p>"}n";
return $prompt;
}
5) AI API-ni wp_remote_post() orqali chaqiring
OpenAI “Responses” API bilan misol. Agar siz boshqa provayderdan (Anthropic, Mistral, Google) foydalansangiz, tuzilma o'zgaradi, lekin tamoyillar o'zgarishsiz qoladi: vaqt tugashi, xatolarni qayta ishlash, qat'iy tahlil.
Men so'rovda JSON javobini majburan ishlataman, keyin uni server tomonida tahlil qilaman. Bu qo'shishni buzadigan "batafsil" javoblarning 80% dan qochadi.
function bpcab_call_openai_responses_api(string $prompt) {
$endpoint = 'https://api.openai.com/v1/responses';
$body = [
// Modèle: choisissez un modèle "mini" pour réduire les coûts si la qualité vous suffit.
// Adaptez selon votre compte et les modèles disponibles.
'model' => 'gpt-4.1-mini',
'input' => [
[
'role' => 'user',
'content' => [
[
'type' => 'input_text',
'text' => $prompt,
],
],
],
],
// Limite raisonnable: descriptions produit, pas un roman.
'max_output_tokens' => 700,
'temperature' => 0.6,
];
$args = [
'timeout' => 25, // Évitez 60s: en admin, ça se ressent vite.
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
],
'body' => wp_json_encode($body),
];
$res = wp_remote_post($endpoint, $args);
if (is_wp_error($res)) {
return new WP_Error('http_error', 'Erreur HTTP vers l’API IA: ' . $res->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($res);
$raw = (string) wp_remote_retrieve_body($res);
if ($code < 200 || $code >= 300) {
// Log minimal (évitez de logger des données sensibles).
error_log('[BPCAB AI] API non-200: ' . $code . ' body=' . substr($raw, 0, 500));
return new WP_Error('api_non_200', 'Réponse IA invalide (HTTP ' . $code . '). Vérifiez votre clé/quota.');
}
$json = json_decode($raw, true);
if (!is_array($json)) {
return new WP_Error('json_decode', 'Réponse IA non JSON (json_decode a échoué).');
}
// Récupération du texte: selon l’API, la sortie peut être structurée.
// On essaie plusieurs chemins connus, puis on échoue proprement.
$text = '';
// Chemin courant: output_text agrégé
if (isset($json['output_text']) && is_string($json['output_text'])) {
$text = $json['output_text'];
}
// Fallback: certaines réponses contiennent output[] avec content[]
if ($text === '' && !empty($json['output']) && is_array($json['output'])) {
foreach ($json['output'] as $item) {
if (!is_array($item) || empty($item['content']) || !is_array($item['content'])) {
continue;
}
foreach ($item['content'] as $c) {
if (is_array($c) && ($c['type'] ?? '') === 'output_text' && isset($c['text'])) {
$text .= (string) $c['text'];
}
}
}
}
$text = trim($text);
if ($text === '') {
error_log('[BPCAB AI] Sortie vide. Raw=' . substr($raw, 0, 500));
return new WP_Error('empty_output', 'L’API IA a renvoyé une sortie vide.');
}
// On attend un JSON strict dans $text
$out = json_decode($text, true);
if (!is_array($out)) {
error_log('[BPCAB AI] JSON attendu mais non parsable. Text=' . substr($text, 0, 500));
return new WP_Error('bad_format', 'Format IA inattendu. Ajustez le prompt (JSON strict).');
}
$long = isset($out['long_html']) ? (string) $out['long_html'] : '';
$short = isset($out['short_html']) ? (string) $out['short_html'] : '';
return [
'long' => $long,
'short' => $short,
];
}
6) Mahsulotni yangilang (kontent + parcha)
WordPressning asosiy posti yangilandi. Keyin WooCommerce tavsifni ko'rsatish uchun ushbu maydonlarni o'qiydi. Men foydalanmoqdaman wp_update_post() standart WordPress ish oqimi doirasida qolish (ilgaklar, agar yoqilgan bo'lsa, tuzatishlar va boshqalar).
function bpcab_update_product_descriptions(int $product_id, string $long_html, string $short_html) {
$update = [
'ID' => $product_id,
'post_content' => $long_html,
'post_excerpt' => $short_html,
];
$res = wp_update_post(wp_slash($update), true, false);
if (is_wp_error($res)) {
return new WP_Error('update_failed', 'Échec mise à jour produit: ' . $res->get_error_message());
}
// Optionnel: forcer une mise à jour du produit WooCommerce (index, lookup tables, etc.)
if (function_exists('wc_get_product')) {
$product = wc_get_product($product_id);
if ($product) {
$product->save();
}
}
return true;
}
To'liq yig'ilgan kod
Ushbu faylni nusxalash va joylashtirish wp-content/mu-plugins/bpcab-ai-woo-descriptions.phpShuningdek, JS yarating bpcab-ai-woo-admin.js uning yonida (yuqorida ko'rsatilgan).
<?php
/**
* Plugin Name: BPCAB - IA descriptions produits WooCommerce
* Description: Génère des descriptions produits via IA depuis l'admin WooCommerce (WP 6.9.4+, PHP 8.1+).
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Meta box sur l'écran produit.
*/
add_action('add_meta_boxes', function () {
add_meta_box(
'bpcab_ai_product_desc',
'Descriptions IA',
'bpcab_render_ai_metabox',
'product',
'side',
'high'
);
});
function bpcab_render_ai_metabox(WP_Post $post): void {
$product_id = (int) $post->ID;
if (!current_user_can('edit_product', $product_id)) {
echo '<p>Vous n’avez pas les droits pour modifier ce produit.</p>';
return;
}
wp_nonce_field('bpcab_ai_generate_desc', 'bpcab_ai_nonce');
echo '<p>
<label for="bpcab_ai_notes"><strong>Notes internes (optionnel)</strong></label>
<textarea id="bpcab_ai_notes" style="width:100%;min-height:70px;" placeholder="Ex: ton premium, mentionner la garantie 2 ans, éviter les superlatifs..."></textarea>
</p>';
echo '<p>
<button type="button" class="button button-primary" id="bpcab-ai-generate" data-product-id="' . esc_attr((string) $product_id) . '">
Générer avec IA
</button>
</p>';
echo '<div id="bpcab-ai-status" style="margin-top:8px;"></div>';
}
/**
* JS admin (uniquement sur l'écran produit).
*/
add_action('admin_enqueue_scripts', function (string $hook_suffix) {
if (!in_array($hook_suffix, ['post.php', 'post-new.php'], true)) {
return;
}
$screen = get_current_screen();
if (!$screen || $screen->post_type !== 'product') {
return;
}
wp_enqueue_script(
'bpcab-ai-woo-admin',
plugins_url('bpcab-ai-woo-admin.js', __FILE__),
['jquery'],
'1.0.0',
true
);
wp_localize_script('bpcab-ai-woo-admin', 'BPCAB_AI', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('bpcab_ai_generate_desc'),
]);
});
/**
* Endpoint AJAX sécurisé.
*/
add_action('wp_ajax_bpcab_ai_generate_product_desc', function () {
$nonce = isset($_POST['nonce']) ? sanitize_text_field((string) $_POST['nonce']) : '';
if (!wp_verify_nonce($nonce, 'bpcab_ai_generate_desc')) {
wp_send_json_error(['message' => 'Nonce invalide. Rechargez la page produit.'], 403);
}
$product_id = isset($_POST['product_id']) ? (int) $_POST['product_id'] : 0;
if ($product_id <= 0) {
wp_send_json_error(['message' => 'ID produit invalide.'], 400);
}
if (!current_user_can('edit_product', $product_id)) {
wp_send_json_error(['message' => 'Droits insuffisants.'], 403);
}
if (!defined('BPCAB_OPENAI_API_KEY') || !BPCAB_OPENAI_API_KEY) {
wp_send_json_error(['message' => 'Clé API manquante. Définissez BPCAB_OPENAI_API_KEY dans wp-config.php.'], 500);
}
$notes = isset($_POST['notes']) ? wp_kses_post((string) $_POST['notes']) : '';
$result = bpcab_ai_generate_and_update_product($product_id, $notes);
if (is_wp_error($result)) {
wp_send_json_error([
'message' => $result->get_error_message(),
'code' => $result->get_error_code(),
], 500);
}
wp_send_json_success(['updated' => true]);
});
function bpcab_ai_generate_and_update_product(int $product_id, string $notes = '') {
if (!function_exists('wc_get_product')) {
return new WP_Error('woocommerce_missing', 'WooCommerce ne semble pas actif.');
}
$product = wc_get_product($product_id);
if (!$product) {
return new WP_Error('product_missing', 'Produit introuvable.');
}
$user_id = get_current_user_id();
$rl_key = 'bpcab_ai_rl_' . $user_id . '_' . $product_id;
if (get_transient($rl_key)) {
return new WP_Error('rate_limited', 'Vous générez trop vite. Attendez 30 secondes et réessayez.');
}
set_transient($rl_key, 1, 30);
$payload = bpcab_build_product_payload_for_prompt($product);
$fingerprint = hash('sha256', wp_json_encode([
'payload' => $payload,
'notes' => $notes,
'v' => '1.0.0',
]));
$cache_key = 'bpcab_ai_desc_' . $product_id . '_' . substr($fingerprint, 0, 12);
$cached = get_transient($cache_key);
if (is_array($cached) && isset($cached['long'], $cached['short'])) {
return bpcab_update_product_descriptions($product_id, $cached['long'], $cached['short']);
}
$prompt = bpcab_build_prompt($payload, $notes);
$ai = bpcab_call_openai_responses_api($prompt);
if (is_wp_error($ai)) {
return $ai;
}
$long = wp_kses_post($ai['long'] ?? '');
$short = wp_kses_post($ai['short'] ?? '');
if (mb_strlen(wp_strip_all_tags($long)) < 80) {
return new WP_Error('ai_empty', 'La réponse IA est trop courte ou vide. Vérifiez vos données produit et le prompt.');
}
if (mb_strlen(wp_strip_all_tags($short)) < 30) {
$short = wp_trim_words(wp_strip_all_tags($long), 35, '…');
}
set_transient($cache_key, ['long' => $long, 'short' => $short], 30 * DAY_IN_SECONDS);
return bpcab_update_product_descriptions($product_id, $long, $short);
}
function bpcab_build_product_payload_for_prompt(WC_Product $product): array {
$product_id = $product->get_id();
$cats = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'names']);
$tags = wp_get_post_terms($product_id, 'product_tag', ['fields' => 'names']);
$attributes_out = [];
foreach ($product->get_attributes() as $attr) {
if ($attr->is_taxonomy()) {
$taxonomy = $attr->get_name();
$label = wc_attribute_label($taxonomy);
$terms = wp_get_post_terms($product_id, $taxonomy, ['fields' => 'names']);
$attributes_out[] = [
'label' => $label,
'values' => array_values(array_filter(array_map('sanitize_text_field', $terms))),
];
} else {
$attributes_out[] = [
'label' => sanitize_text_field($attr->get_name()),
'values' => array_values(array_filter(array_map('sanitize_text_field', $attr->get_options()))),
];
}
}
$sku = (string) $product->get_sku();
$price = $product->get_price();
$regular = $product->get_regular_price();
$sale = $product->get_sale_price();
return [
'title' => sanitize_text_field($product->get_name()),
'sku' => sanitize_text_field($sku),
'categories' => array_values(array_filter(array_map('sanitize_text_field', (array) $cats))),
'tags' => array_values(array_filter(array_map('sanitize_text_field', (array) $tags))),
'attributes' => $attributes_out,
'price' => $price !== '' ? (string) $price : '',
'regular_price' => $regular !== '' ? (string) $regular : '',
'sale_price' => $sale !== '' ? (string) $sale : '',
'short_description_existing' => wp_strip_all_tags((string) $product->get_short_description()),
'description_existing' => wp_strip_all_tags((string) $product->get_description()),
];
}
function bpcab_build_prompt(array $payload, string $notes = ''): string {
$attrs_lines = [];
foreach (($payload['attributes'] ?? []) as $attr) {
$label = $attr['label'] ?? '';
$values = $attr['values'] ?? [];
if (!$label || empty($values)) {
continue;
}
$attrs_lines[] = '- ' . $label . ' : ' . implode(', ', $values);
}
$notes_clean = trim(wp_strip_all_tags($notes));
$prompt = "Vous êtes un rédacteur e-commerce senior. Rédigez pour WooCommerce une description produit en FR.nn";
$prompt .= "Règles STRICTES:n";
$prompt .= "1) N'inventez aucune caractéristique non fournie.n";
$prompt .= "2) Pas de superlatifs gratuits ("le meilleur", "incroyable").n";
$prompt .= "3) Style clair, concret, orienté bénéfices et usages.n";
$prompt .= "4) HTML autorisé: <p>, <ul>, <li>, <strong>, <em>. Pas de titres H1/H2.n";
$prompt .= "5) Retournez STRICTEMENT un JSON valide avec les clés: long_html, short_html.nn";
$prompt .= "Données produit:n";
$prompt .= "- Titre: " . ($payload['title'] ?? '') . "n";
if (!empty($payload['sku'])) {
$prompt .= "- SKU: " . $payload['sku'] . "n";
}
if (!empty($payload['categories'])) {
$prompt .= "- Catégories: " . implode(', ', (array) $payload['categories']) . "n";
}
if (!empty($payload['tags'])) {
$prompt .= "- Tags: " . implode(', ', (array) $payload['tags']) . "n";
}
if (!empty($attrs_lines)) {
$prompt .= "- Attributs:n" . implode("n", $attrs_lines) . "n";
}
if (!empty($payload['price'])) {
$prompt .= "- Prix actuel (indicatif): " . $payload['price'] . "n";
}
if ($notes_clean !== '') {
$prompt .= "nNotes internes:n" . $notes_clean . "n";
}
$existing = trim((string) ($payload['description_existing'] ?? ''));
if ($existing !== '' && mb_strlen($existing) > 80) {
$prompt .= "nTexte existant (à améliorer sans changer le sens):n" . $existing . "n";
}
$prompt .= "nFormat attendu (exemple):n";
$prompt .= "{"long_html":"<p>...</p>","short_html":"<p>...</p>"}n";
return $prompt;
}
function bpcab_call_openai_responses_api(string $prompt) {
$endpoint = 'https://api.openai.com/v1/responses';
$body = [
'model' => 'gpt-4.1-mini',
'input' => [
[
'role' => 'user',
'content' => [
[
'type' => 'input_text',
'text' => $prompt,
],
],
],
],
'max_output_tokens' => 700,
'temperature' => 0.6,
];
$args = [
'timeout' => 25,
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . BPCAB_OPENAI_API_KEY,
],
'body' => wp_json_encode($body),
];
$res = wp_remote_post($endpoint, $args);
if (is_wp_error($res)) {
return new WP_Error('http_error', 'Erreur HTTP vers l’API IA: ' . $res->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($res);
$raw = (string) wp_remote_retrieve_body($res);
if ($code < 200 || $code >= 300) {
error_log('[BPCAB AI] API non-200: ' . $code . ' body=' . substr($raw, 0, 500));
return new WP_Error('api_non_200', 'Réponse IA invalide (HTTP ' . $code . '). Vérifiez votre clé/quota.');
}
$json = json_decode($raw, true);
if (!is_array($json)) {
return new WP_Error('json_decode', 'Réponse IA non JSON (json_decode a échoué).');
}
$text = '';
if (isset($json['output_text']) && is_string($json['output_text'])) {
$text = $json['output_text'];
}
if ($text === '' && !empty($json['output']) && is_array($json['output'])) {
foreach ($json['output'] as $item) {
if (!is_array($item) || empty($item['content']) || !is_array($item['content'])) {
continue;
}
foreach ($item['content'] as $c) {
if (is_array($c) && ($c['type'] ?? '') === 'output_text' && isset($c['text'])) {
$text .= (string) $c['text'];
}
}
}
}
$text = trim($text);
if ($text === '') {
error_log('[BPCAB AI] Sortie vide. Raw=' . substr($raw, 0, 500));
return new WP_Error('empty_output', 'L’API IA a renvoyé une sortie vide.');
}
$out = json_decode($text, true);
if (!is_array($out)) {
error_log('[BPCAB AI] JSON attendu mais non parsable. Text=' . substr($text, 0, 500));
return new WP_Error('bad_format', 'Format IA inattendu. Ajustez le prompt (JSON strict).');
}
return [
'long' => isset($out['long_html']) ? (string) $out['long_html'] : '',
'short' => isset($out['short_html']) ? (string) $out['short_html'] : '',
];
}
function bpcab_update_product_descriptions(int $product_id, string $long_html, string $short_html) {
$update = [
'ID' => $product_id,
'post_content' => $long_html,
'post_excerpt' => $short_html,
];
$res = wp_update_post(wp_slash($update), true, false);
if (is_wp_error($res)) {
return new WP_Error('update_failed', 'Échec mise à jour produit: ' . $res->get_error_message());
}
if (function_exists('wc_get_product')) {
$product = wc_get_product($product_id);
if ($product) {
$product->save();
}
}
return true;
}
Kodning izohi
Nima uchun avtomatik ilgak o'rniga tugma (AJAX) kerak?
WooCommerce’da mahsulotni “Yangilash” tugmasini bosmasdan bir necha marta saqlash mumkin: avtomatik saqlash, tuzatishlar, boshqa plaginlardan meta yangilanishlari, inventarizatsiya sinxronizatsiyasi va boshqalar. Agar siz AI’ni ulasangiz save_post_product Himoya choralarisiz siz fantom API chaqiruvlarini ishga tushirasiz.
Tugma ataylab harakatni majbur qiladi. Va bu nosozliklarni tuzatishni osonlashtiradi: siz bosasiz, holatni ko'rasiz va uni tuzatasiz.
Nima uchun xeshga asoslangan o'tish davri?
Oddiy "har bir mahsulot uchun" keshi (masalan: bpcab_ai_desc_123Bu tezda chalg'itadi, chunki mahsulot o'zgaradi. Foydali yuklama + notalarning SHA-256 xeshi quyidagilarni kafolatlaydi: bir xil kirishlar → bir xil chiqish → to'lov yo'q.
Haqiqiy chekka holat: agar siz buyruqni (tuzilma, qoidalar) o'zgartirsangiz, keshni bekor qilmoqchisiz. Shuning uchun kichik maydon v xeshda.
Nima uchun sanitize_text_field() emas, balki wp_kses_post()?
sanitize_text_field() HTMLni yo'q qiladi. Biroq, WooCommerce tavsifi ro'yxatlar, qalin matn va paragraflarni talab qiladi. Amalda, wp_kses_post() to'g'ri murosaga kelish: bitta post uchun HTMLga ruxsat berilgan, skriptlar olib tashlangan.
Men hali ham "xom" AI javobini kiritadigan saytlarni ko'rmoqdaman post_contentAgar AI shubhali havola yoki g'ayrioddiy HTML qaytarsa, siz shunchaki keraksiz eshikni ochdingiz. Bu "avtomatik" XSS hujumi emas (WordPress ba'zi joylarda allaqachon filtrlaydi), lekin siz o'zingiz uchun narsalarni murakkablashtiryapsiz.
Nima uchun qisqa muddatli tanaffus?
Administrator sohasida 60 soniyali tanaffus foydalanuvchi interfeysini bloklaydi va WordPressni muzlab qolgandek ko'rsatadi. 20-30 soniya yaxshi maksimal miqdor. Agar sizda juda murakkab mahsulotlar bo'lsa, asinxron generatsiya (cron/queue) dan foydalanishni ko'rib chiqing yoki kengaytirilgan variantlarni ko'rib chiqing.
API xarajatlari va optimallashtirish
Narxi modelga va tokenlar hajmiga bog'liq. Odatdagi mahsulot sahifasi (so'rov + javob) taxminan, 800 dan 2000 gacha tokenlar atributlar soni va so'ralgan uzunlikka bog'liq. "Mini" model bilan siz ko'pincha har bir avlod uchun juda past narxga ega bo'lasiz, ammo keng miqyosda bu muhim ahamiyatga ega.
Oddiy smeta (sizning modelingizga moslashtirilishi kerak)
- Keling, har bir mahsulot uchun 1200 ta token (kirish+chiqish) deb faraz qilaylik.
- Oyiga 1000 ta mahsulot → Oyiga 1,2 million token.
- "Mini" model bilan odatda o'rtacha narx, lekin agar siz qayta tug'ilsangiz (keshlashsiz), siz tezda 3 yoki 10 ga ko'paytirasiz.
Haqiqatan ham ishlaydigan optimallashtirishlar
- Barmoq izi yordamida keshlash (allaqachon mavjud): bu eng yaxshi investitsiya daromadliligi.
- Chiqishni cheklang avec
max_output_tokens: uzoq javoblardan qochadi. - Kichikroq model Ommaviy mahsulotlar uchun kuchliroq model faqat premium mahsulotlar uchun.
- Partiya (kengaytirilgan variant): kunlik byudjet bilan tungi cronda 50 ta mahsulotni qayta ishlang.
- So'rovni kamaytiring : bo'sh atributlarni yoki mavjud tavsifni bo'sh bo'lsa yubormang.
Murakkab variantlar va foydalanish holatlari
1-variant: Faqat qisqacha tavsifni (parcha) yarating
Uzoq tavsifingiz allaqachon yozilgan bo'lsa (yoki ishlab chiqaruvchi tomonidan taqdim etilgan bo'lsa), lekin sizga kategoriya sahifalari uchun savdoga qulay va izchil ekstrakt kerak bo'lsa, foydalidir.
- So'rovni faqat so'rash uchun o'zgartiring
short_html. - yilda
bpcab_update_product_descriptions()faqat yangilanishpost_excerpt.
2-variant: Asinxron generatsiya (vaqtinchalik tugashdan qochish)
Sekin xosting serverlarida tashqi qo'ng'iroq 25 soniyadan ko'proq vaqt olishi mumkin. Bunday holda, kechiktirilgan vazifani ishga tushiring:
- AJAX: "so'rov"ni (post meta) ro'yxatdan o'tkazadi va darhol javob beradi.
- Cron ishi (WP-Cron yoki cron server) so'rovlarni navbatda, daqiqada 5 marta qayta ishlaydi.
Men barcha kodni nusxa ko'chirish mumkin bo'lishi uchun bu yerga qo'ymayapman, lekin asosiy nuqta shundaki administrator so'rovida AI qo'ng'irog'ini qilmang agar infratuzilmangiz beqaror bo'lsa.
Variant 3: Divi 5 / Elementor / Avada mosligi
Avlod WooCommerce tomonida sodir bo'ladi, shuning uchun u mos keladi. Eng qiziqarli tomoni shundaki, konstruktoringiz yordamida mahsulot sahifasida "nishon" yoki "Ajoyib lahzalar" blokini ko'rsatish.
- 5-bo'lim Siz o'qiydigan modul yaratishingiz mumkin
post_excerptyoki AI tomonidan yaratilgan "kuchli tomonlar" meta maydoni. Agar siz davom etsangizpost_content/post_excerptDivining hech qanday maxsus ishi yo'q. - Elementor "Mahsulotning qisqacha tavsifi" vidjetidan foydalaning, shunda u ko'rsatiladi avtomatik Yangilangan parcha.
- Avada WooCommerce komponenti "Mahsulot tarkibi" / "Mahsulot parchasi" ushbu maydonlarni moslashtirmasdan aks ettiradi.
Men tez-tez foydalanadigan maslahat: AIdan ro'yxat so'rang <ul> Uzoq tavsifga afzalliklarni kiriting, so'ngra ushbu ro'yxatni mavzu/konstruktor yordamida uslublang. Siz qo'shimcha kodlashsiz vizual izchillikka erishasiz.
Xavfsizlik va eng yaxshi amaliyotlar
API kalitini mijoz tomonida hech qachon oshkor qilmang
JS administratori shunchaki qo'ng'iroq qilmoqda admin-ajax.phpKalit ichkarida qoladi wp-config.phpAgar siz kalitni skriptga, hatto administrator paneliga ham qo'ysangiz, u biron bir joyga (kesh, brauzer kengaytmalari, proksi) ko'chiriladi.
Tasdiqlash va cheklash
- qobiliyat :
edit_productminimal. Nazoratsiz "shop_manager" roli 10 000 avlodni ishga tushirishiga yo'l qo'ymang. - Nonce : CSRF so'rovlarini oldini olish uchun allaqachon mavjud.
- Tarifni cheklash : Har bir foydalanuvchi uchun 30 soniyali vaqtinchalik + mahsulot. Keyinchalik davom etish uchun kuniga kvota qo'shing (vaqtinchalik "hisoblagich").
Sun'iy intellekt javobini dezinfektsiya qiling
wp_kses_post() minimal miqdor. Agar siz qat'iyroq bo'lishni istasangiz, ruxsat etilgan teglar ro'yxatini quyidagiga o'tkazishingiz mumkin wp_kses() va har qanday tashqi havolalarni rad etish.
GDPR / ma'lumotlar yuborildi
Shaxsiy ma'lumotlarni (mijoz nomi, manzili va boshqalar) yubormang. Bu yerda biz faqat mahsulot ma'lumotlarini yuboramiz. Agar siz foydalanuvchi uchun tavsiflarni shaxsiylashtirishni rejalashtirmoqchi bo'lsangiz, siz yanada sezgir GDPR kontekstini (huquqiy asos, subpudratchi, DPA va boshqalar) kiritasiz.
Qochish kerak bo'lgan real xatolar
- Kodni noto'g'ri joyga nusxalash : parcha joylashtirildi
functions.phpKeyingi yangilanishda ota-ona mavzusi yo'qoladi. - Nuqtali vergulni unuting : bitta PHP xatosi → administratorda oq ekran. Sahnalashtirishda sinov.
- Noto'g'ri ilmoq : ishga tushirish yoqilgan
initousave_postxavfsizlik choralarisiz → tasodifiy sun'iy intellekt chaqiruvlari. - Zaxira nusxasisiz ishlab chiqarishda sinovdan o'tkazish : mavjud tavsiflarni ommaviy ravishda qayta yozishingiz mumkin.
- PHP juda eski Yuqoridagi sintaksis/yozishning ba'zilari PHP 8.1+ ni nazarda tutadi. 7.4 da u buziladi.
Qanday qilib sinovdan o'tkazish va disk raskadrovka qilish kerak
1) Jurnalni to'g'ri yoqing
yilda wp-config.php (sahnalashtirilganda), faollashtiring:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Keyin o'qiysiz wp-content/debug.logRasmiy hujjatlar: WordPress-da disk raskadrovka.
2) Avval "oddiy" mahsulotda sinab ko'ring
- Aniq sarlavha
- 2–3 ta atribut to'ldirilgan
- A toifasi
Agar u ishlasa, ko'p atributlarga ega o'zgaruvchan mahsulotga o'ting. Juda uzun so'rovlar mos kelmaydigan (yoki qisqartirilgan) natija xavfini oshiradi.
3) AJAX so'rovini tekshiring
- DevTools brauzerini oching → Tarmoq →
admin-ajax.php. - HTTP kodiga (200/403/500) va qaytarilgan JSONga qarang.
4) API javobini tekshiring
Agar sizda JSON formatida xatolar bo'lsa, faqat parchalarni qayd qiling (allaqachon bajarilgan) substr()). Agar siz unga maxfiy ma'lumotlarni kiritayotgan bo'lsangiz, butun so'rovni qayd qilmang.
Agar bu ishlamasa
Mana, men ushbu turdagi integratsiya muammolarini bartaraf etishda foydalanadigan diagnostika jadvali.
| alomat | Ehtimoliy sabab | tekshiruv | qaror |
|---|---|---|---|
| "Yaratish" tugmasi hech narsa qilmaydi. | JS mahsulot ekranida yuklanmagan | DevTools konsoli/tarmog'i, yo'qligi bpcab-ai-woo-admin.js |
Tekshirish admin_enqueue_scriptsyo'l plugins_url()va JS fayli mavjudligi |
| Xato 403 “Noto'g'ri Nonce” | Bildirishnoma yuborilmadi yoki sahifa juda eski | Tarmoq → POST yuklamasi o'z ichiga oladi nonce ? |
Mahsulot sahifasini qayta yuklang, tekshiring wp_localize_script va nunsioning harakati |
| Xato 500 "API kaliti yo'q" | Doimiy yo'q / bo'sh | Tekshirish wp-config.php va atrof-muhit |
Aniqlang BPCAB_OPENAI_API_KEYagar kerak bo'lsa, opcache-ni tozalang |
| AI API tomonida HTTP 401/403 | Noto'g'ri kalit, ruxsatsiz loyiha | Jurnallar: “API non-200” + kod | Kalitni qayta yarating, provayder tomonidagi loyiha ruxsatnomalarini tekshiring |
| Http429 | Kvotadan oshib ketdi / yetkazib beruvchi narxining chegarasi | Jurnallar + yetkazib beruvchi boshqaruv paneli | Orqaga qaytarish/qayta urinish funksiyasini qo'shing, soat tezligini kamaytiring, keshlashni yoqing va yengilroq modeldan foydalaning. |
| "Kutilmagan AI formati" | Sun'iy intellekt JSON bo'lmagan matnni qaytaradi | Chiqishning qisman jurnali | Buyruqni qat'iyroq, pastroq qiling temperatureSo'ralgan uzunlikni qisqartiring |
| Tavsiflar "tasodifiy" tarzda maydalangan | Ishlab chiqarishda sinov + bir nechta bosish + avtomatik saqlash | Tahrir tarixi / jurnallari | Sahnalashtirish ustida ishlang, uzunroq qulf qo'shing (vaqtinchalik), tasdiqlashni talab qiling |
Ikkita keng tarqalgan xato
- Parcha parcha plagini tomonidan buzilgan Agar siz "Kod parchalari" turidagi plagindan foydalanayotgan bo'lsangiz, tahlil xatosi parchani o'chirib qo'yishi va administrator interfeysini beqaror holatda qoldirishi mumkin. Mu-plagin bu turdagi kod uchun barqarorroq.
- Yashirin mojaro Ba'zi saytlarda agressiv doimiy obyekt keshi mavjud. Agar noto'g'ri sozlangan bo'lsa, o'tish davriyliklarni muhitlar o'rtasida ulashish mumkin. Agar siz mos kelmaydigan tavsiflarni ko'rsangiz, avval bosqichma-bosqich muhitda obyekt keshini vaqtincha o'chirib qo'ying.
resurslari
- WordPress: wp_remote_post()
- WordPress: Transients API
- WordPress: wp_kses_post()
- WordPress: Nonces
- WordPress manba kodi (GitHub oynasi)
- WordPress Core Track
- OpenAI: API javoblari (ma'lumotnoma)
- PHP: json_decode()
- WordPress.org saytidagi WooCommerce
FAQ
O'zgaruvchan mahsulotlar (variatsiyalar) bilan ishlaydimi?
Ha, lekin yuqoridagi kod tavsifni yaratadi ota-ona mahsulotiAgar har bir o'zgarish uchun matn kerak bo'lsa, o'zgarishlar ustidan takrorlashingiz va ularni maxsus meta teglarda saqlashingiz (va displeyni moslashtirishingiz) kerak. Men buni kamdan-kam hollarda qilaman: bu qimmatga tushadi va SEO nuqtai nazaridan ko'pincha keraksiz.
Sun'iy intellektning narxni aytib o'tishiga to'sqinlik qila olamanmi?
Ha: maydonni olib tashlash price foydali yuklama va so'rovnomadagi mos keladigan qator. Agar siz tez-tez aksiyalar o'tkazsangiz, narxlarni kiritmaslikni maslahat beraman, aks holda sizda eskirgan matn bo'ladi.
Nima uchun oddiy HTML o'rniga JSON chiqishini so'rash kerak?
Chunki sizga ikkita maydon (uzun + qisqa) va kuchli tahlil kerak. JSON AI formatdan tashqari jumlalarni qo'shadigan holatlarni kamaytiradi. Va u buzilganda, siz buni darhol ko'rasiz ("bad_format" xatosi).
Buning o'rniga Anthropic, Mistral yoki Google dan foydalanishim mumkinmi?
Ha. Xuddi shu arxitekturani saqlang (AJAX admin → wp_remote_post() → tahlil qilish → wp_kses_post() → yangilash). Faqat oxirgi nuqta va JSON formati o'zgaradi. Agar menga aniq provayderni bersangiz, men sizga funksiyani taqdim eta olaman. bpcab_call_* ekvivalenti.
Buning takroriy kontent yaratish xavfi bormi?
Agar mahsulotlaringiz juda o'xshash bo'lsa (bir xil atributlar, deyarli bir xil nomlar), sun'iy intellekt o'xshash matnlarni yaratishi mumkin. Buni cheklash uchun: taklifga "foydalanish bo'yicha farqlash" cheklovini qo'shing va noyob elementni (brend, material, asosiy afzallik) kiriting. Ammo bir xil kataloglar bilan ba'zi o'xshashliklar muqarrar.
Qanday qilib AIning xususiyatlarni ixtiro qilishiga yo'l qo'ymasligimiz mumkin?
Siz hech qachon undan butunlay qochib qutula olmaysiz. Siz xavfni quyidagilar orqali sezilarli darajada kamaytirasiz:
- Ixtironi (allaqachon bajarilgan) aniq taqiqlash.
- Pastga tushirish
temperature(0.3-0.6). - Faqat tuzilgan ma'lumotlarni (atributlarni) taqdim etish va noaniq "eslatmalar"dan qochish.
Men "Kutilmagan AI Format" xatosini olaman. Avval nima qilishim kerak?
Murakkablikni kamaytiring: kamroq atributlar, max_output_tokens yuqoriroq (agar u qisqartirilsa) va undan ham qat'iyroq buyruq ("Faqat JSONni qaytaring, oldin/keyin matn yo'q"). Mening tajribamda, 10 tadan 9 tasida bu shunchaki JSON bo'lmagan natija.
Nima uchun tugma "OK" deb yozilgan, lekin old tomonida hech narsa ko'rinmayapti?
Ko'pincha, bu eski versiyani taqdim etayotgan sahifa keshi (yoki obyekt keshi) bo'ladi. Keshni tozalang va mavzuning to'g'ri ko'rsatilishini tekshiring. the_content() va standart WooCommerce parchasi. Elementor/Avada/Divi bilan maxsus maydonni ko'rsatmasligingizga ishonch hosil qiling.
Tavsifni qayta yozilishidan oldin oldindan ko'rib chiqa olamanmi?
Ha: qo'ng'iroq qilish o'rniga wp_update_post(), qaytarib yuborish long_html et short_html AJAX javobida ularni modal formatda ko'rsating, so'ngra ikkinchi "Qo'llash" tugmasini qo'shing. Bu men bir nechta odam tahrirlaydigan do'konlarda joylashtiradigan versiya.
Ularning ko'pini yaratish mening SEO-mni buzishi mumkinmi?
Agar siz 500 ta yaratilgan mahsulot varaqlarini korrekturasiz nashr qilsangiz, siz sifat xavfini o'z zimmangizga olasiz (va shuning uchun SEO uchun xavf tug'dirasiz). Sog'lom ish jarayoni: AI yaratish → inson tomonidan tasdiqlash → nashr. Va strategik mahsulotlar uchun siz ularni aslida qayta yozasiz.