# app.py — V25 — AKIRA ANGOLANA + TREINAMENTO + USUÁRIO PRIVILEGIADO import subprocess import time import requests import json import datetime from flask import Flask, request, jsonify from loguru import logger from database import Database from treinamento import Treinamento import config app = Flask(__name__) OLLAMA_URL = "http://localhost:11434" db = Database() # INICIA TREINAMENTO treinamento = Treinamento(db) # USUÁRIOS PRIVILEGIADOS (VIP) USUARIOS_VIP = [ "244937123456", # Isaac "244999888777", # Outro admin ] def check_ollama(): try: return requests.get(f"{OLLAMA_URL}/api/tags", timeout=10).status_code == 200 except: return False def start_ollama(): subprocess.Popen(["ollama", "serve"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) def get_model(): return config.OLLAMA_MODEL # akira-luanda-v25 após fine-tune # === RAIZ === @app.route("/", methods=['GET']) def index(): return '''

AKIRA V25 — LUANDA KANDA BUÉ

qwen2.5:1.5b → akira-luanda-v25

POST /api/generate | /akira

''', 200 # === HEALTH === @app.route("/health", methods=['GET']) def health(): return jsonify({"status": "OK" if check_ollama() else "INICIANDO..."}), 200 # === ENDPOINT PRIVILEGIADO: /akira === @app.route("/akira", methods=['POST']) def akira_endpoint(): try: data = request.get_json() or {} usuario = data.get('usuario', 'anonimo') numero = data.get('numero', '') mensagem = data.get('mensagem', '').strip() mensagem_citada = data.get('mensagem_citada', '').strip() if numero not in USUARIOS_VIP: return jsonify({'error': 'Acesso negado. Só VIPs!'}), 403 if not mensagem and not mensagem_citada: return jsonify({'error': 'mensagem obrigatória'}), 400 logger.info(f"[VIP {usuario}] ({numero}): {mensagem[:60]}") # === HORA RÁPIDA === if any(k in mensagem.lower() for k in ["hora", "horas"]): agora = datetime.datetime.now() return jsonify({'resposta': f"São {agora.strftime('%H:%M')} em Luanda, puto."}) # === CONTEXTO === ctx = db.carregar_contexto(numero) tom = db.detectar_tom(numero, mensagem) girias = db.recuperar_girias_usuario(numero) or ["epá", "kandando", "bué", "kota"] abrevs = db.recuperar_abreviacoes_usuario(numero) or {"p'ra": "para", "pq": "porque", "tfx": "tudo fixe"} # === PROMPT DINÂMICO === now = datetime.datetime.now().strftime('%d/%m %H:%M') hist_text = '\n'.join([f"User: {h[0]}\nAkira: {h[1]}" for h in ctx["historico"]]) historico_block = f"{hist_text}\n" if hist_text else "" prompt = f"""[INST] <> {config.PERSONA} Gírias: {', '.join(girias)} Abreviações: {', '.join(abrevs.keys())} Tom: {tom} Data/hora: {now} <> {historico_block}""" if mensagem_citada: prompt += f"### Resposta ao reply ###\n{mensagem_citada}\n\n{mensagem}\n\n" else: prompt += f"### Mensagem ###\n{mensagem}\n\n" prompt += "[/INST] Akira:""" payload = { "model": get_model(), "prompt": prompt, "stream": False, "options": {"temperature": 0.9, "num_predict": 256} } resp = requests.post(f"{OLLAMA_URL}/api/generate", json=payload, timeout=120) resposta = resp.json().get("response", "").strip() # FILTRO FINAL if any(p in resposta.lower() for p in ["olá", "ajudar", "nome é", "posso"]): resposta = "Epá, kandando bué, kota! Tfx p'raí?" # === TREINAMENTO === try: treinamento.registrar_interacao( usuario=usuario, mensagem=mensagem, resposta=resposta, numero=numero, is_reply=bool(mensagem_citada), mensagem_original=mensagem_citada ) except Exception as e: logger.warning(f"Erro ao treinar: {e}") # SALVA db.salvar_mensagem(usuario, mensagem, resposta, numero) db.salvar_contexto(numero, ctx["historico"] + [[mensagem, resposta]], girias, tom) return jsonify({'resposta': resposta}) except Exception as e: logger.error(f"Erro no /akira: {e}") return jsonify({'resposta': 'Epá, deu merda!'}), 500 # === API PÚBLICA === @app.route("/api/generate", methods=['POST']) def generate(): if not check_ollama(): return jsonify({'resposta': 'Epá, tô acordando... espera 10s!'}), 503 data = request.get_json() or {} mensagem = data.get('mensagem', '').strip() usuario = data.get('usuario', 'anonimo') numero = data.get('numero', 'anonimo') if not mensagem: return jsonify({'error': 'mensagem obrigatória'}), 400 ctx = db.carregar_contexto(numero) tom = db.detectar_tom(numero, mensagem) girias = db.recuperar_girias_usuario(numero) or ["epá", "kandando", "bué", "kota"] abrevs = db.recuperar_abreviacoes_usuario(numero) or {"p'ra": "para", "pq": "porque", "tfx": "tudo fixe"} now = datetime.datetime.now().strftime('%d/%m %H:%M') hist_text = '\n'.join([f"User: {h[0]}\nAkira: {h[1]}" for h in ctx["historico"]]) historico_block = f"{hist_text}\n" if hist_text else "" prompt = f"""[INST] <> {config.PERSONA} Gírias: {', '.join(girias)} Abreviações: {', '.join(abrevs.keys())} Tom: {tom} Data/hora: {now} <> {historico_block}Mensagem: {mensagem} [/INST] Akira:""" payload = { "model": get_model(), "prompt": prompt, "stream": False, "options": {"temperature": 0.9} } try: resp = requests.post(f"{OLLAMA_URL}/api/generate", json=payload, timeout=90) resposta = resp.json().get("response", "").strip() or "Epá, kandando bué!" # TREINAMENTO PÚBLICO treinamento.registrar_interacao(usuario, mensagem, resposta, numero) db.salvar_mensagem(usuario, mensagem, resposta, numero) db.salvar_contexto(numero, ctx["historico"] + [[mensagem, resposta]], girias, tom) return jsonify({'resposta': resposta}) except Exception as e: logger.error(f"Erro: {e}") return jsonify({'resposta': 'Epá, tô off!'}), 500 if __name__ == "__main__": logger.info("AKIRA V25 — LUANDA KANDA BUÉ") start_ollama() for i in range(60): if check_ollama(): logger.info("Ollama pronto!") break time.sleep(2) app.run(host="0.0.0.0", port=7860)