Skip to content
Merged
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
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dependencies = [
"plotly (>=6.0.0)",
"polars",
"python-dotenv",
"scikit-learn",
"scikit-learn (>=1.4)",
"seaborn",
"tabulate (>=0.9.0,<0.10.0)",
"tiktoken",
Expand All @@ -41,7 +41,7 @@ dependencies = [
all = [
"torch (>=2.0.0)",
"xgboost (>=1.5.2,<3.1)",
"scikit-learn (<1.8)",
"scikit-learn (>=1.4,<1.8)",
"transformers (>=4.32.0,<5.0.0)",
"pycocoevalcap",
"ragas (>=0.2.3,<=0.2.7)",
Expand Down Expand Up @@ -111,7 +111,7 @@ pytorch = ["torch (>=2.0.0)"]
stats = ["scipy", "statsmodels (>=0.14.2,<0.15.0)", "arch (>=7.0.0)"]
xgboost = [
"xgboost (>=1.5.2,<3.1)",
"scikit-learn (<1.8)",
"scikit-learn (>=1.4,<1.8)",
]
explainability = [
"shap (>=0.46.0)",
Expand Down
23 changes: 23 additions & 0 deletions tests/test_test_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@
class TestTokenEstimation(unittest.TestCase):
"""Test token estimation and truncation functions."""

@patch("validmind.api_client.generate_test_result_description")
def test_generate_description_params_are_json_serializable(self, mock_generate):
"""Params holding DataFrames (e.g. fit_params eval_set) must not break the request"""
import json

import pandas as pd

from validmind.ai.test_descriptions import generate_description
from validmind.vm_models.result import ResultTable

mock_generate.return_value = {"content": "ok"}

generate_description(
test_id="validmind.model_validation.sklearn.HyperParametersTuning",
test_description="desc",
tables=[ResultTable(data=[{"Optimized for": "recall", "recall": 0.9}])],
params={"eval_set": [(pd.DataFrame({"a": [1]}), pd.Series([0]))]},
)

payload = mock_generate.call_args[0][0]
json.dumps(payload) # stdlib encoder, as used by requests
self.assertIn("eval_set", payload["params"])

def test_estimate_tokens_simple(self):
"""Test simple character-based token estimation."""
# Test with empty string
Expand Down
6 changes: 3 additions & 3 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion validmind/ai/test_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,9 @@ def generate_description(
"figures": [figure._get_b64_url() for figure in figures or []],
"additional_context": additional_context,
"instructions": instructions,
"params": params,
# params can hold anything the test accepts (DataFrames, arrays);
# round-trip so the request body is plain JSON
"params": json.loads(json.dumps(params, cls=NumpyEncoder)),
}
)["content"]

Expand Down
8 changes: 6 additions & 2 deletions validmind/datasets/credit_risk/lending_club.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,9 @@ def woe_encoding(df: pd.DataFrame, verbose: bool = True) -> pd.DataFrame:
print(f"Excluded {target_column} from WoE transformation.")

# Apply the WoE transformation
df = sc.woebin_ply(df, bins=bins)
with warnings.catch_warnings():
warnings.simplefilter("ignore") # scorecardpy uses deprecated pandas APIs
df = sc.woebin_ply(df, bins=bins)

if verbose:
print("Successfully converted features to WoE values.")
Expand Down Expand Up @@ -379,7 +381,9 @@ def _woebin(df: pd.DataFrame, verbose: bool = True) -> Dict[str, Any]:
print(
f"Performing binning with breaks_adj: {breaks_adj}"
) # print the breaks_adj being used
bins = sc.woebin(df, target_column, breaks_list=breaks_adj)
with warnings.catch_warnings():
warnings.simplefilter("ignore") # scorecardpy uses deprecated pandas APIs
bins = sc.woebin(df, target_column, breaks_list=breaks_adj)
except Exception as e:
print("Error during binning: ")
print(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def _create_scoring_dict(scoring, metrics, threshold):
for metric in metrics:
if metric == "recall":
scoring_dict[metric] = make_scorer(
custom_recall, needs_proba=True, threshold=threshold
custom_recall, response_method="predict_proba", threshold=threshold
)
elif metric == "roc_auc":
scoring_dict[metric] = "roc_auc"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def ScoreProbabilityAlignment(

# Calculate statistics per bin
results = []
for bin_name, group in df.groupby("score_bin"):
for bin_name, group in df.groupby("score_bin", observed=True):
bin_stats = {
"Score Range": f"{bin_name.left:.0f}-{bin_name.right:.0f}",
"Mean Score": group[score_column].mean(),
Expand Down
24 changes: 16 additions & 8 deletions validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,22 @@ def WeakspotsDiagnosis(
figures = []
passed = True

df_1 = datasets[0]._df[
feature_columns
+ [datasets[0].target_column, datasets[0].prediction_column(model)]
]
df_2 = datasets[1]._df[
feature_columns
+ [datasets[1].target_column, datasets[1].prediction_column(model)]
]
df_1 = (
datasets[0]
._df[
feature_columns
+ [datasets[0].target_column, datasets[0].prediction_column(model)]
]
.copy()
)
df_2 = (
datasets[1]
._df[
feature_columns
+ [datasets[1].target_column, datasets[1].prediction_column(model)]
]
.copy()
)
results_1 = pd.DataFrame()
results_2 = pd.DataFrame()
for feature in feature_columns:
Expand Down
Loading