Skip to content

fix: generate_dial_config drops model features, misses models, and crashes on localized applications #544

Description

@andrii-novikov

QuickApps version

0.11.1

What steps will reproduce the bug?

make generate_dial_config

(equivalently: poetry run python src/scripts/generate_dial_config.py --models --template docker_compose_files/core/configuration/models-template.json --config docker_compose_files/core/configuration/generated/models.json --applications dial-rag,dial-web-rag)

Three independent problems show up in one run.

1. Model features are stripped by a hardcoded whitelist

DIALModelFeatures (src/scripts/generate_dial_config.py:74-83) declares only 9 boolean fields, so Pydantic's default extra="ignore" discards every other feature the upstream returns, and to_config() (:85-97) then emits a hardcoded 5-key dict. Anything new upstream is dropped twice over.

reasoningEfforts is the current casualty:

grep -c reasoningEfforts docker_compose_files/core/configuration/generated/models.json
# 0

even though GET /openai/models returns reasoning_efforts on all 210 models, non-empty on 13 of them:

"gpt-5.5-2026-04-24": { "features": { "reasoning_efforts": ["low", "medium", "high"] } }
"gemini-3.1-flash-lite": { "features": { "reasoning_efforts": ["low", "medium", "high"] } }

Across the 207 generated models the only feature keys present are systemPromptSupported, toolsSupported, urlAttachmentsSupported, folderAttachmentsSupported and configurationEndpoint.

2. Not every upstream model reaches the local config

gemini-3.5-flash is visible in the admin UI (https://admin.aks.dev.dial.parts/en/models) but never lands in models.json. It is not a script filter — the model is not visible to REMOTE_DIAL_API_KEY at all:

GET /openai/deployments/gemini-3.5-flash        -> 403
GET /openai/deployments/gemini-3-flash-preview  -> 200
GET /openai/models                              -> 210 models, no gemini-3.5* among them

The run reports nothing about this: the config is silently generated without the model. (Separately, 4 upstream ids — kk_test_upstream_extra_data, kuber-fe-model-json, sla-test, test-model-check-all — are skipped correctly, as they declare neither chat_completion nor embeddings.)

3. The applications loader crashes the whole run

DIALDeploymentBase types display_name and description as str | None (:52-54), but DIAL returns a per-locale dict for localized deployments. Unlike to_config_model, to_config_application (:218) has no try/except, so a single unparseable application aborts everything — including the models half, which had already been computed but is never written.

What is the expected behavior?

make generate_dial_config produces a complete, current local model catalog:

  1. Every feature the upstream advertises reaches models.json — adding a new feature upstream should require no script change, just a re-run.
  2. Every model the environment exposes is present, and anything skipped (unsupported capabilities, no access) is reported on stdout rather than silently omitted.
  3. One malformed or localized application does not abort the run.

What do you see instead?

  1. features limited to 5 keys; reasoningEfforts absent for all 207 models. QuickApps reads this via aidial_client.types.deployment.Features.reasoning_efforts, so locally every model looks like it supports no reasoning effort.
  2. gemini-3.5-flash and anything else the key cannot see is missing, with no warning.
  3. The run dies before writing the file:
pydantic_core._pydantic_core.ValidationError: 2 validation errors for DIALApplication
display_name
  Input should be a valid string [type=string_type, input_value={'fr': '[FR] QA 2.0 14.08...0 14.08 default locale'}, input_type=dict]
description
  Input should be a valid string [type=string_type, input_value={'fr': '[FR] QA 2.0 14.08...fault locale', 'en': ''}, input_type=dict]

Additional information

Suggested direction for each:

  1. Pass features through instead of whitelisting them — e.g. keep DIALModelFeatures for the fields that need renaming/derivation (configurationEndpoint) and carry the rest verbatim from the upstream payload, or at minimum set extra="allow" and merge the extras. DIAL Core accepts both spellings (@JsonAlias({"reasoningEfforts", "reasoning_efforts"}) in Features.java), so a passthrough round-trips. A stopgap for reasoningEfforts alone is one field plus one dict entry, but the same gap reopens with the next feature.
  2. Decide whether the generator should use credentials that see the whole catalog (admin API) or whether the dev key's grants should be widened; either way the script should print what it could not fetch.
  3. Widen display_name / description to str | dict[str, str] | None (matching aidial_client.types.deployment.DeploymentBase, which already types them that way) and give to_config_application the same try/except ValidationError + logger.exception treatment to_config_model has, so one bad application is skipped rather than fatal.

Related: #538 (forwarding reasoning_effort / static tools to deployment tools) surfaced item 1 — with no reasoningEfforts in the local catalog, the app's validation treats every local deployment as not supporting reasoning effort.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions