Skip to content

Commit 757260d

Browse files
timmarkhuffAuto-format Bot
andauthored
Switch to edge config models defined in python-sdk (#355)
This PR removes the code defining Edge config and instead uses the edge config defined in `python-sdk`. This is the first step in allowing the `python-sdk` to configure the edge. Related PR: groundlight/python-sdk#413 --------- Co-authored-by: Auto-format Bot <autoformatbot@groundlight.ai>
1 parent c797eb4 commit 757260d

9 files changed

Lines changed: 39 additions & 239 deletions

File tree

app/core/configs.py

Lines changed: 0 additions & 113 deletions
This file was deleted.

app/core/edge_config_loader.py

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,51 @@
22
import os
33
from typing import Dict
44

5-
import yaml
5+
from groundlight.edge import EdgeEndpointConfig, InferenceConfig
66

7-
from .configs import EdgeInferenceConfig, RootEdgeConfig
87
from .file_paths import DEFAULT_EDGE_CONFIG_PATH
98

109
logger = logging.getLogger(__name__)
1110

1211

13-
def load_edge_config() -> RootEdgeConfig:
12+
def load_edge_config() -> EdgeEndpointConfig:
1413
"""
1514
Reads the edge config from the EDGE_CONFIG environment variable if it exists.
1615
If EDGE_CONFIG is not set, reads the default edge config file.
1716
"""
1817
yaml_config = os.environ.get("EDGE_CONFIG", "").strip()
1918
if yaml_config:
20-
return _load_config_from_yaml(yaml_config)
19+
return EdgeEndpointConfig.from_yaml(yaml_str=yaml_config)
2120

22-
logger.warning("EDGE_CONFIG environment variable not set. Checking default locations.")
23-
24-
if os.path.exists(DEFAULT_EDGE_CONFIG_PATH):
25-
logger.info(f"Loading edge config from {DEFAULT_EDGE_CONFIG_PATH}")
26-
with open(DEFAULT_EDGE_CONFIG_PATH, "r") as f:
27-
return _load_config_from_yaml(f)
28-
29-
raise FileNotFoundError(f"Could not find edge config file in default location: {DEFAULT_EDGE_CONFIG_PATH}")
30-
31-
32-
def _load_config_from_yaml(yaml_config) -> RootEdgeConfig:
33-
"""
34-
Creates a `RootEdgeConfig` from the config yaml. Raises an error if there are duplicate detector ids.
35-
"""
36-
config = yaml.safe_load(yaml_config)
37-
38-
detectors = config.get("detectors", [])
39-
detector_ids = [det["detector_id"] for det in detectors]
40-
41-
# Check for duplicate detector IDs
42-
if len(detector_ids) != len(set(detector_ids)):
43-
raise ValueError("Duplicate detector IDs found in the configuration. Each detector should only have one entry.")
44-
45-
config["detectors"] = {det["detector_id"]: det for det in detectors}
46-
47-
return RootEdgeConfig(**config)
21+
logger.info(
22+
f"EDGE_CONFIG environment variable not set. Checking default Edge Config path: {DEFAULT_EDGE_CONFIG_PATH}."
23+
)
24+
return EdgeEndpointConfig.from_yaml(filename=DEFAULT_EDGE_CONFIG_PATH)
4825

4926

5027
def get_detector_inference_configs(
51-
root_edge_config: RootEdgeConfig,
52-
) -> dict[str, EdgeInferenceConfig] | None:
28+
root_edge_config: EdgeEndpointConfig,
29+
) -> dict[str, InferenceConfig] | None:
5330
"""
54-
Produces a dict mapping detector IDs to their associated `EdgeInferenceConfig`.
31+
Produces a dict mapping detector IDs to their associated `InferenceConfig`.
5532
Returns None if there are no detectors in the config file.
5633
"""
57-
# Mapping of config names to EdgeInferenceConfig objects
58-
edge_inference_configs: dict[str, EdgeInferenceConfig] = root_edge_config.edge_inference_configs
34+
# Mapping of config names to InferenceConfig objects
35+
edge_inference_configs: dict[str, InferenceConfig] = root_edge_config.edge_inference_configs
5936

60-
# Filter out detectors whose ID's are empty strings
61-
detectors = {det_id: detector for det_id, detector in root_edge_config.detectors.items() if det_id != ""}
37+
# Filter out detectors whose IDs are empty strings.
38+
detectors = [detector for detector in root_edge_config.detectors if detector.detector_id != ""]
6239

63-
detector_to_inference_config: dict[str, EdgeInferenceConfig] | None = None
40+
detector_to_inference_config: dict[str, InferenceConfig] | None = None
6441
if detectors:
6542
detector_to_inference_config = {
66-
detector_id: edge_inference_configs[detector_config.edge_inference_config]
67-
for detector_id, detector_config in detectors.items()
43+
detector.detector_id: edge_inference_configs[detector.edge_inference_config] for detector in detectors
6844
}
6945

