> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mka1.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Desplegar un servidor de modelos

> Sirve un modelo detrás de un endpoint HTTP autenticado con un servicio de Compute, obtén los pesos desde mka1-repos y registra el endpoint en el gateway LLM.

Utiliza un servicio de Compute cuando necesites GPUs para una carga de trabajo persistente, como servir modelos.
Un servicio es la misma ejecución genérica de contenedor que un [trabajo](/es/docs/compute-fine-tune-job), más puertos con nombre, una sonda de preparación (readiness) opcional y un endpoint público — Compute no tiene un esquema de despliegue ni de modelo, así que esta guía sirve con [vLLM](https://docs.vllm.ai) puramente como carga útil de la carga de trabajo.

Un servicio se ejecuta hasta que lo terminas, y tú eres dueño del ciclo de vida de principio a fin: Compute nunca reinicia, reescala ni cambia revisiones a tus espaldas, así que lo que desplegaste es exactamente lo que está en ejecución.
Esa previsibilidad viene con dos reglas: mantén el proceso del servidor en primer plano durante toda la vida del servicio — una carga de trabajo que sale, incluso con código `0`, termina el servicio como `failed` — y reemplaza un servicio fallido u obsoleto creando uno nuevo.

## Antes de comenzar

Necesitas:

| Requisito                                        | Notas                                                                                                                                                                                        |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Clave de API                                     | Envíala como `Authorization: Bearer <mka1-api-key>` en cada solicitud.                                                                                                                       |
| Compute habilitado para tu organización          | Compute es una lista de permitidos que falla en cerrado (fail-closed). Si las solicitudes devuelven `403 tenant_disabled`, pide a un administrador del clúster que habilite tu organización. |
| Una imagen para servir                           | Cualquier imagen Linux con GPU que el proveedor pueda descargar sin autenticación interactiva, y que mantenga el proceso del servidor en primer plano.                                       |
| Pesos que servir                                 | Un identificador de modelo público, o un repositorio en mka1-repos — por ejemplo uno publicado por un [trabajo de ajuste fino](/es/docs/compute-fine-tune-job).                              |
| Una clave de API para la propia carga de trabajo | Compute expone tu puerto a internet y no autentica las llamadas que le llegan; tu servidor debe hacerlo. Genera una cadena aleatoria fuerte para esto.                                       |

Los servicios pasan por `requested` → `allocating` → `provisioning` → `ready`, y permanecen ahí hasta que algo termina la ejecución:

* Un fallo en cualquier fase, incluida la salida de la carga de trabajo después de `ready`, desmonta el servicio a través de `terminating` hasta `failed`.
* Una terminación explícita, un límite alcanzado o un presupuesto de organización agotado terminan en `terminated` en su lugar.

Con una sonda de preparación, `ready` significa que la sonda pasó.
Sin una, solo significa que la carga de trabajo se lanzó; no hace ninguna afirmación de salud a nivel de aplicación, así que declara una sonda siempre que la imagen ofrezca una ruta de salud.

<Warning>
  **La facturación comienza en la asignación, no en la disponibilidad.**

  El gasto se acumula desde la asignación hasta que el servicio alcanza un estado terminal, incluyendo todo el tiempo de aprovisionamiento y de carga del modelo.
  Un servicio nunca se completa por sí solo — termínalo cuando acabes y establece `limits` como salvaguarda.
</Warning>

## Paso 1 - Guarda la clave del endpoint como un secreto

Pasa la clave de API de la carga de trabajo mediante `secret_env`, no en línea en el comando, para que nunca aparezca en las especificaciones de pod del proveedor.

<CodeGroup>
  ```ts MKA1 SDK theme={null}
  import { SDK } from '@meetkai/mka1';

  const sdk = new SDK({
    bearerAuth: 'Bearer <mka1-api-key>',
  });

  const secret = await sdk.computeSecrets.createComputeSecret({
    computeSecretCreate: {
      name: 'inference-endpoint-key',
      data: { VLLM_API_KEY: '<generated-endpoint-key>' },
    },
  });
  console.log(secret.id);
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/compute/secrets \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --data '{
      "name": "inference-endpoint-key",
      "data": {"VLLM_API_KEY": "<generated-endpoint-key>"}
    }'
  ```
</CodeGroup>

Los valores de los secretos son de solo escritura.
Guarda el id `sec_...` devuelto para el cuerpo de creación, y el valor de la clave en sí para tus clientes.

## Paso 2 - Crea el servicio

Crea el servicio con el encabezado obligatorio `Idempotency-Key`, exactamente igual que con los trabajos.
Este ejemplo sirve Qwen2.5-0.5B-Instruct con el servidor compatible con OpenAI de vLLM, replicando la prueba de humo de la plataforma:

<CodeGroup>
  ```ts MKA1 SDK theme={null}
  const service = await sdk.computeServices.createService({
    idempotencyKey: '<unique-request-id>',
    computeResourceCreate: {
      name: 'qwen-inference',
      compute: {
        accelerator: 'nvidia-rtx-4090-24gb',
        gpuCount: 1,
        ephemeralDiskGb: 60,
      },
      container: {
        image: 'vllm/vllm-openai:v0.26.0-cu129',
        command: [
          'vllm', 'serve', 'Qwen/Qwen2.5-0.5B-Instruct',
          '--host', '0.0.0.0', '--port', '8000',
          '--max-model-len', '4096', '--gpu-memory-utilization', '0.85',
          '--enable-auto-tool-choice', '--tool-call-parser', 'hermes',
        ],
        secretEnv: {
          VLLM_API_KEY: { secretId: 'sec_Qw8pLm2vTn5xRc7J', key: 'VLLM_API_KEY' },
        },
        ports: [{ name: 'api', containerPort: 8000, protocol: 'http' }],
      },
      service: {
        readiness: { type: 'http', port: 'api', path: '/health', successStatus: 200 },
      },
    },
  });
  console.log(service.id, service.state);
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/compute/services \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'Idempotency-Key: <unique-request-id>' \
    --data '{
      "name": "qwen-inference",
      "compute": {
        "accelerator": "nvidia-rtx-4090-24gb",
        "gpu_count": 1,
        "ephemeral_disk_gb": 60
      },
      "container": {
        "image": "vllm/vllm-openai:v0.26.0-cu129",
        "command": ["vllm", "serve", "Qwen/Qwen2.5-0.5B-Instruct", "--host", "0.0.0.0", "--port", "8000", "--max-model-len", "4096", "--gpu-memory-utilization", "0.85", "--enable-auto-tool-choice", "--tool-call-parser", "hermes"],
        "secret_env": {
          "VLLM_API_KEY": {"secret_id": "sec_Qw8pLm2vTn5xRc7J", "key": "VLLM_API_KEY"}
        },
        "ports": [
          {"name": "api", "container_port": 8000, "protocol": "http"}
        ]
      },
      "service": {
        "readiness": {
          "type": "http",
          "port": "api",
          "path": "/health",
          "success_status": 200
        }
      }
    }'
  ```
</CodeGroup>

Notas sobre los campos:

| Campo                                                 | Notas                                                                                                                                                                                                        |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `container.ports`                                     | Cada puerto necesita un nombre único, un puerto de contenedor y un protocolo `http` o `tcp`. Cada puerto con nombre se expone en el endpoint público del servicio.                                           |
| `service.readiness`                                   | Referencia un puerto declarado por su nombre, nunca por su número. Una sonda `http` requiere que el protocolo de ese puerto sea `http`; una sonda `tcp` toma solo el nombre del puerto.                      |
| `secret_env.VLLM_API_KEY`                             | vLLM lee `VLLM_API_KEY` de forma nativa y luego la exige como token bearer en cada solicitud.                                                                                                                |
| `--enable-auto-tool-choice --tool-call-parser hermes` | Obligatorios si el [gateway LLM](#paso-5---regístralo-en-el-gateway-llm) va a llamar a este endpoint: el gateway envía `tool_choice: "auto"` por defecto, y un vLLM sin estos flags lo rechaza con un `400`. |

Como con los trabajos, `201` significa que la solicitud fue aceptada; los problemas de capacidad y aprovisionamiento aparecen después a través de `state`, `reason`, los registros y los eventos.

## Paso 3 - Espera a que esté listo

<CodeGroup>
  ```ts MKA1 SDK theme={null}
  const service = await sdk.computeServices.getService({ id: 'service_2mVx7cKq9dRw4bTn' });
  console.log(service.state, service.ready, service.endpoints);
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/compute/services/service_2mVx7cKq9dRw4bTn \
    --header 'Authorization: Bearer <mka1-api-key>'
  ```
</CodeGroup>

La descarga y la carga del modelo ocurren dentro de la carga de trabajo, así que espera minutos de `provisioning` antes de que la sonda de preparación pase.
Un servicio listo incluye sus endpoints públicos:

```json theme={null}
{
  "id": "service_2mVx7cKq9dRw4bTn",
  "name": "qwen-inference",
  "state": "ready",
  "ready": true,
  "reason": null,
  "compute": {"accelerator": "nvidia-rtx-4090-24gb", "gpu_count": 1, "ephemeral_disk_gb": 60},
  "hardware": {"accelerator": "nvidia-rtx-4090-24gb", "gpu_count": 1, "gpu_memory_gb": 24},
  "price_usd_hr": 0.46,
  "accrued_usd": 0.12,
  "allocated_at": "2026-07-29T13:02:41Z",
  "limits": {},
  "endpoints": [
    {
      "name": "api",
      "protocol": "http",
      "host": "svc-2mvx7ckq.endpoints.example.net",
      "port": 443,
      "url": "https://svc-2mvx7ckq.endpoints.example.net"
    }
  ],
  "created_at": "2026-07-29T13:01:12Z",
  "started_at": "2026-07-29T13:06:30Z",
  "terminal_at": null
}
```

Si en cambio el servicio aterriza en `failed`, lee `reason`, y luego `GET .../logs?source=user` para la salida del propio servidor y `source=system` para problemas de asignación y arranque — la misma superficie de registros y eventos que los [trabajos](/es/docs/compute-fine-tune-job#paso-5---lee-los-registros-y-eventos).

## Paso 4 - Llama a tu endpoint

El endpoint es vLLM puro: una API compatible con OpenAI autenticada con la clave que guardaste en el Paso 1.

```bash curl theme={null}
curl https://svc-2mvx7ckq.endpoints.example.net/v1/chat/completions \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer <generated-endpoint-key>' \
  --data '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "messages": [{"role": "user", "content": "Say hello."}]
  }'
```

Una solicitud sin la clave es rechazada por el propio vLLM — Compute no se interpone delante de tu endpoint.

<Warning>
  Comprueba el esquema de la `url` del endpoint antes de enviar cualquier cosa sensible.
  Dependiendo de dónde se asignó la capacidad, un endpoint puede servirse sobre `http` plano, en cuyo caso los tokens bearer y las cargas útiles cruzan internet sin cifrar.
</Warning>

## Paso 5 - Regístralo en el gateway LLM

Opcionalmente, registra el endpoint como un modelo propio (bring-your-own) en el gateway LLM de MKA1, para que se pueda llamar a través de la API `/responses` de la plataforma con claves normales de la plataforma.

Agrega el endpoint a tu catálogo de modelos:

```bash curl theme={null}
curl https://apigw.mka1.com/api/v1/llm/models/catalog \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer <mka1-api-key>' \
  --data '{
    "apiFormat": "completions",
    "apiProviderType": "openai",
    "baseUrl": "https://svc-2mvx7ckq.endpoints.example.net/v1",
    "auth": {"type": "api-key", "value": "<generated-endpoint-key>"}
  }'
```

Luego registra el id de modelo devuelto:

```bash curl theme={null}
curl https://apigw.mka1.com/api/v1/llm/models/registry \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer <mka1-api-key>' \
  --data '{
    "source": "byo",
    "model_id": "<model-id-from-catalog>"
  }'
```

Los modelos con formato `completions` se aceptan en `/responses`; el gateway maneja por ti el upstream de chat-completions.
Por eso el cuerpo de creación del Paso 2 pasó los flags de tool-choice a vLLM.

## Paso 6 - Termina el servicio

Un servicio se ejecuta, y factura, hasta que lo detienes.

<CodeGroup>
  ```ts MKA1 SDK theme={null}
  const service = await sdk.computeServices.terminateService({ id: 'service_2mVx7cKq9dRw4bTn' });
  console.log(service.state);
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/compute/services/service_2mVx7cKq9dRw4bTn/terminate \
    --request POST \
    --header 'Authorization: Bearer <mka1-api-key>'
  ```
</CodeGroup>

La terminación es idempotente, libera el recurso del proveedor y detiene el gasto; el registro sigue siendo legible para auditoría y uso.

## Servir un modelo desde mka1-repos

Para servir pesos desde [mka1-repos](/es/docs/repositories) — como la salida fusionada de un [trabajo de ajuste fino](/es/docs/compute-fine-tune-job#usar-mka1-repos-para-conjuntos-de-datos-y-pesos), o pesos que [subiste por git](/es/docs/repositories) — cambia solo el identificador del modelo y las credenciales.

Compute siempre inyecta `HF_ENDPOINT` en cada carga de trabajo, apuntando al endpoint de artefactos configurado para tu clúster, y vLLM resuelve los identificadores de modelo contra él.
mka1-repos autentica con tu clave de API de MKA1, inyectada como `HF_TOKEN` mediante `secret_env`:

```json theme={null}
{
  "container": {
    "image": "vllm/vllm-openai:v0.26.0-cu129",
    "command": ["vllm", "serve", "acme/qwen2.5-0.5b-support", "--host", "0.0.0.0", "--port", "8000", "--max-model-len", "4096", "--gpu-memory-utilization", "0.85", "--enable-auto-tool-choice", "--tool-call-parser", "hermes"],
    "secret_env": {
      "VLLM_API_KEY": {"secret_id": "sec_Qw8pLm2vTn5xRc7J", "key": "VLLM_API_KEY"},
      "HF_TOKEN": {"secret_id": "sec_Vb3nRk8sQw1xYz2M", "key": "HF_TOKEN"}
    },
    "ports": [
      {"name": "api", "container_port": 8000, "protocol": "http"}
    ]
  }
}
```

El servicio descarga los pesos desde el repositorio de tu organización al arrancar y los sirve bajo el mismo identificador, cerrando el ciclo: ajusta finamente como trabajo, publica en mka1-repos y sirve como servicio.

## Supervisar el gasto

El gasto de los servicios se acumula por minuto completo desde la asignación y aparece junto a los trabajos en el endpoint de uso:

<CodeGroup>
  ```ts MKA1 SDK theme={null}
  const usage = await sdk.computeUsage.getComputeUsage({ resourceType: 'service' });
  console.log(usage.summary);
  ```

  ```bash curl theme={null}
  curl "https://apigw.mka1.com/api/v1/compute/usage?resource_type=service" \
    --header 'Authorization: Bearer <mka1-api-key>'
  ```
</CodeGroup>

El gasto de Compute se descuenta de los mismos presupuestos de organización que cualquier otro servicio de MKA1, y un servicio que alcanza un presupuesto de la organización o sus propios `limits` se termina sin periodo de gracia.

## Referencia de API

Para ver el esquema completo de solicitud y respuesta, abre los grupos de Compute en la [Referencia de API](/es/api-reference/introduction).

## Ver también

* [Ejecutar un trabajo de ajuste fino](/es/docs/compute-fine-tune-job) - produce los pesos que este servicio sirve.
* [Gestionar repositorios](/es/docs/repositories) - crea y gestiona los repositorios de los que este servicio obtiene los pesos.
* [Usar repositorios con Compute](/es/docs/repositories) - sube pesos por git y sírvelos por referencia.
* [Generar una respuesta](/es/docs/generate-a-response) - llama a tu modelo registrado a través de la API `/responses` de la plataforma.
