modif selection chatbot
This commit is contained in:
@ -28,13 +28,13 @@ function openAddKeyModal(provider = null) {
|
|||||||
document.getElementById('keyAction').value = 'add';
|
document.getElementById('keyAction').value = 'add';
|
||||||
editMode = false;
|
editMode = false;
|
||||||
|
|
||||||
|
// Important : activer le select AVANT de définir la valeur
|
||||||
|
providerSelect.disabled = false;
|
||||||
|
|
||||||
// Pre-select provider if provided
|
// Pre-select provider if provided
|
||||||
if (provider) {
|
if (provider) {
|
||||||
providerSelect.value = provider;
|
providerSelect.value = provider;
|
||||||
updateModelsList();
|
providerSelect.dispatchEvent(new Event('change')); // Trigger updateModelsList
|
||||||
providerSelect.disabled = false;
|
|
||||||
} else {
|
|
||||||
providerSelect.disabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
title.textContent = 'Ajouter une clé API';
|
title.textContent = 'Ajouter une clé API';
|
||||||
@ -282,6 +282,98 @@ function deleteKey(provider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== Set Default Provider ==========
|
||||||
|
|
||||||
|
function setAsDefault(provider, model) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('action', 'set_default');
|
||||||
|
formData.append('provider', provider);
|
||||||
|
formData.append('model', model);
|
||||||
|
|
||||||
|
fetch('chatbot_api_ajax.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
showToast(data.message || 'Provider par défaut mis à jour', 'success');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
showToast(data.error || 'Erreur', 'error');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
showToast('Erreur de connexion', 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Configure Ollama ==========
|
||||||
|
|
||||||
|
function configureOllama() {
|
||||||
|
const availableModels = models['ollama'] || [];
|
||||||
|
|
||||||
|
if (availableModels.length === 0) {
|
||||||
|
showToast('Aucun modèle Ollama disponible', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer une liste des modèles
|
||||||
|
let modelOptions = '<select id="ollama-model-select" style="width: 100%; padding: 0.5rem; margin: 1rem 0; border: 2px solid #e2e8f0; border-radius: 8px;">';
|
||||||
|
availableModels.forEach(model => {
|
||||||
|
modelOptions += `<option value="${model.model_id}">${model.display_name}</option>`;
|
||||||
|
});
|
||||||
|
modelOptions += '</select>';
|
||||||
|
|
||||||
|
// Simple prompt
|
||||||
|
const modelHtml = `
|
||||||
|
<div style="padding: 1rem;">
|
||||||
|
<p style="margin-bottom: 1rem;">Choisir le modèle Ollama par défaut :</p>
|
||||||
|
${modelOptions}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Utiliser une confirm box simple pour l'instant
|
||||||
|
// (dans une vraie app, utiliser le modal existant)
|
||||||
|
const modal = document.getElementById('keyModal');
|
||||||
|
const modalContent = modal.querySelector('.modal-content');
|
||||||
|
const originalContent = modalContent.innerHTML;
|
||||||
|
|
||||||
|
modalContent.innerHTML = `
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2>Configuration Ollama</h2>
|
||||||
|
<button class="modal-close" onclick="closeKeyModal()">×</button>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 1.5rem;">
|
||||||
|
<p style="margin-bottom: 1rem;">Choisir le modèle Ollama à utiliser par défaut :</p>
|
||||||
|
<select id="ollama-model-select" style="width: 100%; padding: 0.75rem; border: 2px solid #e2e8f0; border-radius: 8px; font-family: 'JetBrains Mono', monospace;">
|
||||||
|
${availableModels.map(m => `<option value="${m.model_id}">${m.display_name}</option>`).join('')}
|
||||||
|
</select>
|
||||||
|
<div style="display: flex; gap: 1rem; justify-content: flex-end; margin-top: 1.5rem; padding-top: 1.5rem; border-top: 2px solid #e2e8f0;">
|
||||||
|
<button class="btn-secondary" onclick="closeKeyModal(); document.querySelector('.modal-content').innerHTML = \`${originalContent.replace(/`/g, '\\`')}\`;">Annuler</button>
|
||||||
|
<button class="btn-primary" onclick="saveOllamaConfig()">💾 Enregistrer</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
modal.classList.add('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveOllamaConfig() {
|
||||||
|
const select = document.getElementById('ollama-model-select');
|
||||||
|
const model = select.value;
|
||||||
|
|
||||||
|
if (!model) {
|
||||||
|
showToast('Veuillez sélectionner un modèle', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAsDefault('ollama', model);
|
||||||
|
}
|
||||||
|
|
||||||
// ========== Toast Notifications ==========
|
// ========== Toast Notifications ==========
|
||||||
|
|
||||||
function showToast(message, type = 'info') {
|
function showToast(message, type = 'info') {
|
||||||
|
|||||||
@ -161,6 +161,35 @@ try {
|
|||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'set_default':
|
||||||
|
// Définir le provider par défaut
|
||||||
|
$provider = $_POST['provider'] ?? null;
|
||||||
|
$model = $_POST['model'] ?? null;
|
||||||
|
|
||||||
|
if (!$provider || !$model) {
|
||||||
|
throw new Exception('Paramètres manquants');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::getInstance();
|
||||||
|
|
||||||
|
// Upsert dans chatbot_default_provider
|
||||||
|
$result = $db->query(
|
||||||
|
"INSERT INTO chatbot_default_provider (id_enseignant, provider, model_default)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
ON DUPLICATE KEY UPDATE provider = VALUES(provider), model_default = VALUES(model_default)",
|
||||||
|
[$user['id_utilisateur'], $provider, $model]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
throw new Exception('Erreur lors de la mise à jour');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Provider par défaut mis à jour'
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'stats':
|
case 'stats':
|
||||||
// Récupérer les statistiques d'utilisation
|
// Récupérer les statistiques d'utilisation
|
||||||
$db = Database::getInstance();
|
$db = Database::getInstance();
|
||||||
|
|||||||
@ -21,19 +21,23 @@ $db = Database::getInstance();
|
|||||||
// Récupérer les clés API de l'enseignant
|
// Récupérer les clés API de l'enseignant
|
||||||
$api_keys = APIKeyManager::listKeys($user['id_utilisateur']);
|
$api_keys = APIKeyManager::listKeys($user['id_utilisateur']);
|
||||||
|
|
||||||
// Déterminer le provider par défaut (premier actif ou ollama)
|
// Récupérer le provider par défaut configuré
|
||||||
$default_provider = null;
|
$default_config = $db->fetchOne(
|
||||||
foreach ($api_keys as $key) {
|
"SELECT provider, model_default FROM chatbot_default_provider WHERE id_enseignant = ?",
|
||||||
if ($key['is_active']) {
|
[$user['id_utilisateur']]
|
||||||
$default_provider = $key['provider'];
|
);
|
||||||
break; // Premier actif trouvé
|
|
||||||
}
|
// Si pas de config, initialiser avec Ollama
|
||||||
}
|
if (!$default_config) {
|
||||||
// Si aucune clé active, Ollama par défaut
|
$db->query(
|
||||||
if (!$default_provider) {
|
"INSERT INTO chatbot_default_provider (id_enseignant, provider, model_default) VALUES (?, 'ollama', 'ministral-3:3b')",
|
||||||
$default_provider = 'ollama';
|
[$user['id_utilisateur']]
|
||||||
|
);
|
||||||
|
$default_config = ['provider' => 'ollama', 'model_default' => 'ministral-3:3b'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$default_provider = $default_config['provider'];
|
||||||
|
$default_model = $default_config['model_default'];
|
||||||
|
|
||||||
// Récupérer les modèles disponibles groupés par provider
|
// Récupérer les modèles disponibles groupés par provider
|
||||||
$models_by_provider = [];
|
$models_by_provider = [];
|
||||||
@ -165,10 +169,7 @@ $stats_detail = $db->fetchAll(
|
|||||||
</div>
|
</div>
|
||||||
<div class="key-status">
|
<div class="key-status">
|
||||||
<?php if ($is_active): ?>
|
<?php if ($is_active): ?>
|
||||||
<span class="status-badge active">🟢 Active</span>
|
<span class="status-badge active">🟢 Active</span>
|
||||||
<?php if ($default_provider === $provider_id): ?>
|
|
||||||
<span class="status-badge default">✨ Par défaut</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php elseif ($is_configured): ?>
|
<?php elseif ($is_configured): ?>
|
||||||
<span class="status-badge inactive">🟠 Désactivée</span>
|
<span class="status-badge inactive">🟠 Désactivée</span>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@ -178,7 +179,36 @@ $stats_detail = $db->fetchAll(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="key-body">
|
<div class="key-body">
|
||||||
<?php if ($is_configured): ?>
|
<?php if ($provider_id === 'ollama'): ?>
|
||||||
|
<!-- Card spéciale Ollama (pas de clé API nécessaire) -->
|
||||||
|
<div class="key-info">
|
||||||
|
<div class="info-row">
|
||||||
|
<span class="label">Type :</span>
|
||||||
|
<span class="value">🏠 Local (Jetson)</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-row">
|
||||||
|
<span class="label">Modèle actuel :</span>
|
||||||
|
<span class="value"><?= $default_provider === 'ollama' ? htmlspecialchars($default_model) : 'ministral-3:3b' ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="info-row">
|
||||||
|
<span class="label">Coût :</span>
|
||||||
|
<span class="value">Gratuit ✅</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="key-actions">
|
||||||
|
<button class="btn-secondary btn-sm" onclick="testConnection('ollama')">
|
||||||
|
🔍 Tester
|
||||||
|
</button>
|
||||||
|
<button class="btn-secondary btn-sm" onclick="configureOllama()">
|
||||||
|
⚙️ Changer le modèle
|
||||||
|
</button>
|
||||||
|
<?php if ($default_provider !== 'ollama'): ?>
|
||||||
|
<button class="btn-primary btn-sm" onclick="setAsDefault('ollama', 'ministral-3:3b')">
|
||||||
|
⭐ Définir par défaut
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php elseif ($is_configured): ?>
|
||||||
<div class="key-info">
|
<div class="key-info">
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
<span class="label">Modèle par défaut :</span>
|
<span class="label">Modèle par défaut :</span>
|
||||||
@ -209,6 +239,11 @@ $stats_detail = $db->fetchAll(
|
|||||||
<button class="btn-secondary btn-sm" onclick="editKey('<?= $provider_id ?>')">
|
<button class="btn-secondary btn-sm" onclick="editKey('<?= $provider_id ?>')">
|
||||||
✏️ Modifier
|
✏️ Modifier
|
||||||
</button>
|
</button>
|
||||||
|
<?php if ($default_provider !== $provider_id): ?>
|
||||||
|
<button class="btn-primary btn-sm" onclick="setAsDefault('<?= $provider_id ?>', '<?= htmlspecialchars($key_info['model_default']) ?>')">
|
||||||
|
⭐ Définir par défaut
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
<button class="btn-danger btn-sm" onclick="deleteKey('<?= $provider_id ?>')">
|
<button class="btn-danger btn-sm" onclick="deleteKey('<?= $provider_id ?>')">
|
||||||
🗑️ Supprimer
|
🗑️ Supprimer
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
36
sql/chatbot_default_provider.sql
Normal file
36
sql/chatbot_default_provider.sql
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- WebVal - Configuration provider par défaut
|
||||||
|
-- Table pour stocker le choix de l'enseignant
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- Table de configuration par défaut par enseignant
|
||||||
|
CREATE TABLE IF NOT EXISTS chatbot_default_provider (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
id_enseignant INT NOT NULL,
|
||||||
|
provider VARCHAR(50) NOT NULL,
|
||||||
|
model_default VARCHAR(100) NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (id_enseignant) REFERENCES utilisateurs(id_utilisateur) ON DELETE CASCADE,
|
||||||
|
UNIQUE KEY unique_enseignant (id_enseignant)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- Initialiser Ollama comme défaut pour les enseignants existants
|
||||||
|
INSERT IGNORE INTO chatbot_default_provider (id_enseignant, provider, model_default)
|
||||||
|
SELECT DISTINCT id_utilisateur, 'ollama', 'ministral-3:3b'
|
||||||
|
FROM utilisateurs
|
||||||
|
WHERE id_type = 1; -- Type enseignant
|
||||||
|
|
||||||
|
-- Mettre à jour pour ceux qui ont déjà une clé cloud active
|
||||||
|
UPDATE chatbot_default_provider cdp
|
||||||
|
JOIN (
|
||||||
|
SELECT id_enseignant, provider, model_default
|
||||||
|
FROM api_keys
|
||||||
|
WHERE is_active = 1
|
||||||
|
ORDER BY created_at ASC
|
||||||
|
LIMIT 1
|
||||||
|
) ak ON cdp.id_enseignant = ak.id_enseignant
|
||||||
|
SET cdp.provider = ak.provider,
|
||||||
|
cdp.model_default = ak.model_default;
|
||||||
|
|
||||||
|
SELECT '✅ Table chatbot_default_provider créée et initialisée' as Status;
|
||||||
Reference in New Issue
Block a user