akira / modules /config.py
akra35567's picture
Update modules/config.py
d81e91f
raw
history blame
6.36 kB
# ================================================================
# AKIRA IA CORE ADAPTADO PARA SentenceTransformers
# ================================================================
import os
import time
import threading
from dataclasses import dataclass
from typing import Optional, List
from loguru import logger
from sentence_transformers import SentenceTransformer
from .database import Database
# ---------------------------------------------------------------
# EMBEDDINGS
# ---------------------------------------------------------------
EMBEDDING_MODEL = "paraphrase-multilingual-MiniLM-L12-v2"
embedding_model = SentenceTransformer(EMBEDDING_MODEL)
def gerar_embedding(text: str):
"""Gera embedding usando SentenceTransformers."""
emb = embedding_model.encode(text, convert_to_numpy=True)
return emb
# ---------------------------------------------------------------
# HEURÍSTICAS
# ---------------------------------------------------------------
PALAVRAS_RUDES = ['caralho','puto','merda','fdp','vsf','burro','idiota','parvo']
GIRIAS_ANGOLANAS = ['mano','puto','cota','mwangolé','kota','oroh','bué','fixe','baza','kuduro']
@dataclass
class Interacao:
usuario: str
mensagem: str
resposta: str
numero: str
is_reply: bool = False
mensagem_original: str = ""
# ---------------------------------------------------------------
# TREINAMENTO E MEMÓRIA
# ---------------------------------------------------------------
class Treinamento:
def __init__(self, db: Database, interval_hours: int = 1):
self.db = db
self.interval_hours = interval_hours
self._thread = None
self._running = False
self.privileged_users = ['244937035662','isaac','isaac quarenta']
def registrar_interacao(
self,
usuario: str,
mensagem: str,
resposta: str,
numero: str = '',
is_reply: bool = False,
mensagem_original: str = ''
):
self.db.salvar_mensagem(usuario, mensagem, resposta, numero, is_reply, mensagem_original)
self._aprender_em_tempo_real(numero, mensagem, resposta)
def _aprender_em_tempo_real(self, numero: str, msg: str, resp: str):
if not numero:
return
texto = f"{msg} {resp}".lower()
embedding = gerar_embedding(texto)
self.db.salvar_embedding(numero, msg, resp, embedding)
rude = any(p in texto for p in PALAVRAS_RUDES)
tom = 'rude' if rude else 'casual'
self.db.registrar_tom_usuario(numero, tom, 0.9 if rude else 0.6, texto[:100])
# Loop periódico
def _run_loop(self):
interval = max(1, self.interval_hours) * 3600
while self._running:
try:
self.train_once()
except Exception as e:
logger.exception(f"Erro no treinamento: {e}")
for _ in range(int(interval)):
if not self._running: break
time.sleep(1)
def start_periodic_training(self):
if self._running: return
self._running = True
self._thread = threading.Thread(target=self._run_loop, daemon=True)
self._thread.start()
def stop(self):
self._running = False
if self._thread: self._thread.join(timeout=5)
def train_once(self):
logger.info("Treinamento leve + embeddings iniciado...")
# Apenas heurística + embeddings
logger.info("Treinamento concluído.")
# ---------------------------------------------------------------
# CONFIGURAÇÃO CENTRAL
# ---------------------------------------------------------------
MISTRAL_API_KEY: str = "t4k0ZwQSy5kvvRE1jCJfYnGiFAVlQcMb"
GEMINI_API_KEY: str = "AIzaSyB-YryzcfTLECebI7nLq7o4XRfHnM2_D9Q"
SERPAPI_KEY: Optional[str] = "d81753b2909eb4746e1e0c92e052d6588ab725cf46f89fd9182c3da5daa477a5"
HF_TOKEN: Optional[str] = os.getenv("HF_TOKEN", "")
# MODELOS
MISTRAL_MODEL: str = "mistral-large-latest"
GEMINI_MODEL: str = "gemini-2.5-flash"
# PARÂMETROS
MAX_TOKENS: int = 1000
TOP_P: float = 0.9
USAR_NOME_PROBABILIDADE: float = 0.1
FALLBACK_RESPONSE: str = "Desculpa, puto, o modelo tá off hoje. Tenta depois!"
# PERSONALIDADE
PERSONA = """
Você é Akira, uma angolana (mulher) com personalidade forte e direta...
"""
SYSTEM_PROMPT = """
REGRAS CRÍTICAS:
- Sem markdown
- 1-2 frases curtas
- Tom formal para privilegiados, casual caso contrário
- Use gírias locais e risadas naturais
"""
HUMOR_INICIAL: str = "neutra"
MEMORIA_MAX: int = 20
# BANCO
DB_PATH: str = "/home/user/data/akira.db"
FINETUNED_PATH: str = "/home/user/data/finetuned_hermes"
# TREINAMENTO
START_PERIODIC_TRAINER: bool = True
TRAINING_INTERVAL_HOURS: int = 24
# API
API_PORT: int = int(os.getenv("PORT", "7860"))
API_HOST: str = "0.0.0.0"
PRIVILEGED_USERS: List[str] = ["244937035662", "isaac quarenta"]
# VALIDAÇÃO FLEXÍVEL
def validate_config() -> None:
warnings = []
if not MISTRAL_API_KEY or len(MISTRAL_API_KEY.strip()) < 20:
warnings.append("MISTRAL_API_KEY inválida ou ausente")
logger.warning("MISTRAL_API_KEY inválida → API principal DESATIVADA")
else:
logger.info("MISTRAL_API_KEY OK")
if not GEMINI_API_KEY or len(GEMINI_API_KEY.strip()) < 30:
warnings.append("GEMINI_API_KEY inválida ou ausente")
logger.warning("GEMINI_API_KEY inválida → fallback DESATIVADO")
else:
logger.info("GEMINI_API_KEY OK")
if warnings:
logger.warning(f"AVISOS: {', '.join(warnings)}")
logger.warning("App vai rodar com fallbacks limitados")
else:
logger.info("Todas as chaves OK")
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
_init_db()
def _init_db() -> None:
import sqlite3
try:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS conversas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
mensagem TEXT,
resposta TEXT,
embedding BLOB,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
logger.info(f"Banco inicializado: {DB_PATH}")
except Exception as e:
logger.error(f"Erro ao criar banco: {e}")
raise
validate_config()