-
Notifications
You must be signed in to change notification settings - Fork 46
Add experimental inference runtime API envelope #403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
580a182
da683d8
5131a2d
d402552
63f8b38
2ce669d
390a523
b891eaf
c9da5d3
5f83769
c7c6cc4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Experimental inference runtime API envelope. | ||
|
|
||
| This package defines the small v0 boundary above ``flashdreams.infra``. It is | ||
| intentionally additive while integrations migrate onto it. | ||
| """ | ||
|
|
||
| from flashdreams.runtime.config import ExecutionBackend, InferenceConfig, Precision | ||
| from flashdreams.runtime.inputs import ( | ||
| InputField, | ||
| ModelInputs, | ||
| ModelInputSchema, | ||
| TimeWindow, | ||
| UserInputEvent, | ||
| UserInputs, | ||
| UserInputSchema, | ||
| ) | ||
| from flashdreams.runtime.interfaces import ( | ||
| InferenceRuntime, | ||
| InferenceSession, | ||
| ModelAdapter, | ||
| ) | ||
| from flashdreams.runtime.mapping import IdentityInputMapping, InputMapping | ||
| from flashdreams.runtime.metrics import ( | ||
| InMemoryMetricsRecorder, | ||
| MetricsRecorder, | ||
| NullMetricsRecorder, | ||
| RuntimeMetricSample, | ||
| ) | ||
| from flashdreams.runtime.output import NullOutputTarget, OutputArtifact, OutputTarget | ||
| from flashdreams.runtime.types import StepRequest, StepResult | ||
|
|
||
| __all__ = [ | ||
| "ExecutionBackend", | ||
| "IdentityInputMapping", | ||
| "InferenceConfig", | ||
| "InferenceRuntime", | ||
| "InferenceSession", | ||
| "InMemoryMetricsRecorder", | ||
| "InputField", | ||
| "InputMapping", | ||
| "MetricsRecorder", | ||
| "ModelAdapter", | ||
| "ModelInputs", | ||
| "ModelInputSchema", | ||
| "NullMetricsRecorder", | ||
| "NullOutputTarget", | ||
| "OutputArtifact", | ||
| "OutputTarget", | ||
| "Precision", | ||
| "RuntimeMetricSample", | ||
| "StepRequest", | ||
| "StepResult", | ||
| "TimeWindow", | ||
| "UserInputEvent", | ||
| "UserInputs", | ||
| "UserInputSchema", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| """Small helpers shared by the experimental runtime API.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from collections.abc import Mapping | ||
| from types import MappingProxyType | ||
| from typing import TypeVar | ||
|
|
||
| ValueT = TypeVar("ValueT") | ||
|
|
||
|
|
||
| def freeze_mapping(value: Mapping[str, ValueT]) -> Mapping[str, ValueT]: | ||
| """Return a read-only shallow copy of ``value``.""" | ||
| return MappingProxyType(dict(value)) |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,76 @@ | ||||||||||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||
|
|
||||||||||
| """Runtime-facing configuration envelope.""" | ||||||||||
|
|
||||||||||
| from __future__ import annotations | ||||||||||
|
|
||||||||||
| from collections.abc import Mapping | ||||||||||
| from dataclasses import dataclass, field | ||||||||||
| from pathlib import Path | ||||||||||
| from typing import Any, Literal | ||||||||||
|
|
||||||||||
| from flashdreams.runtime._utils import freeze_mapping | ||||||||||
|
|
||||||||||
| ExecutionBackend = Literal["local", "local-distributed", "external", "hosted"] | ||||||||||
| """Where and how inference compute is run.""" | ||||||||||
|
|
||||||||||
| Precision = Literal["auto", "fp32", "fp16", "bf16"] | ||||||||||
| """Coarse runtime precision choices.""" | ||||||||||
|
|
||||||||||
|
|
||||||||||
| @dataclass(frozen=True, kw_only=True, slots=True) | ||||||||||
| class InferenceConfig: | ||||||||||
| """Runtime settings that affect model execution. | ||||||||||
|
|
||||||||||
| Prompts, user controls, browser settings, output paths, and benchmark | ||||||||||
| directories intentionally live outside this object. The typed optimization | ||||||||||
| fields cover common cross-backend knobs; open-ended adapter-specific choices | ||||||||||
| can use :attr:`runtime_options`. | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| __hash__ = None | ||||||||||
|
|
||||||||||
| model_id: str | ||||||||||
| """Stable identity for the model adapter or runtime integration.""" | ||||||||||
|
|
||||||||||
| preset_id: str | None = None | ||||||||||
| """Optional preset identity under :attr:`model_id`.""" | ||||||||||
|
Comment on lines
+37
to
+38
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this optional? To identify a model given a YAML we need an identity string to refer to
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The model_id is defined earlier, which is non-optional, so this would be an optional extra thing, like if you're using the lingbot model, it could have some optional preset things that you could use instead, like a lingbot+wan or lingbot+taev. Unless you think that should not be optional? |
||||||||||
|
|
||||||||||
| checkpoint: str | Path | None = None | ||||||||||
| """Optional checkpoint or model-asset selector understood by the adapter.""" | ||||||||||
|
Comment on lines
+40
to
+41
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this optional? this would mean we hard-code default checkpoint locations somewhere.
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking here that for some models, the checkpoint may just be implicit and the ModelAdapter would be able to handle it just based on the model_id, or that could be overridden by this checkpoint str. But maybe that's wrong and we should just always require this? What do you think? |
||||||||||
|
|
||||||||||
| backend: ExecutionBackend = "local" | ||||||||||
| """Execution placement and backend family for inference compute.""" | ||||||||||
|
|
||||||||||
| device: str | None = None | ||||||||||
| """Optional device selector such as ``cuda`` or ``cuda:0``; ``None`` leaves placement to the adapter/backend.""" | ||||||||||
|
|
||||||||||
| precision: Precision = "auto" | ||||||||||
| """Preferred compute precision.""" | ||||||||||
|
|
||||||||||
| compile: bool | None = None | ||||||||||
| """Optional - Whether model compilation is requested or disabled. `None` means left to the adapter to decide.""" | ||||||||||
|
|
||||||||||
| cuda_graph: bool | None = None | ||||||||||
| """Optional - Whether CUDA graph capture is requested or disabled. `None` means left to the adapter to decide.""" | ||||||||||
|
|
||||||||||
| attention_backend: str | None = None | ||||||||||
| """Optional attention implementation selector; ``None`` leaves the choice to the adapter.""" | ||||||||||
|
|
||||||||||
| cache_policy: str | None = None | ||||||||||
| """Optional cache policy selector; ``None`` leaves the choice to the adapter.""" | ||||||||||
|
|
||||||||||
| runtime_options: Mapping[str, Any] = field(default_factory=dict) | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we use TypedDict over dict for all dictionary? Again, this should make LSP happier.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For runtime_options/resource_hints, a shared TypedDict would be too generic to help much because the keys are adapter/backend-specific. It's probably better to use adapter-owned typed configs once those shapes are known when we implement them. |
||||||||||
| """Adapter/backend-specific runtime options.""" | ||||||||||
|
|
||||||||||
| resource_hints: Mapping[str, Any] = field(default_factory=dict) | ||||||||||
| """Resource hints for launchers, schedulers, or hosted backends.""" | ||||||||||
|
|
||||||||||
| def __post_init__(self) -> None: | ||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We likely need more validation on parameter values and checks if types assigned were correct & if elements like maybe we stub these checks?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that sounds reasonable, I'll see what checks I can add. |
||||||||||
| if not self.model_id.strip(): | ||||||||||
| raise ValueError("InferenceConfig.model_id must be non-empty.") | ||||||||||
| object.__setattr__( | ||||||||||
| self, "runtime_options", freeze_mapping(self.runtime_options) | ||||||||||
| ) | ||||||||||
| object.__setattr__(self, "resource_hints", freeze_mapping(self.resource_hints)) | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use enum.Enum for all enums, this should make LSP happier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there may be an LSP benefit. I’d keep literal for the T1 task and revisit enum when we actually implement this part of the API.