Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ ipython_config.py
.DS_Store
**/.DS_Store

# Model Card Unit Tests
mlruns/

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
Expand Down
22 changes: 21 additions & 1 deletion src/edvise/reporting/model_card/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def __init__(
self.context: dict[str, t.Any] = {}

self.assets_folder = assets_path or self.DEFAULT_ASSETS_FOLDER
self.run_id = self._resolve_run_id()
self.output_path = self._build_output_path()
self.template_path = self._resolve(
"edvise.reporting.template", self.TEMPLATE_FILENAME
Expand Down Expand Up @@ -348,13 +349,21 @@ def export_to_pdf(self):
filename=self.pdf_path,
catalog=self.catalog,
institution_id=self.cfg.institution_id,
run_id=self.run_id,
)

def _build_output_path(self) -> str:
"""
Builds the output path for the model card.
"""
out_dir = os.path.join(tempfile.gettempdir(), "model_cards")
run_id = getattr(self, "run_id", None)

if not run_id:
raise RuntimeError(
"ModelCard.run_id must be set before building output path"
)

out_dir = os.path.join(tempfile.gettempdir(), "model_cards", run_id)
os.makedirs(out_dir, exist_ok=True)
filename = f"model-card-{self.model_name}.md"
return os.path.join(out_dir, filename)
Expand All @@ -371,3 +380,14 @@ def _resolve(self, package: str, filename: str) -> Traversable:
the file exists within the SST package itself.
"""
return files(package).joinpath(filename)

def _resolve_run_id(self) -> str:
model_cfg = getattr(self.cfg, "model", None)
run_id = getattr(model_cfg, "run_id", None) if model_cfg is not None else None

if not run_id:
raise ValueError(
f"config.model.run_id is required for ModelCard '{self.model_name}', "
"but it was missing (config.model is None or run_id is empty)."
)
return str(run_id)
6 changes: 4 additions & 2 deletions src/edvise/reporting/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ def download_static_asset(
return dst_path


def save_card_to_gold_volume(filename: str, catalog: str, institution_id: str) -> None:
def save_card_to_gold_volume(
filename: str, catalog: str, institution_id: str, run_id: str
) -> None:
"""
Saves the model card PDF to a subdirectory of "model_cards" in a Unity Catalog-backed gold volume.

Expand All @@ -150,7 +152,7 @@ def save_card_to_gold_volume(filename: str, catalog: str, institution_id: str) -
schema = f"{institution_id}_gold"
file_volume = "gold_volume"
volume_dir = f"/Volumes/{catalog}/{schema}/{file_volume}"
model_card_dir = os.path.join(volume_dir, "model_cards")
model_card_dir = os.path.join(volume_dir, "model_cards", run_id)
dst_path = os.path.join(model_card_dir, os.path.basename(filename))

# Check if the volume exists
Expand Down
1 change: 1 addition & 0 deletions tests/reporting/template/test_custom_template_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def make_custom_project_config():
return CustomProjectConfig(
institution_id="custom_inst_id",
institution_name="Custom Institution",
model={"experiment_id": "exp123", "run_id": "abc"},
student_id_col="student_id",
target_col="target",
split_col="split",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def make_custom_project_config():
return CustomProjectConfig(
institution_id="custom_inst_id",
institution_name="Custom Institution",
model={"experiment_id": "exp123", "run_id": "abc"},
student_id_col="student_id",
target_col="target",
split_col="split",
Expand Down
18 changes: 13 additions & 5 deletions tests/reporting/template/test_h2o_pdp_template_context.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
import pandas as pd
import re
from types import SimpleNamespace
from unittest.mock import patch
from edvise.reporting.model_card.h2o_pdp import H2OPDPModelCard
from edvise.configs.pdp import PDPProjectConfig
Expand Down Expand Up @@ -63,13 +64,20 @@ def __init__(self):
self.features = DummyFeaturesConfig()


# Dummy config for base ModelCard
class DummyConfig:
def __init__(self):
self.institution_id = "test_uni"
self.institution_name = "Test University"
self.modeling = DummyModelingConfig()
self.preprocessing = DummyPreprocessingConfig()
self.institution_id = "test_inst"
self.institution_name = "Test Institution"
self.split_col = None

self.model = SimpleNamespace(
run_id="dummy_run_id",
experiment_id="dummy_experiment_id",
mlflow_model_uri="models:/dummy/Production",
framework="sklearn",
)

self.modeling = None


# Valid PDPProjectConfig
Expand Down
19 changes: 14 additions & 5 deletions tests/reporting/template/test_pdp_template_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pandas as pd
import re
from unittest.mock import patch
from types import SimpleNamespace
from edvise.reporting.model_card.base import ModelCard
from edvise.reporting.model_card.pdp import PDPModelCard
from edvise.configs.pdp import PDPProjectConfig
Expand Down Expand Up @@ -67,18 +68,26 @@ def __init__(self):
# Dummy config for base ModelCard
class DummyConfig:
def __init__(self):
self.institution_id = "test_uni"
self.institution_name = "Test University"
self.modeling = DummyModelingConfig()
self.preprocessing = DummyPreprocessingConfig()
self.institution_id = "test_inst"
self.institution_name = "Test Institution"
self.split_col = None

self.model = SimpleNamespace(
run_id="dummy_run_id",
experiment_id="dummy_experiment_id",
mlflow_model_uri="models:/dummy/Production",
framework="sklearn",
)

self.modeling = None


# Valid PDPProjectConfig
def make_pdp_config() -> PDPProjectConfig:
return PDPProjectConfig(
institution_id="inst_id",
institution_name="Inst Name",
model={"experiment_id": "exp123", "run_id": "abc", "framework": "sklearn"},
model={"experiment_id": "exp123", "run_id": "abc"},
datasets={
"raw_course": "dummy.csv",
"raw_cohort": "dummy.csv",
Expand Down
Loading