Augustin 45d6344b18 Améliorations majeures UX et templates professionnels
🎯 Améliorations UX critiques :
- Fix curseur qui revenait au début lors de la saisie
- Suppression autosauvegarde automatique
- Centrage flèche bouton scroll-to-top
- Mode liberté applique automatiquement les itérations

🤖 IA optimisée :
- Migration vers mistral-medium classique
- Suppression raisonnement IA pour réponses directes
- Prompt reformulation strict (texte seul)
- Routes IA complètes fonctionnelles

📚 Templates professionnels complets :
- Structure 12 sections selon standards académiques/industrie
- 6 domaines : informatique, math, business, design, recherche, ingénierie
- 3 niveaux : simple (9 sections), détaillé, complet (12 sections)
- Méthodologies spécialisées par domaine

 Nouvelles fonctionnalités :
- Debounce TOC pour performance saisie
- Navigation sections améliorée
- Sauvegarde/restauration position curseur

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-25 20:19:01 +02:00

350 lines
9.6 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 = 0.7) {
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,
max_tokens: parseInt(process.env.AI_MAX_TOKENS) || 4000,
top_p: parseFloat(process.env.AI_TOP_P) || 0.95
})
});
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.7);
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.3);
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.3);
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.6);
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é (génération créative)
router.post('/liberty-mode', checkAIEnabled, async (req, res) => {
try {
const { content, iterations = 1, focus = 'général' } = 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), 5); // Limite à 5 itérations
const results = [];
for (let i = 0; i < maxIterations; i++) {
const messages = [
{
role: 'system',
content: `Tu es un assistant créatif spécialisé en conception technique.
IMPORTANT: Montre ton raisonnement en suivant cette structure:
## 🧠 Raisonnement (Itération ${i + 1}/${maxIterations})
[Explique ton processus de création et ta logique]
## 🚀 Contenu généré
[Ton contenu créatif complémentaire]
Basé sur le contenu existant, génère de nouvelles idées et sections qui complètent naturellement le document.
Focus: ${focus}
Propose des extensions créatives mais pertinentes :
- Nouvelles sections logiques
- Détails techniques manquants
- Alternatives à considérer
- Implications et conséquences
- Améliorations possibles
Reste cohérent avec le style et le niveau technique du document existant.`
},
{
role: 'user',
content: `Génère du contenu complémentaire pour ce document:\n\n${content}`
}
];
const result = await callMistralAPI(messages, 0.8);
results.push({
iteration: i + 1,
content: result
});
}
res.json({
success: true,
data: {
iterations: maxIterations,
results: results
}
});
} catch (error) {
console.error('Erreur mode liberté:', error);
res.status(500).json({
success: false,
error: 'Erreur lors de la génération: ' + error.message
});
}
});
// 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;