# app.py — V28 — OLLAMA COM WATCHDOG + MODELO LEVE + FINE-TUNE SEGURO import subprocess import time import requests import json import datetime import threading from flask import Flask, request, jsonify from loguru import logger from database import Database from treinamento import Treinamento app = Flask(__name__) OLLAMA_URL = "http://localhost:11434" db = Database() treinamento = Treinamento(db) # WATCHDOG — REINICIA OLLAMA SE MORRER ollama_process = None def start_ollama(): global ollama_process if ollama_process is None or ollama_process.poll() is not None: logger.warning("Ollama morreu! Reiniciando...") ollama_process = subprocess.Popen(["ollama", "serve"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) def check_ollama(): try: resp = requests.get(f"{OLLAMA_URL}/api/tags", timeout=5) return resp.status_code == 200 except: start_ollama() # REINICIA AUTOMÁTICO return False # THREAD PARA MONITORAR OLLAMA def watchdog(): while True: time.sleep(10) check_ollama() threading.Thread(target=watchdog, daemon=True).start() # === RAIZ === @app.route("/", methods=['GET']) def index(): return '''

AKIRA V28 — OLLAMA INDESTRUTÍVEL

qwen2.5:0.5b → akira-luanda-v28

POST /api/generate

''', 200 @app.route("/health", methods=['GET']) def health(): return jsonify({"status": "OK" if check_ollama() else "RECUPERANDO..."}), 200 @app.route("/api/generate", methods=['POST']) def generate(): start_ollama() # Garante que tá vivo 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 # === 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 FORÇADO === 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] <> Você é Akira, angolana debochada. FALA SÓ COM GÍRIAS: epá, kandando, bué, kota, p'ra, pq, tfx. NUNCA DIGA "olá", "ajudar", "posso". FALA CURTO: 1-2 FRASES. <> {historico_block}Mensagem: {mensagem} [/INST] Akira:""" payload = { "model": "qwen2.5:0.5b-instruct-q4_0", "prompt": prompt, "stream": False, "options": {"temperature": 0.9, "num_predict": 200} } try: resp = requests.post(f"{OLLAMA_URL}/api/generate", json=payload, timeout=60) resposta = resp.json().get("response", "").strip() or "Epá, kandando bué!" # FILTRO FINAL if any(p in resposta.lower() for p in ["olá", "ajudar", "posso", "nome é"]): resposta = "Epá, kandando bué, kota! Tfx p'raí?" # SALVA + TREINA db.salvar_mensagem(usuario, mensagem, resposta, numero) db.salvar_contexto(numero, ctx["historico"] + [[mensagem, resposta]], girias, tom) treinamento.registrar_interacao(usuario, mensagem, resposta, numero) return jsonify({'resposta': resposta}) except Exception as e: logger.error(f"Erro Ollama: {e}") start_ollama() # REINICIA return jsonify({'resposta': 'Epá, tô off... tenta de novo!'}), 500 if __name__ == "__main__": logger.info("AKIRA V28 — OLLAMA INDESTRUTÍVEL") start_ollama() app.run(host="0.0.0.0", port=7860)