Skip to main content

Migrate from the standalone adapters

Move a DIAL deployment from the standalone OpenAI, Bedrock, Vertex AI, and DIAL-to-DIAL adapters to DIAL Model Provider. This guide is for platform engineers who maintain the DIAL Core configuration. It assumes you know how a model declares interfaces and how upstreams work. It is checked against DIAL Model Provider 0.1.0-rc.0 and DIAL Core 0.49.4.

Prerequisites​

  • The environment variables of every standalone adapter you run.
  • Access to the DIAL Core configuration: the config file, the Configuration API, or DIAL Admin.

How routing changes​

The migrated models use interfaces instead of endpoint. A model's baseUrl becomes the DIAL Model Provider root of its adapter:

Standalone adapterModel baseUrl with DIAL Model Provider
http://adapter-openai:5000http://model-provider:5000/compat/openai
http://adapter-vertexai:5000http://model-provider:5000/compat/vertexai
http://adapter-bedrock:5000http://model-provider:5000/compat/bedrock
http://adapter-dial:5000http://model-provider:5000/compat/dial

endpoint is a complete URL that Core uses as is, so it carried the adapter's deployment ID in its path. An interfaces entry works differently. Core appends the path it received to the base URL, and rewrites the /deployments/<id>/ segment to the model's overrideName, or to the model name when none is set. So when the deployment ID in the old endpoint differs from the model name, set overrideName to that ID.

Step 1: Deploy DIAL Model Provider​

  1. Merge the environment variables of your standalone adapters into one environment. Check the shared variables: a variable that several adapters read now takes one value for all of them. If the Bedrock adapter used DEFAULT_REGION, rename it to AWS_DEFAULT_REGION; see Region variables.
  2. Deploy the epam/ai-dial-model-provider:0.1.0-rc.0 image next to the standalone adapters. See Deployment.
  3. Check that GET http://<MODEL_PROVIDER_HOST>:5000/health answers {"status": "ok"}.

The standalone adapters keep serving traffic until you change the models.

Step 2: Rewrite each model​

For each model whose endpoint points at a standalone adapter:

  1. Remove endpoint and responsesEndpoint.
  2. Set baseUrl to the DIAL Model Provider root of its adapter, from the table above.
  3. Declare the APIs the model serves under interfaces. An empty entry, {}, is a pass-through interface served by the model's baseUrl.
  4. Set overrideName to the deployment ID from the old endpoint path, when it differs from the model name.
Old fieldInterface
endpoint on a chat modelopenaiChatCompletions
endpoint on an embedding modelopenaiEmbeddings
responsesEndpointopenaiResponses

openaiChatCompletions and openaiEmbeddings never stand in for each other, so declare openaiEmbeddings for an embedding model. A model that already serves an interface through its own base_url, such as anthropicMessages, keeps the entry: change its base_url to the matching /compat/<adapter> root.

Step 3: Rewrite the upstreams​

For each upstream of a migrated model:

  1. Give the upstream an id. Core rejects a model whose upstream declares interfaces without one.
  2. Move endpoint to interfaces.<interface>.endpoint, and responsesEndpoint to interfaces.openaiResponses.endpoint.
  3. Keep key, extraData, and secretExtraData on the upstream. Every interface entry inherits them unless it sets its own.

Core passes the URL of the requested interface to the adapter in the X-UPSTREAM-ENDPOINT header, as it does for endpoint. A model without upstreams, such as the Bedrock and Vertex AI models in the example, needs no change here.

Warning

Feature calls (tokenize, truncate_prompt, and configuration) send the adapter the first upstream's top-level endpoint, not its interfaces. The OpenAI adapter's feature endpoints fail without it. On a model that sets features.tokenizeEndpoint, features.truncatePromptEndpoint, or features.configurationEndpoint, keep endpoint on its upstreams as well.

Step 4: Repoint feature endpoints and translators​

These fields are complete URLs, so insert the /compat/<adapter> prefix after the host:

