import pandas as pd from datetime import datetime from huggingface_hub.hf_api import ModelInfo # constant mapping for precision normalization PRECISION_MAP = { "torch.float16": "float16", "float16": "float16", "fp16": "float16", "torch.float32": "float32", "float32": "float32", "fp32": "float32", "torch.bfloat16": "bfloat16", "bfloat16": "bfloat16", "bf16": "bfloat16", "8bit": "8bit", "4bit": "4bit" } def unify_precision(raw_precision: str) -> str: """ Map raw precision strings to canonical forms. """ if not raw_precision: return "Missing" clean_p = raw_precision.strip().lower() if clean_p in ["missing", "unk", "none"]: return "Missing" return PRECISION_MAP.get(clean_p, "Missing") def get_model_size(model_info: ModelInfo) -> float: """ Return approximate model parameter size in billions. """ try: # Safely access safetensors, defaulting to None if attribute missing safetensors = getattr(model_info, "safetensors", None) total_bytes = safetensors.get("total", 0) if safetensors else 0 model_size = round(total_bytes / 1e9, 3) except (AttributeError, TypeError): return 0.0 # Specific logic for GPTQ models if model_info.modelId and "gptq" in model_info.modelId.lower(): return model_size * 8 return model_size def parse_datetime(dt_str: str) -> datetime: """ Safely parse an ISO datetime string into a Python datetime object. """ try: # Remove Z for compatibility with older fromisoformat versions return datetime.fromisoformat(dt_str.replace("Z", "")) except (ValueError, TypeError): return datetime.min def fix_df_for_display(df: pd.DataFrame) -> pd.DataFrame: """ Converts list columns to strings for st.dataframe compatibility. """ if df.empty: return df target_cols = ["license", "model_type"] for col in target_cols: if col in df.columns: df[col] = df[col].apply( lambda x: ", ".join(x) if isinstance(x, list) else str(x) ) return df # --- Helper: Filter Options Generator --- def get_filter_options(df, column): if df.empty: return ["Missing"] opts = sorted(df[column].dropna().unique().tolist()) if "Missing" not in opts: opts.append("Missing") return opts # Helper for Categorical Filters (Handles 'Missing') def apply_cat_filter(df_in, col_name, selected_opts): if not selected_opts: return df_in if "Missing" in selected_opts: # Valid matches OR Nulls OR "Missing" string return df_in[ df_in[col_name].isin(selected_opts) | df_in[col_name].isna() | (df_in[col_name] == "Missing") | (df_in[col_name] == "") ] return df_in[df_in[col_name].isin(selected_opts)]