validmind 2.13.8__tar.gz → 2.13.11__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.
Files changed (378) hide show
  1. {validmind-2.13.8 → validmind-2.13.11}/.gitignore +0 -4
  2. {validmind-2.13.8 → validmind-2.13.11}/PKG-INFO +6 -4
  3. {validmind-2.13.8 → validmind-2.13.11}/pyproject.toml +7 -3
  4. validmind-2.13.11/validmind/__version__.py +1 -0
  5. {validmind-2.13.8 → validmind-2.13.11}/validmind/ai/utils.py +5 -2
  6. {validmind-2.13.8 → validmind-2.13.11}/validmind/api_client.py +214 -33
  7. {validmind-2.13.8 → validmind-2.13.11}/validmind/client.py +8 -2
  8. {validmind-2.13.8 → validmind-2.13.11}/validmind/client_config.py +4 -0
  9. {validmind-2.13.8 → validmind-2.13.11}/validmind/experimental/agents.py +3 -1
  10. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/CalibrationCurve.py +13 -1
  11. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +12 -7
  12. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/output.py +3 -0
  13. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/run.py +5 -2
  14. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/model.py +4 -2
  15. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/result/result.py +42 -12
  16. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/result/utils.py +13 -3
  17. validmind-2.13.8/validmind/__version__.py +0 -1
  18. {validmind-2.13.8 → validmind-2.13.11}/LICENSE +0 -0
  19. {validmind-2.13.8 → validmind-2.13.11}/README.pypi.md +0 -0
  20. {validmind-2.13.8 → validmind-2.13.11}/validmind/__init__.py +0 -0
  21. {validmind-2.13.8 → validmind-2.13.11}/validmind/ai/test_descriptions.py +0 -0
  22. {validmind-2.13.8 → validmind-2.13.11}/validmind/credentials_store.py +0 -0
  23. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/__init__.py +0 -0
  24. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/__init__.py +0 -0
  25. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/config.json +0 -0
  26. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/customer_churn.py +0 -0
  27. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/datasets/bank_customer_churn.csv +0 -0
  28. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/datasets/taiwan_credit.csv +0 -0
  29. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/classification/taiwan_credit.py +0 -0
  30. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/cluster/digits.py +0 -0
  31. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/credit_risk/__init__.py +0 -0
  32. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/credit_risk/datasets/lending_club_biased.csv.gz +0 -0
  33. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/credit_risk/datasets/lending_club_loan_data_2007_2014_clean.csv.gz +0 -0
  34. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/credit_risk/lending_club.py +0 -0
  35. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/credit_risk/lending_club_bias.py +0 -0
  36. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/__init__.py +0 -0
  37. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/agent_dataset.py +0 -0
  38. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/__init__.py +0 -0
  39. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_1.csv +0 -0
  40. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_2.csv +0 -0
  41. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_3.csv +0 -0
  42. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_4.csv +0 -0
  43. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_5.csv +0 -0
  44. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/llm/rag/rfp.py +0 -0
  45. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/__init__.py +0 -0
  46. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/cnn_dailymail.py +0 -0
  47. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/datasets/Covid_19.csv +0 -0
  48. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/datasets/cnn_dailymail_100_with_predictions.csv +0 -0
  49. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/datasets/cnn_dailymail_500_with_predictions.csv +0 -0
  50. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/datasets/sentiments_with_predictions.csv +0 -0
  51. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/nlp/twitter_covid_19.py +0 -0
  52. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/__init__.py +0 -0
  53. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/california_housing.py +0 -0
  54. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/california_housing.csv +0 -0
  55. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/CPIAUCSL.csv +0 -0
  56. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/CSUSHPISA.csv +0 -0
  57. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/DRSFRMACBS.csv +0 -0
  58. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/FEDFUNDS.csv +0 -0
  59. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/GDP.csv +0 -0
  60. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/GDPC1.csv +0 -0
  61. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/GS10.csv +0 -0
  62. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/GS3.csv +0 -0
  63. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/GS5.csv +0 -0
  64. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/MORTGAGE30US.csv +0 -0
  65. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred/UNRATE.csv +0 -0
  66. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates.csv +0 -0
  67. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates_test_1.csv +0 -0
  68. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates_test_2.csv +0 -0
  69. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates_test_3.csv +0 -0
  70. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates_test_4.csv +0 -0
  71. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/fred_loan_rates_test_5.csv +0 -0
  72. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/datasets/leanding_club_loan_rates.csv +0 -0
  73. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/fred.py +0 -0
  74. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/fred_timeseries.py +0 -0
  75. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/generate_california_housing_csv.py +0 -0
  76. {validmind-2.13.8 → validmind-2.13.11}/validmind/datasets/regression/lending_club.py +0 -0
  77. {validmind-2.13.8 → validmind-2.13.11}/validmind/errors.py +0 -0
  78. {validmind-2.13.8 → validmind-2.13.11}/validmind/experimental/__init__.py +0 -0
  79. {validmind-2.13.8 → validmind-2.13.11}/validmind/html_templates/__init__.py +0 -0
  80. {validmind-2.13.8 → validmind-2.13.11}/validmind/html_templates/content_blocks.py +0 -0
  81. {validmind-2.13.8 → validmind-2.13.11}/validmind/input_registry.py +0 -0
  82. {validmind-2.13.8 → validmind-2.13.11}/validmind/logging.py +0 -0
  83. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/__init__.py +0 -0
  84. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/foundation.py +0 -0
  85. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/function.py +0 -0
  86. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/huggingface.py +0 -0
  87. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/metadata.py +0 -0
  88. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/pipeline.py +0 -0
  89. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/pytorch.py +0 -0
  90. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/r_model.py +0 -0
  91. {validmind-2.13.8 → validmind-2.13.11}/validmind/models/sklearn.py +0 -0
  92. {validmind-2.13.8 → validmind-2.13.11}/validmind/oidc_device.py +0 -0
  93. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/__init__.py +0 -0
  94. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/AbsoluteError.py +0 -0
  95. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/BrierScore.py +0 -0
  96. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/CalibrationError.py +0 -0
  97. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/ClassBalance.py +0 -0
  98. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/Confidence.py +0 -0
  99. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/Correctness.py +0 -0
  100. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/LogLoss.py +0 -0
  101. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/OutlierScore.py +0 -0
  102. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/ProbabilityError.py +0 -0
  103. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/Uncertainty.py +0 -0
  104. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/classification/__init__.py +0 -0
  105. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/AnswerRelevancy.py +0 -0
  106. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/ArgumentCorrectness.py +0 -0
  107. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/Bias.py +0 -0
  108. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/ContextualPrecision.py +0 -0
  109. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/ContextualRecall.py +0 -0
  110. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/ContextualRelevancy.py +0 -0
  111. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/Faithfulness.py +0 -0
  112. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/GEval.py +0 -0
  113. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/Hallucination.py +0 -0
  114. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/PlanAdherence.py +0 -0
  115. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/PlanQuality.py +0 -0
  116. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/Summarization.py +0 -0
  117. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/TaskCompletion.py +0 -0
  118. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/ToolCorrectness.py +0 -0
  119. {validmind-2.13.8 → validmind-2.13.11}/validmind/scorers/llm/deepeval/__init__.py +0 -0
  120. {validmind-2.13.8 → validmind-2.13.11}/validmind/template.py +0 -0
  121. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/__init__.py +0 -0
  122. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/classifier.py +0 -0
  123. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/cluster.py +0 -0
  124. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/embeddings.py +0 -0
  125. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/llm.py +0 -0
  126. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/nlp.py +0 -0
  127. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/parameters_optimization.py +0 -0
  128. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/regression.py +0 -0
  129. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/statsmodels_timeseries.py +0 -0
  130. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/summarization.py +0 -0
  131. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/tabular_datasets.py +0 -0
  132. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/text_data.py +0 -0
  133. {validmind-2.13.8 → validmind-2.13.11}/validmind/test_suites/time_series.py +0 -0
  134. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/__init__.py +0 -0
  135. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/__types__.py +0 -0
  136. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/_store.py +0 -0
  137. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/comparison.py +0 -0
  138. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ACFandPACFPlot.py +0 -0
  139. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ADF.py +0 -0
  140. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/AutoAR.py +0 -0
  141. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/AutoMA.py +0 -0
  142. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/AutoStationarity.py +0 -0
  143. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/BivariateScatterPlots.py +0 -0
  144. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/BoxPierce.py +0 -0
  145. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ChiSquaredFeaturesTable.py +0 -0
  146. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ClassImbalance.py +0 -0
  147. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/DatasetDescription.py +0 -0
  148. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/DatasetSplit.py +0 -0
  149. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/DescriptiveStatistics.py +0 -0
  150. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/DickeyFullerGLS.py +0 -0
  151. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/Duplicates.py +0 -0
  152. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/EngleGrangerCoint.py +0 -0
  153. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/FeatureTargetCorrelationPlot.py +0 -0
  154. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/HighCardinality.py +0 -0
  155. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/HighPearsonCorrelation.py +0 -0
  156. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/IQROutliersBarPlot.py +0 -0
  157. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/IQROutliersTable.py +0 -0
  158. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/IsolationForestOutliers.py +0 -0
  159. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/JarqueBera.py +0 -0
  160. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/KPSS.py +0 -0
  161. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/LJungBox.py +0 -0
  162. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/LaggedCorrelationHeatmap.py +0 -0
  163. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/MissingValues.py +0 -0
  164. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/MissingValuesBarPlot.py +0 -0
  165. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/MutualInformation.py +0 -0
  166. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/PearsonCorrelationMatrix.py +0 -0
  167. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/PhillipsPerronArch.py +0 -0
  168. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ProtectedClassesCombination.py +0 -0
  169. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ProtectedClassesDescription.py +0 -0
  170. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ProtectedClassesDisparity.py +0 -0
  171. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ProtectedClassesThresholdOptimizer.py +0 -0
  172. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/RollingStatsPlot.py +0 -0
  173. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/RunsTest.py +0 -0
  174. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ScatterPlot.py +0 -0
  175. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ScoreBandDefaultRates.py +0 -0
  176. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/SeasonalDecompose.py +0 -0
  177. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ShapiroWilk.py +0 -0
  178. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/Skewness.py +0 -0
  179. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/SpreadPlot.py +0 -0
  180. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TabularCategoricalBarPlots.py +0 -0
  181. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TabularDateTimeHistograms.py +0 -0
  182. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TabularDescriptionTables.py +0 -0
  183. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TabularNumericalHistograms.py +0 -0
  184. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TargetRateBarPlots.py +0 -0
  185. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesDescription.py +0 -0
  186. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesDescriptiveStatistics.py +0 -0
  187. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesFrequency.py +0 -0
  188. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesHistogram.py +0 -0
  189. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesLinePlot.py +0 -0
  190. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesMissingValues.py +0 -0
  191. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TimeSeriesOutliers.py +0 -0
  192. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/TooManyZeroValues.py +0 -0
  193. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/UniqueRows.py +0 -0
  194. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/WOEBinPlots.py +0 -0
  195. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/WOEBinTable.py +0 -0
  196. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/ZivotAndrewsArch.py +0 -0
  197. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/__init__.py +0 -0
  198. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/CommonWords.py +0 -0
  199. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/Hashtags.py +0 -0
  200. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/LanguageDetection.py +0 -0
  201. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/Mentions.py +0 -0
  202. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +0 -0
  203. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/Punctuations.py +0 -0
  204. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/Sentiment.py +0 -0
  205. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/StopWords.py +0 -0
  206. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/TextDescription.py +0 -0
  207. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/Toxicity.py +0 -0
  208. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/data_validation/nlp/__init__.py +0 -0
  209. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/decorator.py +0 -0
  210. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/load.py +0 -0
  211. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/BertScore.py +0 -0
  212. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/BleuScore.py +0 -0
  213. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ClusterSizeDistribution.py +0 -0
  214. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ContextualRecall.py +0 -0
  215. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/FeaturesAUC.py +0 -0
  216. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/MeteorScore.py +0 -0
  217. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ModelMetadata.py +0 -0
  218. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ModelPredictionResiduals.py +0 -0
  219. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/RegardScore.py +0 -0
  220. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/RegressionResidualsPlot.py +0 -0
  221. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/RougeScore.py +0 -0
  222. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/TimeSeriesPredictionWithCI.py +0 -0
  223. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/TimeSeriesPredictionsPlot.py +0 -0
  224. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/TimeSeriesR2SquareBySegments.py +0 -0
  225. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/TokenDisparity.py +0 -0
  226. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ToxicityScore.py +0 -0
  227. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/__init__.py +0 -0
  228. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/ClusterDistribution.py +0 -0
  229. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/CosineSimilarityComparison.py +0 -0
  230. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +0 -0
  231. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/CosineSimilarityHeatmap.py +0 -0
  232. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +0 -0
  233. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +0 -0
  234. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/EuclideanDistanceComparison.py +0 -0
  235. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/EuclideanDistanceHeatmap.py +0 -0
  236. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/PCAComponentsPairwisePlots.py +0 -0
  237. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +0 -0
  238. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +0 -0
  239. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +0 -0
  240. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +0 -0
  241. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/TSNEComponentsPairwisePlots.py +0 -0
  242. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/embeddings/utils.py +0 -0
  243. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/AnswerCorrectness.py +0 -0
  244. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/AspectCritic.py +0 -0
  245. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/ContextEntityRecall.py +0 -0
  246. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/ContextPrecision.py +0 -0
  247. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/ContextPrecisionWithoutReference.py +0 -0
  248. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/ContextRecall.py +0 -0
  249. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/Faithfulness.py +0 -0
  250. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/NoiseSensitivity.py +0 -0
  251. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/ResponseRelevancy.py +0 -0
  252. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/SemanticSimilarity.py +0 -0
  253. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/ragas/utils.py +0 -0
  254. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +0 -0
  255. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +0 -0
  256. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ClassifierPerformance.py +0 -0
  257. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ClassifierThresholdOptimization.py +0 -0
  258. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +0 -0
  259. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +0 -0
  260. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/CompletenessScore.py +0 -0
  261. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ConfusionMatrix.py +0 -0
  262. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/FeatureImportance.py +0 -0
  263. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +0 -0
  264. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/HomogeneityScore.py +0 -0
  265. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/HyperParametersTuning.py +0 -0
  266. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +0 -0
  267. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/MinimumAccuracy.py +0 -0
  268. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/MinimumF1Score.py +0 -0
  269. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +0 -0
  270. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ModelParameters.py +0 -0
  271. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +0 -0
  272. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +0 -0
  273. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +0 -0
  274. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +0 -0
  275. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +0 -0
  276. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ROCCurve.py +0 -0
  277. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RegressionErrors.py +0 -0
  278. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RegressionErrorsComparison.py +0 -0
  279. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RegressionPerformance.py +0 -0
  280. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RegressionR2Square.py +0 -0
  281. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RegressionR2SquareComparison.py +0 -0
  282. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +0 -0
  283. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +0 -0
  284. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/ScoreProbabilityAlignment.py +0 -0
  285. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/SilhouettePlot.py +0 -0
  286. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +0 -0
  287. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/VMeasure.py +0 -0
  288. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/__init__.py +0 -0
  289. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/_diagnosis_metrics.py +0 -0
  290. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/sklearn/_multiclass_proba.py +0 -0
  291. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/AutoARIMA.py +0 -0
  292. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/CumulativePredictionProbabilities.py +0 -0
  293. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/DurbinWatsonTest.py +0 -0
  294. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/GINITable.py +0 -0
  295. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +0 -0
  296. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/Lilliefors.py +0 -0
  297. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/PredictionProbabilitiesHistogram.py +0 -0
  298. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionCoeffs.py +0 -0
  299. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +0 -0
  300. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +0 -0
  301. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +0 -0
  302. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +0 -0
  303. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +0 -0
  304. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +0 -0
  305. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/ScorecardHistogram.py +0 -0
  306. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/__init__.py +0 -0
  307. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/model_validation/statsmodels/statsutils.py +0 -0
  308. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/CalibrationCurveDrift.py +0 -0
  309. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ClassDiscriminationDrift.py +0 -0
  310. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ClassImbalanceDrift.py +0 -0
  311. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ClassificationAccuracyDrift.py +0 -0
  312. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ConfusionMatrixDrift.py +0 -0
  313. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/CumulativePredictionProbabilitiesDrift.py +0 -0
  314. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/FeatureDrift.py +0 -0
  315. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py +0 -0
  316. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/PredictionCorrelation.py +0 -0
  317. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/PredictionProbabilitiesHistogramDrift.py +0 -0
  318. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/PredictionQuantilesAcrossFeatures.py +0 -0
  319. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ROCCurveDrift.py +0 -0
  320. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ScoreBandsDrift.py +0 -0
  321. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/ScorecardHistogramDrift.py +0 -0
  322. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +0 -0
  323. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/plots/BoxPlot.py +0 -0
  324. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/plots/CorrelationHeatmap.py +0 -0
  325. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/plots/HistogramPlot.py +0 -0
  326. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/plots/ViolinPlot.py +0 -0
  327. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/plots/__init__.py +0 -0
  328. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Bias.py +0 -0
  329. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Clarity.py +0 -0
  330. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Conciseness.py +0 -0
  331. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Delimitation.py +0 -0
  332. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/NegativeInstruction.py +0 -0
  333. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Robustness.py +0 -0
  334. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/Specificity.py +0 -0
  335. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/__init__.py +0 -0
  336. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/prompt_validation/ai_powered_test.py +0 -0
  337. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/stats/CorrelationAnalysis.py +0 -0
  338. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/stats/DescriptiveStats.py +0 -0
  339. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/stats/NormalityTests.py +0 -0
  340. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/stats/OutlierDetection.py +0 -0
  341. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/stats/__init__.py +0 -0
  342. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/test_providers.py +0 -0
  343. {validmind-2.13.8 → validmind-2.13.11}/validmind/tests/utils.py +0 -0
  344. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/__init__.py +0 -0
  345. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/classification/Accuracy.py +0 -0
  346. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/classification/F1.py +0 -0
  347. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/classification/Precision.py +0 -0
  348. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/classification/ROC_AUC.py +0 -0
  349. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/classification/Recall.py +0 -0
  350. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/AdjustedRSquaredScore.py +0 -0
  351. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/GiniCoefficient.py +0 -0
  352. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/HuberLoss.py +0 -0
  353. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +0 -0
  354. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/MeanAbsoluteError.py +0 -0
  355. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +0 -0
  356. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/MeanBiasDeviation.py +0 -0
  357. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/MeanSquaredError.py +0 -0
  358. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/QuantileLoss.py +0 -0
  359. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/RSquaredScore.py +0 -0
  360. {validmind-2.13.8 → validmind-2.13.11}/validmind/unit_metrics/regression/RootMeanSquaredError.py +0 -0
  361. {validmind-2.13.8 → validmind-2.13.11}/validmind/utils.py +0 -0
  362. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/__init__.py +0 -0
  363. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/dataset/__init__.py +0 -0
  364. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/dataset/dataset.py +0 -0
  365. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/dataset/utils.py +0 -0
  366. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/figure.py +0 -0
  367. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/html_progress.py +0 -0
  368. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/html_renderer.py +0 -0
  369. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/input.py +0 -0
  370. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/result/__init__.py +0 -0
  371. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/result/pii_filter.py +0 -0
  372. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/result/result.jinja +0 -0
  373. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/test_suite/__init__.py +0 -0
  374. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/test_suite/runner.py +0 -0
  375. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/test_suite/summary.py +0 -0
  376. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/test_suite/test.py +0 -0
  377. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/test_suite/test_suite.py +0 -0
  378. {validmind-2.13.8 → validmind-2.13.11}/validmind/vm_models/text_generation_summary.py +0 -0
