| |
| 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) |
|
|
| |
| 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() |
| return False |
|
|
| |
| def watchdog(): |
| while True: |
| time.sleep(10) |
| check_ollama() |
|
|
| threading.Thread(target=watchdog, daemon=True).start() |
|
|
| |
| @app.route("/", methods=['GET']) |
| def index(): |
| return ''' |
| <div style="font-family: monospace; text-align: center; margin: 50px; background: #000; color: #0f0; padding: 40px;"> |
| <h1>AKIRA V28 — OLLAMA INDESTRUTÍVEL</h1> |
| <p><strong>qwen2.5:0.5b → akira-luanda-v28</strong></p> |
| <p><strong>POST /api/generate</strong></p> |
| </div> |
| ''', 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() |
|
|
| 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] <<SYS>> |
| 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. |
| <</SYS>> |
| |
| {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é!" |
|
|
| |
| if any(p in resposta.lower() for p in ["olá", "ajudar", "posso", "nome é"]): |
| resposta = "Epá, kandando bué, kota! Tfx p'raí?" |
|
|
| |
| 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() |
| 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) |