Éditeur : intégration IA — analyse critique et réécriture article #96

Closed
opened 2026-05-16 09:38:40 +00:00 by cedricAbonnel · 0 comments
Owner

Contexte

Ajouter deux boutons IA dans la sidebar de l'éditeur (/edit/{uuid}/1) pour soumettre le contenu de l'article à Claude (Anthropic) et afficher le résultat sans quitter la page.

Boutons demandés :

  1. Analyse critique — retourne les faiblesses, incohérences, points à approfondir
  2. Réécriture — retourne une version améliorée du texte (style, clarté, structure)

Inspiration technique

Le projet recup-mails (~/Projects/recup-mails/api/ai_core.php) implémente déjà un pattern réutilisable :

  • callAi(cfg, system, userMsg) : abstraction multi-provider (OpenAI, Anthropic, Claude Code CLI)
  • Appel cURL vers api.anthropic.com/v1/messages, clé API en config DB par owner
  • Extraction + normalisation du JSON retourné par le modèle

Folio devra s'en inspirer, adapté à son architecture (pas de DB owner, clé dans .env ou SiteSettings).


Architecture proposée

1. Configuration

Ajouter dans .env (et .env.example) :

ANTHROPIC_API_KEY=sk-ant-...
AI_MODEL=claude-haiku-4-5-20251001

Alternative : stocker dans SiteSettings (config admin) pour pouvoir changer le modèle sans redéployer. À trancher.

2. Endpoint backend

Nouvelle route : POST /api/ai

Fichier : src/Service/AiService.php

class AiService {
    public function query(string $action, string $title, string $content): array
    // $action : 'critique' | 'rewrite'
    // Retourne : ['ok' => true, 'text' => "..."] ou ['error' => "..."]
}

Prompts système :

  • critique : "Tu es un relecteur expert. Analyse cet article de blog : identifie les faiblesses argumentatives, les imprécisions, les manques de clarté, les points à développer. Réponds en markdown avec des sections claires."
  • rewrite : "Tu es un rédacteur expert. Réécris cet article de blog en améliorant le style, la clarté et la structure, sans changer le sens ni les faits. Conserve le format markdown et les images. Réponds uniquement avec le texte réécrit."

L'endpoint vérifie que l'utilisateur est authentifié (requireAuth()) avant tout appel API.

3. Frontend (sidebar éditeur)

Dans templates/post_form.php, section col-lg-4, sous les boutons Enregistrer/Annuler :

<!-- Section IA -->
<div class="mb-3">
  <hr class="my-3">
  <p class="fw-semibold small mb-2">IA</p>
  <div class="d-flex flex-column gap-2">
    <button type="button" id="btn-ai-critique" class="btn btn-outline-secondary btn-sm">
      Analyse critique
    </button>
    <button type="button" id="btn-ai-rewrite" class="btn btn-outline-secondary btn-sm">
      Réécrire l'article
    </button>
  </div>
</div>

<!-- Panneau résultat IA (collapsé par défaut) -->
<div id="ai-result-panel" class="mt-3" style="display:none">
  <div class="d-flex align-items-center justify-content-between mb-1">
    <span id="ai-result-label" class="fw-semibold small"></span>
    <button type="button" id="btn-ai-close" class="btn-close btn-sm"></button>
  </div>
  <div id="ai-result-content"
       class="border rounded p-2 small font-monospace"
       style="max-height:400px;overflow-y:auto;white-space:pre-wrap;background:#f8f9fa">
  </div>
  <!-- Pour la réécriture uniquement -->
  <button type="button" id="btn-ai-apply" class="btn btn-warning btn-sm mt-2" style="display:none">
    Appliquer dans l'éditeur
  </button>
</div>

JS inline (post_form.php ou assets/js/editor.js) :

  • Au clic, lit #content (textarea) et #title
  • fetch('POST /api/ai', { action, title, content })
  • Affiche spinner dans le bouton pendant la requête
  • Affiche le résultat dans #ai-result-panel
  • Pour réécriture : bouton « Appliquer » remplace #content par le texte retourné

