OC_P8 / scripts /export_model.py
KLEB38's picture
Upload folder using huggingface_hub
2bf86cd verified
Raw
History Blame Contribute Delete
3.92 kB
"""
Exports the champion credit scoring model from OC_P6 to a local joblib file
for embedding in the OC_P8 deployment image.
Approach: bypass MLflow Server entirely. Load the model directly from the
filesystem using its physical path. Use MlflowClient only to fetch run-level
metadata (metrics, params) for traceability.
"""
import json
from datetime import datetime
from pathlib import Path
import joblib
import mlflow
from mlflow.tracking import MlflowClient
# ============================================================
# Configuration
# ============================================================
P6_MLFLOW_TRACKING_URI = "http://127.0.0.1:5000"
MODEL_NAME = "lgbm_credit_scoring"
MODEL_VERSION = "2"
# Direct filesystem path to the model artifacts
# Adjust this if your model_id differs (check the "Source" output below)
P6_MODEL_PATH = Path(
"C:/Users/Kevin/projects/OC_P6/mlartifacts/3/models/"
"m-dbe6fc95d74c49a8bb4775a6b7516fcd/artifacts"
)
OUTPUT_DIR = Path("models")
OUTPUT_MODEL = OUTPUT_DIR / "model.joblib"
OUTPUT_INFO = OUTPUT_DIR / "model_info.json"
# ============================================================
# Setup
# ============================================================
mlflow.set_tracking_uri(P6_MLFLOW_TRACKING_URI)
client = MlflowClient()
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
# ============================================================
# 1. Identify the model version (for metadata only)
# ============================================================
mv = client.get_model_version(MODEL_NAME, MODEL_VERSION)
print("=" * 60)
print("Model identified for export:")
print(f" Name : {mv.name}")
print(f" Version : {mv.version}")
print(f" Run ID : {mv.run_id}")
print(f" Source : {mv.source}")
if mv.run_id is None:
raise RuntimeError(f"Model version {MODEL_NAME}/{MODEL_VERSION} has no associated run_id")
run = client.get_run(mv.run_id)
print("\n Run metrics:")
for k, v in run.data.metrics.items():
print(f" {k}: {v:.4f}")
# ============================================================
# 2. Load the model — directly from filesystem (no HTTP, no Registry resolution)
# ============================================================
if not P6_MODEL_PATH.exists():
raise FileNotFoundError(
f"Model artifacts not found at: {P6_MODEL_PATH}\n"
f"Verify the path matches the 'Source' shown above."
)
print(f"\n Loading from filesystem: {P6_MODEL_PATH}")
model = mlflow.pyfunc.load_model(str(P6_MODEL_PATH))
print("\n Model signature:")
sig = model.metadata.signature
if sig is None:
print(" [WARN] No signature logged - inputs will not be validated at inference!")
n_features = None
feature_names = None
else:
inputs = sig.inputs.to_dict()
n_features = len(inputs)
feature_names = [f["name"] for f in inputs]
print(f" Expected input features: {n_features}")
print(f" First 5 feature names: {feature_names[:5]}")
# ============================================================
# 3. Save the model locally
# ============================================================
joblib.dump(model, OUTPUT_MODEL)
size_mb = OUTPUT_MODEL.stat().st_size / 1e6
print(f"\n[OK] Model saved to: {OUTPUT_MODEL} ({size_mb:.2f} MB)")
# ============================================================
# 4. Save provenance metadata
# ============================================================
info = {
"model_name": mv.name,
"version": mv.version,
"model_source": mv.source,
"run_id": mv.run_id,
"physical_path": str(P6_MODEL_PATH),
"exported_at": datetime.now().isoformat(),
"metrics": run.data.metrics,
"params": run.data.params,
"n_features_expected": n_features,
"feature_names": feature_names,
}
with open(OUTPUT_INFO, "w") as f:
json.dump(info, f, indent=2, default=str)
print(f"[OK] Metadata saved to: {OUTPUT_INFO}")
print("=" * 60)