@aiuby-ia/cli 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -2
- package/THIRD_PARTY_LICENSES.md +58 -0
- package/dist/aiuby.mjs +20956 -0
- package/docs/api.md +115 -0
- package/docs/cli.md +98 -0
- package/package.json +40 -4
- package/templates/fastapi-http/Dockerfile +10 -0
- package/templates/fastapi-http/aiuby.toml +17 -0
- package/templates/fastapi-http/main.py +19 -0
- package/templates/fastapi-http/requirements.txt +2 -0
- package/templates/langgraph-agent/Dockerfile +10 -0
- package/templates/langgraph-agent/aiuby.toml +17 -0
- package/templates/langgraph-agent/main.py +40 -0
- package/templates/langgraph-agent/requirements.txt +3 -0
- package/templates/vllm-openai/Dockerfile +6 -0
- package/templates/vllm-openai/aiuby.toml +21 -0
package/docs/api.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Referência da API do Compute
|
|
2
|
+
|
|
3
|
+
Base: `https://aiuby.com/api/platform/compute`. Respostas em JSON.
|
|
4
|
+
|
|
5
|
+
## Autenticação
|
|
6
|
+
|
|
7
|
+
- **Leitura (`GET`)**: sessão da área logada, ou `Authorization: Bearer <chave>` com uma chave
|
|
8
|
+
de API de escopo `compute:read`. A chave vale para um workspace.
|
|
9
|
+
- **Escrita (`POST`)**: sessão de uma pessoa com permissão de gerenciar o workspace, ou chave
|
|
10
|
+
de API com o escopo `compute:write`. Limite: 30 alterações por minuto por pessoa ou chave.
|
|
11
|
+
O escopo `compute:write` não inclui leitura: para ler, a chave precisa também de `compute:read`.
|
|
12
|
+
|
|
13
|
+
## Erros
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{ "error": { "code": "compute_not_deployable", "message": "..." } }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`code` aparece só em alguns erros. Status usados: `400` dados inválidos, `401` sem
|
|
20
|
+
autenticação, `403` sem permissão, `404` não encontrado ou Compute não contratado,
|
|
21
|
+
`409` conflito, `429` muitas chamadas.
|
|
22
|
+
|
|
23
|
+
## Leitura
|
|
24
|
+
|
|
25
|
+
### `GET /whoami`
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{ "organization": "Acme", "workspace": "Principal", "workspaceSlug": "principal",
|
|
29
|
+
"organizationId": "...", "workspaceId": "...", "kind": "credential", "role": null }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### `GET /apps`
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{ "apps": [ { "id": "...", "slug": "minha-api", "name": "Minha API", "currentRevision": 1,
|
|
36
|
+
"archived": false, "createdAt": "2026-11-12T12:00:00.000Z", "runtime": "container",
|
|
37
|
+
"hardwareLabel": "1 vCPU · 512 MB", "region": null } ] }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `GET /apps/{ref}`
|
|
41
|
+
|
|
42
|
+
`ref` é o id ou o identificador (slug). Devolve os campos da listagem mais `revisions`:
|
|
43
|
+
`[{ "revision": 1, "createdAt": "...", "config": { ... } }]`. Revisões são imutáveis.
|
|
44
|
+
|
|
45
|
+
### `GET /apps/{ref}/plan`
|
|
46
|
+
|
|
47
|
+
O plano de implantação da revisão atual. Só leitura.
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{ "deployable": false, "provider": null, "sku": null, "preview": false,
|
|
51
|
+
"blockers": ["runtime_not_enabled"],
|
|
52
|
+
"reasons": [ { "code": "runtime_not_enabled", "message": "A execução de aplicações ainda não está habilitada nesta plataforma." } ] }
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Bloqueios possíveis: `runtime_not_enabled`, `provider_not_enabled`, `sku_unknown`,
|
|
56
|
+
`gpu_count_unsupported`, `quota_unverified`, `no_rate_card`, `no_budget`, `build_not_supported`,
|
|
57
|
+
`preview_limits`, `preview_capacity`.
|
|
58
|
+
|
|
59
|
+
### `GET /capacity`
|
|
60
|
+
|
|
61
|
+
`hardware`: o catálogo de referência, cada item com `availability: "unverified"`.
|
|
62
|
+
`providers`: o que cada adaptador de nuvem implementa hoje.
|
|
63
|
+
|
|
64
|
+
### `GET /templates`
|
|
65
|
+
|
|
66
|
+
`templates`: os modelos de partida, com a configuração inicial de cada um.
|
|
67
|
+
|
|
68
|
+
## Escrita
|
|
69
|
+
|
|
70
|
+
### `POST /apps`
|
|
71
|
+
|
|
72
|
+
Cadastra a aplicação com a primeira revisão. Nada é implantado. Responde `201`.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{ "name": "Minha API", "slug": "minha-api",
|
|
76
|
+
"config": { "runtime": "container", "image": "REGISTRO/minha-api:1", "port": 8080,
|
|
77
|
+
"hardware": { "provider": "any", "cpu": 1, "memoryMb": 512 },
|
|
78
|
+
"scaling": { "minReplicas": 0, "maxReplicas": 2 } } }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Regras: `slug` com 3 a 40 caracteres (minúsculas, dígitos e hífen, começando por letra),
|
|
82
|
+
único no workspace; `runtime` `container` exige `image`; campos desconhecidos são recusados.
|
|
83
|
+
Limites: 50 aplicações por workspace, 200 revisões por aplicação.
|
|
84
|
+
|
|
85
|
+
### `POST /apps/{id}/revisions`
|
|
86
|
+
|
|
87
|
+
Corpo: a nova `config`. Cria uma revisão e a torna a atual. Responde `201`.
|
|
88
|
+
|
|
89
|
+
### `POST /apps/{id}/archive`
|
|
90
|
+
|
|
91
|
+
Corpo: `{ "archived": true }` ou `false`. Responde `204`.
|
|
92
|
+
|
|
93
|
+
### `GET /apps/{ref}/deployments`
|
|
94
|
+
|
|
95
|
+
Leitura. A implantação mais recente, já conferida com a conta de nuvem, ou `null`.
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{ "deployment": { "id": "...", "revision": 2, "status": "running",
|
|
99
|
+
"url": "https://...run.app", "error": null, "region": "southamerica-east1",
|
|
100
|
+
"createdAt": "...", "expiresAt": "..." } }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`status`: `deploying`, `running`, `failed` ou `stopped`.
|
|
104
|
+
|
|
105
|
+
### `POST /apps/{ref}/deployments`
|
|
106
|
+
|
|
107
|
+
Sessão de quem gerencia o workspace, ou chave com `compute:deploy`. Implanta a revisão atual.
|
|
108
|
+
Responde `202` com a implantação em `deploying`. Só funciona em organização com a prévia
|
|
109
|
+
do runtime; nas demais, e sempre que o plano tiver bloqueios, responde `409` com
|
|
110
|
+
`code: "compute_not_deployable"` e os motivos. Limites da prévia: CPU, até 1 vCPU e 1 GB,
|
|
111
|
+
1 réplica, endereço público, com prazo.
|
|
112
|
+
|
|
113
|
+
### `POST /apps/{ref}/deployments/stop`
|
|
114
|
+
|
|
115
|
+
Mesma autenticação. Apaga o serviço na nuvem e encerra a implantação. Responde `204`.
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Referência da CLI `aiuby`
|
|
2
|
+
|
|
3
|
+
Versão 0.3.0. A CLI fala só com a API da AIUBY: nunca pede nem usa credenciais da AWS ou
|
|
4
|
+
do Google Cloud.
|
|
5
|
+
|
|
6
|
+
Instalação: `npm install -g https://aiuby.com/cli/aiuby-cli-latest.tgz` (Node.js 20 ou mais novo).
|
|
7
|
+
|
|
8
|
+
## Autenticação
|
|
9
|
+
|
|
10
|
+
| Comando | O que faz |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `aiuby login [--url <endereço>]` | Lê uma chave de API do terminal (sem eco) ou da entrada padrão, confere com a API e guarda |
|
|
13
|
+
| `aiuby logout` | Apaga a chave deste computador |
|
|
14
|
+
| `aiuby whoami` | Mostra organização, workspace e endereço da API |
|
|
15
|
+
|
|
16
|
+
- A chave **nunca** é aceita como argumento, para não ficar no histórico do shell.
|
|
17
|
+
- Fica em `~/.config/aiuby/credentials.json`, com permissão `0600`.
|
|
18
|
+
- Uma chave que a API recusa não é guardada.
|
|
19
|
+
- A API precisa ser HTTPS. HTTP só é aceito em `localhost`.
|
|
20
|
+
|
|
21
|
+
Exemplo sem interação:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
printf '%s' "$CHAVE" | aiuby login
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Leitura
|
|
28
|
+
|
|
29
|
+
| Comando | O que faz |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `aiuby project list` | O projeto (workspace) da chave em uso |
|
|
32
|
+
| `aiuby apps list` | Aplicações cadastradas no workspace |
|
|
33
|
+
| `aiuby apps status <identificador>` | Detalhe, revisões e plano de uma aplicação |
|
|
34
|
+
| `aiuby capacity list [--provider gcp\|aws]` | Catálogo de hardware. É referência pública: cota, região e preço não foram verificados |
|
|
35
|
+
| `aiuby deploy --dry-run <identificador>` | O plano de implantação, sem criar nada. Sai com código 4 quando há bloqueios |
|
|
36
|
+
|
|
37
|
+
## Escrita
|
|
38
|
+
|
|
39
|
+
Exigem uma chave com os escopos "Ler o Compute" e "Gerenciar aplicações do Compute".
|
|
40
|
+
Nenhum destes comandos implanta: eles só registram a aplicação e a configuração.
|
|
41
|
+
|
|
42
|
+
| Comando | O que faz |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `aiuby apps create [arquivo]` | Cadastra a aplicação descrita no `aiuby.toml` (padrão: o do diretório atual), com a revisão r1 |
|
|
45
|
+
| `aiuby apps update [arquivo]` | Grava a configuração do arquivo como nova revisão da aplicação de mesmo `slug`. Sem mudança, não cria revisão. Não altera o nome |
|
|
46
|
+
|
|
47
|
+
## Implantação (prévia do runtime)
|
|
48
|
+
|
|
49
|
+
Exigem uma chave com o escopo "Implantar no Compute" e uma organização com a prévia do
|
|
50
|
+
runtime habilitada pela AIUBY. Fora dela, a API recusa com os motivos (código de saída 4).
|
|
51
|
+
|
|
52
|
+
| Comando | O que faz |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `aiuby deploy [--no-wait] <identificador>` | Implanta a revisão atual no Google Cloud e acompanha até ficar em execução (até 3 minutos). Mostra o endereço público e o prazo. Reimplantar troca a revisão no mesmo endereço |
|
|
55
|
+
| `aiuby stop <identificador>` | Para a implantação: o serviço é apagado e o endereço deixa de responder |
|
|
56
|
+
|
|
57
|
+
Limites da prévia: só CPU, até 1 vCPU e 1 GB, 1 réplica (escala a zero quando ociosa),
|
|
58
|
+
endereço público sem autenticação, prazo de algumas horas. Sem cobrança nesta fase.
|
|
59
|
+
|
|
60
|
+
## Local
|
|
61
|
+
|
|
62
|
+
| Comando | O que faz |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `aiuby init [template] [diretório]` | Copia um template de partida para um diretório novo ou vazio. Sem argumento, lista os templates |
|
|
65
|
+
| `aiuby config validate [arquivo]` | Valida um `aiuby.toml` (padrão: o do diretório atual). Não usa a rede |
|
|
66
|
+
| `aiuby doctor` | Confere versão do Node.js, credencial, permissão do arquivo e resposta da API |
|
|
67
|
+
|
|
68
|
+
## Ainda não disponíveis
|
|
69
|
+
|
|
70
|
+
`run`, `logs`, `scale`, `rollback`, `volumes`, `secrets`
|
|
71
|
+
e `domains` respondem que ainda não estão disponíveis e saem com código 4. Nenhum deles chama a API.
|
|
72
|
+
|
|
73
|
+
## Opções gerais
|
|
74
|
+
|
|
75
|
+
| Opção | Efeito |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `--json` | Saída em JSON, para scripts |
|
|
78
|
+
| `--help` | Ajuda |
|
|
79
|
+
| `--version` | Versão |
|
|
80
|
+
|
|
81
|
+
## Variáveis de ambiente
|
|
82
|
+
|
|
83
|
+
| Variável | Efeito |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `AIUBY_TOKEN` | Chave de API. Tem prioridade sobre o arquivo; use em CI |
|
|
86
|
+
| `AIUBY_API_URL` | Endereço da API (padrão `https://aiuby.com`) |
|
|
87
|
+
| `AIUBY_CONFIG_DIR` | Diretório do arquivo de credencial |
|
|
88
|
+
|
|
89
|
+
## Códigos de saída
|
|
90
|
+
|
|
91
|
+
| Código | Significado |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| 0 | Sucesso |
|
|
94
|
+
| 1 | Erro (rede, servidor, `doctor` com falha) |
|
|
95
|
+
| 2 | Uso incorreto |
|
|
96
|
+
| 3 | Não autenticado |
|
|
97
|
+
| 4 | Recusado: recurso indisponível, não encontrado, sem permissão ou plano com bloqueios |
|
|
98
|
+
| 5 | Configuração inválida (no arquivo, ou recusada pela API) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiuby-ia/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Linha de comando do AIUBY Compute",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"aiuby": "dist/aiuby.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"templates",
|
|
12
|
+
"docs",
|
|
13
|
+
"THIRD_PARTY_LICENSES.md"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=20"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "esbuild src/main.ts --bundle --platform=node --target=node20 --format=esm --banner:js='#!/usr/bin/env node' --outfile=dist/aiuby.mjs && chmod +x dist/aiuby.mjs",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"check": "npm run typecheck && npm test && npm run build"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^22.10.0",
|
|
26
|
+
"esbuild": "^0.25.0",
|
|
27
|
+
"smol-toml": "1.3.1",
|
|
28
|
+
"typescript": "^5.7.0",
|
|
29
|
+
"vitest": "^3.0.9",
|
|
30
|
+
"zod": "4.6.7"
|
|
31
|
+
},
|
|
32
|
+
"license": "UNLICENSED",
|
|
33
|
+
"homepage": "https://aiuby.com",
|
|
34
|
+
"keywords": [
|
|
35
|
+
"aiuby",
|
|
36
|
+
"compute",
|
|
37
|
+
"cli"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY requirements.txt .
|
|
4
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
5
|
+
COPY main.py .
|
|
6
|
+
# Usuário sem privilégio: o runtime não deve precisar de root.
|
|
7
|
+
RUN useradd --create-home app
|
|
8
|
+
USER app
|
|
9
|
+
EXPOSE 8080
|
|
10
|
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Configuração da aplicação no AIUBY Compute. Valide com: aiuby config validate
|
|
2
|
+
name = "Minha API"
|
|
3
|
+
slug = "minha-api"
|
|
4
|
+
|
|
5
|
+
[config]
|
|
6
|
+
runtime = "container"
|
|
7
|
+
image = "REGISTRO/minha-api:1"
|
|
8
|
+
port = 8080
|
|
9
|
+
|
|
10
|
+
[config.hardware]
|
|
11
|
+
provider = "any"
|
|
12
|
+
cpu = 1
|
|
13
|
+
memoryMb = 512
|
|
14
|
+
|
|
15
|
+
[config.scaling]
|
|
16
|
+
minReplicas = 0
|
|
17
|
+
maxReplicas = 2
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""API HTTP mínima. Ponto de partida do template "API HTTP com FastAPI" do AIUBY Compute."""
|
|
2
|
+
from fastapi import FastAPI
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
app = FastAPI(title="minha-api")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Entrada(BaseModel):
|
|
9
|
+
texto: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.get("/health")
|
|
13
|
+
def health() -> dict[str, str]:
|
|
14
|
+
return {"status": "ok"}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.post("/eco")
|
|
18
|
+
def eco(entrada: Entrada) -> dict[str, int | str]:
|
|
19
|
+
return {"texto": entrada.texto, "caracteres": len(entrada.texto)}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY requirements.txt .
|
|
4
|
+
RUN pip install --no-cache-dir -r requirements.txt
|
|
5
|
+
COPY main.py .
|
|
6
|
+
# Usuário sem privilégio: o runtime não deve precisar de root.
|
|
7
|
+
RUN useradd --create-home app
|
|
8
|
+
USER app
|
|
9
|
+
EXPOSE 8080
|
|
10
|
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Agente LangGraph por HTTP. Valide com: aiuby config validate
|
|
2
|
+
name = "Agente LangGraph"
|
|
3
|
+
slug = "agente-langgraph"
|
|
4
|
+
|
|
5
|
+
[config]
|
|
6
|
+
runtime = "container"
|
|
7
|
+
image = "REGISTRO/agente-langgraph:1"
|
|
8
|
+
port = 8080
|
|
9
|
+
|
|
10
|
+
[config.hardware]
|
|
11
|
+
provider = "any"
|
|
12
|
+
cpu = 1
|
|
13
|
+
memoryMb = 1024
|
|
14
|
+
|
|
15
|
+
[config.scaling]
|
|
16
|
+
minReplicas = 0
|
|
17
|
+
maxReplicas = 2
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Agente mínimo com LangGraph exposto por HTTP. Sem modelo embutido: o nó "responder"
|
|
2
|
+
é onde entra a chamada ao seu modelo (por exemplo, pelo Gateway da AIUBY)."""
|
|
3
|
+
from typing import TypedDict
|
|
4
|
+
|
|
5
|
+
from fastapi import FastAPI
|
|
6
|
+
from langgraph.graph import END, StateGraph
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Estado(TypedDict):
|
|
11
|
+
pergunta: str
|
|
12
|
+
resposta: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def responder(estado: Estado) -> Estado:
|
|
16
|
+
# Troque por uma chamada ao modelo. Aqui só devolve o que recebeu.
|
|
17
|
+
return {"pergunta": estado["pergunta"], "resposta": f"Recebi: {estado['pergunta']}"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
grafo = StateGraph(Estado)
|
|
21
|
+
grafo.add_node("responder", responder)
|
|
22
|
+
grafo.set_entry_point("responder")
|
|
23
|
+
grafo.add_edge("responder", END)
|
|
24
|
+
agente = grafo.compile()
|
|
25
|
+
|
|
26
|
+
app = FastAPI(title="agente-langgraph")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Entrada(BaseModel):
|
|
30
|
+
pergunta: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@app.get("/health")
|
|
34
|
+
def health() -> dict[str, str]:
|
|
35
|
+
return {"status": "ok"}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@app.post("/perguntar")
|
|
39
|
+
def perguntar(entrada: Entrada) -> dict[str, str]:
|
|
40
|
+
return dict(agente.invoke({"pergunta": entrada.pergunta, "resposta": ""}))
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Servidor compatível com a API da OpenAI sobre vLLM. O modelo é baixado na subida:
|
|
2
|
+
# escolha um que caiba na memória da GPU pedida e cuja licença permita o seu uso.
|
|
3
|
+
FROM vllm/vllm-openai:latest
|
|
4
|
+
ENV MODEL_ID="Qwen/Qwen2.5-1.5B-Instruct"
|
|
5
|
+
EXPOSE 8080
|
|
6
|
+
ENTRYPOINT ["/bin/sh", "-c", "python3 -m vllm.entrypoints.openai.api_server --model \"$MODEL_ID\" --host 0.0.0.0 --port 8080"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Inferência compatível com OpenAI em GPU. Valide com: aiuby config validate
|
|
2
|
+
name = "Inferência vLLM"
|
|
3
|
+
slug = "inferencia-vllm"
|
|
4
|
+
|
|
5
|
+
[config]
|
|
6
|
+
runtime = "container"
|
|
7
|
+
image = "REGISTRO/inferencia-vllm:1"
|
|
8
|
+
port = 8080
|
|
9
|
+
|
|
10
|
+
[config.hardware]
|
|
11
|
+
provider = "gcp"
|
|
12
|
+
cpu = 4
|
|
13
|
+
memoryMb = 16384
|
|
14
|
+
|
|
15
|
+
[config.hardware.gpu]
|
|
16
|
+
sku = "gcp-cloudrun-l4"
|
|
17
|
+
count = 1
|
|
18
|
+
|
|
19
|
+
[config.scaling]
|
|
20
|
+
minReplicas = 0
|
|
21
|
+
maxReplicas = 1
|