> ## 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.

# Implantar um servidor de modelos

> Sirva um modelo atrás de um endpoint HTTP autenticado com um serviço do Compute, baixe pesos do mka1-repos e registre o endpoint no gateway de LLM.

Use um serviço do Compute quando precisar de GPUs para uma carga de trabalho persistente, como servir modelos.
Um serviço é a mesma execução genérica de contêiner que um [job](/pt/docs/compute-fine-tune-job), mais portas nomeadas, uma sonda de prontidão (readiness probe) opcional e um endpoint público — o Compute não tem esquema de implantação nem de modelo, então este guia serve com [vLLM](https://docs.vllm.ai) puramente como payload da carga de trabalho.

Um serviço executa até você encerrá-lo, e você é dono do ciclo de vida de ponta a ponta: o Compute nunca reinicia, redimensiona nem troca revisões pelas suas costas, então o que você implantou é exatamente o que está em execução.
Essa previsibilidade vem com duas regras: mantenha o processo do servidor em primeiro plano durante toda a vida do serviço — uma carga de trabalho que sai, mesmo com código `0`, termina o serviço como `failed` — e substitua um serviço que falhou ou ficou desatualizado criando um novo.

## Antes de começar

Você precisa de:

| Requisito                                         | Observações                                                                                                                                                                                     |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Chave de API                                      | Envie-a como `Authorization: Bearer <mka1-api-key>` em toda requisição.                                                                                                                         |
| Compute habilitado para sua organização           | O Compute usa uma lista de permissões que nega por padrão (fail-closed). Se as requisições retornarem `403 tenant_disabled`, peça a um administrador do cluster para habilitar sua organização. |
| Uma imagem de inferência                          | Qualquer imagem Linux com GPU que o provedor consiga baixar sem autenticação interativa, mantendo o processo do servidor em primeiro plano.                                                     |
| Pesos para servir                                 | Um identificador de modelo público, ou um repositório no mka1-repos — por exemplo, um publicado por um [job de ajuste fino](/pt/docs/compute-fine-tune-job).                                    |
| Uma chave de API para a própria carga de trabalho | O Compute expõe sua porta à internet e não autentica as chamadas a ela; seu servidor precisa autenticar. Gere uma string aleatória forte para isso.                                             |

Os serviços passam por `requested` → `allocating` → `provisioning` → `ready` e permanecem lá até algo encerrar a execução:

* Uma falha em qualquer fase, incluindo a carga de trabalho sair depois de `ready`, desmonta o serviço por `terminating` até `failed`.
* Encerramento explícito, um limite atingido ou um orçamento da organização esgotado termina em `terminated`.

Com uma sonda de prontidão, `ready` significa que a sonda passou.
Sem uma, significa apenas que a carga de trabalho foi lançada; não faz nenhuma afirmação de saúde no nível da aplicação, então declare uma sonda sempre que a imagem oferecer uma rota de health check.

<Warning>
  **A cobrança começa na alocação, não na prontidão.**

  Os gastos acumulam da alocação até o serviço alcançar um estado terminal, incluindo todo o tempo de provisionamento e de carregamento do modelo.
  Um serviço nunca termina por conta própria — encerre-o quando terminar e defina `limits` como salvaguarda.
</Warning>

## Passo 1 - Armazene a chave do endpoint como um segredo

Passe a chave de API da carga de trabalho através de `secret_env`, não inline no comando, para que ela nunca apareça nas especificações de pod do provedor.

<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>

Os valores de segredos são somente escrita.
Guarde o id `sec_...` retornado para o corpo de criação, e o valor da chave em si para seus clientes.

## Passo 2 - Crie o serviço

Crie o serviço com um cabeçalho `Idempotency-Key` obrigatório, exatamente como para jobs.
Este exemplo serve o Qwen2.5-0.5B-Instruct com o servidor compatível com OpenAI do vLLM, reproduzindo o smoke test da 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 os campos:

| Campo                                                 | Observações                                                                                                                                                                                             |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `container.ports`                                     | Cada porta precisa de um nome único, uma porta do contêiner e um protocolo `http` ou `tcp`. Toda porta nomeada é exposta no endpoint público do serviço.                                                |
| `service.readiness`                                   | Referencia uma porta declarada pelo nome, nunca pelo número. Uma sonda `http` exige que o protocolo daquela porta seja `http`; uma sonda `tcp` recebe apenas o nome da porta.                           |
| `secret_env.VLLM_API_KEY`                             | O vLLM lê `VLLM_API_KEY` nativamente e passa a exigi-la como token bearer em toda requisição.                                                                                                           |
| `--enable-auto-tool-choice --tool-call-parser hermes` | Obrigatórios se o [gateway de LLM](#passo-5---registre-no-gateway-de-llm) for chamar este endpoint: o gateway envia `tool_choice: "auto"` por padrão, e um vLLM sem essas flags rejeita isso com `400`. |

Como nos jobs, `201` significa que a requisição foi aceita; problemas de capacidade e provisionamento aparecem depois através de `state`, `reason`, logs e eventos.

## Passo 3 - Aguarde ficar pronto

<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>

O download e o carregamento do modelo acontecem dentro da carga de trabalho, então espere minutos de `provisioning` antes de a sonda de prontidão passar.
Um serviço pronto carrega seus 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
}
```

Se, em vez disso, o serviço cair em `failed`, leia o `reason`, depois `GET .../logs?source=user` para a saída do próprio servidor e `source=system` para problemas de alocação e bootstrap — a mesma superfície de logs e eventos dos [jobs](/pt/docs/compute-fine-tune-job#passo-5---leia-logs-e-eventos).

## Passo 4 - Chame seu endpoint

O endpoint é vLLM puro: uma API compatível com OpenAI autenticada com a chave que você armazenou no Passo 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."}]
  }'
```

Uma requisição sem a chave é rejeitada pelo próprio vLLM — o Compute não fica na frente do seu endpoint.

<Warning>
  Verifique o esquema da `url` do endpoint antes de enviar qualquer coisa sensível.
  Dependendo de onde a capacidade foi alocada, um endpoint pode ser servido por `http` puro, caso em que tokens bearer e payloads cruzam a internet sem criptografia.
</Warning>

## Passo 5 - Registre no gateway de LLM

Opcionalmente, registre o endpoint como um modelo bring-your-own no gateway de LLM da MKA1, para que ele possa ser chamado através da API `/responses` da plataforma com chaves normais da plataforma.

Adicione o endpoint ao seu 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>"}
  }'
