mirror of
https://github.com/docker/docker-agent.git
synced 2026-11-04 10:02:15 +00:00
feat: add CloudGPU provider to the embedded catalog
Register cloudgpu as an OpenAI-compatible catalog provider at https://cloudgpu.app/v1, discover CLOUDGPU_API_KEY, and default to deepseek-v4.1-flash. Co-authored-by: CloudGPU <mrhy7176@users.noreply.github.com>
This commit is contained in:
14 files changed
+208
-5
No files matched your search
+1
-1
@@ -224,7 +224,7 @@
|
||||
"properties": {
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"description": "The underlying provider type. Defaults to \"openai\" when not set. Supported values: openai, anthropic, google, amazon-bedrock, dmr, and any built-in alias (requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, azure, xai, ollama, mistral, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, opencode, opencode-go, etc.).",
|
||||
"description": "The underlying provider type. Defaults to \"openai\" when not set. Supported values: openai, anthropic, google, amazon-bedrock, dmr, and any built-in alias (requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, cloudgpu, azure, xai, ollama, mistral, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, opencode, opencode-go, etc.).",
|
||||
"examples": [
|
||||
"openai",
|
||||
"anthropic",
|
||||
|
||||
@@ -18,7 +18,7 @@ models:
|
||||
first_available: [list] # Optional: candidate model refs, tried in order by available credentials.
|
||||
# Mutually exclusive with other model settings.
|
||||
provider: string # Required unless using first_available. One of: openai, anthropic, google, amazon-bedrock,
|
||||
# dmr, mistral, xai, nebius, nvidia, minimax, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud,
|
||||
# dmr, mistral, xai, nebius, nvidia, minimax, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, cloudgpu,
|
||||
# azure, ollama, github-copilot, or a named provider defined
|
||||
# under the top-level `providers:` section.
|
||||
model: string # Required: model identifier
|
||||
@@ -60,7 +60,7 @@ models:
|
||||
| Property | Type | Required | Description |
|
||||
| --------------------- | ---------- | -------- | ------------------------------------------------------------------------------------- |
|
||||
| `first_available` | array | ✗ | Candidate model references tried in order; selects the first whose credentials are configured. Mutually exclusive with other model settings. |
|
||||
| `provider` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Provider: `openai`, `anthropic`, `google`, `amazon-bedrock`, `dmr`, `mistral`, `xai`, `nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `api-route`, `lunaroute`, `orcarouter`, `atlascloud`, `azure`, `ollama`, `github-copilot`, `chatgpt`, `opencode`, `opencode-go`, or any [named provider](../../providers/custom/index.md). |
|
||||
| `provider` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Provider: `openai`, `anthropic`, `google`, `amazon-bedrock`, `dmr`, `mistral`, `xai`, `nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `api-route`, `lunaroute`, `orcarouter`, `atlascloud`, `cloudgpu`, `azure`, `ollama`, `github-copilot`, `chatgpt`, `opencode`, `opencode-go`, or any [named provider](../../providers/custom/index.md). |
|
||||
| `model` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Model name (e.g., `gpt-4o`, `claude-sonnet-4-5`, `gemini-3.5-flash`) |
|
||||
| `description` | string | ✗ | Informational, human-readable summary of the model's purpose or strengths (e.g., "fast and cheap, good for summaries"). Not sent to the model. Can be combined with `first_available` (a selector's description is kept when it resolves). |
|
||||
| `temperature` | float | ✗ | Sampling randomness. Range is provider-dependent — typically `0.0–2.0` (Anthropic caps at `1.0`). `0.0` is deterministic. |
|
||||
@@ -558,7 +558,7 @@ for a complete local-server configuration.
|
||||
## Custom HTTP Headers
|
||||
|
||||
For OpenAI-compatible providers (`openai`, `github-copilot`, `mistral`, `xai`,
|
||||
`nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `lunaroute`, `orcarouter`, `atlascloud`, `ollama`, and any custom provider using the OpenAI API),
|
||||
`nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `lunaroute`, `orcarouter`, `atlascloud`, `cloudgpu`, `ollama`, and any custom provider using the OpenAI API),
|
||||
`provider_opts.http_headers` adds arbitrary HTTP headers to every outgoing
|
||||
request:
|
||||
|
||||
|
||||
@@ -191,6 +191,8 @@
|
||||
url: /providers/cloudflare-workers-ai/
|
||||
- title: ChatGPT
|
||||
url: /providers/chatgpt/
|
||||
- title: CloudGPU
|
||||
url: /providers/cloudgpu/
|
||||
- title: DaoXE
|
||||
url: /providers/daoxe/
|
||||
- title: DeepSeek
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: "CloudGPU"
|
||||
description: "Use CloudGPU models with Docker Agent."
|
||||
keywords: docker agent, ai agents, model providers, llm, cloudgpu
|
||||
weight: 26
|
||||
canonical: https://docs.docker.com/ai/docker-agent/providers/cloudgpu/
|
||||
---
|
||||
|
||||
_Use CloudGPU models with Docker Agent._
|
||||
|
||||
## Overview
|
||||
|
||||
[CloudGPU](https://cloudgpu.app/api/docs) serves DeepSeek, Kimi, GLM and MiniMax
|
||||
models through an OpenAI-compatible API. Docker Agent includes built-in support
|
||||
for CloudGPU as an alias provider. Current model IDs are on the live
|
||||
[model list](https://cloudgpu.app/v1/models).
|
||||
|
||||
## Setup
|
||||
|
||||
1. Create an API key in the [CloudGPU console](https://cloudgpu.app/)
|
||||
2. Set the environment variable:
|
||||
|
||||
```bash
|
||||
export CLOUDGPU_API_KEY=your-api-key
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Inline Syntax
|
||||
|
||||
Use a CloudGPU model by prefixing its model ID with `cloudgpu/`:
|
||||
|
||||
```yaml
|
||||
agents:
|
||||
root:
|
||||
model: cloudgpu/deepseek-v4.1-flash
|
||||
description: Assistant using CloudGPU
|
||||
instruction: You are a helpful assistant.
|
||||
```
|
||||
|
||||
### Named Model
|
||||
|
||||
For more control over parameters:
|
||||
|
||||
```yaml
|
||||
models:
|
||||
cloudgpu_kimi:
|
||||
provider: cloudgpu
|
||||
model: kimi-k2.6
|
||||
temperature: 0.7
|
||||
max_tokens: 8192
|
||||
|
||||
agents:
|
||||
root:
|
||||
model: cloudgpu_kimi
|
||||
description: Assistant using CloudGPU
|
||||
instruction: You are a helpful assistant.
|
||||
```
|
||||
|
||||
When CloudGPU is selected automatically from available credentials, the default
|
||||
model is `deepseek-v4.1-flash`.
|
||||
|
||||
## Available Models
|
||||
|
||||
Some chat model IDs CloudGPU serves:
|
||||
|
||||
| Model ID | Model |
|
||||
| --- | --- |
|
||||
| `deepseek-v4.1-flash` | DeepSeek V4.1 Flash (default) |
|
||||
| `deepseek-v4-pro` | DeepSeek V4 Pro |
|
||||
| `kimi-k2.6` | Kimi K2.6 |
|
||||
| `glm-5.2` | GLM 5.2 |
|
||||
| `minimax-m3` | MiniMax M3 |
|
||||
|
||||
Model IDs are case-sensitive. The live [`/v1/models` endpoint](https://cloudgpu.app/v1/models)
|
||||
lists current IDs, and the [API docs](https://cloudgpu.app/api/docs) describe
|
||||
the endpoints. A listing does not guarantee that inference is currently available.
|
||||
|
||||
CloudGPU is absent from the embedded models.dev catalog. Docker Agent does not
|
||||
import context limits or attachment capabilities from CloudGPU's model list.
|
||||
Attachment capabilities fall back to text-only, so image and PDF attachments
|
||||
are dropped, with a warning logged once per model.
|
||||
|
||||
If you have verified that your chosen model accepts a particular attachment
|
||||
type, set `models.<name>.capabilities` to override detection. See
|
||||
[Attachment Capability Overrides](../../configuration/models/index.md#attachment-capability-overrides)
|
||||
for all supported flags.
|
||||
|
||||
## How It Works
|
||||
|
||||
CloudGPU is a built-in alias in Docker Agent:
|
||||
|
||||
- **API type:** OpenAI-compatible Chat Completions (`openai_chatcompletions`)
|
||||
- **Base URL:** `https://cloudgpu.app/v1`
|
||||
- **Token variable:** `CLOUDGPU_API_KEY`
|
||||
|
||||
Some models CloudGPU serves require a single leading system message, so Docker
|
||||
Agent coalesces consecutive system messages into one.
|
||||
|
||||
## Example: Code Assistant
|
||||
|
||||
```yaml
|
||||
agents:
|
||||
coder:
|
||||
model: cloudgpu/deepseek-v4.1-flash
|
||||
description: Code assistant using CloudGPU
|
||||
instruction: |
|
||||
You are an expert programmer.
|
||||
Write clean code and follow language best practices.
|
||||
toolsets:
|
||||
- type: filesystem
|
||||
- type: shell
|
||||
- type: think
|
||||
```
|
||||
@@ -73,6 +73,7 @@ Use this table to find a built-in provider's config key and authentication metho
|
||||
| OrcaRouter | `orcarouter` | `ORCAROUTER_API_KEY` |
|
||||
| Atlas Cloud | [`atlascloud`](../atlascloud/index.md) | `ATLASCLOUD_API_KEY` |
|
||||
| Runcrate | [`runcrate`](../runcrate/index.md) | `RUNCRATE_API_KEY` |
|
||||
| CloudGPU | [`cloudgpu`](../cloudgpu/index.md) | `CLOUDGPU_API_KEY` |
|
||||
| Azure OpenAI | `azure` | `AZURE_API_KEY` + `base_url` (override the key with `token_key`) |
|
||||
| [Ollama](../local/index.md) | `ollama` | None (local; optional `base_url`) |
|
||||
| GitHub Copilot | `github-copilot` | `GITHUB_TOKEN` or `GH_TOKEN` (PAT with `copilot` scope) |
|
||||
|
||||
@@ -223,6 +223,7 @@ remote MCP endpoints.
|
||||
| [`huggingface.yaml`](huggingface.yaml) | Hugging Face Inference Providers open-model router. |
|
||||
| [`moonshot.yaml`](moonshot.yaml) | Moonshot AI Kimi provider (`moonshotai`). |
|
||||
| [`vercel.yaml`](vercel.yaml) | Vercel AI Gateway multi-provider router. |
|
||||
| [`cloudgpu.yaml`](cloudgpu.yaml) | CloudGPU OpenAI-compatible provider (`cloudgpu`). |
|
||||
| [`cloudflare-workers-ai.yaml`](cloudflare-workers-ai.yaml) | Cloudflare Workers AI edge-hosted open models. |
|
||||
| [`cloudflare-ai-gateway.yaml`](cloudflare-ai-gateway.yaml) | Cloudflare AI Gateway multi-provider router. |
|
||||
| [`grok.yaml`](grok.yaml) | xAI Grok model. |
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# yaml-language-server: $schema=../agent-schema.json
|
||||
|
||||
models:
|
||||
cloudgpu_model:
|
||||
provider: cloudgpu
|
||||
model: deepseek-v4.1-flash
|
||||
|
||||
agents:
|
||||
root:
|
||||
model: cloudgpu_model
|
||||
description: Assistant using CloudGPU
|
||||
instruction: |
|
||||
You are a helpful assistant.
|
||||
toolsets:
|
||||
- type: filesystem
|
||||
- type: shell
|
||||
- type: think
|
||||
+20
-1
@@ -113,6 +113,13 @@ func TestAvailableProviders_NoGateway(t *testing.T) {
|
||||
},
|
||||
expectedProvider: "runcrate",
|
||||
},
|
||||
{
|
||||
name: "cloudgpu api key present",
|
||||
envVars: map[string]string{
|
||||
"CLOUDGPU_API_KEY": "test-key",
|
||||
},
|
||||
expectedProvider: "cloudgpu",
|
||||
},
|
||||
{
|
||||
name: "baseten api key present",
|
||||
envVars: map[string]string{
|
||||
@@ -379,6 +386,15 @@ func TestAutoModelConfig(t *testing.T) {
|
||||
expectedModel: "deepseek-ai/DeepSeek-V4.1-Flash",
|
||||
expectedMaxTokens: 32000,
|
||||
},
|
||||
{
|
||||
name: "cloudgpu provider",
|
||||
envVars: map[string]string{
|
||||
"CLOUDGPU_API_KEY": "test-key",
|
||||
},
|
||||
expectedProvider: "cloudgpu",
|
||||
expectedModel: "deepseek-v4.1-flash",
|
||||
expectedMaxTokens: 32000,
|
||||
},
|
||||
{
|
||||
name: "lunaroute provider",
|
||||
envVars: map[string]string{"LUNAROUTE_API_KEY": "lr_test"},
|
||||
@@ -596,6 +612,7 @@ func TestDefaultModels(t *testing.T) {
|
||||
assert.Equal(t, "meta-llama/llama-4-maverick", DefaultModels["openrouter"])
|
||||
assert.Equal(t, "orcarouter/auto", DefaultModels["orcarouter"])
|
||||
assert.Equal(t, "glm-5.3", DefaultModels["lunaroute"])
|
||||
assert.Equal(t, "deepseek-v4.1-flash", DefaultModels["cloudgpu"])
|
||||
assert.Equal(t, "qwen/qwen3.8-max", DefaultModels["atlascloud"])
|
||||
assert.Equal(t, "deepseek-ai/DeepSeek-V4-Pro-0813", DefaultModels["baseten"])
|
||||
assert.Equal(t, "Qwen3.5-397B-A17B", DefaultModels["ovhcloud"])
|
||||
@@ -616,7 +633,7 @@ func TestAutoModelConfig_IntegrationWithDefaultModels(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Verify that AutoModelConfig always returns a model from DefaultModels
|
||||
providers := []string{"openai", "anthropic", "google", "mistral", "openrouter", "api-route", "orcarouter", "atlascloud", "baseten", "ovhcloud", "groq", "fireworks-ai", "deepseek", "cerebras", "togetherai", "huggingface", "moonshotai", "vercel", "opencode", "github-copilot"}
|
||||
providers := []string{"openai", "anthropic", "google", "mistral", "openrouter", "api-route", "orcarouter", "atlascloud", "cloudgpu", "baseten", "ovhcloud", "groq", "fireworks-ai", "deepseek", "cerebras", "togetherai", "huggingface", "moonshotai", "vercel", "opencode", "github-copilot"}
|
||||
|
||||
for _, provider := range providers {
|
||||
t.Run(provider, func(t *testing.T) {
|
||||
@@ -644,6 +661,8 @@ func TestAutoModelConfig_IntegrationWithDefaultModels(t *testing.T) {
|
||||
envVars["ORCAROUTER_API_KEY"] = "test-key"
|
||||
case "atlascloud":
|
||||
envVars["ATLASCLOUD_API_KEY"] = "test-key"
|
||||
case "cloudgpu":
|
||||
envVars["CLOUDGPU_API_KEY"] = "test-key"
|
||||
case "baseten":
|
||||
envVars["BASETEN_API_KEY"] = "test-key"
|
||||
case "ovhcloud":
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/docker/docker-agent/pkg/config/latest"
|
||||
"github.com/docker/docker-agent/pkg/environment"
|
||||
)
|
||||
|
||||
func TestCloudGPURequiredCredentials(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := &latest.Config{
|
||||
Agents: []latest.AgentConfig{{Name: "root", Model: "cloudgpu/deepseek-v4.1-flash"}},
|
||||
Models: map[string]latest.ModelConfig{
|
||||
"cloudgpu/deepseek-v4.1-flash": {Provider: "cloudgpu", Model: "deepseek-v4.1-flash"},
|
||||
},
|
||||
}
|
||||
err := CheckRequiredEnvVars(t.Context(), cfg, "", environment.NewNoEnvProvider())
|
||||
var required *environment.RequiredEnvError
|
||||
require.ErrorAs(t, err, &required)
|
||||
assert.Equal(t, []string{"CLOUDGPU_API_KEY"}, required.Missing)
|
||||
assert.True(t, required.MissingModelCredentials)
|
||||
require.NoError(t, CheckRequiredEnvVars(t.Context(), cfg, "", environment.NewMapEnvProvider(map[string]string{"CLOUDGPU_API_KEY": "test-key"})))
|
||||
}
|
||||
@@ -32,6 +32,7 @@ var modelsDevAbsentProviders = map[string]bool{
|
||||
"api-route": true, // API Route model IDs come from its own /v1/models endpoint, not models.dev.
|
||||
"lunaroute": true, // Lunaroute model IDs come from its own /v1/models endpoint, not models.dev.
|
||||
"atlascloud": true, // Atlas Cloud model IDs come from its own /v1/models endpoint, not models.dev.
|
||||
"cloudgpu": true, // CloudGPU model IDs come from its own /v1/models endpoint, not models.dev.
|
||||
"runcrate": true, // Runcrate model IDs come from its own /v1/models endpoint, not models.dev.
|
||||
"dmr": true, // Docker Model Runner (local, not in catalog)
|
||||
"cloudflare-workers-ai": true, // example uses an @cf/... model id not present in the models.dev snapshot (only variant ids like -fp8 are listed)
|
||||
|
||||
@@ -134,6 +134,16 @@
|
||||
"RUNCRATE_API_KEY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cloudgpu",
|
||||
"merge_consecutive_messages": true,
|
||||
"api_type": "openai",
|
||||
"base_url": "https://cloudgpu.app/v1",
|
||||
"default_model": "deepseek-v4.1-flash",
|
||||
"token_env_vars": [
|
||||
"CLOUDGPU_API_KEY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "baseten",
|
||||
"merge_consecutive_messages": true,
|
||||
|
||||
@@ -74,6 +74,7 @@ func TestProviderIDsMatchEmbeddedCatalog(t *testing.T) {
|
||||
absent := map[string]string{
|
||||
"api-route": "model IDs come from API Route's /v1/models endpoint, not models.dev",
|
||||
"atlascloud": "model IDs come from Atlas Cloud's /v1/models endpoint, not models.dev",
|
||||
"cloudgpu": "model IDs come from CloudGPU's /v1/models endpoint, not models.dev",
|
||||
"chatgpt": "subscription backend, distinct from OpenAI",
|
||||
"lunaroute": "model IDs come from Lunaroute’s /v1/models endpoint, not models.dev",
|
||||
"runcrate": "model IDs come from Runcrate's /v1/models endpoint, not models.dev",
|
||||
|
||||
@@ -164,6 +164,7 @@ func TestShouldMergeConsecutiveMessages_Gating(t *testing.T) {
|
||||
{"daoxe, no base_url", &latest.ModelConfig{Provider: "daoxe", Model: "claude-sonnet-4-6"}, true},
|
||||
{"opper, no base_url", &latest.ModelConfig{Provider: "opper", Model: "claude-sonnet-4-6"}, true},
|
||||
{"runcrate, no base_url", &latest.ModelConfig{Provider: "runcrate", Model: "deepseek-ai/DeepSeek-V4.1-Flash"}, true},
|
||||
{"cloudgpu, no base_url", &latest.ModelConfig{Provider: "cloudgpu", Model: "deepseek-v4.1-flash"}, true},
|
||||
{"ovhcloud", &latest.ModelConfig{Provider: "ovhcloud", Model: "Qwen3.5-397B-A17B"}, true},
|
||||
{"open-model host alias cerebras", &latest.ModelConfig{Provider: "cerebras", Model: "qwen-3-coder-480b"}, true},
|
||||
{"open-model host fireworks", &latest.ModelConfig{Provider: "fireworks", Model: "accounts/fireworks/models/kimi-k3"}, true},
|
||||
|
||||
@@ -97,6 +97,14 @@ var openAIAliasProviders = []openAIAliasProvider{
|
||||
greeting: "Hello from Runcrate",
|
||||
mergesSystemMessages: true,
|
||||
},
|
||||
{
|
||||
provider: "cloudgpu",
|
||||
envVar: "CLOUDGPU_API_KEY",
|
||||
testKey: "test-cloudgpu-key",
|
||||
model: "deepseek-v4.1-flash",
|
||||
greeting: "Hello from CloudGPU",
|
||||
mergesSystemMessages: true,
|
||||
},
|
||||
{
|
||||
provider: "deepseek",
|
||||
envVar: "DEEPSEEK_API_KEY",
|
||||
|
||||
Reference in new issue
Block a user