AKIRA-SOFTEDGE / main.py
akra35567's picture
Upload main.py
b11fe41 verified
Raw
History Blame
7.49 kB
# main.py — AKIRA V21 ULTIMATE (Janeiro 2025)
"""
Entry point Flask API para Akira IA V21
- Multi-API com fallback (6 provedores)
- Suporte a .env para secrets
- Otimizado para Hugging Face Spaces
"""
import os
import sys
# === CORREÇÃO: Garante que os imports funcionam (local e produção) ===
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
if PROJECT_ROOT not in sys.path:
sys.path.insert(0, PROJECT_ROOT)
# Carregar variáveis de ambiente (.env) o mais cedo possível
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
from flask import Flask, jsonify
from loguru import logger
import datetime
# === LOGS ===
logger.remove()
logger.add(
sys.stderr,
format="<green>{time:HH:mm:ss}</green> | <level>{level}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> -> <level>{message}</level>",
colorize=True,
backtrace=True,
diagnose=True,
level="INFO"
)
# === FLASK APP ===
app = Flask(__name__)
# Make app available for Gunicorn
application = app
# === ROTAS BASICAS ===
@app.route("/")
def index():
"""Pagina inicial com status dinamico"""
try:
from modules import config
apis_configuradas = []
if getattr(config, "MISTRAL_API_KEY", None): apis_configuradas.append("Mistral")
if getattr(config, "GEMINI_API_KEY", None): apis_configuradas.append("Gemini")
if getattr(config, "GROQ_API_KEY", None): apis_configuradas.append("Groq")
if getattr(config, "COHERE_API_KEY", None): apis_configuradas.append("Cohere")
if getattr(config, "TOGETHER_API_KEY", None): apis_configuradas.append("Together")
if getattr(config, "OPENROUTER_API_KEY", None): apis_configuradas.append("OpenRouter")
apis_texto = ", ".join(apis_configuradas) if apis_configuradas else "Nenhuma (Verifique os Secrets)"
except Exception:
apis_texto = "Erro ao ler configuracoes"
return f'''
<div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; text-align: center; margin: 50px; background: #0a0a0a; color: #00ff41; padding: 40px; border: 2px solid #00ff41; border-radius: 10px; box-shadow: 0 0 20px rgba(0,255,65,0.2);">
<h1 style="text-shadow: 0 0 10px #00ff41;">AKIRA V21 ULTIMATE ONLINE!</h1>
<p style="color: #fff;"><strong>Multi-API System — Core Infrastructure V21</strong></p>
<p><strong>APIs Ativas:</strong> <span style="color: #fff;">{apis_texto}</span></p>
<p><strong>Status:</strong> <span style="background: #00ff41; color: #000; padding: 2px 8px; border-radius: 4px; font-weight: bold;">OPERACIONAL</span></p>
<hr style="border-color: #333; margin: 25px 0;">
<p style="font-size: 0.8em; color: #888;"><em>Luanda, Angola — Softedge Corporation & Quarenta softwares</em></p>
</div>
''', 200
@app.route("/health")
def health():
"""Health check para Docker/HF Spaces"""
return "OK", 200
@app.route("/status")
def status():
"""Status detalhado das APIs dinâmico"""
try:
from modules import config
status_info = {
"timestamp": datetime.datetime.now().isoformat(),
"versao": "V21 ULTIMATE",
"uptime_status": "OK",
"apis_disponiveis": [],
}
providers = {
"mistral": "MISTRAL_API_KEY",
"gemini": "GEMINI_API_KEY",
"groq": "GROQ_API_KEY",
"cohere": "COHERE_API_KEY",
"together": "TOGETHER_API_KEY",
"openrouter": "OPENROUTER_API_KEY"
}
for name, key in providers.items():
if getattr(config, key, None):
status_info["apis_disponiveis"].append(name)
return jsonify(status_info), 200
except Exception as e:
return jsonify({"error": str(e), "status": "parcial"}), 500
# === INTEGRAÇÃO DA API ===
akira_api = None
api_disponivel = False
try:
# Tenta importar a API
from modules.api import AkiraAPI, get_blueprint
import modules.config as config
# API_AVAILABLE está em config.py
API_AVAILABLE = getattr(config, 'API_AVAILABLE', {})
if API_AVAILABLE or True: # Always try if imports succeeded
logger.info("Modulos importados com sucesso")
if hasattr(config, 'validate_config'):
config.validate_config()
logger.info("Config validada")
akira_api = AkiraAPI()
app.register_blueprint(get_blueprint(), url_prefix="/api")
logger.success("API V21 integrada -> /api/akira")
apis_ok = []
if config.MISTRAL_API_KEY:
apis_ok.append("Mistral")
if config.GEMINI_API_KEY:
apis_ok.append("Gemini")
if config.GROQ_API_KEY:
apis_ok.append("Groq")
if config.COHERE_API_KEY:
apis_ok.append("Cohere")
if config.TOGETHER_API_KEY:
apis_ok.append("Together")
# HF não está sendo usado mais
if apis_ok:
logger.info(f"APIs: {', '.join(apis_ok)}")
else:
logger.warning("NENHUMA API CONFIGURADA!")
api_disponivel = True
else:
logger.warning("API nao disponivel (erro de import)")
except ImportError as e:
logger.critical(f"ERRO DE IMPORTACAO: {e}")
import traceback
logger.critical(traceback.format_exc())
except Exception as e:
logger.critical(f"FALHA: {e}")
import traceback
logger.critical(traceback.format_exc())
# === SERVIÇO DE BACKUP AUTOMÁTICO PARA HF BUCKETS ===
def periodic_hf_sync_checkpoint():
"""
Roda um processo nativo em background que faz backup seguro
do SQLite para a pasta cloud_sync a cada 2 horas, evitando
qualquer interferência do SQLite WAL na hora de sincronizar p/ HF.
"""
import time
import threading
def _run_checkpoint():
try:
from modules.database import Database
import modules.config as config
db = Database(getattr(config, 'DB_PATH', 'akira.db'))
while True:
# Dorme por 2 horas (7200 segundos)
time.sleep(7200)
db.fazer_checkpoint_hf_sync()
except Exception as e:
logger.error(f"Erro no scheduler de backup HF Sync: {e}")
thread = threading.Thread(target=_run_checkpoint, daemon=True)
thread.start()
logger.info("⏱️ Background Job: Checkpoint HF Sync agendado p/ cada 2 horas.")
# Inicia o serviço
if api_disponivel:
periodic_hf_sync_checkpoint()
# === INICIO DO SERVIDOR ===
if __name__ == "__main__":
logger.info("=" * 60)
logger.info("AKIRA V21 ULTIMATE — SISTEMA MULTI-API")
logger.info("=" * 60)
host = os.getenv("API_HOST", "0.0.0.0")
port = int(os.getenv("API_PORT", "7860"))
logger.info(f"Servidor: http://{host}:{port}")
logger.info("Endpoints: /, /health, /status, /api/akira")
logger.info("=" * 60)
if os.getenv("PRODUCTION", "false").lower() == "true":
logger.info("Modo: PRODUCAO (Gunicorn)")
else:
logger.info("Modo: DESENVOLVIMENTO")
app.run(host=host, port=port, debug=False, use_reloader=False)