jade_port / jade /core.py
Madras1's picture
Upload 13 files
831e835 verified
raw
history blame
6.15 kB
import json
import logging
import os
import sys
import time
import uuid
from groq import Groq
# Importa nossos módulos customizados
from .handlers import ImageHandler
from .tts import TTSPlayer
from .utils import slim_history
from .shorestone import ShoreStoneMemory
from .curator_heuristic import MemoryCuratorHeuristic
# Configura o logger principal
logging.basicConfig(level=logging.INFO, format="%(asctime)s - JADE - %(levelname)s - %(message)s")
class JadeAgent:
def __init__(self, config_path="jade/config.json"):
# Carrega configurações
# Try to load from absolute path first, then relative
try:
with open(config_path) as f:
self.cfg = json.load(f)
except FileNotFoundError:
# Fallback: try to find it relative to this file
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(base_dir, "config.json")
with open(config_path) as f:
self.cfg = json.load(f)
# --- Configuração da API Groq ---
logging.info("Iniciando J.A.D.E. em modo API (Groq)...")
self.api_key = self._get_api_key()
self.client = Groq(api_key=self.api_key)
self.model_name = self.cfg.get("groq_model", "meta-llama/llama-4-maverick-17b-128e-instruct")
# System Prompt Base
self.system_prompt = {"role": "system", "content": "Você é J.A.D.E., uma IA multimodal calma e inteligente. Seja direta. Responda de forma concisa e natural. NÃO explique seu processo de pensamento. Apenas responda à pergunta."}
# --- Inicialização dos Módulos ---
logging.info("Carregando módulos de percepção e memória...")
# Visão e Fala
self.image_handler = ImageHandler(self.cfg.get("caption_model", "Salesforce/blip-image-captioning-large"))
self.tts = TTSPlayer(lang=self.cfg.get("language", "pt"))
# 1. Memória ShoreStone (Persistente)
self.memory = ShoreStoneMemory()
# Inicializa com sessão padrão, mas será trocada dinamicamente no respond()
self.memory.load_or_create_session("sessao_padrao_gabriel")
# 2. Curador Heurístico (Manutenção Automática)
self.curator = MemoryCuratorHeuristic(shorestone_memory=self.memory)
self.response_count = 0
self.maintenance_interval = 10 # Executar a manutenção a cada 10 interações
logging.info(f"J.A.D.E. pronta e conectada ao modelo {self.model_name}.")
def _get_api_key(self):
"""Recupera a chave da API do ambiente de forma segura."""
key = os.getenv("GROQ_API_KEY")
if not key:
logging.error("Chave GROQ_API_KEY não encontrada nas variáveis de ambiente.")
# For development, try to warn but not crash if possible, but Groq needs it.
# raise RuntimeError("❌ GROQ_API_KEY não encontrada. Defina a variável de ambiente.")
print("WARNING: GROQ_API_KEY not found.")
return key
def _chat(self, messages):
"""Envia as mensagens para a Groq e retorna a resposta."""
try:
chat = self.client.chat.completions.create(
messages=messages,
model=self.model_name,
temperature=0.7, # Criatividade balanceada
max_tokens=1024 # Limite de resposta razoável
)
return chat.choices[0].message.content.strip()
except Exception as e:
logging.error(f"Erro na comunicação com a Groq: {e}")
return "Desculpe, tive um problema ao me conectar com meu cérebro na nuvem."
def respond(self, history, user_input, user_id="default", vision_context=None):
"""Processo principal de raciocínio: Lembrar -> Ver -> Responder -> Memorizar -> Manter."""
# TROCA A SESSÃO DA MEMÓRIA PARA O USUÁRIO ATUAL
session_name = f"user_{user_id}"
self.memory.load_or_create_session(session_name)
messages = history[:]
# 1. Lembrar (Recuperação de Contexto)
memories = self.memory.remember(user_input)
if memories:
memory_context = f"--- MEMÓRIAS RELEVANTES (ShoreStone) ---\n{memories}\n--- FIM DAS MEMÓRIAS ---"
# Inserimos as memórias como contexto de sistema para guiar a resposta
messages.append({"role": "system", "content": memory_context})
# 2. Ver (Contexto Visual)
if vision_context:
messages.append({"role": "system", "content": f"Contexto visual da imagem que o usuário enviou: {vision_context}"})
# Adiciona a pergunta atual ao histórico temporário e ao prompt
history.append({"role": "user", "content": user_input})
messages.append({"role": "user", "content": user_input})
# 3. Responder (Geração)
resposta = self._chat(messages)
# Atualiza histórico
history.append({"role": "assistant", "content": resposta})
history = slim_history(history, keep=self.cfg.get("max_context", 12))
# 4. Memorizar (Armazenamento Persistente)
self.memory.memorize(user_input, resposta)
print(f"\n🤖 J.A.D.E.: {resposta}")
# Falar (TTS) - Modified for Backend compatibility
audio_path = None
try:
# Uses the TTSPlayer from tts.py which has save_audio_to_file
audio_path = self.tts.save_audio_to_file(resposta)
except Exception as e:
logging.warning(f"TTS falhou (silenciado): {e}")
# 5. Manter (Ciclo de Curadoria Automática)
self.response_count += 1
if self.response_count % self.maintenance_interval == 0:
logging.info(f"Ciclo de manutenção agendado (interação {self.response_count}). Verificando saúde da memória...")
try:
self.curator.run_maintenance_cycle()
except Exception as e:
logging.error(f"Erro no Curador de Memória: {e}")
return resposta, audio_path, history