@@ -189,12 +189,8 @@ lending_club_loan_data_*.csv
189
189
 
190
190
  # Pickle files
191
191
  *.pkl
192
- # Sample application scorecard model for validation notebook — do not remove!
193
- !notebooks/use_cases/validation/xgb_model_champion.pkl
194
192
  # Sample logistic regression model for validation series — do not remove!
195
193
  !notebooks/tutorials/validation/lr_model_champion.pkl
196
- # Sample XGBoost model for validation quickstart — do not remove!
197
- !notebooks/quickstart/xgboost_model_champion.pkl
198
194
 
199
195
  notebooks/llm/datasets/*.jsonl
200
196
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: validmind
3
- Version: 2.13.8
3
+ Version: 2.13.11
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
@@ -735,6 +735,7 @@ Requires-Dist: pyarrow<23,>=22; (python_version >= '3.14') and extra == 'all'
735
735
  Requires-Dist: pycocoevalcap; extra == 'all'
736
736
  Requires-Dist: ragas<=0.2.7,>=0.2.3; extra == 'all'
737
737
  Requires-Dist: rouge>=1; extra == 'all'
738
+ Requires-Dist: scikit-learn<1.8; extra == 'all'
738
739
  Requires-Dist: scipy; extra == 'all'
739
740
  Requires-Dist: scorecardpy==0.1.9.6; extra == 'all'
740
741
  Requires-Dist: sentencepiece<0.3.0,>=0.2.0; extra == 'all'
@@ -744,7 +745,7 @@ Requires-Dist: statsmodels<0.15.0,>=0.14.2; extra == 'all'
744
745
  Requires-Dist: textblob<0.19.0,>=0.18.0.post0; extra == 'all'
745
746
  Requires-Dist: torch>=2.0.0; extra == 'all'
746
747
  Requires-Dist: transformers<5.0.0,>=4.32.0; extra == 'all'
747
- Requires-Dist: xgboost<3,>=1.5.2; extra == 'all'
748
+ Requires-Dist: xgboost<3.1,>=1.5.2; extra == 'all'
748
749
  Provides-Extra: credit-risk
749
750
  Requires-Dist: scorecardpy==0.1.9.6; extra == 'credit-risk'
750
751
  Requires-Dist: setuptools<82; extra == 'credit-risk'
@@ -802,7 +803,8 @@ Requires-Dist: arch>=7.0.0; extra == 'stats'
802
803
  Requires-Dist: scipy; extra == 'stats'
803
804
  Requires-Dist: statsmodels<0.15.0,>=0.14.2; extra == 'stats'
804
805
  Provides-Extra: xgboost
805
- Requires-Dist: xgboost<3,>=1.5.2; extra == 'xgboost'
806
+ Requires-Dist: scikit-learn<1.8; extra == 'xgboost'
807
+ Requires-Dist: xgboost<3.1,>=1.5.2; extra == 'xgboost'
806
808
  Description-Content-Type: text/markdown
807
809
 
808
810
  # ValidMind Library
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "validmind"
3
- version = "2.13.8"
3
+ version = "2.13.11"
4
4
  description = "ValidMind Library"
5
5
  readme = "README.pypi.md"
6
6
  requires-python = ">=3.9,<3.15"
@@ -40,7 +40,8 @@ dependencies = [
40
40
  [project.optional-dependencies]
41
41
  all = [
42
42
  "torch (>=2.0.0)",
43
- "xgboost (>=1.5.2,<3)",
43
+ "xgboost (>=1.5.2,<3.1)",
44
+ "scikit-learn (<1.8)",
44
45
  "transformers (>=4.32.0,<5.0.0)",
45
46
  "pycocoevalcap",
46
47
  "ragas (>=0.2.3,<=0.2.7)",
@@ -108,7 +109,10 @@ nlp = [
108
109
  ]
109
110
  pytorch = ["torch (>=2.0.0)"]
110
111
  stats = ["scipy", "statsmodels (>=0.14.2,<0.15.0)", "arch (>=7.0.0)"]
111
- xgboost = ["xgboost (>=1.5.2,<3)"]
112
+ xgboost = [
113
+ "xgboost (>=1.5.2,<3.1)",
114
+ "scikit-learn (<1.8)",
115
+ ]
112
116
  explainability = [
113
117
  "shap (>=0.46.0)",
114
118
  "numba (>=0.65.1) ; python_version >= '3.14'",
@@ -0,0 +1 @@
1
+ __version__ = "2.13.11"
@@ -8,7 +8,7 @@ import os
8
8
  from openai import AzureOpenAI, OpenAI
9
9
 
10
10
  from ..logging import get_logger
11
- from ..utils import md_to_html
11
+ from ..utils import is_html, md_to_html
12
12
 
13
13
  logger = get_logger(__name__)
14
14
 
@@ -38,6 +38,7 @@ class DescriptionFuture:
38
38
 
39
39
  def __init__(self, future):
40
40
  self._future = future
41
+ self.markdown_source = None
41
42
 
42
43
  def get_description(self):
43
44
  if isinstance(self._future, tuple):
@@ -46,7 +47,9 @@ class DescriptionFuture:
46
47
  # This will block until the future is completed
47
48
  description = self._future.result()
48
49
 
49
- return md_to_html(description[0], mathml=True), description[1]
50
+ source, was_generated = description
51
+ self.markdown_source = source if not is_html(source) else None
52
+ return md_to_html(source, mathml=True), was_generated
50
53
 
51
54
 
52
55
  def _get_google_api_key():
@@ -11,6 +11,7 @@ import asyncio
11
11
  import atexit
12
12
  import json
13
13
  import os
14
+ import threading
14
15
  from io import BytesIO
15
16
  from typing import Any, Dict, List, Optional, Tuple, Union
16
17
  from urllib.parse import urlencode, urljoin
@@ -42,6 +43,10 @@ _monitoring = False
42
43
  _auth_mode = "api_key"
43
44
  _access_token: Optional[str] = None
44
45
  _oidc_login_context: Optional[Dict[str, str]] = None
46
+ # Expiry (ISO-8601) of the in-memory OIDC access token, for cheap request-path
47
+ # staleness checks; guarded together with the token by _oidc_refresh_lock.
48
+ _oidc_expires_at: Optional[str] = None
49
+ _oidc_refresh_lock = threading.Lock()
45
50
 
46
51
  __api_session: Optional[aiohttp.ClientSession] = None
47
52
 
@@ -147,12 +152,21 @@ def _get_url(
147
152
  async def _get(
148
153
  endpoint: str, params: Optional[Dict[str, str]] = None
149
154
  ) -> Dict[str, Any]:
155
+ _ensure_fresh_oidc_token()
150
156
  url = _get_url(endpoint, params)
151
157
  session = _get_session()
152
158
 
153
159
  async with session.get(url) as r:
160
+ # A 401 can still slip through if the token was revoked ahead of its
161
+ # stated expiry; force a refresh and retry once (safe — GET has no body).
162
+ if r.status == 401 and _ensure_fresh_oidc_token(force=True):
163
+ session = _get_session()
164
+ async with session.get(url) as retry:
165
+ if retry.status != 200:
166
+ _raise_for_api_error(retry.status, await retry.text())
167
+ return await retry.json()
154
168
  if r.status != 200:
155
- raise_api_error(await r.text())
169
+ _raise_for_api_error(r.status, await r.text())
156
170
 
157
171
  return await r.json()
158
172
 
@@ -163,6 +177,7 @@ async def _post(
163
177
  data: Optional[Union[dict, FormData]] = None,
164
178
  files: Optional[Dict[str, Tuple[str, BytesIO, str]]] = None,
165
179
  ) -> Dict[str, Any]:
180
+ _ensure_fresh_oidc_token()
166
181
  url = _get_url(endpoint, params)
167
182
  session = _get_session()
168
183
 
@@ -186,20 +201,29 @@ async def _post(
186
201
  _data = data
187
202
 
188
203
  async with session.post(url, data=_data) as r:
204
+ # Not retried on 401: the request body / upload stream may already be
205
+ # consumed. Proactive refresh above covers the expiry case; a 401 here
206
+ # means a genuinely rejected token, surfaced as a clear auth error.
189
207
  if r.status != 200:
190
- raise_api_error(await r.text())
208
+ _raise_for_api_error(r.status, await r.text())
191
209
 
192
210
  return await r.json()
193
211
 
194
212
 
195
213
  def _ping() -> Dict[str, Any]:
196
214
  """Validates that we can connect to the ValidMind API (does not use the async session)."""
215
+ _ensure_fresh_oidc_token()
197
216
  r = requests.get(
198
217
  url=_get_url("ping"),
199
218
  headers=_get_api_headers(),
200
219
  )
220
+ if r.status_code == 401 and _ensure_fresh_oidc_token(force=True):
221
+ r = requests.get(
222
+ url=_get_url("ping"),
223
+ headers=_get_api_headers(),
224
+ )
201
225
  if r.status_code != 200:
202
- raise_api_error(r.text)
226
+ _raise_for_api_error(r.status_code, r.text)
203
227
 
204
228
  client_info = r.json()
205
229
 
@@ -224,6 +248,36 @@ def _ping() -> Dict[str, Any]:
224
248
  )
225
249
 
226
250
 
251
+ def _refresh_oidc_from_cache(
252
+ issuer: str,
253
+ client_id: str,
254
+ refresh_token: str,
255
+ scope: Optional[str],
256
+ audience: Optional[str] = None,
257
+ ) -> Optional[Dict[str, Any]]:
258
+ """Exchange a cached refresh token for new tokens, persisting the result.
259
+
260
+ Shared by the ``init()`` path (``_obtain_oidc_tokens``) and the request path
261
+ (``_ensure_fresh_oidc_token``) so their refresh behaviour can't drift. On
262
+ success the refreshed entry is cached and returned. On a failed refresh (e.g.
263
+ revoked token / ``invalid_grant``) the stale entry is deleted and None is
264
+ returned, so a dead refresh token isn't re-attempted; the caller decides how
265
+ to recover (``init()`` falls back to device flow, the request path stops).
266
+ """
267
+ from .credentials_store import delete_cached_entry, upsert_cached_entry
268
+ from .oidc_device import try_refresh_cached_tokens
269
+
270
+ try:
271
+ new_tokens = try_refresh_cached_tokens(
272
+ issuer, client_id, refresh_token, scope, audience=audience
273
+ )
274
+ except ValidMindAuthError:
275
+ delete_cached_entry(issuer, client_id, audience=audience)
276
+ return None
277
+ upsert_cached_entry(issuer, client_id, new_tokens, audience=audience)
278
+ return new_tokens
279
+
280
+
227
281
  def _obtain_oidc_tokens(
228
282
  issuer: str,
229
283
  client_id: str,
@@ -232,14 +286,13 @@ def _obtain_oidc_tokens(
232
286
  ) -> Dict[str, Any]:
233
287
  """Return a credentials entry dict with access_token, expires_at, refresh_token, etc."""
234
288
  from .credentials_store import (
235
- delete_cached_entry,
236
289
  get_cached_entry,
237
290
  is_expired,
238
291
  normalize_client_id,
239
292
  normalize_issuer,
240
293
  upsert_cached_entry,
241
294
  )
242
- from .oidc_device import run_device_flow, try_refresh_cached_tokens
295
+ from .oidc_device import run_device_flow
243
296
 
244
297
  norm_issuer = normalize_issuer(issuer)
245
298
  norm_client_id = normalize_client_id(client_id)
@@ -247,20 +300,11 @@ def _obtain_oidc_tokens(
247
300
  if cached and not is_expired(cached):
248
301
  return cached
249
302
  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
- )
303
+ new_tokens = _refresh_oidc_from_cache(
304
+ norm_issuer, norm_client_id, cached["refresh_token"], scope, audience
305
+ )
306
+ if new_tokens is not None:
261
307
  return new_tokens
262
- except ValidMindAuthError:
263
- delete_cached_entry(norm_issuer, norm_client_id, audience=audience)
264
308
  tokens = run_device_flow(norm_issuer, norm_client_id, scope, audience=audience)
265
309
  upsert_cached_entry(norm_issuer, norm_client_id, tokens, audience=audience)
266
310
  return tokens
@@ -276,6 +320,100 @@ def _select_oidc_bearer_token(entry: Dict[str, Any]) -> str:
276
320
  return entry["access_token"]
277
321
 
278
322
 
323
+ def _set_oidc_access_token(entry: Dict[str, Any]) -> None:
324
+ """Adopt the bearer token from a credentials entry as the active token.
325
+
326
+ Records its expiry for cheap request-path staleness checks and drops the
327
+ pooled aiohttp session so the next request rebuilds it with the new token.
328
+ """
329
+ global _access_token, _oidc_expires_at
330
+ _access_token = _select_oidc_bearer_token(entry)
331
+ _oidc_expires_at = entry.get("expires_at")
332
+ _invalidate_async_session()
333
+
334
+
335
+ def _clear_oidc_access_token() -> None:
336
+ """Drop the in-memory OIDC token and pooled session after an unrecoverable refresh.
337
+
338
+ Pairs with deleting the cached entry: with no usable token in memory, the next
339
+ request fails fast at header build with the clear "run vm.init()" error instead
340
+ of sending a doomed request just to get a 401 back.
341
+ """
342
+ global _access_token, _oidc_expires_at
343
+ _access_token = None
344
+ _oidc_expires_at = None
345
+ _invalidate_async_session()
346
+
347
+
348
+ def _oidc_token_is_stale() -> bool:
349
+ """Cheap in-memory expiry check (no file I/O) using the 120s skew in is_expired."""
350
+ from .credentials_store import is_expired
351
+
352
+ return is_expired({"expires_at": _oidc_expires_at})
353
+
354
+
355
+ def _ensure_fresh_oidc_token(force: bool = False) -> bool:
356
+ """Refresh the OIDC access token on the request path when it has expired.
357
+
358
+ The token captured at ``init()`` is otherwise reused unchanged for the life of
359
+ the process, so a session that outlives the provider's access-token lifetime
360
+ starts failing on every call until ``init()`` is re-run. This uses the cached
361
+ refresh token (requires ``offline_access``, the default scope) to obtain a new
362
+ access token in place. Returns True when a usable token is in place, False when
363
+ no refresh was possible (non-OIDC mode, no cached refresh token, or a failed
364
+ refresh — in which case the cached entry is dropped, matching init()).
365
+ """
366
+ if _auth_mode != "oidc" or _oidc_login_context is None:
367
+ return False
368
+ # Hot path: skip file I/O and the lock while the current token is still valid.
369
+ if not force and not _oidc_token_is_stale():
370
+ return True
371
+
372
+ from .credentials_store import get_cached_entry, is_expired
373
+
374
+ ctx = _oidc_login_context
375
+ issuer = ctx["issuer"]
376
+ client_id = ctx["client_id"]
377
+ scope = ctx.get("scope")
378
+ audience = ctx.get("audience") or None
379
+
380
+ with _oidc_refresh_lock:
381
+ entry = get_cached_entry(issuer, client_id, audience=audience)
382
+ if entry is None:
383
+ return False
384
+ # Another caller may have refreshed the token while we waited on the lock.
385
+ if not force and not is_expired(entry):
386
+ _set_oidc_access_token(entry)
387
+ return True
388
+ refresh_token = entry.get("refresh_token")
389
+ if not refresh_token:
390
+ return False
391
+ # Shared with init(): on failure the cached entry is dropped so a
392
+ # bad/revoked refresh token isn't re-attempted on every request. Recovery
393
+ # is re-running vm.init() (surfaced by the clear 401 auth error); unlike
394
+ # init() the request path can't fall back to interactive device flow.
395
+ new_tokens = _refresh_oidc_from_cache(
396
+ issuer, client_id, refresh_token, scope, audience
397
+ )
398
+ if new_tokens is None:
399
+ # Hard failure: the cache entry was dropped; clear the in-memory token
400
+ # too so the next request fails fast with the clear re-auth message.
401
+ _clear_oidc_access_token()
402
+ return False
403
+ _set_oidc_access_token(new_tokens)
404
+ return True
405
+
406
+
407
+ def _raise_for_api_error(status: int, text: str) -> None:
408
+ """Raise a clear, actionable auth error for an OIDC 401, else defer to raise_api_error."""
409
+ if status == 401 and _auth_mode == "oidc":
410
+ raise ValidMindAuthError(
411
+ "ValidMind rejected the OAuth access token (HTTP 401); it may have "
412
+ "expired or been revoked. Run vm.init() again to re-authenticate."
413
+ )
414
+ raise_api_error(text)
415
+
416
+
279
417
  def init(
280
418
  api_key: Optional[str] = None,
281
419
  api_secret: Optional[str] = None,
@@ -330,7 +468,7 @@ def init(
330
468
  ValidMindAuthError: If OIDC configuration conflicts or login fails.
331
469
  """
332
470
  global _api_key, _api_secret, _api_host, _model_cuid, _monitoring, _document
333
- global _auth_mode, _access_token, _oidc_login_context
471
+ global _auth_mode, _access_token, _oidc_login_context, _oidc_expires_at
334
472
 
335
473
  if api_key == "...":
336
474
  # special case to detect when running a notebook placeholder (...)
@@ -402,20 +540,21 @@ def init(
402
540
  entry = _obtain_oidc_tokens(
403
541
  oidc_issuer, oidc_client_id, scope_val, audience=oidc_audience_opt
404
542
  )
405
- _access_token = _select_oidc_bearer_token(entry)
406
543
  _oidc_login_context = {
407
544
  "issuer": entry["issuer"],
408
545
  "client_id": entry["client_id"],
409
546
  "scope": scope_val,
410
547
  "audience": entry.get("audience") or oidc_audience_val,
411
548
  }
412
- _invalidate_async_session()
549
+ # Sets _access_token / _oidc_expires_at and invalidates the async session.
550
+ _set_oidc_access_token(entry)
413
551
  else:
414
552
  if env_key is None or env_secret is None:
415
553
  raise MissingAPICredentialsError()
416
554
  _auth_mode = "api_key"
417
555
  _access_token = None
418
556
  _oidc_login_context = None
557
+ _oidc_expires_at = None
419
558
  _api_key = env_key
420
559
  _api_secret = env_secret
421
560
  _api_host = resolved_host
@@ -449,6 +588,7 @@ async def alog_metadata(
449
588
  text: Optional[str] = None,
450
589
  _json: Optional[Dict[str, Any]] = None,
451
590
  section_id: Optional[str] = None,
591
+ text_format: Optional[str] = None,
452
592
  ) -> Dict[str, Any]:
453
593
  """Logs free-form metadata to ValidMind API.
454
594
 
@@ -458,6 +598,9 @@ async def alog_metadata(
458
598
  _json (dict, optional): Free-form key-value pairs to assign to the metadata. Defaults to None.
459
599
  section_id (str, optional): Section ID to append the text block to when the
460
600
  content ID does not already exist.
601
+ text_format (str, optional): Format of ``text``. Markdown is sent as-is when
602
+ the backend advertises support so conversion happens after the request
603
+ passes through the WAF. Older backends receive locally converted HTML.
461
604
 
462
605
  Raises:
463
606
  Exception: If the API call fails.
@@ -465,11 +608,17 @@ async def alog_metadata(
465
608
  Returns:
466
609
  dict: The response from the API.
467
610
  """
611
+ if text_format == "markdown" and not client_config.supports_log_metadata_markdown():
612
+ text = md_to_html(text, mathml=True)
613
+ text_format = None
614
+
468
615
  metadata_dict = {"content_id": content_id}
469
616
  if text is not None:
470
617
  metadata_dict["text"] = text
471
618
  if _json is not None:
472
619
  metadata_dict["json"] = _json
620
+ if text_format is not None:
621
+ metadata_dict["text_format"] = text_format
473
622
 
474
623
  request_params = {}
475
624
  if section_id:
@@ -656,6 +805,7 @@ def _validate_log_text_context(
656
805
 
657
806
  def generate_qualitative_text(text_generation_data: Dict[str, Any]) -> Dict[str, Any]:
658
807
  """Generate qualitative text using the ValidMind AI API."""
808
+ _ensure_fresh_oidc_token()
659
809
  r = requests.post(
660
810
  url=_get_url("ai/generate/qualitative_text_generation"),
661
811
  headers=_get_api_headers(),
@@ -663,16 +813,23 @@ def generate_qualitative_text(text_generation_data: Dict[str, Any]) -> Dict[str,
663
813
  )
664
814
 
665
815
  if r.status_code != 200:
666
- raise_api_error(r.text)
816
+ _raise_for_api_error(r.status_code, r.text)
667
817
 
668
818
  return r.json()
669
819
 
670
820
 
671
- def _normalize_logged_text(text: str, field_name: str) -> str:
672
- """Validate text content and convert Markdown to HTML when needed."""
821
+ def _validate_logged_text(text: str, field_name: str) -> str:
822
+ """Validate text accepted by log_text."""
673
823
  if not isinstance(text, str) or not text:
674
824
  raise ValueError(f"`{field_name}` must be a non-empty string")
675
825
 
826
+ return text
827
+
828
+
829
+ def _normalize_logged_text(text: str, field_name: str) -> str:
830
+ """Validate text content and convert Markdown to HTML for local rendering."""
831
+ text = _validate_logged_text(text, field_name)
832
+
676
833
  if not is_html(text):
677
834
  return md_to_html(text, mathml=True)
678
835
 
@@ -688,7 +845,7 @@ def _validate_manual_log_text_args(
688
845
  if context is not None:
689
846
  raise ValueError("`context` is only supported when `text` is omitted")
690
847
 
691
- return _normalize_logged_text(text, "text")
848
+ return _validate_logged_text(text, "text")
692
849
 
693
850
 
694
851
  def _build_log_text_generation_request(
@@ -720,13 +877,13 @@ def _build_log_text_generation_request(
720
877
  return request_data
721
878
 
722
879
 
723
- def _generate_log_text(
880
+ def _generate_log_text_source(
724
881
  content_id: str,
725
882
  prompt: Optional[str],
726
883
  context: Optional[Dict[str, Any]],
727
884
  section_id: Optional[str] = None,
728
885
  ) -> str:
729
- """Generate text for log_text and normalize it to HTML."""
886
+ """Generate and validate source text without converting it to HTML."""
730
887
  request_data = _build_log_text_generation_request(
731
888
  content_id,
732
889
  prompt,
@@ -734,6 +891,22 @@ def _generate_log_text(
734
891
  section_id=section_id,
735
892
  )
736
893
  generated_text = generate_qualitative_text(request_data)["content"]
894
+ return _validate_logged_text(generated_text, "generated text")
895
+
896
+
897
+ def _generate_log_text(
898
+ content_id: str,
899
+ prompt: Optional[str],
900
+ context: Optional[Dict[str, Any]],
901
+ section_id: Optional[str] = None,
902
+ ) -> str:
903
+ """Generate text and normalize it to HTML for local result rendering."""
904
+ generated_text = _generate_log_text_source(
905
+ content_id,
906
+ prompt,
907
+ context,
908
+ section_id=section_id,
909
+ )
737
910
  return _normalize_logged_text(generated_text, "generated text")
738
911
 
739
912
 
@@ -762,14 +935,21 @@ async def alog_text(
762
935
  if text is not None:
763
936
  text = _validate_manual_log_text_args(text, prompt, context)
764
937
  else:
765
- text = _generate_log_text(
938
+ text = _generate_log_text_source(
766
939
  content_id,
767
940
  prompt,
768
941
  context,
769
942
  section_id=section_id,
770
943
  )
771
944
 
772
- return await alog_metadata(content_id, text, _json, section_id=section_id)
945
+ text_format = None if is_html(text) else "markdown"
946
+ return await alog_metadata(
947
+ content_id,
948
+ text,
949
+ _json,
950
+ section_id=section_id,
951
+ text_format=text_format,
952
+ )
773
953
 
774
954
 
775
955
  def log_text(
@@ -784,9 +964,9 @@ def log_text(
784
964
 
785
965
  Args:
786
966
  content_id (str): Unique content identifier for the text.
787
- text (str, optional): The text to log. Will be converted to HTML with
788
- MathML support when Markdown is provided. If omitted, text is
789
- generated using the qualitative text generation backend.
967
+ text (str, optional): The text to log. Markdown is sent to the backend for
968
+ HTML and math conversion. If omitted, text is generated using the
969
+ qualitative text generation backend.
790
970
  prompt (str, optional): Custom prompt used for AI-assisted text
791
971
  generation. Only supported when `text` is omitted.
792
972
  context (dict, optional): Context object for AI-assisted text
@@ -901,6 +1081,7 @@ def log_metric(
901
1081
 
902
1082
 
903
1083
  def generate_test_result_description(test_result_data: Dict[str, Any]) -> str:
1084
+ _ensure_fresh_oidc_token()
904
1085
  r = requests.post(
905
1086
  url=_get_url("ai/generate/test_result_description"),
906
1087
  headers=_get_api_headers(),
@@ -908,6 +1089,6 @@ def generate_test_result_description(test_result_data: Dict[str, Any]) -> str:
908
1089
  )
909
1090
 
910
1091
  if r.status_code != 200:
911
- raise_api_error(r.text)
1092
+ _raise_for_api_error(r.status_code, r.text)
912
1093
 
913
1094
  return r.json()
@@ -38,7 +38,7 @@ from .template import preview_template as _preview_template
38
38
  from .test_suites import get_by_id as get_test_suite_by_id
39
39
  from .tests.run import _get_run_metadata
40
40
  from .utils import display as vm_display
41
- from .utils import get_dataset_info, get_model_info
41
+ from .utils import get_dataset_info, get_model_info, is_html
42
42
  from .vm_models import TestSuite, TestSuiteRunner
43
43
  from .vm_models.dataset import DataFrameDataset, PolarsDataset, TorchDataset, VMDataset
44
44
  from .vm_models.html_progress import HTMLLabel, HTMLProgressBar
@@ -479,9 +479,12 @@ def run_text_generation(
479
479
  A TextGenerationResult containing the generated text.
480
480
  """
481
481
  start_time = time.perf_counter()
482
- description = api_client._generate_log_text(
482
+ description_source = api_client._generate_log_text_source(
483
483
  content_id, prompt, context, section_id=section_id
484
484
  )
485
+ description = api_client._normalize_logged_text(
486
+ description_source, "generated text"
487
+ )
485
488
  metadata = _get_run_metadata(duration_seconds=time.perf_counter() - start_time)
486
489
  result = TextGenerationResult(
487
490
  result_id=content_id,
@@ -494,6 +497,9 @@ def run_text_generation(
494
497
  section_id=section_id,
495
498
  context=context,
496
499
  _was_description_generated=True,
500
+ _description_source=(
501
+ description_source if not is_html(description_source) else None
502
+ ),
497
503
  )
498
504
 
499
505
  if show:
@@ -39,6 +39,10 @@ class ClientConfig:
39
39
  """Returns True if the client can generate LLM-based test descriptions."""
40
40
  return self.feature_flags.get("llm_test_descriptions", True)
41
41
 
42
+ def supports_log_metadata_markdown(self):
43
+ """Return whether the backend converts Markdown logged as metadata."""
44
+ return self.feature_flags.get("log_metadata_markdown", False)
45
+
42
46
 
43
47
  client_config = ClientConfig(
44
48
  model=None,
@@ -54,7 +54,8 @@ def run_task(
54
54
  else:
55
55
  raise ValueError(f"Unsupported task: {task}")
56
56
 
57
- if not is_html(generated_text):
57
+ description_source = generated_text if not is_html(generated_text) else None
58
+ if description_source is not None:
58
59
  generated_text = md_to_html(generated_text, mathml=True)
59
60
 
60
61
  # Create a test result with the generated text
@@ -68,6 +69,7 @@ def run_task(
68
69
  section_id=input.get("section_id"),
69
70
  context=input.get("context"),
70
71
  _was_description_generated=True,
72
+ _description_source=description_source,
71
73
  )
72
74
  if show:
73
75
  result.show()
@@ -2,6 +2,7 @@
2
2
  # Refer to the LICENSE file in the root of this repository for details.
3
3
  # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
4
 
5
+ import inspect
5
6
  from typing import Tuple
6
7
 
7
8
  import numpy as np
@@ -80,8 +81,19 @@ def CalibrationCurve(
80
81
  "Calibration Curve is only supported for binary classification models"
81
82
  )
82
83
 
84
+ # A two-class target encoded outside {0, 1} (e.g. {0, 4} or string labels)
85
+ # passes the guard above but hits sklearn's "pos_label is not specified" error.
86
+ # Pass the largest label as the positive class, matching the "largest label is
87
+ # positive" convention in _diagnosis_metrics.resolve_averaging; for {0, 1} this
88
+ # is byte-identical to sklearn's default. pos_label was added to
89
+ # calibration_curve in scikit-learn 1.1, so guard by signature inspection to
90
+ # keep pre-1.1 installs working (pyproject sets no scikit-learn floor).
91
+ kwargs = {}
92
+ if "pos_label" in inspect.signature(calibration_curve).parameters:
93
+ kwargs["pos_label"] = np.unique(dataset.y).max()
94
+
83
95
  prob_true, prob_pred = calibration_curve(
84
- dataset.y, dataset.y_prob(model), n_bins=n_bins
96
+ dataset.y, dataset.y_prob(model), n_bins=n_bins, **kwargs
85
97
  )
86
98
 
87
99
  # Create DataFrame for raw data