Critères d'acceptation

  • Bouton « Analyse critique » visible en mode édition uniquement ($action === 'edit')
  • Bouton « Réécriture » visible en mode édition uniquement
  • Requête AJAX vers POST /api/ai avec { action, title, content }
  • Spinner pendant l'appel, bouton désactivé
  • Résultat affiché dans le panneau latéral (pas de page reload)
  • Bouton « Appliquer » présent pour la réécriture ; injecte le texte dans le textarea
  • Gestion d'erreur : message lisible si API key manquante ou quota dépassé
  • Accès refusé (403) si non authentifié
  • Clé Anthropic configurable sans redeployer (.env ou admin)
  • Modèle configurable (défaut : claude-haiku-4-5-20251001 pour le coût)

Fichiers à créer / modifier

Fichier Action
src/Service/AiService.php Créer — abstraction Anthropic (inspirée de recup-mails/api/ai_core.php)
public/index.php Ajouter route POST /api/ai
templates/post_form.php Ajouter boutons + panneau résultat dans col-lg-4
.env.example Ajouter ANTHROPIC_API_KEY et AI_MODEL
config/config.php Lire et exposer ANTHROPIC_API_KEY / AI_MODEL

Notes

  • Modèle par défaut recommandé : claude-haiku-4-5-20251001 (rapide, peu coûteux pour des articles de blog)
  • Le bouton « Réécriture » doit demander confirmation avant d'appliquer (data-confirm ou confirm() JS)
  • Prévoir max_tokens généreux pour la réécriture (≥ 2000) ; moins pour la critique (≤ 1000)
  • La réécriture ne sauvegarde pas automatiquement : l'utilisateur doit cliquer « Enregistrer » ensuite
  • Pas de streaming dans un premier temps (réponse complète puis affichage)
