Skip to content

Inference section — user-configured model connections #421

Description

@JArmandoAnaya

Feature spanning kernel + wire + server + CLI + MCP + UI. cf. #417, #418.

deferred-needs-input: the two open questions at the bottom block UI placement and
persistence design — not the kernel work.

Summary

VisionSet never bundles or auto-downloads inference models. Auto-labeling operates
against model connections the user creates: a new top-level configuration surface
where connections to local or remote models are created, set up, tested, and managed.
The auto-labeling feature itself is always present (not an optional extra); only the
local runtime ships as visionset[local-inference].

Ratified direction (Armando, 2026-08-07; cf. #418):

  • ModelProvider adapters are instantiated from user-created connections, never from a
    bundled default.
  • VisionSet never downloads weights at install time; download is an explicit user
    action during local-connection setup, with the size shown beforehand.
  • Nothing may preclude cloud execution later — a hosted adapter is just another
    connection type against the same port.

The user journey (design target)

Empty state. Centered card: "Connect a model to enable auto-labeling", primary CTA
Add connection. Meta line stating the policy as a value proposition: "VisionSet
never downloads models on its own — you choose what runs and where."

List. Compact rows (density principle): connection name · type chip (Local /
HTTP) · model identity (grounding-dino-base @ <revision>) · status (Ready /
Not set up / Unreachable), semantic token + text, never color alone. Per-row
overflow: edit, test, delete.

Create — two steps. Step 1: pick type. Step 2 by type:

  • Local: HF model id + revision (suggested default; download size shown before
    confirming), device, precision. If local-inference is not installed, the form stays
    usable and shows the exact command (pip install "visionset[local-inference]") —
    never a bare disabled control (design principle 9). Creating the connection downloads
    nothing; the row lands at Not set up with a Download weights action.
  • HTTP: endpoint URL, optional credential, and a Test button that makes a real
    call and reports what answered. The endpoint contract is defined by this project —
    the same contract a future hosted adapter implements, and anyone may implement it.
    Third-party inference protocols are not adopted as the contract.

Download weights runs as a background job on the existing infrastructure (SQLite
queue in visionset.db, workers in the FastAPI lifespan, /background-jobs routes,
observable progress).

Delete states its blast radius accurately: annotation provenance stores model
identity denormalized (id + revision copied at write time, no FK to the
connection), so deleting a connection never breaks provenance. Dialog copy: "Annotations
keep their model provenance; only this configuration is removed."

Scope by layer

Kernel (visionset.kernel) — one home, one spelling:

Persistence:

  • New workspace-scoped table (like background_job: no project_id), narrow port
    methods only.

Wire + server:

  • ConnectionOut with allowed_actions derived from the same transition tables the
    service enforces (standing contract): download_weights only for local + not-set-up;
    test only for HTTP; delete always, with the blast-radius message.
  • Routes under /inference/connections. Weight download responds 202 pointing at its
    background job. Regenerate and commit openapi.json.

CLI + MCP (SDK-first parity):

  • visionset inference list|create|test|download with --json.
  • Equivalent MCP tools — an agent must be able to make a workspace auto-label-ready
    without a browser.

UI:

  • Screens in ui-core, navigation as callbacks, render allowed_actions only, existing
    semantic status tokens — zero new colors.
  • Annotation-workspace suture: when auto-labeling is offered in the editor with no
    connections configured, principle 10 forbids forcing navigation out of the editor or
    losing work — same pattern as in-editor quick class creation, or minimally a
    state-preserving link. Design explicitly, do not improvise at implementation time.

Open questions — Armando's, do not decide (deferred-needs-input)

  1. Navigation placement. A top-level Inference section re-litigates app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58 ("Home,
    Projects, avatar — nothing else" on the rail). Options to prepare, not pick:
    (a) new rail entry Inference; (b) another placement that keeps app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58 intact.
    Whichever is chosen must be recorded as a superseding decision on app: routes and composition — deliberately thin; all domain logic lives in ui-core (the enterprise rule) #58's rule, same
    turn it is confirmed.
  2. Credential storage. HTTP-connection credentials would land in plain SQLite inside
    the workspace. Local-first makes this defensible, but it ships only as an explicit
    decision, never a silent default. Options to prepare: plain storage documented as
    such; OS keyring integration; env-var indirection.

Non-goals

  • No model marketplace/registry — out of scope for this distribution.
  • No training or fine-tuning surfaces.
  • No bundled default connection of any kind.

Metadata

Metadata

Assignees

No one assigned

    Labels

    deferred-needs-inputBlocked on a decision that belongs to the founderenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions