Reservar LlamadaContáctenos
Volver a todas las notas
7 de junio de 2026

Cómo construimos un relay de IA de offline a la nube usando Bluetooth y GPT-4o

Cómo construimos un relay de IA de offline a la nube usando Bluetooth y GPT-4o

Cómo construimos un relay de IA de offline a la nube usando Bluetooth y GPT-4o

En entornos empresariales de alta seguridad (como salas de operaciones financieras, laboratorios de I+D sensibles e instalaciones del sector defensa), las estaciones de trabajo suelen tener restringido el acceso a la red pública de Internet. Aunque este aislamiento físico (air-gapping) o segmentación estricta de la red mitiga los riesgos de filtración de datos, también impide por completo el acceso a los modernos Large Language Models (LLMs) alojados en la nube. Los ingenieros y analistas se ven privados de herramientas como GPT-4o de OpenAI, lo que ralentiza su productividad.

En Seven Labs, asumimos el reto de solucionar este cuello de botella específico para un cliente que operaba en una zona de red altamente restringida. El requisito era claro: permitir que las estaciones de trabajo ubicadas en un segmento sin conexión a Internet realizaran consultas de forma segura a LLMs en la nube, sin modificar las políticas del firewall de la estación de trabajo ni introducir hardware no autorizado como adaptadores Wi-Fi.

Nuestra solución fue el Bluetooth AI Relay-un puente del edge a la nube que canaliza las solicitudes de una PC local a través de un relay RFCOMM basado en Android hacia GPT-4o, utilizando protocolos de Bluetooth estándar. A continuación se presenta el desglose técnico de cómo diseñamos, implementamos y reforzamos este sistema en producción.


1. Arquitectura del sistema: el puente del Edge a la Nube

La arquitectura consta de tres componentes principales:

  1. El Cliente (PC sin conexión): Un servicio local que se ejecuta en la estación de trabajo y expone una API loopback (por ejemplo, http://localhost:8080/v1/chat/completions) que cumple con la especificación de la API estándar de OpenAI.
  2. El Relay (Dispositivo móvil Android): Una aplicación en React Native que ejecuta un servicio persistente (foreground service) en Kotlin. El dispositivo Android cuenta con acceso a datos móviles (LTE/5G) y a Bluetooth, funcionando como puente.
  3. La Nube (OpenAI GPT-4o): El backend del LLM de destino al que se accede mediante HTTPS.
+-------------+                    +-------------------------+                    +-----------------+
|             |     Bluetooth      | Dispositivo Relay Android|    Red Móvil WAN   |                 |
|  PC Offline |  (Socket RFCOMM)   |                         |  (Cliente HTTPS)   |  OpenAI GPT-4o  |
|  [Cliente]  |<==================>| [Servicio Kotlin]       |------------------->|   Endpoint API  |
|             |                    | [Motor React Native]    |                    |                 |
+-------------+                    +-------------------------+                    +-----------------+

¿Por qué RFCOMM?

Para transmitir payloads JSON de prompts y respuestas, necesitábamos un protocolo de transporte confiable y orientado a flujos de datos. Aunque Bluetooth Low Energy (BLE) con atributos GATT es excelente para telemetría de bajo rendimiento, no es adecuado para bloques de texto grandes debido a sus estrictas limitaciones de la Unidad de Transmisión Máxima (MTU) y la sobrecarga que genera la fragmentación de paquetes.

Elegimos RFCOMM (Radio Frequency Communication), que emula un puerto serie RS-232 sobre el protocolo L2CAP. RFCOMM maneja la secuenciación de paquetes, el control de flujo y la retransmisión de forma nativa, proporcionando un socket confiable orientado a flujos (similar a la interfaz java.net.Socket) capaz de soportar el flujo de texto de alto rendimiento requerido para los prompts y respuestas de LLMs.


2. Implementación del servidor RFCOMM en Android con Kotlin

Para garantizar que la aplicación de Android gestionara las conexiones entrantes de Bluetooth de forma confiable, evitamos el uso de librerías wrapper de React Native (que a menudo sufren fugas de memoria y carecen de soporte para persistencia en segundo plano) e implementamos la pila de Bluetooth directamente en Kotlin.

El hilo del servidor de Bluetooth

El servidor de Bluetooth se ejecuta en un hilo dedicado, escuchando en un Identificador Único Universal (UUID) específico:

package com.sevenlabs.airelay
 
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import android.util.Log
import java.io.IOException
import java.util.UUID
 
class BluetoothServerThread(
    private val adapter: BluetoothAdapter,
    private val onConnectionEstablished: (BluetoothSocket) -> Unit
) : Thread() {
 
    private val serverSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        adapter.listenUsingRfcommWithServiceRecord(
            "SevenLabsAIRelay",
            UUID.fromString("4a8b8c2d-9e0f-11ed-a8fc-0242ac120002")
        )
    }
 
    private var shouldKeepListening = true
 
    override fun run() {
        name = "SevenLabs-RFCOMM-Listener"
        Log.i("AIRelay", "RFCOMM Server Socket listening...")
 
        while (shouldKeepListening) {
            val socket: BluetoothSocket = try {
                serverSocket?.accept()
            } catch (e: IOException) {
                Log.e("AIRelay", "Server Socket accept failed", e)
                break
            }
 
            socket?.let {
                Log.i("AIRelay", "Incoming RFCOMM client connection accepted")
                onConnectionEstablished(it)
            }
        }
    }
 
    fun cancel() {
        try {
            shouldKeepListening = false
            serverSocket?.close()
        } catch (e: IOException) {
            Log.e("AIRelay", "Could not close server socket", e)
        }
    }
}

3. Operación persistente: Kotlin Foreground Services y gestión de Wake-Locks

Uno de los mayores desafíos de ingeniería en las versiones modernas de Android (Android 12+) es la optimización de la batería. Si la pantalla del dispositivo móvil se apaga o la aplicación se minimiza, el sistema operativo de Android coloca la CPU en un estado de sueño profundo (Doze Mode) y cierra los sockets de red en segundo plano.

Para garantizar operaciones ininterrumpidas, Seven Labs implementó dos mecanismos fundamentales:

  1. Kotlin Foreground Service: Colocar el servidor RFCOMM y el cliente API dentro de un Android Foreground Service. Esto registra la aplicación como un proceso persistente reconocido por el sistema, mostrando una notificación permanente en la barra de estado.
  2. Wake-Locks y Wi-Fi Locks: Indicar explícitamente al planificador del kernel que mantenga la CPU activa y las antenas de datos móviles operativas durante una sesión activa.

Implementación del Foreground Service

A continuación se muestra el núcleo del servicio en primer plano que gestiona el ciclo de vida del hilo y las notificaciones:

package com.sevenlabs.airelay
 
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
 
class AIRelayService : Service() {
 
    private var wakeLock: PowerManager.WakeLock? = null
    private var serverThread: BluetoothServerThread? = null
 
    override fun onCreate() {
        super.onCreate()
        acquireWakeLock()
        startForegroundService()
    }
 
    private fun acquireWakeLock() {
        val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        wakeLock = powerManager.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK,
            "SevenLabs::AIRelayWakeLock"
        ).apply {
            acquire(30 * 60 * 1000L) // Límite de seguridad de 30 minutos
        }
    }
 
    private fun startForegroundService() {
        val channelId = "seven_labs_ai_relay"
        val channelName = "AI Relay Foreground Service"
 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW)
            val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            manager.createNotificationChannel(channel)
        }
 
        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this, 0, notificationIntent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
 
        val notification: Notification = NotificationCompat.Builder(this, channelId)
            .setContentTitle("Seven Labs AI Relay Active")
            .setContentText("Routing Bluetooth RFCOMM data to GPT-4o...")
            .setSmallIcon(R.drawable.ic_notification)
            .setContentIntent(pendingIntent)
            .build()
 
        startForeground(1, notification)
    }
 
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // Comenzar a escuchar a través de Bluetooth
        val adapter = BluetoothAdapter.getDefaultAdapter()
        serverThread = BluetoothServerThread(adapter) { socket ->
            // Enrutar datos de flujo (stream)
            ConnectionHandler(socket).start()
        }
        serverThread?.start()
        return START_STICKY
    }
 
    override fun onDestroy() {
        serverThread?.cancel()
        wakeLock?.let {
            if (it.isHeld) it.release()
        }
        super.onDestroy()
    }
 
    override fun onBind(intent: Intent?): IBinder? = null
}

4. Estructuración del Payload de datos y el protocolo

Dado que RFCOMM funciona como un flujo continuo de bytes crudos, tuvimos que definir un protocolo de estructuración de tramas a nivel de aplicación para segmentar los paquetes individuales de solicitud y respuesta.

Diseñamos un formato de trama de mensaje ligero:

  • Bytes mágicos (4 bytes): SLAR (Seven Labs AI Relay) para validar el origen de los paquetes.
  • Longitud del Payload (4 bytes): Entero big-endian que especifica el tamaño exacto del payload.
  • Tipo de Payload (1 byte): Indica si el paquete es texto plano, un fragmento de SSE (Server-Sent Events), metadatos o un código de error.
  • Payload cifrado (Variable): Datos JSON cifrados con AES-GCM.
+------------+------------------+--------------+-----------------------+
| Magic (4B) | Longitud(4B, Int)| Tipo (1B, B) | Payload Cifrado (N)   |
+------------+------------------+--------------+-----------------------+

Cuando el Cliente en la PC offline envía un prompt de completación, el daemon local lo empaqueta en esta trama, lo transmite a través del socket RFCOMM y se bloquea a la espera de las tramas de respuesta.

En el extremo del Android Relay, el lector del socket en Kotlin lee el prefijo de longitud, lee el número de bytes especificado, descifra el payload y reenvía la solicitud HTTP al endpoint de OpenAI. Para soportar la transmisión de tokens en tiempo real, procesamos los fragmentos de datos de Server-Sent Events (SSE) que regresan de OpenAI, los estructuramos bajo el tipo SSE Chunk y los escribimos secuencialmente de vuelta en el flujo del socket de Bluetooth.


5. Arquitectura de seguridad: Zero-Trust sobre Bluetooth

Transmitir datos corporativos a través de Bluetooth plantea importantes preocupaciones de seguridad. Las conexiones de Bluetooth son vulnerables a la interceptación de datos y a ataques de intermediario (Man-in-the-Middle, MitM). Para que este relay fuera viable en entornos empresariales, Seven Labs añadió una capa de criptografía a nivel de aplicación.

Cifrado de extremo a extremo (E2EE)

Incluso si la capa de emparejamiento de Bluetooth se ve comprometida, el payload de los datos permanece seguro.

  1. Intercambio de claves: Cuando la PC offline inicia una conexión, realiza un intercambio de claves Diffie-Hellman basado en curvas elípticas (ECDH) con el dispositivo Android a través del socket de Bluetooth crudo.
  2. Clave de sesión efímera: Ambos extremos derivan una clave simétrica compartida (AES-256-GCM) que es única para esa sesión de conexión específica.
  3. Cifrado de payload: Cada payload de trama de datos se cifra utilizando la clave de sesión, con un vector de inicialización (IV) generado para cada trama. Esto evita ataques de repetición y de escucha no autorizada.

6. Ajuste de rendimiento y optimización de latencia

Nuestras pruebas de rendimiento arrojaron las siguientes métricas en producción:

MétricaWi-Fi Directo (Control)Relay RFCOMM (Sin Streaming)Relay RFCOMM (Con Streaming SSE)
Tiempo al primer token (TTFT)~320ms~980ms~410ms
Rendimiento (Tokens/Seg)654258
Tamaño máximo de payloadIlimitado5 MBTransmitido (Streamed)

Optimización del rendimiento

Dado que el ancho de banda de Bluetooth está restringido en comparación con Wi-Fi, la transmisión de respuestas token por token es fundamental. Al enviar los fragmentos SSE de vuelta al cliente a medida que llegan desde el extremo de OpenAI, redujimos la latencia percibida (TTFT) en más del 50%.

Además, aplicamos compresión Gzip a las entradas de prompt que superaban los 20KB, disminuyendo el tiempo de transmisión por Bluetooth y evitando cuellos de botella en el búfer de RFCOMM.


7. Preguntas frecuentes de empresas

¿Viola esto los principios de aislamiento físico (air-gapping)?

El sistema funciona como un proxy de protocolo estricto. La estación de trabajo sin conexión no dispone de una ruta a nivel de IP hacia la red móvil, lo que evita el acceso general a Internet, escaneos de puertos por canales laterales o vulnerabilidades de shells inversas. Solo se permiten tramas SLAR estructuradas correctamente a nivel de aplicación a través de la interfaz.

¿Cómo escala el consumo de batería en el dispositivo de relay?

Operar el radio de Bluetooth y el de datos móviles simultáneamente consume aproximadamente un 8% de batería por hora de procesamiento continuo. Al aprovechar de forma selectiva los Wake-Locks de PowerManager en Android (manteniendo los wake-locks únicamente durante las sesiones activas del socket y entrando en estados inactivos en las horas no laborables), minimizamos el consumo.

¿Cómo se gestiona la contabilidad de los tokens?

Todas las claves de uso y autorización se almacenan en la aplicación Android Relay o se recuperan de un servidor de claves empresarial. Los inicios de sesión individuales de los usuarios se pueden autenticar localmente en el dispositivo antes de realizar la negociación Diffie-Hellman.


Esquema SEO técnico y enlaces internos


Construya sistemas seguros del Edge a la Nube con Seven Labs

Navegar por la intersección de tecnologías avanzadas de IA y los estrictos controles de seguridad corporativos requiere de arquitectos de sistemas experimentados. Ya sea que necesite un despliegue de LLMs en un entorno aislado, computación edge de alto rendimiento o relays seguros de IoT, Seven Labs cuenta con la experiencia de ingeniería necesaria para diseñar y desplegar soluciones conformes a las normativas.

Póngase en contacto con el Equipo de Ingeniería de Seven Labs para analizar las necesidades de infraestructura e IA personalizadas de su organización.

Servicio de Seven Labs

Desarrollo de Agentes de IA y Pipelines RAG

Construimos pipelines RAG de producción. Ver nuestro trabajo →
Loading...

Leer siguiente

Why Your VPN is a Liability: Zero-Trust Network Access in Modern SaaS

Implementing Zero-Trust Network Access in modern SaaS environments is hard but necessary. This techn...

Leer artículo

Edge AI vs Cloud AI: Choosing the Right Architecture for Enterprise Systems

An in-depth systems engineering guide comparing Edge AI and Cloud AI. Learn about quantization, infe...

Leer artículo
Chat with us