133 lines
6.4 KiB
HTML
133 lines
6.4 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Configuration IA - GMAO{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid">
|
||
<nav aria-label="breadcrumb" class="mb-3">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.index') }}">Tableau de bord</a></li>
|
||
<li class="breadcrumb-item active">Configuration IA</li>
|
||
</ol>
|
||
</nav>
|
||
|
||
<h2 class="h4 mb-3"><i class="bi bi-robot"></i> Configuration IA (OpenRouter)</h2>
|
||
<div class="alert alert-warning"><i class="bi bi-person-check"></i> <strong>Validation humaine obligatoire :</strong> l’IA produit uniquement des propositions. Elle ne crée, ne modifie et ne clôture jamais automatiquement une intervention.</div>
|
||
|
||
<div class="row">
|
||
<div class="col-lg-8">
|
||
<div class="card border-0 shadow-sm mb-3">
|
||
<div class="card-body">
|
||
<h6 class="text-muted"><i class="bi bi-key"></i> Cle API OpenRouter</h6>
|
||
<form method="POST" action="{{ url_for('ai_config.save') }}">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Cle API</label>
|
||
<input type="password" name="api_key" class="form-control"
|
||
value="{{ masked_key if has_key else '' }}"
|
||
placeholder="sk-or-v1-...">
|
||
<small class="text-muted">
|
||
{% if has_key %}
|
||
Cle configuree ({{ masked_key }}). Laisser tel quel pour conserver.
|
||
{% else %}
|
||
Non configuree. Obtenez votre cle sur <a href="https://openrouter.ai/keys" target="_blank">openrouter.ai/keys</a>.
|
||
{% endif %}
|
||
</small>
|
||
</div>
|
||
|
||
<div class="mb-3">
|
||
<label class="form-label">Nom du modele</label>
|
||
<input type="text" name="model" class="form-control"
|
||
value="{{ model }}"
|
||
placeholder="ex: poolside/laguna-m.1:free"
|
||
required>
|
||
<small class="text-muted">
|
||
Liste des modeles : <a href="https://openrouter.ai/models" target="_blank">openrouter.ai/models</a>.
|
||
Modeles gratuits recommandes : <code>poolside/laguna-m.1:free</code>, <code>z-ai/glm-4.5-air:free</code>, <code>meta-llama/llama-3.1-8b-instruct:free</code>
|
||
</small>
|
||
</div>
|
||
|
||
<div class="d-flex gap-2">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="bi bi-check-circle"></i> Enregistrer
|
||
</button>
|
||
<button type="button" class="btn btn-outline-info" id="btn-test-model">
|
||
<i class="bi bi-play-circle"></i> Tester le modele
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Statut du modele -->
|
||
<div class="card border-0 shadow-sm mb-3">
|
||
<div class="card-body">
|
||
<h6 class="text-muted"><i class="bi bi-activity"></i> Statut du modele</h6>
|
||
{% if model_status == 'ok' %}
|
||
<div class="alert alert-success mb-0">
|
||
<i class="bi bi-check-circle"></i> Le modele <strong>{{ model }}</strong> repond correctement.
|
||
</div>
|
||
{% elif model_status == 'error' %}
|
||
<div class="alert alert-danger mb-0">
|
||
<i class="bi bi-x-circle"></i> Erreur : {{ model_error }}
|
||
<br><small class="text-muted">Le modele <code>{{ model }}</code> ne semble pas exister ou la cle API est invalide.</small>
|
||
</div>
|
||
{% else %}
|
||
<div class="alert alert-secondary mb-0">
|
||
<i class="bi bi-question-circle"></i> Non teste. Cliquez sur "Tester le modele".
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-lg-4">
|
||
<div class="card border-0 shadow-sm">
|
||
<div class="card-body">
|
||
<h6 class="text-muted"><i class="bi bi-info-circle"></i> Aide</h6>
|
||
<p class="small">
|
||
L'IA analyse les emails Outlook et les messages ENT pour creer des interpretations.
|
||
Ces interpretations sont ensuite validees dans la page <a href="{{ url_for('messagerie.index') }}">Messagerie</a>.
|
||
</p>
|
||
<p class="small text-muted">
|
||
Le modele doit etre un modele de chat compatible OpenAI disponible sur OpenRouter.
|
||
Les modeles gratuits ont un suffixe <code>:free</code>.
|
||
</p>
|
||
<p class="small text-muted">
|
||
Si le modele n'existe plus, une alerte s'affiche sur le tableau de bord principal.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.getElementById('btn-test-model').addEventListener('click', async function() {
|
||
const btn = this;
|
||
const original = btn.innerHTML;
|
||
btn.disabled = true;
|
||
btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Test...';
|
||
|
||
const model = document.querySelector('input[name="model"]').value;
|
||
|
||
try {
|
||
const r = await fetch('/ai-config/api/test-model', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({model: model})
|
||
});
|
||
const d = await r.json();
|
||
if (d.success) {
|
||
alert('Modele OK ! Reponse: ' + d.response);
|
||
} else {
|
||
alert('Erreur: ' + d.error);
|
||
}
|
||
} catch(e) {
|
||
alert('Erreur: ' + e.message);
|
||
}
|
||
btn.disabled = false;
|
||
btn.innerHTML = original;
|
||
});
|
||
</script>
|
||
{% endblock %}
|