# GRACE - Servicio de IA Cognitiva **Versión:** 5.0 **Fecha:** 2024-12-24 --- ## Estado Actual **BLOQUEADO:** RunPod no inicia workers. | Aspecto | Valor | |---------|-------| | Plataforma | RunPod Serverless | | Endpoint ID | r00x4g3rrwkbyh | | Balance | ~$72 USD | | Workers activos | 0 | | Estado | Inoperativo | --- ## Descripción GRACE es el servicio de extracción de información mediante IA. Procesa contenido multimedia para extraer datos estructurados. ``` Contenido Raw (audio, imagen, video, documento) │ ▼ ┌─────────────────────────────────────────┐ │ GRACE (GPU) │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ ASR │ │ OCR │ │ TTS │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ Face │ │Embeddings│ │ Avatar │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ + 12 módulos pendientes │ └─────────────────────────────────────────┘ │ ▼ Datos Estructurados (JSON, vectores, metadatos) ``` --- ## Módulos Implementados (6 de 18) ### ASR - Automatic Speech Recognition | Campo | Valor | |-------|-------| | Modelo | Whisper Large v3 | | Input | Audio (mp3, wav, m4a) | | Output | Texto + timestamps | | GPU | A10G recomendado | ```python @grace.module("asr") def process_asr(audio_bytes: bytes) -> dict: """Transcribe audio a texto.""" model = whisper.load_model("large-v3") result = model.transcribe(audio_bytes) return { "text": result["text"], "segments": result["segments"], "language": result["language"] } ``` ### OCR - Optical Character Recognition | Campo | Valor | |-------|-------| | Modelo | EasyOCR + Tesseract | | Input | Imagen (jpg, png) | | Output | Texto + bounding boxes | | GPU | A10G recomendado | ```python @grace.module("ocr") def process_ocr(image_bytes: bytes) -> dict: """Extrae texto de imagen.""" reader = easyocr.Reader(['es', 'en']) result = reader.readtext(image_bytes) return { "text": " ".join([r[1] for r in result]), "boxes": [{"text": r[1], "bbox": r[0], "confidence": r[2]} for r in result] } ``` ### TTS - Text to Speech | Campo | Valor | |-------|-------| | Modelo | Coqui TTS | | Input | Texto | | Output | Audio (wav) | | GPU | A10G recomendado | ### Face - Reconocimiento Facial | Campo | Valor | |-------|-------| | Modelo | InsightFace | | Input | Imagen | | Output | Embeddings faciales | | GPU | A10G recomendado | ### Embeddings - Vectores Semánticos | Campo | Valor | |-------|-------| | Modelo | Sentence Transformers | | Input | Texto | | Output | Vector 384/768 dims | | GPU | A10G recomendado | ### Avatar - Generación de Avatares | Campo | Valor | |-------|-------| | Modelo | StyleGAN | | Input | Imagen facial | | Output | Avatar estilizado | | GPU | A10G recomendado | --- ## Módulos Pendientes (12) | Módulo | Descripción | Prioridad | |--------|-------------|-----------| | Document parsing | Extracción de PDFs | Alta | | Image classification | Clasificación de imágenes | Media | | Object detection | Detección de objetos | Media | | Sentiment analysis | Análisis de sentimiento | Media | | Named entity recognition | Extracción de entidades | Alta | | Translation | Traducción de texto | Media | | Summarization | Resumen de texto | Media | | Question answering | Respuestas a preguntas | Baja | | Code generation | Generación de código | Baja | | Audio classification | Clasificación de audio | Baja | | Video analysis | Análisis de video | Baja | | Multimodal fusion | Fusión multimodal | Baja | --- ## Código en R2 El código está listo y disponible: ``` s3://architect/gpu-services/ ├── base/ │ └── bootstrap.sh # Script de inicialización ├── grace/ │ └── code/ │ └── handler.py # Handler principal ├── penny/ │ └── code/ │ └── handler.py └── factory/ └── code/ └── handler.py ``` ### Descargar Código ```bash source /home/orchestrator/orchestrator/.env export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY" export AWS_SECRET_ACCESS_KEY="$R2_SECRET_KEY" aws s3 sync s3://architect/gpu-services/grace/ ./grace/ \ --endpoint-url https://7dedae6030f5554d99d37e98a5232996.r2.cloudflarestorage.com ``` --- ## Handler RunPod ```python import runpod def handler(event): """ Handler principal de GRACE para RunPod Serverless. Input: { "input": { "module": "asr|ocr|tts|face|embeddings|avatar", "data": "base64 encoded content", "options": {} } } Output: { "output": { ... resultado del módulo ... }, "error": null } """ try: module = event["input"]["module"] data = base64.b64decode(event["input"]["data"]) options = event["input"].get("options", {}) if module == "asr": result = process_asr(data, **options) elif module == "ocr": result = process_ocr(data, **options) elif module == "tts": result = process_tts(data, **options) elif module == "face": result = process_face(data, **options) elif module == "embeddings": result = process_embeddings(data, **options) elif module == "avatar": result = process_avatar(data, **options) else: return {"error": f"Módulo desconocido: {module}"} return {"output": result, "error": None} except Exception as e: return {"error": str(e)} runpod.serverless.start({"handler": handler}) ``` --- ## Uso desde MASON ```python import runpod import base64 runpod.api_key = "..." # Desde Infisical def call_grace(module: str, content: bytes, options: dict = None) -> dict: """Llama a GRACE para procesar contenido.""" job = runpod.run( endpoint_id="r00x4g3rrwkbyh", input={ "module": module, "data": base64.b64encode(content).decode(), "options": options or {} } ) # Polling hasta completar while True: status = runpod.status(job["id"]) if status["status"] == "COMPLETED": return status["output"] elif status["status"] == "FAILED": raise Exception(status.get("error", "Job failed")) time.sleep(1) ``` --- ## Problema Actual: Workers No Inician ### Incidente 2024-12-24 - **Síntoma:** 0 workers activos a pesar de jobs en cola - **Balance:** $72+ (suficiente) - **Configuración:** Correcta - **Causa probable:** Problema de capacidad RunPod ### Intentos de Diagnóstico 1. Verificado endpoint activo en dashboard 2. Verificado balance suficiente 3. Verificado configuración de scaling 4. Jobs quedan en estado "IN_QUEUE" indefinidamente ### Log de Errores ``` No hay logs disponibles - workers nunca inician ``` --- ## Alternativas Evaluadas ### 1. Modal (Recomendado) ```python import modal stub = modal.Stub("grace") image = modal.Image.debian_slim().pip_install("whisper", "easyocr") @stub.function(gpu="A10G", image=image) def process_asr(audio_bytes: bytes) -> dict: import whisper model = whisper.load_model("large-v3") result = model.transcribe(audio_bytes) return {"text": result["text"]} ``` **Pros:** - Serverless real - Buen DX (developer experience) - Python-native - Cold start rápido **Contras:** - Menos GPUs disponibles que RunPod - Pricing puede ser mayor ### 2. Replicate ```python import replicate output = replicate.run( "openai/whisper:large-v3", input={"audio": audio_url} ) ``` **Pros:** - Modelos pre-entrenados - API simple - Sin gestión de infraestructura **Contras:** - Menos control - Más caro a escala - Dependencia de modelos de terceros ### 3. Lambda Labs **Pros:** - Hardware dedicado - GPUs disponibles **Contras:** - Menos flexible - Reserva manual - No serverless ### 4. Self-Hosted **Pros:** - Control total - Sin dependencias externas - Costo fijo a largo plazo **Contras:** - CapEx alto - Mantenimiento - Requiere expertise --- ## Plan de Migración ### Fase 1: Evaluación - [ ] Crear cuenta Modal - [ ] Portar módulo ASR a Modal - [ ] Comparar latencia con RunPod (cuando funcione) - [ ] Comparar costos ### Fase 2: Migración - [ ] Portar 6 handlers a Modal - [ ] Actualizar endpoints en MASON - [ ] Actualizar documentación - [ ] Testing end-to-end ### Fase 3: Producción - [ ] Desplegar en Modal - [ ] Monitorear costos y performance - [ ] Deprecar RunPod endpoints - [ ] Cancelar cuenta RunPod --- ## Principio Fundamental **GRACE nunca modifica datos.** GRACE es read-only: extrae información pero no puede modificar el contenido original ni los datos del sistema. Las extracciones se almacenan como metadatos asociados al contenido original. ``` Contenido Original ────► GRACE ────► Metadatos Extraídos (inmutable) (nuevos datos) ```