7046
return detector_to_inference_config
7147

7248

73-
def get_detector_edge_configs_by_id() -> Dict[str, EdgeInferenceConfig]:
49+
def get_detector_edge_configs_by_id() -> Dict[str, InferenceConfig]:
7450
"""
7551
Convenience helper that loads the edge config and returns detector-level inference configs,
7652
defaulting to an empty dict when none are defined.

app/core/edge_inference.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import yaml
1111
from cachetools import TTLCache, cached
1212
from fastapi import HTTPException, status
13+
from groundlight.edge import InferenceConfig
1314
from jinja2 import Template
1415
from model import ModeEnum
1516

16-
from app.core.configs import EdgeInferenceConfig
1717
from app.core.file_paths import MODEL_REPOSITORY_PATH
1818
from app.core.speedmon import SpeedMonitor
1919
from app.core.utils import ModelInfoBase, ModelInfoWithBinary, parse_model_info
@@ -229,15 +229,14 @@ class EdgeInferenceManager:
229229

230230
def __init__(
231231
self,
232-
detector_inference_configs: dict[str, EdgeInferenceConfig] | None,
232+
detector_inference_configs: dict[str, InferenceConfig] | None,
233233
verbose: bool = False,
234234
separate_oodd_inference: bool = True,
235235
) -> None:
236236
"""
237237
Initializes the edge inference manager.
238238
Args:
239-
detector_inference_configs: Dictionary of detector IDs to EdgeInferenceConfig objects
240-
edge_config: RootEdgeConfig object
239+
detector_inference_configs: Dictionary of detector IDs to InferenceConfig objects
241240
verbose: Whether to print verbose logs from the inference server client
242241
separate_oodd_inference: Whether to run inference separately for the OODD model
243242
"""
@@ -277,7 +276,9 @@ def update_inference_config(self, detector_id: str, api_token: str) -> None:
277276
278277
"""
279278
if detector_id not in self.detector_inference_configs.keys():
280-
self.detector_inference_configs[detector_id] = EdgeInferenceConfig(enabled=True, api_token=api_token)
279+
self.detector_inference_configs[detector_id] = InferenceConfig(
280+
name="runtime_detector_config", enabled=True, api_token=api_token
281+
)
281282
self.inference_client_urls[detector_id] = get_edge_inference_service_name(detector_id) + ":8000"
282283
if self.separate_oodd_inference:
283284
logger.info(f"Performing separate OODD inference, updating OODD inference URL for {detector_id}")

app/metrics/system_metrics.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
import psutil
77
import tzlocal
88
import yaml
9+
from groundlight.edge import InferenceConfig
910
from kubernetes import client, config
1011

11-
from app.core.configs import EdgeInferenceConfig
1212
from app.core.edge_config_loader import get_detector_edge_configs_by_id
1313
from app.core.edge_inference import get_current_pipeline_config, get_predictor_metadata, get_primary_edge_model_dir
1414
from app.core.file_paths import MODEL_REPOSITORY_PATH
1515

1616
logger = logging.getLogger(__name__)
1717

1818

19-
def _edge_config_to_dict(config: EdgeInferenceConfig | None) -> dict | None:
20-
"""Convert an EdgeInferenceConfig to a plain dict for JSON serialization."""
19+
def _edge_config_to_dict(config: InferenceConfig | None) -> dict | None:
20+
"""Convert an InferenceConfig to a plain dict for JSON serialization."""
2121
if config is None:
2222
return None
2323
return {

app/model_updater/update_models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import os
33
import time
44

5-
from app.core.configs import RootEdgeConfig
5+
from groundlight.edge import EdgeEndpointConfig
6+
67
from app.core.database import DatabaseManager
78
from app.core.edge_config_loader import get_detector_inference_configs, load_edge_config
89
from app.core.edge_inference import (
@@ -234,7 +235,7 @@ def manage_update_models(
234235
if __name__ == "__main__":
235236
logger.info("Starting model updater.")
236237

237-
edge_config: RootEdgeConfig = load_edge_config()
238+
edge_config: EdgeEndpointConfig = load_edge_config()
238239
logger.info(f"{edge_config=}")
239240

240241
refresh_rate = edge_config.global_config.refresh_rate

poetry.lock

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ license = "MIT"
99
APScheduler = "3.10.4"
1010
cachetools = "^5.3.1"
1111
fastapi = "^0.115.0"
12-
groundlight = ">=0.23.3, <0.24.0"
12+
groundlight = ">=0.25.0, <0.26.0"
1313
httpx = "^0.27.2"
1414
jinja2 = "^3.1.6"
1515
kubernetes = "^27.2.0"

0 commit comments

Comments
 (0)