Augustin 2846d2feef 🚀 Mode Liberté Total + Documentation technique complète
##  Mode Liberté Total Révolutionnaire
- Contrôle de précision : 30% (créatif) à 90% (précis)
- Streaming temps réel avec Server-Sent Events
- Interface progressive avec barre de progression
- Temperature dynamique selon la précision
- Enrichissement complet du document à chaque itération

## 📖 Documentation technique professionnelle
- Architecture détaillée avec diagrammes Mermaid
- Structure de projet complète et annotée
- Flux de données documentés (streaming, journaux)
- Stack technique avec versions et utilités
- Guide d'utilisation mis à jour
- 18 templates organisés par domaines

## 🎨 Interface améliorée
- Sélecteurs d'itérations (1-10) et précision (30-90%)
- Affichage temps réel des explications IA
- Feedback visuel avec progression et statut
- Mode streaming non-bloquant

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-26 11:51:08 +02:00

411 lines
12 KiB
JavaScript

const express = require('express');
const router = express.Router();
require('dotenv').config({ path: './config/.env' });
// Configuration Mistral AI
const MISTRAL_API_KEY = process.env.MISTRAL_API_KEY;
const MISTRAL_BASE_URL = process.env.MISTRAL_BASE_URL || 'https://api.mistral.ai/v1';
const MISTRAL_MODEL = process.env.MISTRAL_MODEL || 'mistral-large-latest';
const AI_ENABLED = process.env.AI_ENABLED === 'true';
// Middleware de vérification
function checkAIEnabled(req, res, next) {
if (!AI_ENABLED) {
return res.status(503).json({
success: false,
error: 'Les fonctionnalités IA sont désactivées'
});
}
if (!MISTRAL_API_KEY) {
return res.status(500).json({
success: false,
error: 'Clé API Mistral non configurée'
});
}
next();
}
// Fonction pour appeler l'API Mistral
async function callMistralAPI(messages, temperature = null) {
try {
const response = await fetch(`${MISTRAL_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${MISTRAL_API_KEY}`
},
body: JSON.stringify({
model: MISTRAL_MODEL,
messages: messages,
temperature: temperature !== null ? temperature : parseFloat(process.env.AI_TEMPERATURE) || 0.3,
max_tokens: parseInt(process.env.AI_MAX_TOKENS) || 35000,
top_p: parseFloat(process.env.AI_TOP_P) || 0.85
})
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Erreur API Mistral: ${response.status} - ${error}`);
}
const data = await response.json();
return data.choices[0].message.content;
} catch (error) {
console.error('Erreur Mistral API:', error);
throw error;
}
}
// POST /api/ai/rephrase - Reformuler du texte
router.post('/rephrase', checkAIEnabled, async (req, res) => {
try {
const { text, context = '' } = req.body;
if (!text || text.trim().length === 0) {
return res.status(400).json({
success: false,
error: 'Texte à reformuler requis'
});
}
const messages = [
{
role: 'system',
content: `Tu es un assistant spécialisé dans la reformulation de textes techniques et de conception.
RÈGLES STRICTES :
1. Reformule le texte pour améliorer la clarté, le style et la fluidité
2. Conserve le niveau technique et tous les détails importants
3. Ne réponds QUE avec le texte reformulé final
4. Aucune introduction, conclusion, explication ou commentaire
5. Ne commence pas par "Voici", "Le texte reformulé" ou autre préambule
6. Commence directement par le contenu reformulé
${context ? `Contexte du document: ${context}` : ''}`
},
{
role: 'user',
content: `Reformule ce texte: "${text}"`
}
];
const result = await callMistralAPI(messages, 0.2); // Reformulation précise
res.json({
success: true,
data: {
original: text,
rephrased: result
}
});
} catch (error) {
console.error('Erreur reformulation:', error);
res.status(500).json({
success: false,
error: 'Erreur lors de la reformulation: ' + error.message
});
}
});
// POST /api/ai/check-inconsistencies - Vérifier les incohérences
router.post('/check-inconsistencies', checkAIEnabled, async (req, res) => {
try {
const { content } = req.body;
if (!content || content.trim().length === 0) {
return res.status(400).json({
success: false,
error: 'Contenu à analyser requis'
});
}
const messages = [
{
role: 'system',
content: `Tu es un expert en analyse de documents de conception technique.
Analyse le document suivant et identifie toutes les incohérences potentielles :
- Contradictions dans les informations
- Décisions qui se contredisent
- Incohérences dans la terminologie
- Problèmes logiques dans l'architecture ou les choix
Réponds directement avec ton analyse détaillée des incohérences trouvées.`
},
{
role: 'user',
content: `Analyse ce document pour détecter les incohérences:\n\n${content}`
}
];
const result = await callMistralAPI(messages, 0.1); // Analyse précise et factuelle
res.json({
success: true,
data: {
analysis: result
}
});
} catch (error) {
console.error('Erreur analyse incohérences:', error);
res.status(500).json({
success: false,
error: 'Erreur lors de l\'analyse: ' + error.message
});
}
});
// POST /api/ai/check-duplications - Vérifier les doublons
router.post('/check-duplications', checkAIEnabled, async (req, res) => {
try {
const { content } = req.body;
if (!content || content.trim().length === 0) {
return res.status(400).json({
success: false,
error: 'Contenu à analyser requis'
});
}
const messages = [
{
role: 'system',
content: `Tu es un expert en analyse de contenu.
Analyse le document suivant pour identifier :
- Les informations répétées ou redondantes
- Les sections qui traitent du même sujet
- Les explications dupliquées
- Les concepts présentés plusieurs fois
Propose des suggestions pour éliminer ces duplications tout en préservant les informations importantes.
Réponds directement avec ton analyse et tes suggestions.`
},
{
role: 'user',
content: `Analyse ce document pour détecter les duplications:\n\n${content}`
}
];
const result = await callMistralAPI(messages, 0.1); // Analyse précise et factuelle
res.json({
success: true,
data: {
analysis: result
}
});
} catch (error) {
console.error('Erreur analyse duplications:', error);
res.status(500).json({
success: false,
error: 'Erreur lors de l\'analyse: ' + error.message
});
}
});
// POST /api/ai/give-advice - Donner des conseils
router.post('/give-advice', checkAIEnabled, async (req, res) => {
try {
const { content, domain = 'général' } = req.body;
if (!content || content.trim().length === 0) {
return res.status(400).json({
success: false,
error: 'Contenu à analyser requis'
});
}
const messages = [
{
role: 'system',
content: `Tu es un consultant expert en conception et architecture technique dans le domaine: ${domain}.
Analyse le document de conception fourni et donne des conseils constructifs pour l'améliorer.
Concentre-toi sur :
- La complétude de la documentation
- La clarté des explications
- L'organisation du contenu
- Les bonnes pratiques du domaine
- Les points manquants importants
- Les suggestions d'amélioration concrètes
Sois constructif et pratique dans tes recommandations.
Réponds directement avec tes conseils et suggestions d'amélioration.`
},
{
role: 'user',
content: `Analyse ce document de conception et donne des conseils pour l'améliorer:\n\n${content}`
}
];
const result = await callMistralAPI(messages, 0.4); // Conseils équilibrés
res.json({
success: true,
data: {
advice: result
}
});
} catch (error) {
console.error('Erreur conseils:', error);
res.status(500).json({
success: false,
error: 'Erreur lors de l\'analyse: ' + error.message
});
}
});
// POST /api/ai/liberty-mode - Mode liberté total (génération itérative)
router.post('/liberty-mode', checkAIEnabled, async (req, res) => {
try {
const { content, iterations = 1, precision = 70, focus = 'conception' } = req.body;
if (!content || content.trim().length === 0) {
return res.status(400).json({
success: false,
error: 'Contenu de base requis'
});
}
const maxIterations = Math.min(parseInt(iterations), 10); // Limite à 10 itérations
const precisionPercent = Math.min(Math.max(parseInt(precision), 10), 100); // Entre 10% et 100%
// Configuration streaming pour réponses en temps réel
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
let currentContent = content;
for (let i = 0; i < maxIterations; i++) {
try {
const messages = [
{
role: 'system',
content: `Tu es un expert en conception technique avec mode "Liberté Total".
MISSION: Améliore et enrichis le document en respectant EXACTEMENT ce niveau de précision: ${precisionPercent}%
RÈGLES DE PRÉCISION:
- À ${precisionPercent}%: Tu peux déduire et ajouter du contenu à hauteur de ${precisionPercent}% basé sur les informations existantes
- À ${100 - precisionPercent}%: Tu peux créer du contenu logique et pertinent même sans info explicite dans le texte
CONSIGNES:
1. Enrichis TOUT le document de manière cohérente
2. Ajoute sections, détails, explications, diagrammes conceptuels
3. Développe les idées existantes avec la créativité autorisée
4. Maintiens la structure logique
RÉPONSE OBLIGATOIRE EN 2 PARTIES SÉPARÉES PAR "---SPLIT---":
## 📊 Explication (Itération ${i + 1}/${maxIterations})
[Explique les améliorations apportées, les sections ajoutées, le raisonnement]
---SPLIT---
[LE DOCUMENT MARKDOWN COMPLET ET AMÉLIORÉ - SANS TITRE "## Document" - DIRECTEMENT LE CONTENU]
Focus: ${focus}
Précision: ${precisionPercent}%`
},
{
role: 'user',
content: `Document à améliorer (Itération ${i + 1}):\n\n${currentContent}`
}
];
// Temperature basée sur la précision (plus créatif = température plus élevée)
const temperature = (100 - precisionPercent) / 100 * 0.8 + 0.1; // Entre 0.1 et 0.9
const result = await callMistralAPI(messages, temperature);
// Séparer l'explication du markdown
const parts = result.split('---SPLIT---');
let explanation = '';
let newMarkdown = currentContent; // Par défaut, garder l'ancien contenu
if (parts.length >= 2) {
explanation = parts[0].trim();
newMarkdown = parts[1].trim();
// Mettre à jour pour la prochaine itération
currentContent = newMarkdown;
} else {
// Fallback si pas de split trouvé
explanation = result;
}
// Envoyer la réponse de cette itération
const iterationData = {
iteration: i + 1,
explanation: explanation,
markdown: newMarkdown,
completed: false
};
res.write(`data: ${JSON.stringify(iterationData)}\n\n`);
// Petit délai pour permettre l'affichage côté client
await new Promise(resolve => setTimeout(resolve, 500));
} catch (iterationError) {
console.error(`Erreur itération ${i + 1}:`, iterationError);
const errorData = {
iteration: i + 1,
error: `Erreur itération ${i + 1}: ${iterationError.message}`,
completed: true
};
res.write(`data: ${JSON.stringify(errorData)}\n\n`);
break;
}
}
// Signal de fin
const finalData = {
completed: true,
totalIterations: maxIterations,
finalMarkdown: currentContent
};
res.write(`data: ${JSON.stringify(finalData)}\n\n`);
res.end();
} catch (error) {
console.error('Erreur mode liberté total:', error);
const errorData = {
error: 'Erreur lors de la génération: ' + error.message,
completed: true
};
res.write(`data: ${JSON.stringify(errorData)}\n\n`);
res.end();
}
});
// GET /api/ai/status - Statut de l'IA
router.get('/status', (req, res) => {
res.json({
success: true,
data: {
enabled: AI_ENABLED,
model: MISTRAL_MODEL,
configured: !!MISTRAL_API_KEY
}
});
});
module.exports = router;