Coverage for streamwise/container_config.py: 95%
40 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
1"""
2Shared container deployment configuration for StreamWise.
4Central source of truth for container resource defaults, MIG profiles,
5GPU type mappings, and related deployment constants. Both allocator_bridge
6and streamwise.py import from here to avoid duplication.
7"""
9from __future__ import annotations
11import sys
12import os
13from dataclasses import dataclass
14from typing import Union
16_HERE = os.path.dirname(os.path.abspath(__file__))
17if _HERE not in sys.path:
18 sys.path.insert(0, _HERE)
20_REPO_ROOT = os.path.dirname(_HERE)
21if _REPO_ROOT not in sys.path:
22 sys.path.insert(0, _REPO_ROOT)
24# model_provisioner import adds simulator/ to sys.path
25import model_provisioner # noqa: E402, F401
27from sim_types import GPUType # noqa: E402
28from sim_types import Model # noqa: E402
31@dataclass(frozen=True)
32class ContainerResourceSpec:
33 """Default resource settings for a container deployment."""
34 cpu: int
35 memory_gib: int
36 ephemeral_storage_gib: int
37 gpu: Union[int, str] = 0
40# Default CPU/memory/storage and baseline GPU settings for key services.
41# Keep in sync with deployment defaults in streamwise/templates/add_pod.html.
42MODEL_TO_CONTAINER_NAME: dict[Model, str] = {
43 Model.GEMMA: "gemma",
44 Model.FLUX: "flux",
45 Model.HF: "hunyuanframepackf1",
46 Model.HF_VAE: "hunyuanframepackvae",
47 Model.FT: "fantasytalking",
48}
50MODEL_CONTAINER_RESOURCES: dict[Model, ContainerResourceSpec] = {
51 Model.GEMMA: ContainerResourceSpec(cpu=16, memory_gib=192, ephemeral_storage_gib=64, gpu=2),
52 Model.FLUX: ContainerResourceSpec(cpu=12, memory_gib=128, ephemeral_storage_gib=64, gpu=2),
53 Model.HF: ContainerResourceSpec(cpu=24, memory_gib=128, ephemeral_storage_gib=64, gpu=2),
54 Model.HF_VAE: ContainerResourceSpec(cpu=4, memory_gib=32, ephemeral_storage_gib=16, gpu=1),
55 Model.FT: ContainerResourceSpec(cpu=12, memory_gib=192, ephemeral_storage_gib=64, gpu=2),
56}
58CONTAINER_RESOURCES: dict[str, ContainerResourceSpec] = {
59 MODEL_TO_CONTAINER_NAME[model]: spec
60 for model, spec in MODEL_CONTAINER_RESOURCES.items()
61}
62CONTAINER_RESOURCES.update({
63 "realesrgan": ContainerResourceSpec(cpu=4, memory_gib=32, ephemeral_storage_gib=16, gpu="1g.10gb"),
64 "kokoro": ContainerResourceSpec(cpu=2, memory_gib=8, ephemeral_storage_gib=16, gpu="1g.10gb"),
65 "yolo": ContainerResourceSpec(cpu=4, memory_gib=8, ephemeral_storage_gib=16, gpu="1g.10gb"),
66})
68# GPU type string used by pod_manager (lowercase).
69GPU_TYPE_TO_POD_STR: dict[GPUType, str] = {
70 GPUType.A100: "a100",
71 GPUType.H100: "h100",
72 GPUType.H200: "h200",
73 GPUType.GB200: "gb200",
74}
76# MIG is only supported by pod_manager on these GPU types.
77MIG_CAPABLE_GPU_TYPES: frozenset[GPUType] = frozenset({GPUType.A100, GPUType.H100})
79# Containers that prefer a MIG slice when the selected GPU type supports MIG.
80# When MIG is available on the cluster, these services use a MIG slice (shared GPU).
81# When MIG is NOT available, they fall back to 1 full GPU each and the extra GPUs
82# are counted against the budget (with a warning if exceeded).
83MIG_CONTAINERS: dict[str, str] = {
84 "kokoro": "1g.10gb",
85 "yolo": "1g.10gb",
86 "realesrgan": "1g.10gb",
87}
89# Containers that are co-located with their parent model (sharing GPUs on the same server).
90# The allocator counts their GPUs as part of the parent model's allocation, so they should
91# deploy with gpu=0 to avoid double-counting.
92COLOCATED_CONTAINERS: frozenset[str] = frozenset({"hunyuanframepackvae"})
94# Whether MIG is actually configured on the cluster.
95# When False, MIG_CONTAINERS entries fall back to full GPUs.
96MIG_AVAILABLE: bool = False
99def get_minimum_service_container_specs(max_gpus: int) -> dict[str, ContainerResourceSpec]:
100 """Build container defaults for /api/service minimal deployment.
102 Negative `max_gpus` values are clamped to 0 to avoid invalid GPU assignments.
103 """
104 validated_max_gpus = max(0, max_gpus)
105 container_specs: dict[str, ContainerResourceSpec] = {
106 "podcasttranscript": ContainerResourceSpec(cpu=1, memory_gib=4, ephemeral_storage_gib=16, gpu=0),
107 "slidetranscript": ContainerResourceSpec(cpu=1, memory_gib=4, ephemeral_storage_gib=16, gpu=0),
108 "fluxkontext": ContainerResourceSpec(cpu=12, memory_gib=128, ephemeral_storage_gib=64, gpu=1),
109 "whisper": ContainerResourceSpec(cpu=2, memory_gib=8, ephemeral_storage_gib=16, gpu=1),
110 }
112 for name, spec in CONTAINER_RESOURCES.items():
113 if name in MIG_CONTAINERS:
114 assigned_gpu: Union[int, str] = MIG_CONTAINERS[name]
115 elif name == "hunyuanframepackvae":
116 assigned_gpu = 1
117 else:
118 assigned_gpu = min(2, validated_max_gpus)
120 container_specs[name] = ContainerResourceSpec(
121 cpu=spec.cpu,
122 memory_gib=spec.memory_gib,
123 ephemeral_storage_gib=spec.ephemeral_storage_gib,
124 gpu=assigned_gpu,
125 )
127 return container_specs