akra35567 commited on
Commit
bc6d235
·
verified ·
1 Parent(s): 11ebde4

Upload 19 files

Browse files
.env ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # .env.example — Copie para .env e preencha suas chaves
2
+ # ============================================================================
3
+ # 🔥 CHAVES DE API — OBTENHA EM:
4
+ # ============================================================================
5
+
6
+ # MISTRAL (https://console.mistral.ai/)
7
+ # Limite: 60k tokens/mês grátis
8
+ MISTRAL_API_KEY=uuK8bVZ5BJQtcnhqQoimaNzWDr10WTu3
9
+
10
+ # GOOGLE GEMINI (https://aistudio.google.com/app/apikey)
11
+ # Limite: 1.5M tokens/mês grátis
12
+ GEMINI_API_KEY=AIzaSyBcX3wqmEDYTrggNNbv31-A2QG2A7IssRc
13
+
14
+ # GROQ (https://console.groq.com/keys)
15
+ # Limite: ~10k tokens/dia grátis
16
+ GROQ_API_KEY=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
17
+
18
+ # COHERE (https://dashboard.cohere.com/api-keys)
19
+ # Limite: 1k gerações/mês grátis
20
+ COHERE_API_KEY=sua_chave_aqui
21
+
22
+ # TOGETHER AI (https://api.together.xyz/settings/api-keys)
23
+ # Limite: $25 créditos iniciais grátis
24
+ TOGETHER_API_KEY=sua_chave_aqui
25
+
26
+ # HUGGING FACE (https://huggingface.co/settings/tokens)
27
+ # Limite: Ilimitado com rate limit
28
+ HF_API_KEY=hf_sua_chave_aqui
29
+
30
+ # ============================================================================
31
+ # 🌐 CONFIGURAÇÕES DE SERVIDOR (OPCIONAL)
32
+ # ============================================================================
33
+
34
+ API_HOST=0.0.0.0
35
+ API_PORT=7860
36
+
37
+ # ============================================================================
38
+ # 📝 NOTAS
39
+ # ============================================================================
40
+ #
41
+ # 1. Copie este arquivo: cp .env.example .env
42
+ # 2. Preencha PELO MENOS Mistral + Gemini (mínimo 2 APIs)
43
+ # 3. Adicione .env ao .gitignore (NUNCA commite chaves!)
44
+ # 4. Para Hugging Face Spaces: adicione chaves em Repository Secrets
45
+ #
RELATORIO_TECNICO_OTIMIZACAO.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Relatório Técnico: Otimização AKIRA AI para Hugging Face Spaces
2
+
3
+ Este documento descreve detalhadamente a transição técnica do sistema AKIRA de uma execução local pesada para uma arquitetura híbrida focada em Cloud, visando a estabilidade no plano Free do Hugging Face (HF).
4
+
5
+ ## 1. Contexto e Problema
6
+ O projeto AKIRA utilizava o `llama-cpp-python` para rodar modelos GGUF (como TinyLlama) localmente. No entanto:
7
+ - **Build Timeouts**: A compilação nativa do `llama.cpp` no Docker demorava mais de 30 minutos, excedendo os limites do HF Spaces.
8
+ - **Consumo de RAM**: Carregar um modelo na RAM (mesmo 1.1B) em conjunto com o `BART` (Emotion Analyzer) e `BERT` causava instabilidade no limite de 16GB.
9
+ - **Alucinações**: O modelo local excessivamente quantizado apresentava respostas inconsistentes.
10
+
11
+ ## 2. Solução Implementada: Arquitetura Cloud-First
12
+ A estratégia foi migrar o fallback de "Local Offline" para "Cloud API Fallback".
13
+
14
+ ### 2.1 Alterações no Dockerfile
15
+ - **Remoção de Compiladores**: Eliminamos `cmake`, `build-essential`, `libopenblas-dev`.
16
+ - **Simplificação do Pip**: Removida a flag `CMAKE_ARGS` e a biblioteca `llama-cpp-python`.
17
+ - **Resultado**: O build agora é instantâneo (apenas instala pacotes binários prontos).
18
+
19
+ ### 2.2 Reestruturação do `local_llm.py`
20
+ O módulo foi transformado num "Proxy de Emergência":
21
+ - **Variáveis Chave**:
22
+ - `_hf_client`: Instância do `InferenceClient` da Hugging Face.
23
+ - `_is_hf_inference_mode`: Flag que indica que o sistema está em modo Cloud.
24
+ - **Fluxo Lógico**:
25
+ 1. O sistema tenta as APIs principais (Groq, Google, etc.).
26
+ 2. Se falharem, o `local_llm.py` é acionado.
27
+ 3. Em vez de abrir um ficheiro `.gguf`, ele faz uma chamada rápida ao modelo `TinyLlama-1.1B-Chat-v1.0` através da API de Inferência Gratuita da Hugging Face.
28
+ 4. Isso garante **zero uso de RAM local** para o LLM e **zero uso de CPU** para inferência.
29
+
30
+ ### 2.3 Manutenção do Emotion Analyzer
31
+ Apesar da remoção do LLM local, mantivemos as dependências `torch` e `transformers` no `requirements.txt` a pedido do utilizador. Isso permite que o modulo de análise emocional (baseado em BART) continue funcionando localmente, já que é um modelo muito menor e crítico para a persona.
32
+
33
+ ## 3. Ferramentas Utilizadas
34
+ - **Hugging Face Inference API**: Para o fallback final sem custo de hardware.
35
+ - **Docker (Slim Python)**: Para manter a imagem leve.
36
+ - **Loguru**: Monitorização em tempo real de falhas nas APIs.
37
+
38
+ ## 4. Benefícios
39
+ - **Escalabilidade**: O bot pode crescer sem medo de exceder a RAM.
40
+ - **Velocidade**: Sem compilações pesadas no deploy.
41
+ - **Estabilidade**: Sem alucinações causadas por falta de recursos locais.
42
+
43
+ ---
44
+ **Assinado:** Antigravity AI Engineer | Google Deepmind Team
debug_mistral.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+
4
+ def debug_mistral_key():
5
+ print("--- Debug Detalhado Mistral Key ---")
6
+ # Tenta ler do environment primeiro
7
+ key = os.getenv("MISTRAL_API_KEY", "")
8
+
9
+ if not key:
10
+ # Tenta ler do .env manualmente para ver o que tem lá
11
+ env_path = Path(".env")
12
+ if env_path.exists():
13
+ with open(env_path, "r", encoding="utf-8") as f:
14
+ for line in f:
15
+ if line.strip().startswith("MISTRAL_API_KEY="):
16
+ key = line.strip().split("=", 1)[1]
17
+ print("Encontrada no .env via leitura manual.")
18
+ break
19
+
20
+ if not key:
21
+ print("❌ Chave não encontrada em lugar nenhum.")
22
+ return
23
+
24
+ print(f"Comprimento da chave: {len(key)}")
25
+ print(f"Primeiros 4 caracteres: {key[:4]}")
26
+ print(f"Últimos 4 caracteres: {key[-4:]}")
27
+
28
+ # Verifica caracteres invisíveis ou espaços
29
+ if key != key.strip():
30
+ print("⚠️ A chave tem espaços no início ou fim!")
31
+
32
+ import unicodedata
33
+ print(f"Representação da chave (primeiros 10): {[hex(ord(c)) for c in key[:10]]}")
34
+
35
+ # Limpeza da chave antes de usar
36
+ clean_key = key.strip().replace('"', '').replace("'", "")
37
+
38
+ # Teste de conexão simples com modelo ultra-básico
39
+ import requests
40
+ url = "https://api.mistral.ai/v1/models"
41
+ headers = {"Authorization": f"Bearer {clean_key}"}
42
+
43
+ try:
44
+ print("\nTestando listagem de modelos (Endpoint /v1/models)...")
45
+ res = requests.get(url, headers=headers, timeout=10)
46
+ print(f"Status: {res.status_code}")
47
+ if res.status_code == 200:
48
+ models = res.json().get('data', [])
49
+ print(f"✅ Sucesso! Modelos disponíveis: {[m['id'] for m in models[:5]]}")
50
+ else:
51
+ print(f"❌ Falha: {res.text}")
52
+ except Exception as e:
53
+ print(f"💥 Erro: {e}")
54
+
55
+ if __name__ == "__main__":
56
+ debug_mistral_key()
requirements.txt CHANGED
@@ -39,8 +39,8 @@ huggingface-hub>=0.23.0,<0.27.0
39
  # Transformers core (BERT, BART, etc.) - MANTIDO A PEDIDO DO UTILIZADOR
40
  transformers>=4.38.0,<4.50.0
41
 
42
- # 🦙 Llama.cpp Python - REMOVIDO POR INCOMPATIBILIDADE COM BUILD FREE TIER
43
- # llama-cpp-python>=0.2.56
44
 
45
  # PyTorch - versão estável e compatível - MANTIDO A PEDIDO
46
  torch>=2.1.0,<2.6.0
 
39
  # Transformers core (BERT, BART, etc.) - MANTIDO A PEDIDO DO UTILIZADOR
40
  transformers>=4.38.0,<4.50.0
41
 
42
+
43
+ llama-cpp-python>=0.2.56
44
 
45
  # PyTorch - versão estável e compatível - MANTIDO A PEDIDO
46
  torch>=2.1.0,<2.6.0
test_direct_mistral.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from dotenv import load_dotenv
4
+
5
+ # Configurações de saída
6
+ RESULT_FILE = "mistral_status.txt"
7
+
8
+ def test_direct_mistral():
9
+ print("Iniciando teste direto Mistral...")
10
+ with open(RESULT_FILE, "w", encoding="utf-8") as f:
11
+ f.write("=== STATUS MISTRAL DIRECT ===\n")
12
+
13
+ # 1. Carrega .env
14
+ load_dotenv()
15
+ key = os.getenv("MISTRAL_API_KEY")
16
+
17
+ if not key:
18
+ f.write("❌ MISTRAL_API_KEY não encontrada no .env\n")
19
+ return
20
+
21
+ f.write(f"🔑 Chave detectada: {key[:5]}...{key[-5:]}\n")
22
+
23
+ # 2. Faz requisição
24
+ url = "https://api.mistral.ai/v1/chat/completions"
25
+ headers = {
26
+ "Authorization": f"Bearer {key}",
27
+ "Content-Type": "application/json"
28
+ }
29
+ payload = {
30
+ "model": "mistral-small-latest",
31
+ "messages": [{"role": "user", "content": "Olá, você é a IA Akira? Responda em uma frase curta."}],
32
+ "max_tokens": 100
33
+ }
34
+
35
+ try:
36
+ response = requests.post(url, json=payload, headers=headers, timeout=15)
37
+ if response.status_code == 200:
38
+ data = response.json()
39
+ content = data['choices'][0]['message']['content']
40
+ f.write(f"✅ SUCESSO! Mistral respondeu.\n")
41
+ f.write(f"🤖 RESPOSTA: {content}\n")
42
+ else:
43
+ f.write(f"❌ ERRO API: Status {response.status_code}\n")
44
+ f.write(f"🔍 DETALHES: {response.text}\n")
45
+ except Exception as e:
46
+ f.write(f"❌ ERRO CONEXÃO: {str(e)}\n")
47
+
48
+ if __name__ == "__main__":
49
+ test_direct_mistral()
50
+ print("Teste finalizado.")
test_integration_mistral.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+
5
+ # Adiciona o diretório atual ao path para importar os módulos
6
+ sys.path.append(os.getcwd())
7
+
8
+ # Tenta carregar config e api
9
+ try:
10
+ from modules.config import load_dotenv, validate_config, logger
11
+ from modules.api import AkiraAPI
12
+ CONFIG_OK = True
13
+ except Exception as e:
14
+ CONFIG_OK = False
15
+ CONFIG_ERROR = str(e)
16
+
17
+ OUTPUT_FILE = "mistral_test_results.txt"
18
+
19
+ def run_test():
20
+ with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
21
+ f.write("=== LOG DE TESTE MISTRAL ===\n")
22
+
23
+ if not CONFIG_OK:
24
+ f.write(f"❌ Erro ao importar módulos: {CONFIG_ERROR}\n")
25
+ return
26
+
27
+ try:
28
+ # 1. Validar config
29
+ warnings = validate_config()
30
+ f.write(f"✅ Configuração validada. Avisos: {warnings}\n")
31
+
32
+ # 2. Inicializar API
33
+ api = AkiraAPI()
34
+ f.write(f"✅ Provedores ativos: {api.provedores_ativos}\n")
35
+
36
+ if 'mistral' not in api.provedores_ativos:
37
+ f.write("❌ Mistral não está entre os provedores ativos nos logs da API.\n")
38
+ # Tenta forçar via setup_mistral se necessário, mas AkiraAPI já deveria ter feito
39
+
40
+ # 3. Testar Resposta
41
+ prompt = "Responda apenas: 'IA_MISTRAL_ONLINE'. Não diga mais nada."
42
+ f.write(f"🚀 Enviando prompt: {prompt}\n")
43
+
44
+ response_data = api.processar_requisicao(prompt, usuario_id="tester_888")
45
+
46
+ resposta = response_data.get("resposta", "")
47
+ provedor = response_data.get("provedor", "desconhecido")
48
+
49
+ f.write(f"✅ Resposta recebida do provedor: {provedor}\n")
50
+ f.write(f"🤖 RESPOSTA: {resposta}\n")
51
+
52
+ if "IA_MISTRAL_ONLINE" in resposta:
53
+ f.write("\n✨ CONCLUSÃO: MISTRAL ESTÁ FUNCIONANDO PERFEITAMENTE!")
54
+ else:
55
+ f.write("\n⚠️ Resposta recebida, mas não contém a senha esperada. Verifique os logs.")
56
+
57
+ except Exception as e:
58
+ f.write(f"❌ Erro crítico no teste: {str(e)}\n")
59
+ import traceback
60
+ f.write(traceback.format_exc())
61
+
62
+ if __name__ == "__main__":
63
+ run_test()
64
+ print(f"Teste concluído. Resultado em {OUTPUT_FILE}")
test_keys.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ # Tentativa 1: python-dotenv
7
+ try:
8
+ from dotenv import load_dotenv
9
+ loaded = load_dotenv()
10
+ print(f"INFO: python-dotenv carregou .env? {'Sim' if loaded else 'Não (arquivo não encontrado ou erro)'}")
11
+ except ImportError:
12
+ print("INFO: python-dotenv não instalado. Vou tentar ler .env manualmente.")
13
+
14
+ # Tentativa 2: Carregamento Manual (Fallback)
15
+ def manual_load_env():
16
+ env_path = Path(".env")
17
+ if env_path.exists():
18
+ print(f"INFO: Carregando {env_path.absolute()} manualmente...")
19
+ with open(env_path, "r", encoding="utf-8") as f:
20
+ for line in f:
21
+ line = line.strip()
22
+ if line and not line.startswith("#") and "=" in line:
23
+ key, value = line.split("=", 1)
24
+ os.environ[key.strip()] = value.strip()
25
+ return True
26
+ return False
27
+
28
+ if not os.getenv("MISTRAL_API_KEY"):
29
+ manual_load_env()
30
+
31
+ print(f"CWD: {os.getcwd()}")
32
+ print(f"Arquivos no CWD: {os.listdir('.')}")
33
+
34
+ def test_mistral():
35
+ print("\n--- Testando Mistral ---")
36
+ key = os.getenv("MISTRAL_API_KEY", "").strip()
37
+ if not key:
38
+ print("❌ MISTRAL_API_KEY não encontrada no ambiente.")
39
+ return
40
+
41
+ if (key.startswith('"') and key.endswith('"')) or (key.startswith("'") and key.endswith("'")):
42
+ key = key[1:-1]
43
+
44
+ print(f"Chave encontrada (prefixo): {key[:6]}...")
45
+
46
+ url = "https://api.mistral.ai/v1/chat/completions"
47
+ headers = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}
48
+ payload = {
49
+ "model": "mistral-large-latest",
50
+ "messages": [{"role": "user", "content": "Oi"}],
51
+ "max_tokens": 10
52
+ }
53
+
54
+ try:
55
+ response = requests.post(url, headers=headers, json=payload, timeout=10)
56
+ if response.status_code == 200:
57
+ print("✅ Mistral OK!")
58
+ else:
59
+ print(f"❌ Mistral erro {response.status_code}: {response.text}")
60
+ except Exception as e:
61
+ print(f"💥 Erro na requisição Mistral: {e}")
62
+
63
+ def test_gemini():
64
+ print("\n--- Testando Gemini ---")
65
+ key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY", "").strip()
66
+ if not key:
67
+ print("❌ Chave Gemini/Google não encontrada.")
68
+ return
69
+
70
+ print(f"Chave encontrada (prefixo): {key[:6]}...")
71
+
72
+ # Teste via endpoint v1 estável
73
+ url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.0-flash:generateContent?key={key}"
74
+ payload = {"contents": [{"parts":[{"text": "Oi"}]}]}
75
+
76
+ try:
77
+ response = requests.post(url, json=payload, timeout=10)
78
+ if response.status_code == 200:
79
+ print("✅ Gemini OK!")
80
+ else:
81
+ print(f"❌ Gemini erro {response.status_code}: {response.text}")
82
+ except Exception as e:
83
+ print(f"💥 Erro na requisição Gemini: {e}")
84
+
85
+ def test_groq():
86
+ print("\n--- Testando Groq ---")
87
+ key = os.getenv("GROQ_API_KEY", "").strip()
88
+ if not key:
89
+ print("❌ GROQ_API_KEY não encontrada.")
90
+ return
91
+
92
+ url = "https://api.groq.com/openai/v1/chat/completions"
93
+ headers = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}
94
+ payload = {
95
+ "model": "llama-3.3-70b-versatile",
96
+ "messages": [{"role": "user", "content": "Oi"}],
97
+ "max_tokens": 10
98
+ }
99
+
100
+ try:
101
+ response = requests.post(url, headers=headers, json=payload, timeout=10)
102
+ if response.status_code == 200:
103
+ print("✅ Groq OK!")
104
+ else:
105
+ print(f"❌ Groq erro {response.status_code}: {response.text}")
106
+ except Exception as e:
107
+ print(f"💥 Erro na requisição Groq: {e}")
108
+
109
+ if __name__ == "__main__":
110
+ print(f"Python: {sys.version}")
111
+ test_mistral()
112
+ test_gemini()
113
+ test_groq()
test_mistral.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from dotenv import load_dotenv
4
+
5
+ def test_mistral():
6
+ print("--- Teste de Ambiente AKIRA ---")
7
+
8
+ # 1. Testar carregamento do .env
9
+ dotenv_path = os.path.join(os.getcwd(), ".env")
10
+ if os.path.exists(dotenv_path):
11
+ load_dotenv(dotenv_path)
12
+ print(f"✅ Arquivo .env encontrado em: {dotenv_path}")
13
+ else:
14
+ print("❌ Arquivo .env NÃO encontrado no diretório atual.")
15
+ return
16
+
17
+ mistral_key = os.getenv("MISTRAL_API_KEY")
18
+ if not mistral_key or mistral_key == "sua_chave_aqui":
19
+ print("❌ MISTRAL_API_KEY não configurada corretamente no .env")
20
+ return
21
+ else:
22
+ print(f"✅ MISTRAL_API_KEY carregada (Início: {mistral_key[:5]}...)")
23
+
24
+ # 2. Testar chamada real para a Mistral
25
+ print("\n--- Testando API Mistral ---")
26
+ url = "https://api.mistral.ai/v1/chat/completions"
27
+ headers = {
28
+ "Content-Type": "application/json",
29
+ "Authorization": f"Bearer {mistral_key}"
30
+ }
31
+ data = {
32
+ "model": "mistral-tiny",
33
+ "messages": [{"role": "user", "content": "Oi, você está funcionando? Responda curto."}],
34
+ "max_tokens": 50
35
+ }
36
+
37
+ try:
38
+ response = requests.post(url, headers=headers, json=data, timeout=10)
39
+ if response.status_code == 200:
40
+ result = response.json()
41
+ message = result['choices'][0]['message']['content']
42
+ print(f"✅ API Mistral respondendo com sucesso!")
43
+ print(f"💬 Resposta: {message}")
44
+ else:
45
+ print(f"❌ Erro na API Mistral: Status {response.status_code}")
46
+ print(f"🔍 Detalhes: {response.text}")
47
+ except Exception as e:
48
+ print(f"❌ Erro ao conectar com API Mistral: {e}")
49
+
50
+ if __name__ == "__main__":
51
+ test_mistral()