Files
webval/enseignant/chatbot_api_settings.php
2026-01-04 17:53:54 +01:00

378 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Configuration des clés API pour le chatbot
* Interface de gestion pour les enseignants
*/
session_start();
require_once '../config/config.php';
require_once '../config/database.php';
require_once '../config/session.php';
require_once '../config/api_key_manager.php';
// Vérifier authentification et type enseignant
if (!SessionManager::isLoggedIn() || !SessionManager::isEnseignant()) {
header('Location: ../login.php');
exit;
}
$user = SessionManager::getUser();
$db = Database::getInstance();
// Récupérer les clés API de l'enseignant
$api_keys = APIKeyManager::listKeys($user['id_utilisateur']);
// Récupérer les modèles disponibles groupés par provider
$models_by_provider = [];
$all_models = $db->fetchAll(
"SELECT * FROM available_models WHERE active = TRUE ORDER BY provider, recommended DESC, display_name"
);
foreach ($all_models as $model) {
$models_by_provider[$model['provider']][] = $model;
}
// Récupérer les statistiques d'utilisation
$stats = $db->fetchOne(
"SELECT
COUNT(DISTINCT id_conversation) as total_conversations,
SUM(total_messages) as total_messages,
provider,
model_used
FROM v_chatbot_usage_stats
WHERE id_enseignant = ?
GROUP BY provider, model_used
ORDER BY total_conversations DESC
LIMIT 1",
[$user['id_utilisateur']]
);
$stats_detail = $db->fetchAll(
"SELECT
provider,
model_used,
SUM(total_conversations) as conversations,
SUM(total_messages) as messages,
month
FROM v_chatbot_usage_stats
WHERE id_enseignant = ?
GROUP BY provider, model_used, month
ORDER BY month DESC, conversations DESC",
[$user['id_utilisateur']]
);
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuration API Chatbot - WebVal</title>
<link rel="stylesheet" href="../assets/css/chatbot_settings.css">
</head>
<body>
<div class="container">
<!-- Header -->
<header class="page-header">
<div class="header-content">
<a href="dashboard.php" class="back-link">← Retour au dashboard</a>
<h1>⚙️ Configuration API Chatbot</h1>
<p class="subtitle">Gérez vos clés API et choisissez les modèles pour vos évaluations</p>
</div>
</header>
<!-- Stats overview -->
<?php if ($stats): ?>
<div class="stats-banner">
<div class="stat-card">
<div class="stat-icon">💬</div>
<div class="stat-content">
<div class="stat-value"><?= number_format($stats['total_conversations'] ?? 0) ?></div>
<div class="stat-label">Conversations</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">📨</div>
<div class="stat-content">
<div class="stat-value"><?= number_format($stats['total_messages'] ?? 0) ?></div>
<div class="stat-label">Messages</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">🤖</div>
<div class="stat-content">
<div class="stat-value"><?= htmlspecialchars($stats['provider'] ?? 'Aucun') ?></div>
<div class="stat-label">Provider actuel</div>
</div>
</div>
</div>
<?php endif; ?>
<!-- Main content -->
<div class="content-grid">
<!-- Section clés API -->
<section class="api-keys-section">
<div class="section-header">
<h2>🔑 Mes clés API</h2>
<button class="btn-primary" onclick="openAddKeyModal()">
Ajouter une clé
</button>
</div>
<div class="keys-list">
<?php
$providers = ['gemini' => 'Gemini', 'mistral' => 'Mistral', 'openai' => 'OpenAI', 'ollama' => 'Ollama'];
$provider_icons = [
'gemini' => '✨',
'mistral' => '⚡',
'openai' => '🧠',
'ollama' => '🏠'
];
foreach ($providers as $provider_id => $provider_name):
$key_info = null;
foreach ($api_keys as $key) {
if ($key['provider'] === $provider_id) {
$key_info = $key;
break;
}
}
$is_configured = $key_info !== null;
$is_active = $is_configured && $key_info['is_active'];
?>
<div class="key-card <?= $is_active ? 'active' : 'inactive' ?>">
<div class="key-header">
<div class="key-provider">
<span class="provider-icon"><?= $provider_icons[$provider_id] ?></span>
<span class="provider-name"><?= $provider_name ?></span>
</div>
<div class="key-status">
<?php if ($is_active): ?>
<span class="status-badge active">🟢 Active</span>
<?php elseif ($is_configured): ?>
<span class="status-badge inactive">🟠 Désactivée</span>
<?php else: ?>
<span class="status-badge none">⚪ Aucune</span>
<?php endif; ?>
</div>
</div>
<div class="key-body">
<?php if ($is_configured): ?>
<div class="key-info">
<div class="info-row">
<span class="label">Modèle par défaut :</span>
<span class="value"><?= htmlspecialchars($key_info['model_default'] ?? '-') ?></span>
</div>
<?php if ($key_info['quota_max']): ?>
<div class="info-row">
<span class="label">Quota :</span>
<span class="value">
<?= number_format($key_info['quota_used']) ?> / <?= number_format($key_info['quota_max']) ?>
<span class="quota-bar">
<span class="quota-fill" style="width: <?= min(100, ($key_info['quota_used'] / $key_info['quota_max']) * 100) ?>%"></span>
</span>
</span>
</div>
<?php endif; ?>
<div class="info-row">
<span class="label">Dernière utilisation :</span>
<span class="value">
<?= $key_info['last_used'] ? date('d/m/Y H:i', strtotime($key_info['last_used'])) : 'Jamais' ?>
</span>
</div>
</div>
<div class="key-actions">
<button class="btn-secondary btn-sm" onclick="testConnection('<?= $provider_id ?>')">
🔍 Tester
</button>
<button class="btn-secondary btn-sm" onclick="editKey('<?= $provider_id ?>')">
✏️ Modifier
</button>
<button class="btn-danger btn-sm" onclick="deleteKey('<?= $provider_id ?>')">
🗑️ Supprimer
</button>
</div>
<?php else: ?>
<div class="key-empty">
<p>Aucune clé configurée pour <?= $provider_name ?></p>
<button class="btn-primary btn-sm" onclick="openAddKeyModal('<?= $provider_id ?>')">
Ajouter
</button>
</div>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</section>
<!-- Section modèles disponibles -->
<aside class="models-sidebar">
<div class="section-header">
<h3>📚 Modèles disponibles</h3>
</div>
<div class="models-list">
<?php foreach ($models_by_provider as $provider => $models): ?>
<div class="provider-group">
<h4><?= $provider_icons[$provider] ?? '🤖' ?> <?= ucfirst($provider) ?></h4>
<?php foreach ($models as $model): ?>
<div class="model-item <?= $model['recommended'] ? 'recommended' : '' ?>">
<div class="model-name">
<?= htmlspecialchars($model['display_name']) ?>
<?php if ($model['recommended']): ?>
<span class="badge-recommended">⭐</span>
<?php endif; ?>
</div>
<div class="model-meta">
<?php if ($model['is_free']): ?>
<span class="badge-free">🆓 Gratuit</span>
<?php else: ?>
<span class="badge-paid">💰 <?= number_format($model['cost_per_1m_tokens'], 2) ?>€/1M</span>
<?php endif; ?>
<span class="badge-speed">
<?php
$speed_icons = ['⏱️', '🐌', '🚶', '🏃', '🚀', '⚡'];
echo $speed_icons[$model['speed_rating']] ?? '🚶';
?>
</span>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
<div class="help-box">
<h4>💡 Recommandations</h4>
<ul>
<li><strong>Gemini 2.0 Flash</strong> : Gratuit, rapide, excellent pour les évaluations</li>
<li><strong>Ministral 8B</strong> : Bon rapport qualité/prix</li>
<li><strong>Ollama local</strong> : Gratuit mais 1 élève à la fois</li>
</ul>
</div>
</aside>
</div>
<!-- Section statistiques détaillées -->
<?php if (!empty($stats_detail)): ?>
<section class="stats-section">
<div class="section-header">
<h2>📊 Historique d'utilisation</h2>
</div>
<div class="stats-table-wrapper">
<table class="stats-table">
<thead>
<tr>
<th>Mois</th>
<th>Provider</th>
<th>Modèle</th>
<th>Conversations</th>
<th>Messages</th>
</tr>
</thead>
<tbody>
<?php foreach ($stats_detail as $stat): ?>
<tr>
<td><?= date('M Y', strtotime($stat['month'] . '-01')) ?></td>
<td>
<span class="provider-badge">
<?= $provider_icons[$stat['provider']] ?? '🤖' ?>
<?= ucfirst($stat['provider']) ?>
</span>
</td>
<td><?= htmlspecialchars($stat['model_used']) ?></td>
<td><?= number_format($stat['conversations']) ?></td>
<td><?= number_format($stat['messages']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
<?php endif; ?>
</div>
<!-- Modal ajout/modification clé API -->
<div id="keyModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2 id="modalTitle">Ajouter une clé API</h2>
<button class="modal-close" onclick="closeKeyModal()">×</button>
</div>
<form id="keyForm">
<input type="hidden" id="keyAction" value="add">
<div class="form-group">
<label for="provider">Provider *</label>
<select id="provider" name="provider" required onchange="updateModelsList()">
<option value="">-- Choisir --</option>
<option value="gemini">✨ Gemini (Google)</option>
<option value="mistral">⚡ Mistral</option>
<option value="openai">🧠 OpenAI</option>
</select>
</div>
<div class="form-group">
<label for="api_key">Clé API *</label>
<div class="input-with-button">
<input type="password" id="api_key" name="api_key" required
placeholder="AIza... ou sk-... ou votre clé">
<button type="button" class="btn-toggle-visibility" onclick="toggleKeyVisibility()">
👁️
</button>
</div>
<small class="help-text" id="keyHelp"></small>
</div>
<div class="form-group">
<label for="model_default">Modèle par défaut *</label>
<select id="model_default" name="model_default" required>
<option value="">-- Sélectionner un provider d'abord --</option>
</select>
</div>
<div class="form-group">
<label>
<input type="checkbox" id="set_quota" onchange="toggleQuotaInput()">
Limiter le quota mensuel
</label>
</div>
<div class="form-group" id="quotaGroup" style="display: none;">
<label for="quota_max">Limite mensuelle (requêtes)</label>
<input type="number" id="quota_max" name="quota_max" min="1" placeholder="ex: 1000">
</div>
<div class="form-actions">
<button type="button" class="btn-secondary" onclick="closeKeyModal()">
Annuler
</button>
<button type="button" class="btn-test" onclick="testKeyBeforeSave()">
🔍 Tester la connexion
</button>
<button type="submit" class="btn-primary">
💾 Enregistrer
</button>
</div>
<div id="testResult" class="test-result" style="display: none;"></div>
</form>
</div>
</div>
<!-- Toast notifications -->
<div id="toast-container"></div>
<script>
const models = <?= json_encode($models_by_provider) ?>;
const userId = <?= $user['id_utilisateur'] ?>;
</script>
<script src="../assets/js/chatbot_settings.js"></script>
</body>
</html>