validmind 2.13.4__tar.gz → 2.13.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {validmind-2.13.4 → validmind-2.13.6}/PKG-INFO +7 -1
- {validmind-2.13.4 → validmind-2.13.6}/pyproject.toml +11 -3
- validmind-2.13.6/validmind/__version__.py +1 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/ai/utils.py +184 -23
- {validmind-2.13.4 → validmind-2.13.6}/validmind/api_client.py +183 -13
- validmind-2.13.6/validmind/credentials_store.py +179 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/agent_dataset.py +8 -6
- {validmind-2.13.4 → validmind-2.13.6}/validmind/errors.py +4 -0
- validmind-2.13.6/validmind/oidc_device.py +421 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/AnswerRelevancy.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/ArgumentCorrectness.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/Bias.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/ContextualPrecision.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/ContextualRecall.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/ContextualRelevancy.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/Faithfulness.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/Hallucination.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/Summarization.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/ToolCorrectness.py +2 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/__init__.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/IQROutliersBarPlot.py +6 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/IQROutliersTable.py +5 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/MissingValues.py +3 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ModelPredictionResiduals.py +2 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/AnswerCorrectness.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/AspectCritic.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/ContextEntityRecall.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/ContextPrecision.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/ContextPrecisionWithoutReference.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/ContextRecall.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/Faithfulness.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/SemanticSimilarity.py +1 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/FeatureImportance.py +3 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/HyperParametersTuning.py +1 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/MinimumF1Score.py +12 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +1 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ROCCurve.py +1 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +3 -3
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/CumulativePredictionProbabilities.py +2 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/PredictionProbabilitiesHistogram.py +2 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/ScorecardHistogram.py +2 -2
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/ai_powered_test.py +2 -1
- {validmind-2.13.4 → validmind-2.13.6}/validmind/utils.py +16 -15
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/dataset/dataset.py +1 -1
- validmind-2.13.4/validmind/__version__.py +0 -1
- {validmind-2.13.4 → validmind-2.13.6}/.gitignore +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/LICENSE +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/README.pypi.md +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/ai/test_descriptions.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/client.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/client_config.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/config.json +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/customer_churn.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/datasets/bank_customer_churn.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/datasets/taiwan_credit.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/classification/taiwan_credit.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/cluster/digits.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/credit_risk/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/credit_risk/datasets/lending_club_biased.csv.gz +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/credit_risk/datasets/lending_club_loan_data_2007_2014_clean.csv.gz +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/credit_risk/lending_club.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/credit_risk/lending_club_bias.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_1.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_2.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_3.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_4.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_5.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/llm/rag/rfp.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/cnn_dailymail.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/datasets/Covid_19.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/datasets/cnn_dailymail_100_with_predictions.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/datasets/cnn_dailymail_500_with_predictions.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/datasets/sentiments_with_predictions.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/nlp/twitter_covid_19.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/california_housing.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/california_housing.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/CPIAUCSL.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/CSUSHPISA.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/DRSFRMACBS.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/FEDFUNDS.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/GDP.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/GDPC1.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/GS10.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/GS3.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/GS5.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/MORTGAGE30US.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred/UNRATE.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates_test_1.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates_test_2.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates_test_3.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates_test_4.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/fred_loan_rates_test_5.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/datasets/leanding_club_loan_rates.csv +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/fred.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/fred_timeseries.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/generate_california_housing_csv.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/datasets/regression/lending_club.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/experimental/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/experimental/agents.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/html_templates/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/html_templates/content_blocks.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/input_registry.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/logging.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/foundation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/function.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/huggingface.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/metadata.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/pipeline.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/pytorch.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/r_model.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/models/sklearn.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/AbsoluteError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/BrierScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/CalibrationError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/ClassBalance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/Confidence.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/Correctness.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/LogLoss.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/OutlierScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/ProbabilityError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/Uncertainty.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/classification/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/GEval.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/PlanAdherence.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/PlanQuality.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/scorers/llm/deepeval/TaskCompletion.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/template.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/classifier.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/cluster.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/embeddings.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/llm.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/nlp.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/parameters_optimization.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/regression.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/statsmodels_timeseries.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/summarization.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/tabular_datasets.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/text_data.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/test_suites/time_series.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/__types__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/_store.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/comparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ACFandPACFPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ADF.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/AutoAR.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/AutoMA.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/AutoStationarity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/BivariateScatterPlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/BoxPierce.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ChiSquaredFeaturesTable.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ClassImbalance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/DatasetDescription.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/DatasetSplit.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/DescriptiveStatistics.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/DickeyFullerGLS.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/Duplicates.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/EngleGrangerCoint.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/FeatureTargetCorrelationPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/HighCardinality.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/HighPearsonCorrelation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/IsolationForestOutliers.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/JarqueBera.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/KPSS.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/LJungBox.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/LaggedCorrelationHeatmap.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/MissingValuesBarPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/MutualInformation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/PearsonCorrelationMatrix.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/PhillipsPerronArch.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ProtectedClassesCombination.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ProtectedClassesDescription.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ProtectedClassesDisparity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ProtectedClassesThresholdOptimizer.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/RollingStatsPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/RunsTest.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ScatterPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ScoreBandDefaultRates.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/SeasonalDecompose.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ShapiroWilk.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/Skewness.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/SpreadPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TabularCategoricalBarPlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TabularDateTimeHistograms.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TabularDescriptionTables.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TabularNumericalHistograms.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TargetRateBarPlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesDescription.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesDescriptiveStatistics.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesFrequency.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesHistogram.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesLinePlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesMissingValues.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TimeSeriesOutliers.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/TooManyZeroValues.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/UniqueRows.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/WOEBinPlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/WOEBinTable.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/ZivotAndrewsArch.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/CommonWords.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/Hashtags.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/LanguageDetection.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/Mentions.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/Punctuations.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/Sentiment.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/StopWords.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/TextDescription.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/Toxicity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/data_validation/nlp/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/decorator.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/load.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/BertScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/BleuScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ClusterSizeDistribution.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ContextualRecall.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/FeaturesAUC.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/MeteorScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ModelMetadata.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/RegardScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/RegressionResidualsPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/RougeScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/TimeSeriesPredictionWithCI.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/TimeSeriesPredictionsPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/TimeSeriesR2SquareBySegments.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/TokenDisparity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ToxicityScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/ClusterDistribution.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/CosineSimilarityComparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/CosineSimilarityHeatmap.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/EuclideanDistanceComparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/EuclideanDistanceHeatmap.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/PCAComponentsPairwisePlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/TSNEComponentsPairwisePlots.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/embeddings/utils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/NoiseSensitivity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/ResponseRelevancy.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/ragas/utils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/CalibrationCurve.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ClassifierPerformance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ClassifierThresholdOptimization.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/CompletenessScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ConfusionMatrix.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/HomogeneityScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/MinimumAccuracy.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ModelParameters.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RegressionErrors.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RegressionErrorsComparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RegressionPerformance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RegressionR2Square.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/RegressionR2SquareComparison.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/ScoreProbabilityAlignment.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/SilhouettePlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/VMeasure.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/sklearn/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/AutoARIMA.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/DurbinWatsonTest.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/GINITable.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/Lilliefors.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionCoeffs.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/model_validation/statsmodels/statsutils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/CalibrationCurveDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ClassDiscriminationDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ClassImbalanceDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ClassificationAccuracyDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ConfusionMatrixDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/CumulativePredictionProbabilitiesDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/FeatureDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/PredictionCorrelation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/PredictionProbabilitiesHistogramDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/PredictionQuantilesAcrossFeatures.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ROCCurveDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ScoreBandsDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/ScorecardHistogramDrift.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/output.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/plots/BoxPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/plots/CorrelationHeatmap.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/plots/HistogramPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/plots/ViolinPlot.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/plots/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Bias.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Clarity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Conciseness.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Delimitation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/NegativeInstruction.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Robustness.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/Specificity.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/prompt_validation/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/run.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/stats/CorrelationAnalysis.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/stats/DescriptiveStats.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/stats/NormalityTests.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/stats/OutlierDetection.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/stats/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/test_providers.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/tests/utils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/classification/Accuracy.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/classification/F1.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/classification/Precision.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/classification/ROC_AUC.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/classification/Recall.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/AdjustedRSquaredScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/GiniCoefficient.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/HuberLoss.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/MeanAbsoluteError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/MeanBiasDeviation.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/MeanSquaredError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/QuantileLoss.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/RSquaredScore.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/unit_metrics/regression/RootMeanSquaredError.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/dataset/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/dataset/utils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/figure.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/html_progress.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/html_renderer.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/input.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/model.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/result/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/result/pii_filter.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/result/result.jinja +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/result/result.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/result/utils.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/test_suite/__init__.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/test_suite/runner.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/test_suite/summary.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/test_suite/test.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/test_suite/test_suite.py +0 -0
- {validmind-2.13.4 → validmind-2.13.6}/validmind/vm_models/text_generation_summary.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: validmind
|
|
3
|
-
Version: 2.13.
|
|
3
|
+
Version: 2.13.6
|
|
4
4
|
Summary: ValidMind Library
|
|
5
5
|
Author-email: Andres Rodriguez <andres@validmind.ai>, Juan Martinez <juan@validmind.ai>, Anil Sorathiya <anil@validmind.ai>, Luis Pallares <luis@validmind.ai>, John Walz <john@validmind.ai>
|
|
6
6
|
License: DUAL LICENSE NOTICE
|
|
@@ -707,8 +707,10 @@ Requires-Dist: pandas<3.0.0,>=2.0.3
|
|
|
707
707
|
Requires-Dist: plotly>=6.0.0
|
|
708
708
|
Requires-Dist: polars
|
|
709
709
|
Requires-Dist: python-dotenv
|
|
710
|
+
Requires-Dist: requests<3.0.0,>=2.28.0
|
|
710
711
|
Requires-Dist: scikit-learn
|
|
711
712
|
Requires-Dist: seaborn
|
|
713
|
+
Requires-Dist: segno<2.0.0,>=1.6.6
|
|
712
714
|
Requires-Dist: tabulate<0.10.0,>=0.9.0
|
|
713
715
|
Requires-Dist: tiktoken
|
|
714
716
|
Requires-Dist: tqdm
|
|
@@ -724,7 +726,9 @@ Requires-Dist: langchain-google-genai; extra == 'all'
|
|
|
724
726
|
Requires-Dist: langchain-openai>=0.1.8; extra == 'all'
|
|
725
727
|
Requires-Dist: langchain<0.4.0,>=0.2.0; extra == 'all'
|
|
726
728
|
Requires-Dist: langdetect; extra == 'all'
|
|
729
|
+
Requires-Dist: llvmlite<0.48,>=0.47.0; (python_version >= '3.14') and extra == 'all'
|
|
727
730
|
Requires-Dist: nltk<4.0.0,>=3.8.1; extra == 'all'
|
|
731
|
+
Requires-Dist: numba>=0.65.1; (python_version >= '3.14') and extra == 'all'
|
|
728
732
|
Requires-Dist: pyarrow<16; (python_version < '3.13') and extra == 'all'
|
|
729
733
|
Requires-Dist: pyarrow<21,>=20; (python_version == '3.13') and extra == 'all'
|
|
730
734
|
Requires-Dist: pyarrow<23,>=22; (python_version >= '3.14') and extra == 'all'
|
|
@@ -751,6 +755,8 @@ Requires-Dist: pyarrow<16; (python_version < '3.13') and extra == 'datasets'
|
|
|
751
755
|
Requires-Dist: pyarrow<21,>=20; (python_version == '3.13') and extra == 'datasets'
|
|
752
756
|
Requires-Dist: pyarrow<23,>=22; (python_version >= '3.14') and extra == 'datasets'
|
|
753
757
|
Provides-Extra: explainability
|
|
758
|
+
Requires-Dist: llvmlite<0.48,>=0.47.0; (python_version >= '3.14') and extra == 'explainability'
|
|
759
|
+
Requires-Dist: numba>=0.65.1; (python_version >= '3.14') and extra == 'explainability'
|
|
754
760
|
Requires-Dist: shap>=0.46.0; extra == 'explainability'
|
|
755
761
|
Provides-Extra: huggingface
|
|
756
762
|
Requires-Dist: sentencepiece<0.3.0,>=0.2.0; extra == 'huggingface'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "validmind"
|
|
3
|
-
version = "2.13.
|
|
3
|
+
version = "2.13.6"
|
|
4
4
|
description = "ValidMind Library"
|
|
5
5
|
readme = "README.pypi.md"
|
|
6
6
|
requires-python = ">=3.9,<3.15"
|
|
@@ -14,6 +14,7 @@ authors = [
|
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
16
|
"aiohttp[speedups] (<3.13.1)",
|
|
17
|
+
"requests (>=2.28.0,<3.0.0)",
|
|
17
18
|
"ipywidgets",
|
|
18
19
|
"kaleido (>=1.2.0,<2.0.0)",
|
|
19
20
|
"matplotlib",
|
|
@@ -33,6 +34,7 @@ dependencies = [
|
|
|
33
34
|
"tqdm",
|
|
34
35
|
"anywidget",
|
|
35
36
|
"beautifulsoup4",
|
|
37
|
+
"segno (>=1.6.6,<2.0.0)",
|
|
36
38
|
]
|
|
37
39
|
|
|
38
40
|
[project.optional-dependencies]
|
|
@@ -63,6 +65,8 @@ all = [
|
|
|
63
65
|
"pyarrow (>=22,<23) ; python_version >= '3.14'",
|
|
64
66
|
"arch (>=7.0.0)",
|
|
65
67
|
"shap (>=0.46.0)",
|
|
68
|
+
"numba (>=0.65.1) ; python_version >= '3.14'",
|
|
69
|
+
"llvmlite (>=0.47.0,<0.48) ; python_version >= '3.14'",
|
|
66
70
|
"scorecardpy==0.1.9.6",
|
|
67
71
|
"setuptools (<82)",
|
|
68
72
|
]
|
|
@@ -105,7 +109,11 @@ nlp = [
|
|
|
105
109
|
pytorch = ["torch (>=2.0.0)"]
|
|
106
110
|
stats = ["scipy", "statsmodels (>=0.14.2,<0.15.0)", "arch (>=7.0.0)"]
|
|
107
111
|
xgboost = ["xgboost (>=1.5.2,<3)"]
|
|
108
|
-
explainability = [
|
|
112
|
+
explainability = [
|
|
113
|
+
"shap (>=0.46.0)",
|
|
114
|
+
"numba (>=0.65.1) ; python_version >= '3.14'",
|
|
115
|
+
"llvmlite (>=0.47.0,<0.48) ; python_version >= '3.14'",
|
|
116
|
+
]
|
|
109
117
|
credit_risk = ["scorecardpy==0.1.9.6", "setuptools (<82)"]
|
|
110
118
|
datasets = [
|
|
111
119
|
"datasets (>=2.10.0,<3.0.0) ; python_version < '3.14'",
|
|
@@ -122,7 +130,7 @@ pii-detection = [
|
|
|
122
130
|
|
|
123
131
|
[dependency-groups]
|
|
124
132
|
dev = [
|
|
125
|
-
"black>=22.1.0,<
|
|
133
|
+
"black>=22.1.0,<26",
|
|
126
134
|
"click",
|
|
127
135
|
"cython>=0.29.34,<0.30",
|
|
128
136
|
"docstring-parser",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.13.6"
|
|
@@ -17,10 +17,11 @@ __client = None
|
|
|
17
17
|
__model = None
|
|
18
18
|
__judge_llm = None
|
|
19
19
|
__judge_embeddings = None
|
|
20
|
+
__judge_llm_explicitly_set = False
|
|
20
21
|
OPENAI_MODEL = "gpt-4.1"
|
|
21
22
|
OPENAI_EMBEDDINGS_MODEL = "text-embedding-3-small"
|
|
22
23
|
GEMINI_MODEL = "gemini-2.5-pro"
|
|
23
|
-
GEMINI_EMBEDDINGS_MODEL = "
|
|
24
|
+
GEMINI_EMBEDDINGS_MODEL = "gemini-embedding-001"
|
|
24
25
|
|
|
25
26
|
# can be None, True or False (ternary to represent initial state, ack and failed ack)
|
|
26
27
|
__ack = None
|
|
@@ -59,10 +60,7 @@ def _get_configured_provider():
|
|
|
59
60
|
if os.getenv("AZURE_OPENAI_KEY"):
|
|
60
61
|
return "azure"
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
return "gemini"
|
|
64
|
-
|
|
65
|
-
return None
|
|
63
|
+
return "gemini"
|
|
66
64
|
|
|
67
65
|
|
|
68
66
|
def get_client_and_model():
|
|
@@ -104,18 +102,12 @@ def get_client_and_model():
|
|
|
104
102
|
|
|
105
103
|
logger.debug(f"Using Azure OpenAI {__model} for generating descriptions")
|
|
106
104
|
|
|
107
|
-
|
|
105
|
+
else:
|
|
108
106
|
__client = None
|
|
109
107
|
__model = os.getenv("GEMINI_MODEL", GEMINI_MODEL)
|
|
110
108
|
|
|
111
109
|
logger.debug(f"Using Gemini {__model} for generating descriptions")
|
|
112
110
|
|
|
113
|
-
else:
|
|
114
|
-
raise ValueError(
|
|
115
|
-
"OPENAI_API_KEY, AZURE_OPENAI_KEY, GOOGLE_API_KEY, or GEMINI_API_KEY "
|
|
116
|
-
"must be setup to use LLM features"
|
|
117
|
-
)
|
|
118
|
-
|
|
119
111
|
return __client, __model
|
|
120
112
|
|
|
121
113
|
|
|
@@ -202,16 +194,18 @@ def _build_gemini_judge_config(model):
|
|
|
202
194
|
langchain_google_genai, "GoogleGenerativeAIEmbeddings"
|
|
203
195
|
)
|
|
204
196
|
google_api_key = _get_google_api_key()
|
|
197
|
+
chat_kwargs = {"model": model}
|
|
198
|
+
embeddings_kwargs = {
|
|
199
|
+
"model": os.getenv("GEMINI_EMBEDDINGS_MODEL", GEMINI_EMBEDDINGS_MODEL),
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if google_api_key:
|
|
203
|
+
chat_kwargs["api_key"] = google_api_key
|
|
204
|
+
embeddings_kwargs["google_api_key"] = google_api_key
|
|
205
205
|
|
|
206
206
|
return (
|
|
207
|
-
ChatGoogleGenerativeAI(
|
|
208
|
-
|
|
209
|
-
api_key=google_api_key,
|
|
210
|
-
),
|
|
211
|
-
GoogleGenerativeAIEmbeddings(
|
|
212
|
-
model=os.getenv("GEMINI_EMBEDDINGS_MODEL", GEMINI_EMBEDDINGS_MODEL),
|
|
213
|
-
google_api_key=google_api_key,
|
|
214
|
-
),
|
|
207
|
+
ChatGoogleGenerativeAI(**chat_kwargs),
|
|
208
|
+
GoogleGenerativeAIEmbeddings(**embeddings_kwargs),
|
|
215
209
|
)
|
|
216
210
|
|
|
217
211
|
|
|
@@ -230,6 +224,162 @@ def _build_openai_judge_config(client, model):
|
|
|
230
224
|
)
|
|
231
225
|
|
|
232
226
|
|
|
227
|
+
def _import_deepeval_base_llm():
|
|
228
|
+
try:
|
|
229
|
+
deepeval_base_model = importlib.import_module("deepeval.models.base_model")
|
|
230
|
+
except ImportError:
|
|
231
|
+
raise ImportError(
|
|
232
|
+
"Please run `pip install validmind[llm]` to use Gemini DeepEval scorers"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return getattr(deepeval_base_model, "DeepEvalBaseLLM")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _unwrap_deepeval_response(response):
|
|
239
|
+
return getattr(response, "content", response)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _is_reason_only_schema(schema):
|
|
243
|
+
"""True when ``schema`` is a single-field ``{reason}`` explanation schema.
|
|
244
|
+
|
|
245
|
+
DeepEval's ``*ScoreReason`` schemas carry only the human-readable explanation
|
|
246
|
+
and do not affect the metric score, so a missing value can be degraded safely.
|
|
247
|
+
"""
|
|
248
|
+
fields = getattr(schema, "model_fields", None) or getattr(
|
|
249
|
+
schema, "__fields__", None
|
|
250
|
+
)
|
|
251
|
+
try:
|
|
252
|
+
return set(fields.keys()) == {"reason"}
|
|
253
|
+
except Exception:
|
|
254
|
+
return False
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _require_structured_response(result, schema):
|
|
258
|
+
"""Guard against a judge LLM returning no parseable structured output.
|
|
259
|
+
|
|
260
|
+
Gemini's default function-calling path yields ``None`` when the model
|
|
261
|
+
response contains no tool call. Returning that ``None`` to DeepEval surfaces
|
|
262
|
+
as a cryptic ``'NoneType' object has no attribute 'reason'``.
|
|
263
|
+
|
|
264
|
+
For reason-only schemas the metric score is already computed from earlier
|
|
265
|
+
verdict calls, so a missing explanation is cosmetic: degrade to a placeholder
|
|
266
|
+
reason and keep the score. Score-bearing schemas (statements, verdicts) are
|
|
267
|
+
never faked -- doing so would yield a silently wrong score -- so those raise.
|
|
268
|
+
"""
|
|
269
|
+
if result is not None:
|
|
270
|
+
return result
|
|
271
|
+
|
|
272
|
+
schema_name = getattr(schema, "__name__", schema)
|
|
273
|
+
|
|
274
|
+
if _is_reason_only_schema(schema):
|
|
275
|
+
logger.warning(
|
|
276
|
+
"Judge LLM returned no structured output for %s; recording the score "
|
|
277
|
+
"with an empty explanation.",
|
|
278
|
+
schema_name,
|
|
279
|
+
)
|
|
280
|
+
return schema(reason="N/A (judge LLM returned no explanation)")
|
|
281
|
+
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"Judge LLM returned no parseable structured output for {schema_name}. "
|
|
284
|
+
"This usually means the model produced no tool call for the requested "
|
|
285
|
+
"schema. Try a different judge model, or check provider quotas and "
|
|
286
|
+
"safety settings."
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _structured_generate(chat_model, prompt, schema):
|
|
291
|
+
"""Invoke ``chat_model`` for structured output, retrying via json_mode.
|
|
292
|
+
|
|
293
|
+
Gemini's default function-calling path can return ``None`` when the model
|
|
294
|
+
emits no tool call; json_mode binds a response schema and is deterministic.
|
|
295
|
+
"""
|
|
296
|
+
result = chat_model.with_structured_output(schema).invoke(prompt)
|
|
297
|
+
if result is None:
|
|
298
|
+
try:
|
|
299
|
+
result = chat_model.with_structured_output(
|
|
300
|
+
schema, method="json_mode"
|
|
301
|
+
).invoke(prompt)
|
|
302
|
+
except Exception:
|
|
303
|
+
pass
|
|
304
|
+
return _require_structured_response(result, schema)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
async def _a_structured_generate(chat_model, prompt, schema):
|
|
308
|
+
"""Async counterpart of :func:`_structured_generate`."""
|
|
309
|
+
result = await chat_model.with_structured_output(schema).ainvoke(prompt)
|
|
310
|
+
if result is None:
|
|
311
|
+
try:
|
|
312
|
+
result = await chat_model.with_structured_output(
|
|
313
|
+
schema, method="json_mode"
|
|
314
|
+
).ainvoke(prompt)
|
|
315
|
+
except Exception:
|
|
316
|
+
pass
|
|
317
|
+
return _require_structured_response(result, schema)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _build_langchain_deepeval_model(chat_model):
|
|
321
|
+
"""Wrap any LangChain BaseChatModel as a DeepEval-compatible model.
|
|
322
|
+
|
|
323
|
+
Used when set_judge_config() has been called so that DeepEval scorers
|
|
324
|
+
honour the same judge model as prompt-validation and RAGAS tests.
|
|
325
|
+
"""
|
|
326
|
+
DeepEvalBaseLLM = _import_deepeval_base_llm()
|
|
327
|
+
|
|
328
|
+
class LangChainDeepEvalModel(DeepEvalBaseLLM):
|
|
329
|
+
def __init__(self, model):
|
|
330
|
+
self._chat_model = model
|
|
331
|
+
self.model = self.load_model()
|
|
332
|
+
|
|
333
|
+
def load_model(self, *args, **kwargs):
|
|
334
|
+
return self._chat_model
|
|
335
|
+
|
|
336
|
+
def generate(self, prompt: str, schema=None):
|
|
337
|
+
chat_model = self.load_model()
|
|
338
|
+
if schema is not None and hasattr(chat_model, "with_structured_output"):
|
|
339
|
+
return _structured_generate(chat_model, prompt, schema)
|
|
340
|
+
return _unwrap_deepeval_response(chat_model.invoke(prompt))
|
|
341
|
+
|
|
342
|
+
async def a_generate(self, prompt: str, schema=None):
|
|
343
|
+
chat_model = self.load_model()
|
|
344
|
+
if schema is not None and hasattr(chat_model, "with_structured_output"):
|
|
345
|
+
return await _a_structured_generate(chat_model, prompt, schema)
|
|
346
|
+
return _unwrap_deepeval_response(await chat_model.ainvoke(prompt))
|
|
347
|
+
|
|
348
|
+
def get_model_name(self, *args, **kwargs):
|
|
349
|
+
for attr in ("model", "model_name", "azure_deployment"):
|
|
350
|
+
val = getattr(self._chat_model, attr, None)
|
|
351
|
+
if val:
|
|
352
|
+
return val
|
|
353
|
+
return type(self._chat_model).__name__
|
|
354
|
+
|
|
355
|
+
return LangChainDeepEvalModel(chat_model)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _build_gemini_deepeval_model(model):
|
|
359
|
+
judge_llm, _ = _build_gemini_judge_config(model)
|
|
360
|
+
return _build_langchain_deepeval_model(judge_llm)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def run_deepeval_evaluation(*, test_cases, metrics):
|
|
364
|
+
try:
|
|
365
|
+
from deepeval import evaluate
|
|
366
|
+
|
|
367
|
+
deepeval_test_run = importlib.import_module("deepeval.test_run.test_run")
|
|
368
|
+
except ImportError:
|
|
369
|
+
raise ImportError(
|
|
370
|
+
"Please run `pip install validmind[llm]` to use Gemini DeepEval scorers"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
original_is_confident = deepeval_test_run.is_confident
|
|
374
|
+
|
|
375
|
+
try:
|
|
376
|
+
# ValidMind scorers should run locally without depending on Confident AI login state.
|
|
377
|
+
deepeval_test_run.is_confident = lambda: False
|
|
378
|
+
return evaluate(test_cases=test_cases, metrics=metrics)
|
|
379
|
+
finally:
|
|
380
|
+
deepeval_test_run.is_confident = original_is_confident
|
|
381
|
+
|
|
382
|
+
|
|
233
383
|
def get_judge_config(judge_llm=None, judge_embeddings=None):
|
|
234
384
|
Embeddings, BaseChatModel, FunctionModel = _import_judge_dependencies()
|
|
235
385
|
|
|
@@ -265,11 +415,21 @@ def get_deepeval_model():
|
|
|
265
415
|
OpenAI/Azure scorers currently pass a model string. Gemini support requires a
|
|
266
416
|
native DeepEval model object so the provider can be configured correctly.
|
|
267
417
|
"""
|
|
418
|
+
if (
|
|
419
|
+
__judge_llm_explicitly_set
|
|
420
|
+
and __judge_llm is not None
|
|
421
|
+
and __judge_embeddings is not None
|
|
422
|
+
):
|
|
423
|
+
return _build_langchain_deepeval_model(__judge_llm)
|
|
268
424
|
|
|
269
425
|
provider = _get_configured_provider()
|
|
270
426
|
_, model = get_client_and_model()
|
|
271
427
|
|
|
272
428
|
if provider == "gemini":
|
|
429
|
+
google_api_key = _get_google_api_key()
|
|
430
|
+
if google_api_key is None:
|
|
431
|
+
return _build_gemini_deepeval_model(model)
|
|
432
|
+
|
|
273
433
|
try:
|
|
274
434
|
deepeval_models = importlib.import_module("deepeval.models")
|
|
275
435
|
except ImportError:
|
|
@@ -280,7 +440,7 @@ def get_deepeval_model():
|
|
|
280
440
|
GeminiModel = getattr(deepeval_models, "GeminiModel")
|
|
281
441
|
return GeminiModel(
|
|
282
442
|
model=model,
|
|
283
|
-
api_key=
|
|
443
|
+
api_key=google_api_key,
|
|
284
444
|
temperature=0,
|
|
285
445
|
)
|
|
286
446
|
|
|
@@ -288,7 +448,7 @@ def get_deepeval_model():
|
|
|
288
448
|
|
|
289
449
|
|
|
290
450
|
def set_judge_config(judge_llm, judge_embeddings):
|
|
291
|
-
global __judge_llm, __judge_embeddings
|
|
451
|
+
global __judge_llm, __judge_embeddings, __judge_llm_explicitly_set
|
|
292
452
|
try:
|
|
293
453
|
from langchain_core.embeddings import Embeddings
|
|
294
454
|
from langchain_core.language_models.chat_models import BaseChatModel
|
|
@@ -301,12 +461,13 @@ def set_judge_config(judge_llm, judge_embeddings):
|
|
|
301
461
|
):
|
|
302
462
|
__judge_llm = judge_llm
|
|
303
463
|
__judge_embeddings = judge_embeddings
|
|
304
|
-
|
|
464
|
+
__judge_llm_explicitly_set = True
|
|
305
465
|
elif isinstance(judge_llm, FunctionModel) and isinstance(
|
|
306
466
|
judge_embeddings, FunctionModel
|
|
307
467
|
):
|
|
308
468
|
__judge_llm = judge_llm.model
|
|
309
469
|
__judge_embeddings = judge_embeddings.model
|
|
470
|
+
__judge_llm_explicitly_set = True
|
|
310
471
|
else:
|
|
311
472
|
raise ValueError(
|
|
312
473
|
"Provided Judge LLM/Embeddings are not Langchain compatible. Ensure the judge LLM/embedding provided are an instance of "
|
|
@@ -21,7 +21,12 @@ from aiohttp import FormData
|
|
|
21
21
|
|
|
22
22
|
from .__version__ import __version__
|
|
23
23
|
from .client_config import client_config
|
|
24
|
-
from .errors import
|
|
24
|
+
from .errors import (
|
|
25
|
+
MissingAPICredentialsError,
|
|
26
|
+
MissingModelIdError,
|
|
27
|
+
ValidMindAuthError,
|
|
28
|
+
raise_api_error,
|
|
29
|
+
)
|
|
25
30
|
from .logging import get_logger, log_api_operation
|
|
26
31
|
from .utils import NumpyEncoder, is_html, md_to_html, run_async
|
|
27
32
|
from .vm_models.figure import Figure
|
|
@@ -34,10 +39,30 @@ _api_host = os.getenv("VM_API_HOST")
|
|
|
34
39
|
_model_cuid = os.getenv("VM_API_MODEL")
|
|
35
40
|
_document = None
|
|
36
41
|
_monitoring = False
|
|
42
|
+
_auth_mode = "api_key"
|
|
43
|
+
_access_token: Optional[str] = None
|
|
44
|
+
_oidc_login_context: Optional[Dict[str, str]] = None
|
|
37
45
|
|
|
38
46
|
__api_session: Optional[aiohttp.ClientSession] = None
|
|
39
47
|
|
|
40
48
|
|
|
49
|
+
def _invalidate_async_session() -> None:
|
|
50
|
+
"""Drop the aiohttp session so the next request picks up new headers."""
|
|
51
|
+
global __api_session
|
|
52
|
+
sess = __api_session
|
|
53
|
+
__api_session = None
|
|
54
|
+
if sess is None or sess.closed:
|
|
55
|
+
return
|
|
56
|
+
try:
|
|
57
|
+
loop = asyncio.get_running_loop()
|
|
58
|
+
loop.create_task(sess.close())
|
|
59
|
+
except RuntimeError:
|
|
60
|
+
try:
|
|
61
|
+
asyncio.run(sess.close())
|
|
62
|
+
except RuntimeError:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
41
66
|
@atexit.register
|
|
42
67
|
def _close_session():
|
|
43
68
|
"""Closes the async client session at exit."""
|
|
@@ -70,14 +95,21 @@ def get_api_model() -> Optional[str]:
|
|
|
70
95
|
|
|
71
96
|
def _get_api_headers() -> Dict[str, str]:
|
|
72
97
|
headers = {
|
|
73
|
-
"X-API-KEY": _api_key,
|
|
74
|
-
"X-API-SECRET": _api_secret,
|
|
75
98
|
"X-MODEL-CUID": _model_cuid,
|
|
76
99
|
"X-MONITORING": str(_monitoring),
|
|
77
100
|
"X-LIBRARY-VERSION": __version__,
|
|
78
101
|
}
|
|
79
102
|
if _document:
|
|
80
103
|
headers["X-DOCUMENT-TYPE"] = _document
|
|
104
|
+
if _auth_mode == "oidc":
|
|
105
|
+
if not _access_token:
|
|
106
|
+
raise ValidMindAuthError(
|
|
107
|
+
"OAuth access token is missing. Run vm.init() again with issuer and client_id."
|
|
108
|
+
)
|
|
109
|
+
headers["Authorization"] = f"Bearer {_access_token}"
|
|
110
|
+
else:
|
|
111
|
+
headers["X-API-KEY"] = _api_key
|
|
112
|
+
headers["X-API-SECRET"] = _api_secret
|
|
81
113
|
return headers
|
|
82
114
|
|
|
83
115
|
|
|
@@ -192,14 +224,71 @@ def _ping() -> Dict[str, Any]:
|
|
|
192
224
|
)
|
|
193
225
|
|
|
194
226
|
|
|
227
|
+
def _obtain_oidc_tokens(
|
|
228
|
+
issuer: str,
|
|
229
|
+
client_id: str,
|
|
230
|
+
scope: str,
|
|
231
|
+
audience: Optional[str] = None,
|
|
232
|
+
) -> Dict[str, Any]:
|
|
233
|
+
"""Return a credentials entry dict with access_token, expires_at, refresh_token, etc."""
|
|
234
|
+
from .credentials_store import (
|
|
235
|
+
delete_cached_entry,
|
|
236
|
+
get_cached_entry,
|
|
237
|
+
is_expired,
|
|
238
|
+
normalize_client_id,
|
|
239
|
+
normalize_issuer,
|
|
240
|
+
upsert_cached_entry,
|
|
241
|
+
)
|
|
242
|
+
from .oidc_device import run_device_flow, try_refresh_cached_tokens
|
|
243
|
+
|
|
244
|
+
norm_issuer = normalize_issuer(issuer)
|
|
245
|
+
norm_client_id = normalize_client_id(client_id)
|
|
246
|
+
cached = get_cached_entry(norm_issuer, norm_client_id, audience=audience)
|
|
247
|
+
if cached and not is_expired(cached):
|
|
248
|
+
return cached
|
|
249
|
+
if cached and cached.get("refresh_token"):
|
|
250
|
+
try:
|
|
251
|
+
new_tokens = try_refresh_cached_tokens(
|
|
252
|
+
norm_issuer,
|
|
253
|
+
norm_client_id,
|
|
254
|
+
cached["refresh_token"],
|
|
255
|
+
scope,
|
|
256
|
+
audience=audience,
|
|
257
|
+
)
|
|
258
|
+
upsert_cached_entry(
|
|
259
|
+
norm_issuer, norm_client_id, new_tokens, audience=audience
|
|
260
|
+
)
|
|
261
|
+
return new_tokens
|
|
262
|
+
except ValidMindAuthError:
|
|
263
|
+
delete_cached_entry(norm_issuer, norm_client_id, audience=audience)
|
|
264
|
+
tokens = run_device_flow(norm_issuer, norm_client_id, scope, audience=audience)
|
|
265
|
+
upsert_cached_entry(norm_issuer, norm_client_id, tokens, audience=audience)
|
|
266
|
+
return tokens
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _is_entra_issuer(issuer: str) -> bool:
|
|
270
|
+
return "login.microsoftonline.com" in issuer.lower()
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _select_oidc_bearer_token(entry: Dict[str, Any]) -> str:
|
|
274
|
+
if _is_entra_issuer(entry.get("issuer", "")) and entry.get("id_token"):
|
|
275
|
+
return entry["id_token"]
|
|
276
|
+
return entry["access_token"]
|
|
277
|
+
|
|
278
|
+
|
|
195
279
|
def init(
|
|
196
280
|
api_key: Optional[str] = None,
|
|
197
281
|
api_secret: Optional[str] = None,
|
|
198
282
|
api_host: Optional[str] = None,
|
|
283
|
+
api_url: Optional[str] = None,
|
|
199
284
|
model: Optional[str] = None,
|
|
200
285
|
monitoring: bool = False,
|
|
201
286
|
generate_descriptions: Optional[bool] = None,
|
|
202
287
|
document: Optional[str] = None,
|
|
288
|
+
issuer: Optional[str] = None,
|
|
289
|
+
client_id: Optional[str] = None,
|
|
290
|
+
scope: Optional[str] = None,
|
|
291
|
+
audience: Optional[str] = None,
|
|
203
292
|
):
|
|
204
293
|
"""
|
|
205
294
|
Initializes the API client instances and calls the /ping endpoint to ensure
|
|
@@ -208,36 +297,82 @@ def init(
|
|
|
208
297
|
If the API key and secret are not provided, the client will attempt to
|
|
209
298
|
retrieve them from the environment variables `VM_API_KEY` and `VM_API_SECRET`.
|
|
210
299
|
|
|
300
|
+
Alternatively, pass ``issuer`` and ``client_id`` or set their ``VM_OIDC_*``
|
|
301
|
+
environment variables to authenticate via the OIDC device authorization flow
|
|
302
|
+
(RFC 8628). Tokens are cached under ``~/.validmind/credentials.json``. Do not
|
|
303
|
+
combine API keys with OIDC parameters.
|
|
304
|
+
|
|
211
305
|
Args:
|
|
212
306
|
model (str, optional): The model CUID. Defaults to None.
|
|
213
307
|
api_key (str, optional): The API key. Defaults to None.
|
|
214
308
|
api_secret (str, optional): The API secret. Defaults to None.
|
|
215
|
-
api_host (str, optional): The API host. Defaults to
|
|
309
|
+
api_host (str, optional): The API host (tracking base URL). Defaults to
|
|
310
|
+
env ``VM_API_HOST`` or ``VM_API_URL``.
|
|
311
|
+
api_url (str, optional): Alias for ``api_host``. Defaults to env
|
|
312
|
+
``VM_API_URL`` or ``VM_API_HOST``.
|
|
216
313
|
monitoring (bool): The ongoing monitoring flag. Defaults to False.
|
|
217
314
|
generate_descriptions (bool, optional): Whether to use GenAI to generate test result descriptions. Defaults to True.
|
|
218
315
|
document (str, optional): The name of the document. Omitting this argument is deprecated.
|
|
316
|
+
issuer (str, optional): OIDC issuer URL (e.g. Entra tenant ``.../v2.0``).
|
|
317
|
+
Can be set via env ``VM_OIDC_ISSUER``.
|
|
318
|
+
client_id (str, optional): OAuth public client id for device flow. Can be
|
|
319
|
+
set via env ``VM_OIDC_CLIENT_ID``.
|
|
320
|
+
scope (str, optional): OAuth scopes (default ``openid profile email``).
|
|
321
|
+
Can be set via env ``VM_OIDC_SCOPE``.
|
|
322
|
+
audience (str, optional): Resource / API identifier for the access token
|
|
323
|
+
(e.g. Auth0 API Identifier). Use the same value the ValidMind backend
|
|
324
|
+
expects as ``api_audience`` so the provider can issue RS256 API tokens.
|
|
325
|
+
Can be set via env ``VM_OIDC_AUDIENCE``.
|
|
326
|
+
|
|
219
327
|
Raises:
|
|
220
|
-
|
|
328
|
+
MissingAPICredentialsError: If neither API keys nor OIDC parameters can be resolved.
|
|
329
|
+
MissingModelIdError: If model id is missing.
|
|
330
|
+
ValidMindAuthError: If OIDC configuration conflicts or login fails.
|
|
221
331
|
"""
|
|
222
332
|
global _api_key, _api_secret, _api_host, _model_cuid, _monitoring, _document
|
|
333
|
+
global _auth_mode, _access_token, _oidc_login_context
|
|
223
334
|
|
|
224
335
|
if api_key == "...":
|
|
225
336
|
# special case to detect when running a notebook placeholder (...)
|
|
226
337
|
# will override with environment variables for easier local development
|
|
227
|
-
api_host = api_key = api_secret = model =
|
|
338
|
+
api_host = api_url = api_key = api_secret = model = issuer = client_id = (
|
|
339
|
+
audience
|
|
340
|
+
) = None
|
|
228
341
|
|
|
229
342
|
_model_cuid = model or os.getenv("VM_API_MODEL")
|
|
230
343
|
if _model_cuid is None:
|
|
231
344
|
raise MissingModelIdError()
|
|
232
345
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
346
|
+
resolved_host = (
|
|
347
|
+
api_url
|
|
348
|
+
or api_host
|
|
349
|
+
or os.getenv("VM_API_URL")
|
|
350
|
+
or os.getenv("VM_API_HOST", "http://localhost:5000/api/v1/tracking/")
|
|
351
|
+
)
|
|
352
|
+
oidc_issuer = issuer if issuer is not None else os.getenv("VM_OIDC_ISSUER")
|
|
353
|
+
oidc_client_id = (
|
|
354
|
+
client_id if client_id is not None else os.getenv("VM_OIDC_CLIENT_ID")
|
|
355
|
+
)
|
|
356
|
+
oidc_scope = scope if scope is not None else os.getenv("VM_OIDC_SCOPE")
|
|
357
|
+
|
|
358
|
+
env_key = api_key if api_key is not None else os.getenv("VM_API_KEY")
|
|
359
|
+
env_secret = api_secret if api_secret is not None else os.getenv("VM_API_SECRET")
|
|
360
|
+
has_api_creds = (
|
|
361
|
+
env_key is not None
|
|
362
|
+
and env_secret is not None
|
|
363
|
+
and env_key != ""
|
|
364
|
+
and env_secret != ""
|
|
240
365
|
)
|
|
366
|
+
has_oidc = bool(oidc_issuer and oidc_client_id)
|
|
367
|
+
if has_oidc and has_api_creds:
|
|
368
|
+
raise ValidMindAuthError(
|
|
369
|
+
"Provide either API credentials (api_key and api_secret) or OIDC "
|
|
370
|
+
"(issuer and client_id), not both."
|
|
371
|
+
)
|
|
372
|
+
if oidc_issuer and not oidc_client_id:
|
|
373
|
+
raise ValidMindAuthError("client_id is required when issuer is set.")
|
|
374
|
+
if oidc_client_id and not oidc_issuer:
|
|
375
|
+
raise ValidMindAuthError("issuer is required when client_id is set.")
|
|
241
376
|
|
|
242
377
|
_monitoring = monitoring
|
|
243
378
|
|
|
@@ -251,6 +386,41 @@ def init(
|
|
|
251
386
|
)
|
|
252
387
|
|
|
253
388
|
_document = document
|
|
389
|
+
|
|
390
|
+
if has_oidc:
|
|
391
|
+
_auth_mode = "oidc"
|
|
392
|
+
_api_key = None
|
|
393
|
+
_api_secret = None
|
|
394
|
+
_api_host = resolved_host
|
|
395
|
+
scope_val = oidc_scope or "openid profile email"
|
|
396
|
+
from .credentials_store import normalize_audience
|
|
397
|
+
|
|
398
|
+
oidc_audience_val = normalize_audience(
|
|
399
|
+
audience if audience is not None else os.getenv("VM_OIDC_AUDIENCE")
|
|
400
|
+
)
|
|
401
|
+
oidc_audience_opt = oidc_audience_val or None
|
|
402
|
+
entry = _obtain_oidc_tokens(
|
|
403
|
+
oidc_issuer, oidc_client_id, scope_val, audience=oidc_audience_opt
|
|
404
|
+
)
|
|
405
|
+
_access_token = _select_oidc_bearer_token(entry)
|
|
406
|
+
_oidc_login_context = {
|
|
407
|
+
"issuer": entry["issuer"],
|
|
408
|
+
"client_id": entry["client_id"],
|
|
409
|
+
"scope": scope_val,
|
|
410
|
+
"audience": entry.get("audience") or oidc_audience_val,
|
|
411
|
+
}
|
|
412
|
+
_invalidate_async_session()
|
|
413
|
+
else:
|
|
414
|
+
if env_key is None or env_secret is None:
|
|
415
|
+
raise MissingAPICredentialsError()
|
|
416
|
+
_auth_mode = "api_key"
|
|
417
|
+
_access_token = None
|
|
418
|
+
_oidc_login_context = None
|
|
419
|
+
_api_key = env_key
|
|
420
|
+
_api_secret = env_secret
|
|
421
|
+
_api_host = resolved_host
|
|
422
|
+
_invalidate_async_session()
|
|
423
|
+
|
|
254
424
|
reload()
|
|
255
425
|
|
|
256
426
|
|