FieldBeforeAfter
features.tokenizeEndpointhttp://adapter-openai:5000/openai/deployments/gpt-4o/tokenizehttp://model-provider:5000/compat/openai/openai/deployments/gpt-4o/tokenize
features.truncatePromptEndpoint, features.configurationEndpoint, features.rateEndpointhttp://adapter-<adapter>:5000/…http://model-provider:5000/compat/<adapter>/…
Translator baseUrlhttp://adapter-bedrock:5000/openaiChatCompletionshttp://model-provider:5000/compat/bedrock/openaiChatCompletions

See Features and Translators.

Example​

Three models before the migration, on the standalone adapters:

{
"models": {
"gpt-4o": {
"type": "chat",
"endpoint": "http://adapter-openai:5000/openai/deployments/gpt-4o/chat/completions",
"upstreams": [
{
"endpoint": "https://contoso.openai.azure.com/openai/deployments/gpt-4o/chat/completions",
"key": "<AZURE_OPENAI_KEY>"
}
]
},
"gemini-2.5-pro": {
"type": "chat",
"endpoint": "http://adapter-vertexai:5000/openai/deployments/gemini-2.5-pro/chat/completions"
},
"anthropic.claude-sonnet-4-5": {
"type": "chat",
"endpoint": "http://adapter-bedrock:5000/openai/deployments/anthropic.claude-sonnet-4-5-20250929-v1:0/chat/completions"
}
}
}

The same models after the migration, on DIAL Model Provider with interfaces:

{
"models": {
"gpt-4o": {
"type": "chat",
"baseUrl": "http://model-provider:5000/compat/openai",
"interfaces": {
"openaiChatCompletions": {}
},
"upstreams": [
{
"id": "contoso",
"key": "<AZURE_OPENAI_KEY>",
"interfaces": {
"openaiChatCompletions": {
"endpoint": "https://contoso.openai.azure.com/openai/deployments/gpt-4o/chat/completions"
}
}
}
]
},
"gemini-2.5-pro": {
"type": "chat",
"baseUrl": "http://model-provider:5000/compat/vertexai",
"interfaces": {
"openaiChatCompletions": {}
}
},
"anthropic.claude-sonnet-4-5": {
"type": "chat",
"overrideName": "anthropic.claude-sonnet-4-5-20250929-v1:0",
"baseUrl": "http://model-provider:5000/compat/bedrock",
"interfaces": {
"openaiChatCompletions": {}
}
}
}
}

Chat Completions requests for these models go to:

ModelDIAL Model Provider URL
gpt-4ohttp://model-provider:5000/compat/openai/openai/deployments/gpt-4o/chat/completions
gemini-2.5-prohttp://model-provider:5000/compat/vertexai/openai/deployments/gemini-2.5-pro/chat/completions
anthropic.claude-sonnet-4-5http://model-provider:5000/compat/bedrock/openai/deployments/anthropic.claude-sonnet-4-5-20250929-v1:0/chat/completions

The Bedrock model name differs from its Bedrock model ID, so overrideName carries the ID.

Result​

Send a request through DIAL Core for each migrated model:

curl -X POST "http://0.0.0.0:8080/openai/deployments/gpt-4o/chat/completions" \
-H "Api-Key: <DIAL_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "What is 2 + 3?"}]}'

When every model answers, stop the standalone adapter containers.

SymptomWhat to check
Core rejects the modelEach interface needs a base URL: its own base_url or the model's baseUrl. Each upstream that declares interfaces needs an id.
The Bedrock adapter answers 404The deployment segment carries the model name, not the Bedrock model ID. Set overrideName.
A tokenize or truncate call fails with X-UPSTREAM-ENDPOINT header is missingKeep the top-level endpoint on the model's upstreams. See Step 3.
Requests fail with Connection was closedTIMEOUT_KEEP_ALIVE is not above DIAL Core's client.keepAliveTimeout. See Keep-alive timeout.

Further reading​