Skip to content

Upscaling dispatch: replace label/recipe ad-hoc guards with a capability interface #3349

Description

@ramkrishna2910

Summary

Upscaling is dispatched two different ways, with two different guards, and neither is a capability check. The result is that the same input is accepted on one path and rejected on the other.

The direct endpoint doesn't check the upscaling label

Server::handle_image_upscale resolves the model, reads its recipe, and dispatches — but never checks that the model is actually an upscaler. Verified at runtime against a local build:

POST /v1/images/upscale  {"model": "SD-Turbo", ...}

SD-Turbo is a generation model labelled image, not upscaling. It is accepted and handed to sd-cli as though it were an upscaler. (It failed later only because the sd-cpp backend wasn't installed in that cache directory — the label never entered into it.)

This is pre-existing behavior, not introduced by #3327.

The auto-upscale path does check the label, but not the recipe

#2842 adds Server::do_upscale, which gates on has_label(info.labels, "upscaling") and then hardcodes try_get_spec_for_recipe("sd-cpp") and SDServer::upscale_via_cli. So it enforces the label the endpoint ignores, and ignores the recipe the endpoint dispatches on.

Once both land, the two paths disagree in both directions:

Input /v1/images/upscale auto-upscale (upscale_model)
sd-cpp generation model (no upscaling label) accepted, sent to sd-cli rejected (400)
TheNoise upscaler (upscaling label, thenoise recipe) dispatched correctly accepted, sent to sd-cli — wrong binary

The second row is the harmful one: #3327 adds five recipe: "thenoise" upscalers, all suggested: true, so it is the natural thing for a user to select.

Proposal

Replace both ad-hoc guards with a capability interface alongside the others in src/cpp/include/lemon/server_capabilities.h — e.g. IUpscaleServer, with supports_capability<IUpscaleServer>(server) as the single gate. That gives one place that answers "can this model upscale, and who does it", rather than a label check in one path and a recipe if/else in the other.

Concretely:

  1. Add the capability interface and implement it on SDServer and TheNoiseServer.
  2. Replace the if (recipe == "thenoise") ... else if (recipe == "sd-cpp") chain in handle_image_upscale with a capability lookup.
  3. Have do_upscale use the same lookup instead of hardcoding sd-cpp.
  4. Keep the upscaling label as the discovery filter (what the UI lists), but make the capability the dispatch gate.

Context

Found while reviewing #3327 and #2842 together, and confirmed against a local build (ctest -L cpp-ci: 55/55 passing at #3327's head). Not blocking either PR — #3327's recipe dispatch is a strict improvement over what main does today, and #2842 has been asked to route through it. This issue is the cleanup that makes the split unnecessary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions