akira / modules /cellcog_integration.py
akra35567's picture
Upload 37 files
4f90e1d verified
"""
================================================================================
CELLCOG INTEGRATION - MULTI-MODAL AI CAPABILITIES
================================================================================
Integração com CellCog para geração de imagens, vídeos, áudio, pesquisa, análise.
TIER 1: Primário — Usa CellCog API (se disponível)
TIER 2: Fallback — Usa Pollinations Flux (se CellCog falhar)
================================================================================
"""
import os
import json
import base64
import requests
from typing import Dict, Any, Optional, List
from loguru import logger
class CellCogClient:
"""
Cliente para integração com CellCog.
Suporta: Image, Video, Audio, Research, Data Analysis, e mais.
"""
def __init__(self, api_key: Optional[str] = None):
"""
Inicializa cliente CellCog.
Args:
api_key: Chave da API CellCog (obtém de env se não fornecido)
"""
self.api_key = api_key or os.getenv("CELLCOG_API_KEY")
self.base_url = os.getenv("CELLCOG_BASE_URL", "https://api.cellcog.ai/v1")
self.available = bool(self.api_key)
if self.available:
logger.success("✅ CellCog integrado com sucesso")
else:
logger.warning("⚠️ CellCog não configurado - usando fallbacks")
def generate_image(
self,
prompt: str,
model: str = "image",
aspect_ratio: str = "1:1",
quality: str = "high"
) -> Dict[str, Any]:
"""
Gera imagem via CellCog Image Cog.
Args:
prompt: Descrição da imagem
model: Tipo de geração (image, anime, photo, 3d, etc.)
aspect_ratio: Proporção (1:1, 16:9, 9:16, 4:3, etc.)
quality: Qualidade (low, medium, high, ultra)
Returns:
Dict com imagem gerada ou erro
"""
if not self.available:
logger.warning("⚠️ CellCog não configurado, pulando para Flux...")
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"🖼️ [CellCog] Gerando imagem: '{prompt[:50]}...'")
payload = {
"prompt": prompt,
"model": model,
"aspect_ratio": aspect_ratio,
"quality": quality,
"format": "url" # Retorna URL ao invés de base64
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/image",
json=payload,
headers=headers,
timeout=60
)
if response.status_code == 200:
result = response.json()
image_url = result.get("url")
if image_url:
# Download da imagem para retornar como buffer
try:
img_response = requests.get(image_url, timeout=30)
if img_response.status_code == 200 and len(img_response.content) > 1000:
logger.success(f"✅ [CellCog] Imagem gerada e baixada com sucesso")
return {
"success": True,
"image_data": base64.b64encode(img_response.content).decode('utf-8'),
"mime_type": "image/png",
"model": "cellcog",
"prompt": prompt
}
except Exception as dl_err:
logger.warning(f"⚠️ [CellCog] Falha ao baixar imagem: {dl_err}")
return {"success": False, "error": f"Falha ao baixar: {str(dl_err)}"}
return {"success": False, "error": "URL de imagem não retornada"}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}: {response.text[:200]}")
return {"success": False, "error": f"Status {response.status_code}"}
except requests.exceptions.Timeout:
logger.error(f"❌ [CellCog] Timeout na requisição")
return {"success": False, "error": "Timeout - CellCog lento"}
except requests.exceptions.ConnectionError as e:
logger.error(f"❌ [CellCog] Erro de conexão: {str(e)[:100]}")
return {"success": False, "error": "Erro de conexão - CellCog indisponível"}
except Exception as e:
logger.error(f"❌ [CellCog Image] Erro: {str(e)[:150]}")
return {"success": False, "error": str(e)[:100]}
def generate_video(
self,
prompt: str,
duration: int = 10,
resolution: str = "1080p"
) -> Dict[str, Any]:
"""
Gera vídeo via CellCog Video Cog.
Args:
prompt: Descrição do vídeo
duration: Duração em segundos (5-240)
resolution: Resolução (720p, 1080p, 4k)
Returns:
Dict com vídeo gerado ou erro
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"🎬 [CellCog] Gerando vídeo: '{prompt[:50]}...' ({duration}s)")
payload = {
"prompt": prompt,
"duration": min(duration, 240), # Máximo 4 minutos
"resolution": resolution,
"format": "url"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/video",
json=payload,
headers=headers,
timeout=120 # Videos levam mais tempo
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Vídeo gerado com sucesso")
return {
"success": True,
"video_url": result.get("url"),
"model": "cellcog",
"prompt": prompt,
"duration": duration
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}: {response.text}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Video] Erro: {e}")
return {"success": False, "error": str(e)}
def generate_audio(
self,
text: str,
voice: str = "default",
language: str = "pt-PT"
) -> Dict[str, Any]:
"""
Gera áudio/TTS via CellCog Audio Cog.
Args:
text: Texto a converter
voice: Voz a usar
language: Idioma (pt-PT, pt-BR, en-US, etc.)
Returns:
Dict com áudio gerado ou erro
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"🎙️ [CellCog] Gerando áudio ({language}): '{text[:40]}...'")
payload = {
"text": text,
"voice": voice,
"language": language,
"format": "mp3"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/audio",
json=payload,
headers=headers,
timeout=60
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Áudio gerado com sucesso")
return {
"success": True,
"audio_url": result.get("url"),
"model": "cellcog",
"duration": result.get("duration"),
"language": language
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Audio] Erro: {e}")
return {"success": False, "error": str(e)}
def research(
self,
query: str,
depth: str = "medium"
) -> Dict[str, Any]:
"""
Realiza pesquisa profunda via CellCog Research Cog.
Args:
query: Pergunta ou tópico
depth: Profundidade (quick, medium, thorough)
Returns:
Dict com resultados da pesquisa
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"🔬 [CellCog] Pesquisando: '{query}'")
payload = {
"query": query,
"depth": depth,
"sources": 10,
"format": "json"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/research",
json=payload,
headers=headers,
timeout=90
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Pesquisa concluída")
return {
"success": True,
"findings": result.get("findings"),
"sources": result.get("sources", []),
"model": "cellcog"
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Research] Erro: {e}")
return {"success": False, "error": str(e)}
def analyze_data(
self,
csv_data: str,
analysis_type: str = "exploratory"
) -> Dict[str, Any]:
"""
Analisa dados via CellCog Data Cog.
Args:
csv_data: Dados em formato CSV
analysis_type: Tipo (exploratory, statistical, predictive)
Returns:
Dict com análise
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"📊 [CellCog] Analisando dados ({analysis_type})")
payload = {
"data": csv_data,
"analysis_type": analysis_type,
"format": "json"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/analyze",
json=payload,
headers=headers,
timeout=90
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Análise concluída")
return {
"success": True,
"analysis": result.get("analysis"),
"insights": result.get("insights", []),
"model": "cellcog"
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Data] Erro: {e}")
return {"success": False, "error": str(e)}
def think_brainstorm(
self,
prompt: str,
depth: str = "medium"
) -> Dict[str, Any]:
"""
Raciocínio avançado e brainstorming via CellCog Think Cog.
Args:
prompt: Pergunta ou problema a resolver
depth: Profundidade (quick, medium, thorough)
Returns:
Dict com ideias e soluções
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"💭 [CellCog] Brainstorming: '{prompt[:50]}...'")
payload = {
"prompt": prompt,
"depth": depth,
"format": "json"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/think",
json=payload,
headers=headers,
timeout=90
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Raciocínio concluído")
return {
"success": True,
"ideas": result.get("ideas", []),
"reasoning": result.get("reasoning", ""),
"solutions": result.get("solutions", []),
"model": "cellcog"
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Think] Erro: {e}")
return {"success": False, "error": str(e)}
def generate_document(
self,
content: str,
doc_type: str = "report",
format: str = "pdf"
) -> Dict[str, Any]:
"""
Gera documentos (PDF/DOCX) via CellCog Docs Cog.
Args:
content: Conteúdo do documento
doc_type: Tipo (report, contract, invoice, resume, letter)
format: Formato (pdf, docx)
Returns:
Dict com documento gerado
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"📄 [CellCog] Gerando documento ({doc_type})...")
payload = {
"content": content,
"doc_type": doc_type,
"format": format
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/document",
json=payload,
headers=headers,
timeout=120
)
if response.status_code == 200:
result = response.json()
doc_url = result.get("url")
if doc_url:
# Download do documento
try:
doc_response = requests.get(doc_url, timeout=30)
if doc_response.status_code == 200:
logger.success(f"✅ [CellCog] Documento gerado e baixado")
return {
"success": True,
"buffer": doc_response.content,
"mime_type": f"application/{format}" if format == "pdf" else "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"filename": result.get("filename", f"documento.{format}"),
"model": "cellcog"
}
except Exception as dl_err:
logger.warning(f"⚠️ [CellCog] Falha ao baixar documento: {dl_err}")
return {"success": False, "error": "URL de documento não retornada"}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Document] Erro: {e}")
return {"success": False, "error": str(e)}
def generate_presentation(
self,
title: str,
content: str,
slides: int = 10,
style: str = "professional"
) -> Dict[str, Any]:
"""
Gera apresentações (PPTX) via CellCog Slides Cog.
Args:
title: Título da apresentação
content: Conteúdo/tópicos
slides: Número de slides
style: Estilo (professional, creative, minimal)
Returns:
Dict com apresentação gerada
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"📊 [CellCog] Gerando apresentação: '{title[:40]}...'")
payload = {
"title": title,
"content": content,
"num_slides": slides,
"style": style,
"format": "pptx"
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/presentation",
json=payload,
headers=headers,
timeout=120
)
if response.status_code == 200:
result = response.json()
pptx_url = result.get("url")
if pptx_url:
# Download da apresentação
try:
pptx_response = requests.get(pptx_url, timeout=30)
if pptx_response.status_code == 200:
logger.success(f"✅ [CellCog] Apresentação gerada e baixada")
return {
"success": True,
"buffer": pptx_response.content,
"mime_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"filename": f"{title}.pptx",
"num_slides": slides,
"model": "cellcog"
}
except Exception as dl_err:
logger.warning(f"⚠️ [CellCog] Falha ao baixar apresentação: {dl_err}")
return {"success": False, "error": "URL de apresentação não retornada"}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Presentation] Erro: {e}")
return {"success": False, "error": str(e)}
def generate_brand_identity(
self,
brand_name: str,
description: str,
industry: str = "general"
) -> Dict[str, Any]:
"""
Gera identidade de marca completa via CellCog Brand Cog.
Args:
brand_name: Nome da marca
description: Descrição da marca
industry: Indústria/setor
Returns:
Dict com identidade de marca (logo, cores, guidelines)
"""
if not self.available:
return {"success": False, "error": "CellCog não disponível"}
try:
logger.info(f"🎨 [CellCog] Gerando branding para '{brand_name}'...")
payload = {
"brand_name": brand_name,
"description": description,
"industry": industry
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
response = requests.post(
f"{self.base_url}/brand",
json=payload,
headers=headers,
timeout=120
)
if response.status_code == 200:
result = response.json()
logger.success(f"✅ [CellCog] Identidade de marca gerada")
# Tentar baixar logo se disponível
logo_url = result.get("logo_url")
logo_buffer = None
if logo_url:
try:
logo_response = requests.get(logo_url, timeout=30)
if logo_response.status_code == 200:
logo_buffer = logo_response.content
except:
pass
return {
"success": True,
"brand_name": brand_name,
"logo_buffer": logo_buffer,
"colors": result.get("color_palette", []),
"typography": result.get("typography", {}),
"guidelines": result.get("guidelines", ""),
"style": result.get("style", ""),
"model": "cellcog"
}
else:
logger.error(f"❌ [CellCog] Status {response.status_code}")
return {"success": False, "error": f"Status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [CellCog Brand] Erro: {e}")
return {"success": False, "error": str(e)}
# ============================================================================
# FALLBACK: Pollinations Flux (quando CellCog não está disponível)
# ============================================================================
class PollinationsFluxFallback:
"""
Fallback para geração de imagens usando Pollinations Flux.
"""
BASE_URL = "https://image.pollinations.ai/prompt"
@staticmethod
def generate(
prompt: str,
aspect_ratio: str = "1:1",
model: str = "flux"
) -> Dict[str, Any]:
"""
Gera imagem via Pollinations Flux como fallback (baixa e retorna como buffer).
"""
try:
logger.info(f"🔄 [Flux Fallback] Gerando imagem: '{prompt[:50]}...'")
# Converte aspect_ratio para width/height
ratio_map = {
"1:1": (1024, 1024),
"16:9": (1344, 756),
"9:16": (756, 1344),
"4:3": (1024, 768),
"3:4": (768, 1024)
}
width, height = ratio_map.get(aspect_ratio, (1024, 1024))
# Monta URL com parâmetros
import urllib.parse
encoded_prompt = urllib.parse.quote(prompt)
url = f"{PollinationsFluxFallback.BASE_URL}/{encoded_prompt}"
params = {
"width": width,
"height": height,
"model": model,
"nologo": "true"
}
# Monta URL completa
image_url = f"{url}?{'&'.join(f'{k}={v}' for k, v in params.items())}"
# Retry logic para Flux
max_retries = 2
for attempt in range(max_retries):
try:
# Baixa a imagem
response = requests.get(image_url, timeout=60) # Aumentado para 60s
if response.status_code == 200 and len(response.content) > 1000:
logger.success(f"✅ [Flux Fallback] Imagem gerada e baixada com sucesso (tentativa {attempt + 1})")
return {
"success": True,
"image_data": base64.b64encode(response.content).decode('utf-8'),
"mime_type": "image/png",
"model": "flux-fallback",
"prompt": prompt
}
if response.status_code == 429:
logger.warning(f"⚠️ [Flux Fallback] Rate limit (429). Tentativa {attempt + 1}/{max_retries}...")
import time
time.sleep(5)
continue
except requests.exceptions.Timeout:
logger.warning(f"⚠️ [Flux Fallback] Timeout na tentativa {attempt + 1}/{max_retries}")
if attempt < max_retries - 1:
import time
time.sleep(2)
continue
except Exception as e:
logger.error(f"❌ [Flux Fallback] Erro na tentativa {attempt + 1}: {e}")
if attempt < max_retries - 1:
continue
break
return {"success": False, "error": f"Flux retornou status {response.status_code}"}
except Exception as e:
logger.error(f"❌ [Flux Fallback] Erro: {e}")
return {"success": False, "error": str(e)}
# ============================================================================
# FACTORY: Escolhe melhor provider (CellCog ou Flux)
# ============================================================================
class AIMediaFactory:
"""
Factory que escolhe o melhor provider disponível.
"""
def __init__(self):
self.cellcog = CellCogClient()
self.flux = PollinationsFluxFallback()
def generate_image(
self,
prompt: str,
model: str = "flux",
aspect_ratio: str = "1:1"
) -> Dict[str, Any]:
"""
Gera imagem com fallback automático.
Tenta CellCog primeiro, depois Flux.
"""
# Tenta CellCog se disponível
if self.cellcog.available:
result = self.cellcog.generate_image(
prompt=prompt,
aspect_ratio=aspect_ratio,
quality="high"
)
if result.get("success"):
return result
logger.warning("⚠️ CellCog falhou, tentando Flux...")
# Fallback para Flux
return self.flux.generate(prompt, aspect_ratio, model)
# Instância global
_media_factory = None
def get_media_factory() -> AIMediaFactory:
"""Retorna instância singleton do factory."""
global _media_factory
if _media_factory is None:
_media_factory = AIMediaFactory()
return _media_factory