Spaces:
Running
Running
File size: 6,359 Bytes
446e02b 55a60a8 446e02b f3cecb0 321e902 446e02b 1ab5ab0 5add2bf 085955a 8c657ef 321e902 5add2bf 321e902 085955a d81e91f 321e902 61aa0bb 085955a 321e902 5add2bf 55a60a8 5add2bf 321e902 5add2bf 321e902 5add2bf e97f201 085955a b58fc00 321e902 bcb5dca 321e902 55a60a8 5add2bf eef58ce 5add2bf 55a60a8 ef8f81a 5add2bf ef8f81a 321e902 085955a ef8f81a 5add2bf ef8f81a bcb5dca 085955a eef58ce ef8f81a 321e902 f3cecb0 085955a 321e902 085955a f3cecb0 5add2bf f3cecb0 085955a f3cecb0 085955a f3cecb0 5add2bf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# ================================================================
# 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()
|