## Contexte Ajouter deux boutons IA dans la sidebar de l'éditeur (`/edit/{uuid}/1`) pour soumettre le contenu de l'article à Claude (Anthropic) et afficher le résultat sans quitter la page. **Boutons demandés :** 1. **Analyse critique** — retourne les faiblesses, incohérences, points à approfondir 2. **Réécriture** — retourne une version améliorée du texte (style, clarté, structure) --- ## Inspiration technique Le projet `recup-mails` (`~/Projects/recup-mails/api/ai_core.php`) implémente déjà un pattern réutilisable : - `callAi(cfg, system, userMsg)` : abstraction multi-provider (OpenAI, Anthropic, Claude Code CLI) - Appel cURL vers `api.anthropic.com/v1/messages`, clé API en config DB par owner - Extraction + normalisation du JSON retourné par le modèle Folio devra s'en inspirer, adapté à son architecture (pas de DB owner, clé dans `.env` ou `SiteSettings`). --- ## Architecture proposée ### 1. Configuration Ajouter dans `.env` (et `.env.example`) : ``` ANTHROPIC_API_KEY=sk-ant-... AI_MODEL=claude-haiku-4-5-20251001 ``` Alternative : stocker dans `SiteSettings` (config admin) pour pouvoir changer le modèle sans redéployer. À trancher. ### 2. Endpoint backend Nouvelle route : `POST /api/ai` **Fichier :** `src/Service/AiService.php` ```php class AiService { public function query(string $action, string $title, string $content): array // $action : 'critique' | 'rewrite' // Retourne : ['ok' => true, 'text' => "..."] ou ['error' => "..."] } ``` **Prompts système :** - `critique` : *"Tu es un relecteur expert. Analyse cet article de blog : identifie les faiblesses argumentatives, les imprécisions, les manques de clarté, les points à développer. Réponds en markdown avec des sections claires."* - `rewrite` : *"Tu es un rédacteur expert. Réécris cet article de blog en améliorant le style, la clarté et la structure, sans changer le sens ni les faits. Conserve le format markdown et les images. Réponds uniquement avec le texte réécrit."* L'endpoint vérifie que l'utilisateur est authentifié (`requireAuth()`) avant tout appel API. ### 3. Frontend (sidebar éditeur) Dans `templates/post_form.php`, section `col-lg-4`, sous les boutons Enregistrer/Annuler : ```html <!-- Section IA --> <div class="mb-3"> <hr class="my-3"> <p class="fw-semibold small mb-2">IA</p> <div class="d-flex flex-column gap-2"> <button type="button" id="btn-ai-critique" class="btn btn-outline-secondary btn-sm"> Analyse critique </button> <button type="button" id="btn-ai-rewrite" class="btn btn-outline-secondary btn-sm"> Réécrire l'article </button> </div> </div> <!-- Panneau résultat IA (collapsé par défaut) --> <div id="ai-result-panel" class="mt-3" style="display:none"> <div class="d-flex align-items-center justify-content-between mb-1"> <span id="ai-result-label" class="fw-semibold small"></span> <button type="button" id="btn-ai-close" class="btn-close btn-sm"></button> </div> <div id="ai-result-content" class="border rounded p-2 small font-monospace" style="max-height:400px;overflow-y:auto;white-space:pre-wrap;background:#f8f9fa"> </div> <!-- Pour la réécriture uniquement --> <button type="button" id="btn-ai-apply" class="btn btn-warning btn-sm mt-2" style="display:none"> Appliquer dans l'éditeur </button> </div> ``` **JS inline** (`post_form.php` ou `assets/js/editor.js`) : - Au clic, lit `#content` (textarea) et `#title` - `fetch('POST /api/ai', { action, title, content })` - Affiche spinner dans le bouton pendant la requête - Affiche le résultat dans `#ai-result-panel` - Pour réécriture : bouton « Appliquer » remplace `#content` par le texte retourné --- ## Critères d'acceptation - [ ] Bouton « Analyse critique » visible en mode édition uniquement (`$action === 'edit'`) - [ ] Bouton « Réécriture » visible en mode édition uniquement - [ ] Requête AJAX vers `POST /api/ai` avec `{ action, title, content }` - [ ] Spinner pendant l'appel, bouton désactivé - [ ] Résultat affiché dans le panneau latéral (pas de page reload) - [ ] Bouton « Appliquer » présent pour la réécriture ; injecte le texte dans le textarea - [ ] Gestion d'erreur : message lisible si API key manquante ou quota dépassé - [ ] Accès refusé (403) si non authentifié - [ ] Clé Anthropic configurable sans redeployer (`.env` ou admin) - [ ] Modèle configurable (défaut : `claude-haiku-4-5-20251001` pour le coût) --- ## Fichiers à créer / modifier | Fichier | Action | |---------|--------| | `src/Service/AiService.php` | Créer — abstraction Anthropic (inspirée de `recup-mails/api/ai_core.php`) | | `public/index.php` | Ajouter route `POST /api/ai` | | `templates/post_form.php` | Ajouter boutons + panneau résultat dans col-lg-4 | | `.env.example` | Ajouter `ANTHROPIC_API_KEY` et `AI_MODEL` | | `config/config.php` | Lire et exposer `ANTHROPIC_API_KEY` / `AI_MODEL` | --- ## Notes - Modèle par défaut recommandé : `claude-haiku-4-5-20251001` (rapide, peu coûteux pour des articles de blog) - Le bouton « Réécriture » doit demander confirmation avant d'appliquer (data-confirm ou `confirm()` JS) - Prévoir `max_tokens` généreux pour la réécriture (≥ 2000) ; moins pour la critique (≤ 1000) - La réécriture ne sauvegarde pas automatiquement : l'utilisateur doit cliquer « Enregistrer » ensuite - Pas de streaming dans un premier temps (réponse complète puis affichage)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cedricAbonnel/folio#96