```

Depois registre o id de modelo retornado:

```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>"
  }'
```

Modelos no formato `completions` são aceitos em `/responses`; o gateway conduz o upstream de chat-completions por você.
É por isso que o corpo de criação no Passo 2 passou as flags de tool-choice ao vLLM.

## Passo 6 - Encerre o serviço

Um serviço executa, e cobra, até você pará-lo.

<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>

O encerramento é idempotente, desaloca o recurso do provedor e interrompe os gastos; o registro permanece legível para auditoria e uso.

## Sirva um modelo a partir do mka1-repos

Para servir pesos do [mka1-repos](/pt/docs/repositories) — como a saída mesclada de um [job de ajuste fino](/pt/docs/compute-fine-tune-job#use-o-mka1-repos-para-datasets-e-pesos), ou pesos que você [enviou via git](/pt/docs/repositories) — mude apenas o identificador do modelo e as credenciais.

O Compute sempre injeta `HF_ENDPOINT` em toda carga de trabalho, apontando para o endpoint de artefatos configurado para o seu cluster, e o vLLM resolve identificadores de modelo contra ele.
O mka1-repos autentica com sua chave de API MKA1, injetada como `HF_TOKEN` através de `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"}
    ]
  }
}
```

O serviço baixa os pesos do repositório da sua organização na inicialização e os serve sob o mesmo identificador, fechando o ciclo: fazer o ajuste fino como job, publicar no mka1-repos, servir como serviço.

## Acompanhe os gastos

Os gastos de serviço acumulam por minuto inteiro a partir da alocação e aparecem junto com os jobs no 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>

Os gastos do Compute saem dos mesmos orçamentos da organização que qualquer outro serviço MKA1, e um serviço que atinge um orçamento da organização ou seus próprios `limits` é encerrado sem período de carência.

## Referência da API

Para o esquema completo de requisição e resposta, abra os grupos do Compute na [Referência de API](/pt/api-reference/introduction).

## Veja também

* [Executar um job de ajuste fino](/pt/docs/compute-fine-tune-job) - produza os pesos que este serviço serve.
* [Gerenciar repositórios](/pt/docs/repositories) - crie e gerencie os repositórios dos quais este serviço baixa pesos.
* [Usar repositórios com o Compute](/pt/docs/repositories) - envie pesos via git e sirva-os por referência.
* [Gerar uma resposta](/pt/docs/generate-a-response) - chame seu modelo registrado através da API `/responses` da plataforma.
