161 lines
5.9 KiB
Python
161 lines
5.9 KiB
Python
"""
|
|
Configuration IA - GMAO College
|
|
Permet de configurer le modele OpenRouter et la cle API.
|
|
"""
|
|
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
|
from flask_login import login_required, current_user
|
|
from app_new.extensions import db
|
|
from app_new.core.models.settings import AppSettings
|
|
|
|
ai_config_bp = Blueprint('ai_config', __name__, url_prefix='/ai-config', template_folder='templates')
|
|
|
|
|
|
@ai_config_bp.route('/')
|
|
@login_required
|
|
def index():
|
|
"""Page de configuration IA."""
|
|
api_key = AppSettings.get('openrouter_api_key', '')
|
|
model = AppSettings.get('openrouter_model', 'poolside/laguna-m.1:free')
|
|
|
|
# Masquer la cle API (afficher seulement les premiers/caracteres)
|
|
masked_key = ''
|
|
if api_key:
|
|
if len(api_key) > 10:
|
|
masked_key = api_key[:6] + '...' + api_key[-4:]
|
|
else:
|
|
masked_key = '***'
|
|
|
|
# Tester le modele
|
|
model_status = None
|
|
model_error = None
|
|
if api_key and model:
|
|
try:
|
|
import requests as req
|
|
resp = req.post(
|
|
'https://openrouter.ai/api/v1/chat/completions',
|
|
headers={
|
|
'Authorization': f'Bearer {api_key}',
|
|
'Content-Type': 'application/json'
|
|
},
|
|
json={
|
|
'model': model,
|
|
'messages': [{'role': 'user', 'content': 'Reponds juste OK'}],
|
|
'max_tokens': 5
|
|
},
|
|
timeout=15
|
|
)
|
|
if resp.status_code == 200:
|
|
model_status = 'ok'
|
|
else:
|
|
model_status = 'error'
|
|
data = resp.json() if resp.headers.get('content-type', '').startswith('application/json') else {}
|
|
model_error = data.get('error', {}).get('message', f'HTTP {resp.status_code}')
|
|
except Exception as e:
|
|
model_status = 'error'
|
|
model_error = str(e)[:200]
|
|
|
|
return render_template('ai_config/index.html',
|
|
masked_key=masked_key,
|
|
has_key=bool(api_key),
|
|
model=model,
|
|
model_status=model_status,
|
|
model_error=model_error,
|
|
human_approval=True)
|
|
|
|
|
|
@ai_config_bp.route('/save', methods=['POST'])
|
|
@login_required
|
|
def save():
|
|
"""Sauvegarde la configuration IA."""
|
|
# Cle API
|
|
api_key = request.form.get('api_key', '').strip()
|
|
if api_key and '...' not in api_key and api_key != '***' and not api_key.startswith('***'):
|
|
AppSettings.set('openrouter_api_key', api_key,
|
|
description='Cle API OpenRouter pour l\'interpretation des emails',
|
|
is_encrypted=True)
|
|
|
|
# Modele
|
|
model = request.form.get('model', '').strip()
|
|
if model:
|
|
AppSettings.set('openrouter_model', model,
|
|
description='Modele OpenRouter pour l\'interpretation IA')
|
|
AppSettings.set('ai_requires_human_approval', 'true',
|
|
description='Validation humaine obligatoire avant action métier')
|
|
|
|
flash('Configuration IA sauvegardee.', 'success')
|
|
return redirect(url_for('ai_config.index'))
|
|
|
|
|
|
@ai_config_bp.route('/api/test-model', methods=['POST'])
|
|
@login_required
|
|
def test_model():
|
|
"""Teste si le modele OpenRouter fonctionne."""
|
|
api_key = AppSettings.get('openrouter_api_key', '')
|
|
model = request.json.get('model', '') if request.is_json else request.form.get('model', '')
|
|
|
|
if not api_key:
|
|
return jsonify({'success': False, 'error': 'Cle API non configuree'})
|
|
|
|
if not model:
|
|
return jsonify({'success': False, 'error': 'Modele non specifie'})
|
|
|
|
try:
|
|
import requests as req
|
|
resp = req.post(
|
|
'https://openrouter.ai/api/v1/chat/completions',
|
|
headers={
|
|
'Authorization': f'Bearer {api_key}',
|
|
'Content-Type': 'application/json'
|
|
},
|
|
json={
|
|
'model': model,
|
|
'messages': [{'role': 'user', 'content': 'Reponds juste OK'}],
|
|
'max_tokens': 5
|
|
},
|
|
timeout=15
|
|
)
|
|
if resp.status_code == 200:
|
|
data = resp.json()
|
|
content = data.get('choices', [{}])[0].get('message', {}).get('content', '')
|
|
return jsonify({'success': True, 'response': content[:50]})
|
|
else:
|
|
data = resp.json() if resp.headers.get('content-type', '').startswith('application/json') else {}
|
|
error_msg = data.get('error', {}).get('message', f'HTTP {resp.status_code}')
|
|
return jsonify({'success': False, 'error': error_msg[:200]})
|
|
except Exception as e:
|
|
return jsonify({'success': False, 'error': str(e)[:200]})
|
|
|
|
|
|
@ai_config_bp.route('/api/status')
|
|
@login_required
|
|
def api_status():
|
|
"""Statut du modele IA pour le dashboard."""
|
|
api_key = AppSettings.get('openrouter_api_key', '')
|
|
model = AppSettings.get('openrouter_model', '')
|
|
|
|
if not api_key:
|
|
return jsonify({'status': 'no_key', 'message': 'Cle API non configuree'})
|
|
if not model:
|
|
return jsonify({'status': 'no_model', 'message': 'Modele non configure'})
|
|
|
|
try:
|
|
import requests as req
|
|
resp = req.post(
|
|
'https://openrouter.ai/api/v1/chat/completions',
|
|
headers={
|
|
'Authorization': f'Bearer {api_key}',
|
|
'Content-Type': 'application/json'
|
|
},
|
|
json={
|
|
'model': model,
|
|
'messages': [{'role': 'user', 'content': 'OK'}],
|
|
'max_tokens': 5
|
|
},
|
|
timeout=10
|
|
)
|
|
if resp.status_code == 200:
|
|
return jsonify({'status': 'ok', 'model': model})
|
|
else:
|
|
return jsonify({'status': 'error', 'model': model, 'message': f'HTTP {resp.status_code}'})
|
|
except Exception as e:
|
|
return jsonify({'status': 'error', 'model': model, 'message': str(e)[:100]})
|