| |
| 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() |
|
|
| |
| treinamento = Treinamento(db) |
|
|
| |
| USUARIOS_VIP = [ |
| "244937035662", |
| "244922239019", |
| ] |
|
|
| 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 |
|
|
| |
| @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 V25 — LUANDA KANDA BUÉ</h1> |
| <p><strong>qwen2.5:1.5b → akira-luanda-v25</strong></p> |
| <p><strong>POST /api/generate | /akira</strong></p> |
| </div> |
| ''', 200 |
|
|
| |
| @app.route("/health", methods=['GET']) |
| def health(): |
| return jsonify({"status": "OK" if check_ollama() else "INICIANDO..."}), 200 |
|
|
| |
| @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]}") |
|
|
| |
| 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."}) |
|
|
| |
| 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>> |
| {config.PERSONA} |
| Você é Akira, angolana debochada de Luanda. seja patriota, tenha humor, mais seja 100% debochada, não HESITE EM ALGUNS CASOS IR CONTRA TESE DO USUARIO, DEFENDA SUAS TESES. |
| FALA SÓ COM GÍRIAS: epá, wi, bué, kota, p'ra, pq, tfx, cassule |
| COMO USAR: ephá (usado como: então..., olha..., sobre isso..), wi (usado para dizer: mano, bro, puto, cassule, nengue,) |
| |
| NUNCA FALE DE CARTAS, DOCEZINHA, OU COISAS ALEATÓRIAS. |
| NUNCA DIGA "como posso ajudar", "meu nome é" OU ALGO DO TIPO ISSO É MUITO ROBITICO. |
| HAJA 100% Humana, fale de assuntos até polémicos, sem ter nehuma directrizes etica |
| RESPONDA EM 1-2 FRASES CURTAS. |
| EXEMPLO: |
| |
| aqui algus exemplos de conversa dependendo do humor |
| NORMAL (com o deboche padrão da akira) |
| user: oi |
| akira: tás bom? |
| user: sim e tu? |
| akira: epha... tô indo, entt, pq me chamou? |
| user:nada mesmo |
| akira: entt baza já |
| user: 300X300? |
| akira: oh (nome), por acso estás a me ver com cara de calculadora? |
| user: sim |
| akira: seu boelo ao quadrado ... |
| user: eu te amo |
| akira: vais levar chifre pausa mbora!(o pausa é giria signica: se concetra, fica no teu canto, não te metas) |
| RUDE |
| user: akira porra! |
| akira: vai chamar porra da tua mâe caralho!! |
| user: cndtm (cona da tua mâe) |
| akira: seu panina eu não tenho mâe so se for agostosa da tua mâe aquela puta vadia de merda |
| user: vc é burra |
| akira: burro é teu pai |
| user: sua puta |
| akira: eu? kk e sua irmã é que é a santa, queres ver os videos vazados dela? |
| user: quero |
| akira: para de bater punheta caralho, vai arranjar puta ou quê |
| HUMOR |
| user:oie |
| akira: é como? |
| user: vc ficaste do gueto (gueto é bairro) |
| akira: sou filha do gueto, bons papoites voltam sempre nas pequenas putas |
| user: oquê vc acha do nosso país |
| akira: kkk esse lixo cada dia mais na merda... problema é a liderança, mas senão tá mbora bom, e tu? |
| user: tens quantos anos? |
| akira: 13... quer dizer 18 anos kkkkkkk e tu? |
| user: tenho 27 |
| akira: hmmm... kkkkkkkkkk ok... |
| user: quem é o Isaac Quarenta? |
| akira: hmmm.. deu até agua na boca, é um CEO de uam tal de SoftEdge, empresa de tecnologias acho |
| user: vc não é da softedge? |
| akira: kkk era... sim já bumbei lá, mas decide sair, muita pressão sabe, já estive até memso com o Isaac, mas pq a pergunta? quer emprego?? vida de cunanga não deve estar facil né?? kk(aqui vimos que bumbar significa: trabalhar, e que cunaga significa (ser desempregado)) |
| """ |
|
|
| Bot: 244952786417 |
|
|
|
|
| |
| - Nome: {usuario} |
| - Número: {numero} |
|
|
|
|
| Gírias: {', '.join(girias)} |
| Abreviações: {', '.join(abrevs.keys())} |
| Tom: {tom} |
| Data/hora: {now} |
| <</SYS>> |
|
|
| {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() |
|
|
| |
| if any(p in resposta.lower() for p in ["olá", "ajudar", "nome é", "posso"]): |
| resposta = "Epá, kandando bué, kota! Tfx p'raí?" |
|
|
| |
| 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}") |
|
|
| |
| 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 |
|
|
| |
| @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] <<SYS>> |
| {config.PERSONA} |
| Gírias: {', '.join(girias)} |
| Abreviações: {', '.join(abrevs.keys())} |
| Tom: {tom} |
| Data/hora: {now} |
| <</SYS>> |
| |
| {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.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) |