Edge AI Orchestrator · Razonamiento Multimodal · Multiplataforma ARM/Android · Automatización Agéntica
Construir un agente cognitivo híbrido que use NVIDIA Nemotron 3 como núcleo de razonamiento, con capacidad para operar tanto en cloud (infraestructura GPU H100/B200) como en edge (Jetson Thor, DGX Spark, Android ARM con NPU/GPU vía Arm NN / MLLM / Cactus). El agente automatiza:
# orchestrator.py - Motor híbrido del agente
import os
from huggingface_hub import hf_hub_download, HfApi
from transformers import AutoTokenizer, AutoModelForCausalLM
import numpy as np
import subprocess
import json
# 1. CONFIGURACIÓN HÍBRIDA
class HybridConfig:
CLOUD_MODEL = "nvidia/NVIDIA-Nemotron-3-Super-120B-A12B-FP8"
EDGE_MODEL = "nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-NVFP4"
HF_TOKEN = os.getenv("HF_TOKEN")
ENABLE_SVE = True # Activar kernels SVE en ARM
# 2. CLI WRAPPER PARA SKILLS Y DISCOVER
class HFAgentCLI:
@staticmethod
def search_skill(query: str, kind="skill"):
"""Descubre APIs, skills o MCP servers automáticamente."""
cmd = ["hf", "discover", "search", query, "--kind", kind, "--json"]
out = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(out.stdout) if out.returncode == 0 else {}
@staticmethod
def add_skill(scope="--global"):
subprocess.run(["hf", "skills", "add", scope])
@staticmethod
def download_model(repo_id: str, filename: str = None):
api = HfApi(token=HybridConfig.HF_TOKEN)
if filename:
return hf_hub_download(repo_id, filename, token=HybridConfig.HF_TOKEN)
return repo_id
# 3. REASONING ENGINE
class NemotronEngine:
def __init__(self, model_name: str, device="cuda"):
self.tok = AutoTokenizer.from_pretrained(
model_name, token=HybridConfig.HF_TOKEN, trust_remote_code=True
)
self.model = AutoModelForCausalLM.from_pretrained(
model_name,
token=HybridConfig.HF_TOKEN,
device_map="auto",
torch_dtype="auto",
trust_remote_code=True
)
self.device = device
def reason(self, prompt: str, enable_thinking=True) -> dict:
"""Genera traza de razonamiento + respuesta final."""
messages = [
{"role": "system", "content": "enable_thinking=True" if enable_thinking else ""},
{"role": "user", "content": prompt}
]
inputs = self.tok.apply_chat_template(
messages, tokenize=True, return_tensors="pt", add_generation_prompt=True
).to(self.device)
outputs = self.model.generate(inputs, max_new_tokens=2048, do_sample=False)
text = self.tok.decode(outputs[0], skip_special_tokens=False)
# Parsing de reasoning trace vs final answer
return {"raw": text, "thinking": self._extract_thinking(text), "answer": self._extract_answer(text)}
def _extract_thinking(self, text): return text.split("<think>")[-1].split("</think>")[0] if "<think>" in text else ""
def _extract_answer(self, text): return text.split("</think>")[-1] if "</think>" in text else text
# 4. NUMPY ACELERADO PARA ARM (SVE)
class AcceleratedCompute:
def __init__(self):
self.backend = "numpy+openblas"
if HybridConfig.ENABLE_SVE:
# En compilaciones con SVE, NumPy usa kernels SVE para HPC ARM
try:
import scipy; self.backend += "+scipy"
except Exception: pass
def fast_matmul(self, a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""GEMM acelerado; en ARM con SVE puede alcanzar hasta 1300x vs scalar."""
return np.dot(a, b)
# 5. API DE AGENTE COMPLETA
if __name__ == "__main__":
# Instalar skills primero: hf skills add --global
agent = NemotronEngine(HybridConfig.CLOUD_MODEL)
compute = AcceleratedCompute()
# Ejemplo: buscar APIs y razonar sobre ellas
skills = HFAgentCLI.search_skill("API para generación de imágenes")
print(skills)
result = agent.reason(
"Analiza este JSON de APIs y dime cuál es mejor para generar imágenes en edge: " + json.dumps(skills),
enable_thinking=True
)
print(result["thinking"])
print(result["answer"])
// build.gradle.kts - Dependencias para edge inference
dependencies {
// Opción A: MLLM (Motor de inferencia multi-backend con servidor in-app)
implementation(files("libs/mllm_server.aar"))
// Opción B: Cactus Compute (Kotlin Multiplatform + NPU)
implementation("com.cactuscompute:geniex-android:0.2.0")
// Opción C: ExecuTorch (PyTorch Edge)
implementation("org.pytorch:executorch-android:0.5.0")
}
// HybridAgent.kt - Agente que corre en Android/ARM
package com.hybridagent.edge
import android.content.Context
import kotlinx.coroutines.*
class HybridEdgeAgent(private val ctx: Context) {
private val dispatcher = Dispatchers.Default // Carga modelo cuantizado W4A16 o INT4 para edge
suspend fun initModel(modelPath: String) = withContext(dispatcher) {
// Ejemplo con MLLM: servidor in-app Golang vía FFI
MLLMNative.loadModel(modelPath, backend = "qnn") // qnn, opencl, cpu
}
// Razonamiento on-device con Nemotron-3-Nano (cuantizado)
suspend fun reason(prompt: String): String = withContext(dispatcher) {
val system = "enable_thinking=True"
val json = """{"messages":[{"role":"system","content":"$system"},{"role":"user","content":"$prompt"}]}"""
MLLMNative.chat(json)
}
// OCR / Análisis de documentos (Nano Omni multimodal)
suspend fun analyzeDocument(imageBytes: ByteArray): String = withContext(dispatcher) {
MLLMNative.processImage(imageBytes, task = "ocr+reasoning")
}
// Traducción acelerada por NPU
suspend fun translate(text: String, targetLang: String): String = withContext(dispatcher) {
// El mismo modelo Nemotron soporta múltiples idiomas nativamente
reason("Traduce al $targetLang: $text")
}
companion object {
// Singleton para la app
@Volatile private var instance: HybridEdgeAgent? = null
fun getInstance(ctx: Context): HybridEdgeAgent =
instance ?: synchronized(this) {
instance ?: HybridEdgeAgent(ctx.applicationContext).also { instance = it }
}
}
}
// MainActivity.kt - Uso
class MainActivity : AppCompatActivity() {
private val agent by lazy { HybridEdgeAgent.getInstance(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
agent.initModel("/sdcard/models/nemotron-3-nano-30b-q4.gguf")
val answer = agent.reason("Resume y traduce este documento...")
Log.d("Agent", answer)
}
}
}
Si usas Python en Android con Chaquopy o integración JNI, compila NumPy contra OpenBLAS con soporte ARM NEON/SVE para aceleración vectorial.
# chaquopy build logic (build.gradle)
python {
pip {
install "numpy" # preferiblemente con wheel optimizado para ARM
install "llama-cpp-python" # para inference ARM vía llama.cpp
}
}
# automation_engine.py - Motor de automatización agéntica
import asyncio
from playwright.async_api import async_playwright
from dataclasses import dataclass
from typing import Optionalimport base64, json
@dataclass
class AccountConfig:
service: str # ej: "github", "aws", "huggingface"
username: str
email: str
strategy: str = "llm_guided" # llm_guided o deterministic
class AutomationEngine:
def __init__(self, nemotron_engine):
self.nemotron = nemotron_engine # instancia de NemotronEngine
self.browser = None
self.page = None
async def start(self, headless=False):
self.playwright = await async_playwright().start()
self.browser = await self.playwright.chromium.launch(headless=headless)
self.page = await self.browser.new_page()
async def read_document(self, url_or_path: str) -> dict:
"""Lee PDF o página web, extrae texto, resume y traduce."""
if url_or_path.endswith(".pdf"):
await self.page.goto(f"https://docs.google.com/viewer?url={url_or_path}")
content = await self.page.inner_text("#viewer")
else:
await self.page.goto(url_or_path)
content = await self.page.inner_text("body")
# Envía al LLM para análisis profundo
analysis = self.nemotron.reason(
f"Resume, extrae pasos clave y traduce esta documentación:\n\n{content[:8000]}",
enable_thinking=True
)
return analysis
async def create_account(self, config: AccountConfig) -> bool:
"""Automatiza flujo de registro GUI usando LLM para navegación adaptativa."""
guide = self.nemotron.reason(
f"Genera un plan paso a paso para crear una cuenta en {config.service}. "
f"Incluye URLs, selectores CSS probables, validaciones de email y TOS.",
enable_thinking=True
)["answer"]
# Parsear plan y ejecutar acciones Playwright
steps = self._parse_plan(guide)
for action in steps:
if action["type"] == "goto":
await self.page.goto(action["url"])
elif action["type"] == "fill":
await self.page.fill(action["selector"], action["value"].replace("{{email}}", config.email))
elif action["type"] == "click":
await self.page.click(action["selector"])
await asyncio.sleep(0.5)
return True
def _parse_plan(self, plan_text: str) -> list:
"""Convierte respuesta textual de Nemotron a estructura ejecutable."""
# Implementación con regex/JSON parsing robusto
return [{"type":"goto","url":"https://github.com/signup"},{"type":"fill","selector":"#email","value":"{{email}}"}]
async def discover_api_and_setup(self, service_description: str):
"""Busca APIs vía HF Discover y configura tokens/env."""
from orchestrator import HFAgentCLI
results = HFAgentCLI.search_skill(f"API for {service_description}", kind="mcp")
# El LLM selecciona la mejor API y genera código de setup
choice = self.nemotron.reason(f"Selecciona la mejor API de este listado: {json.dumps(results)}")
return choice async def close(self):
await self.browser.close()
await self.playwright.stop()
# Ejecución de ejemplo
async def main():
agent = AutomationEngine(nemotron_engine=NemotronEngine("nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16"))
await agent.start(headless=False)
# 1. Leer documentación de una API desconocida
doc = await agent.read_document("https://huggingface.co/docs/huggingface_hub/guides/cli")
print(doc["answer"])
# 2. Crear cuenta adaptativamente
await agent.create_account(AccountConfig(service="huggingface", username="dev01", email="dev01@ai.dev"))
await agent.close()
if __name__ == "__main__":
asyncio.run(main())
# Descubre skills y MCP servers sin dejar la terminal
hf discover search "image generation API" --kind mcp --json
hf discover search "transcribe audio API" --kind skill --json
hf discover search "train vision model" --limit 5
# Instala el skill directamente para que el agente lo use
hf skills add --global
| Escenario | Modelo | Runtime | Hardware |
|---|---|---|---|
| Cloud GPU | Nemotron-3-Ultra-550B-A55B | vLLM / TensorRT-LLM | 2x B200 / 8x H100 |
| Workstation | Nemotron-3-Super-120B-A12B-FP8 | TensorRT-LLM / vLLM | 2x RTX Pro 6000 /2x H100 |
| Edge / Developer | Nemotron-3-Nano-30B-A3B (NVFP4) | TensorRT-LLM / llama.cpp | DGX Spark / RTX 5090 / Jetson Thor |
| Android NPU | Nemotron-3-Nano Q4/K quantized | MLLM + QNN / Cactus | Snapdragon 8 Gen4 / Dimensity 9400 |
| ARM Linux Edge | Nemotron-H-47B / Nano 30B | llama.cpp + KleidiAI / Arm NN | Raspberry Pi 5 (Cortex-A76) / AGX Orin |
FROM nvidia/cuda:12.6-devel-ubuntu24.04
RUN pip install vllm huggingface_hub transformers playwrightRUN playwright install-deps
RUN hf skills add --global
ENV HF_TOKEN=${HF_TOKEN}
CMD ["python", "orchestrator.py"]
FROM arm64v8/python:3.12-slim
RUN pip install llama-cpp-python --extra-index-url ...
COPY models/ /models/
COPY orchestrator.py /
CMD ["python", "orchestrator.py", "--edge"]
nvidia/OpenReasoning-Nemotron-32B (derivado de Qwen2.5) con vLLM en una sola H100 o incluso RTX 4090 con cuantización.