├── .coveragerc
├── .flake8
├── .git-blame-ignore-revs
├── .gitattributes
├── .github
├── .stale.yml
├── CODEOWNERS
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature_request.md
│ ├── giskard_bug_template.yaml
│ └── question.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ ├── build-python.yml
│ ├── clear-cache.yml
│ ├── create-release.yml
│ ├── lock-deps.yml
│ ├── nightly-test.yml
│ ├── pre-commit-checks.yml
│ └── retry-workflow.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yaml
├── .vscode
└── launch.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUES.md
├── LICENSE
├── README.md
├── SECURITY.md
├── conftest.py
├── docs
├── Makefile
├── _static
│ ├── catalog_example.png
│ ├── catalog_slice.png
│ ├── catalog_transfo.png
│ ├── css
│ │ └── custom.css
│ ├── debug.png
│ ├── giskard_logo.png
│ ├── hey.png
│ ├── js
│ │ ├── githubStargazers.js
│ │ ├── reodev.js
│ │ └── sidebarKeepScroll.js
│ ├── logo_black.png
│ ├── logo_white.png
│ ├── ragas_metrics.png
│ ├── raget.png
│ ├── scan_example.png
│ └── test_suite_example.png
├── _templates
│ ├── base.html
│ ├── page.html
│ └── sidebar
│ │ └── brand.html
├── assets
│ ├── Architecture.jpg
│ ├── RAG.png
│ ├── catalog.png
│ ├── comparison.png
│ ├── create_project.gif
│ ├── credit_scoring_comment.png
│ ├── discussion.png
│ ├── feedback.png
│ ├── gh_discussion.png
│ ├── gh_readme.png
│ ├── image_(1)_(1)_(2).png
│ ├── image_(3).png
│ ├── integrations
│ │ ├── avid
│ │ │ └── avid_taxonomy.gif
│ │ ├── dagshub
│ │ │ └── dagshub.png
│ │ ├── hfs
│ │ │ ├── copy_token.png
│ │ │ ├── create_from_template.png
│ │ │ ├── create_new_space.png
│ │ │ ├── duplicate_this_space.png
│ │ │ ├── eval_copy_id.png
│ │ │ ├── eval_input_hf_access_token.png
│ │ │ ├── eval_input_model_and_dataset_id.png
│ │ │ ├── eval_job_id.png
│ │ │ ├── eval_label_matched.png
│ │ │ ├── eval_label_matching.png
│ │ │ ├── eval_label_unmatched.png
│ │ │ ├── eval_logs.png
│ │ │ ├── eval_model_and_dataset_checking.png
│ │ │ ├── eval_scan_conf.png
│ │ │ ├── free_tier.png
│ │ │ ├── generate_token.png
│ │ │ ├── giskard_client.png
│ │ │ ├── hfs.svg
│ │ │ ├── input_hf_access_token.png
│ │ │ ├── mlworker.png
│ │ │ ├── paid_tier.png
│ │ │ └── where_to_create_access_token.png
│ │ ├── mlflow
│ │ │ ├── MLflow-logo-final-white-TM.png
│ │ │ ├── llms
│ │ │ │ ├── artifact_comparison.png
│ │ │ │ ├── scan-summary.png
│ │ │ │ ├── table_view.png
│ │ │ │ ├── text-davinci-001-metrics.png
│ │ │ │ ├── text-davinci-001-scanresults.png
│ │ │ │ └── text-davinci-001-scanresults2.png
│ │ │ └── tabular
│ │ │ │ ├── metrics.png
│ │ │ │ ├── scan-summary.png
│ │ │ │ ├── scanresults.png
│ │ │ │ └── table_view.png
│ │ └── wandb
│ │ │ ├── categorical-chart.png
│ │ │ ├── dataset.png
│ │ │ ├── global-chart.png
│ │ │ ├── numerical-chart.png
│ │ │ ├── scanning-result.png
│ │ │ ├── test-suite-result.png
│ │ │ ├── wandb-categorical-chart.png
│ │ │ ├── wandb-dataset.png
│ │ │ ├── wandb-global-chart.png
│ │ │ ├── wandb-logo-yellow-dots-black-wb.png
│ │ │ ├── wandb-numerical-chart.png
│ │ │ ├── wandb-scanning-result.png
│ │ │ └── wandb-test-suite-result.png
│ ├── intro
│ │ ├── Giskard_Turtle_Computer.png
│ │ ├── Giskard_Turtle_Kungfu.png
│ │ ├── Giskard_Turtle_Lab.png
│ │ ├── Giskard_Turtle_SK8.png
│ │ ├── Giskard_Turtle_new_set_FINAL_05.png
│ │ ├── Giskard_Turtle_new_set_FINAL_06.png
│ │ ├── Giskard_Turtle_waving.png
│ │ ├── coffee.png
│ │ ├── hey.png
│ │ ├── integrations.png
│ │ ├── ninja.png
│ │ ├── slice.jpg
│ │ └── test_turtle.png
│ ├── llm_debug.png
│ ├── llm_monitoring_dashboard.gif
│ ├── model_insights_titanic.png
│ ├── ngrok_aut.png
│ ├── ngrok_aut2.png
│ ├── output_filter.png
│ ├── push.png
│ ├── scan_llm.png
│ ├── scan_nlp.png
│ ├── scan_results.png
│ ├── scan_tabular.png
│ ├── scan_vision.png
│ ├── scan_widget.html
│ ├── slice.png
│ ├── test_suite_scan_llm.png
│ └── test_suite_tabular.png
├── community
│ ├── contribution_guidelines
│ │ ├── configuration.md
│ │ ├── dev-environment.md
│ │ ├── giskard-architecture.md
│ │ └── index.rst
│ ├── discord
│ │ └── index.md
│ ├── github
│ │ └── index.md
│ └── index.md
├── conf.py
├── favicon.ico
├── getting_started
│ ├── index.md
│ └── quickstart
│ │ ├── index.md
│ │ ├── quickstart_llm.ipynb
│ │ ├── quickstart_nlp.ipynb
│ │ ├── quickstart_tabular.ipynb
│ │ └── quickstart_vision.ipynb
├── index.md
├── integrations
│ ├── avid
│ │ ├── avid-integration-llm.ipynb
│ │ └── index.md
│ ├── cicd
│ │ ├── index.md
│ │ └── pipeline.ipynb
│ ├── dagshub
│ │ └── index.md
│ ├── huggingface
│ │ ├── evaluator.md
│ │ └── index.md
│ ├── index.md
│ ├── mlflow
│ │ ├── index.md
│ │ ├── mlflow-evaluation.png
│ │ ├── mlflow-harmfulness.png
│ │ ├── mlflow-llm-example.ipynb
│ │ ├── mlflow-metrics.png
│ │ ├── mlflow-prompt-injection.png
│ │ ├── mlflow-runs.png
│ │ ├── mlflow-scan.png
│ │ ├── mlflow-tabular-example.ipynb
│ │ └── mlflow_overview.png
│ ├── nemoguardrails
│ │ ├── index.md
│ │ └── nemoguardrails-integration.ipynb
│ ├── pytest
│ │ ├── full_example.ipynb
│ │ └── index.md
│ └── wandb
│ │ ├── index.md
│ │ ├── wandb-llm-example.ipynb
│ │ └── wandb-tabular-example.ipynb
├── knowledge
│ ├── catalogs
│ │ ├── index.md
│ │ ├── slicing-function-catalog
│ │ │ └── index.rst
│ │ ├── test-catalog
│ │ │ ├── classification
│ │ │ │ └── index.rst
│ │ │ ├── index.rst
│ │ │ ├── regression
│ │ │ │ └── index.rst
│ │ │ └── text_generation
│ │ │ │ └── index.rst
│ │ └── transformation-function-catalog
│ │ │ └── index.rst
│ ├── index.md
│ ├── key_vulnerabilities
│ │ ├── data_leakage
│ │ │ └── index.md
│ │ ├── ethics
│ │ │ └── index.md
│ │ ├── index.rst
│ │ ├── overconfidence
│ │ │ └── index.md
│ │ ├── performance_bias
│ │ │ └── index.md
│ │ ├── robustness
│ │ │ └── index.md
│ │ ├── spurious
│ │ │ └── index.md
│ │ ├── stochasticity
│ │ │ └── index.md
│ │ └── underconfidence
│ │ │ └── index.md
│ └── llm_vulnerabilities
│ │ ├── disclosure
│ │ └── index.md
│ │ ├── formatting
│ │ └── index.md
│ │ ├── hallucination
│ │ └── index.md
│ │ ├── harmfulness
│ │ └── index.md
│ │ ├── index.rst
│ │ ├── injection
│ │ └── index.md
│ │ ├── robustness
│ │ └── index.md
│ │ └── stereotypes
│ │ └── index.md
├── make.bat
├── open_source
│ ├── ai_quality_copilot
│ │ └── index.md
│ ├── customize_tests
│ │ ├── data_slices
│ │ │ └── index.md
│ │ ├── data_transformations
│ │ │ └── index.md
│ │ ├── index.md
│ │ └── test_model
│ │ │ └── index.md
│ ├── index.md
│ ├── installation_library
│ │ └── index.md
│ ├── integrate_tests
│ │ └── index.md
│ ├── scan
│ │ ├── advanced_scan
│ │ │ └── index.rst
│ │ ├── index.md
│ │ ├── scan_llm
│ │ │ ├── html.rst
│ │ │ ├── index.md
│ │ │ └── scan_result_iframe.html
│ │ ├── scan_nlp
│ │ │ └── index.md
│ │ ├── scan_tabular
│ │ │ └── index.md
│ │ └── scan_vision
│ │ │ └── index.md
│ ├── setting_up
│ │ └── index.md
│ └── testset_generation
│ │ ├── index.md
│ │ ├── rag_evaluation
│ │ └── index.md
│ │ └── testset_generation
│ │ └── index.md
├── reference
│ ├── datasets
│ │ └── index.rst
│ ├── index.rst
│ ├── models
│ │ ├── index.rst
│ │ └── integrations
│ │ │ ├── base_classes.rst
│ │ │ ├── catboost.rst
│ │ │ ├── function.rst
│ │ │ ├── huggingface.rst
│ │ │ ├── langchain.rst
│ │ │ ├── pytorch.rst
│ │ │ ├── sklearn.rst
│ │ │ └── tensorflow.rst
│ ├── notebooks
│ │ ├── LLM_Description_Product.ipynb
│ │ ├── LLM_Newspaper_Comment_Generation.ipynb
│ │ ├── LLM_QA_Documentation.ipynb
│ │ ├── LLM_QA_Google.ipynb
│ │ ├── LLM_QA_IPCC.ipynb
│ │ ├── LLM_QA_Winter_Olympics.ipynb
│ │ ├── RAGET_Banking_Supervision.ipynb
│ │ ├── RAGET_IPCC.ipynb
│ │ ├── airline_tweets_sentiment_analysis.ipynb
│ │ ├── amazon_review_classification_sklearn.ipynb
│ │ ├── cancer_detection_xgboost.ipynb
│ │ ├── churn_prediction_lgbm.ipynb
│ │ ├── credit_scoring.ipynb
│ │ ├── drug_classification_sklearn.ipynb
│ │ ├── enron_email_classification_sklearn.ipynb
│ │ ├── fake_real_news_classification.ipynb
│ │ ├── hotel_text_regression.ipynb
│ │ ├── ieee_fraud_detection_adversarial_validation.ipynb
│ │ ├── insurance_prediction_lgbm.ipynb
│ │ ├── m5_sales_prediction_lgbm.ipynb
│ │ ├── medical_transcript_classification_sklearn.ipynb
│ │ ├── movie_review_sentiment_classification_pytorch_sklearn.ipynb
│ │ ├── newspaper_classification_pytorch.ipynb
│ │ ├── tripadvisor_sentiment_classification.ipynb
│ │ ├── twitter_sentiment_analysis_roberta.ipynb
│ │ ├── vision_landmark_detection.ipynb
│ │ ├── vision_object_detection.ipynb
│ │ └── wage_classification.ipynb
│ ├── rag-toolset
│ │ ├── evaluation.rst
│ │ ├── index.rst
│ │ ├── knowledge_base.rst
│ │ ├── metrics.rst
│ │ ├── question_generation.rst
│ │ └── testset_generation.rst
│ ├── scan
│ │ ├── detectors.rst
│ │ ├── index.rst
│ │ ├── llm_detectors.rst
│ │ └── report.rst
│ ├── slicing-functions
│ │ └── index.rst
│ ├── suite
│ │ └── index.rst
│ ├── tests
│ │ ├── data.rst
│ │ ├── drift.rst
│ │ ├── index.rst
│ │ ├── llm.rst
│ │ ├── metamorphic.rst
│ │ ├── performance.rst
│ │ ├── stability.rst
│ │ └── statistic.rst
│ └── transformation-functions
│ │ └── index.rst
├── scrapper.py
└── tutorials
│ ├── index.md
│ ├── llm_tutorials
│ └── index.md
│ ├── nlp_tutorials
│ └── index.md
│ ├── rag_tutorials
│ └── index.md
│ ├── tabular_tutorials
│ └── index.md
│ └── vision_tutorials
│ └── index.md
├── giskard
├── __init__.py
├── client
│ ├── dtos.py
│ ├── io_utils.py
│ └── python_utils.py
├── core
│ ├── __init__.py
│ ├── core.py
│ ├── dataset_validation.py
│ ├── errors.py
│ ├── kwargs_utils.py
│ ├── model_validation.py
│ ├── savable.py
│ ├── suite.py
│ ├── test_result.py
│ └── validation.py
├── datasets
│ ├── __init__.py
│ ├── base
│ │ └── __init__.py
│ └── metadata
│ │ ├── __init__.py
│ │ ├── indexing.py
│ │ ├── registry.py
│ │ └── text_metadata_provider.py
├── demo
│ ├── __init__.py
│ ├── linear_regression.py
│ ├── llm_ipcc_climate_change.py
│ ├── titanic.csv
│ └── titanic_classification.py
├── exceptions
│ ├── IllegalArgumentError.py
│ ├── __init__.py
│ └── giskard_exception.py
├── functions
│ ├── __init__.py
│ ├── slicing.py
│ └── transformation.py
├── integrations
│ ├── __init__.py
│ ├── avid.py
│ ├── mlflow
│ │ ├── __init__.py
│ │ ├── evaluation_artifacts.py
│ │ ├── giskard_evaluator.py
│ │ └── giskard_evaluator_utils.py
│ ├── nemoguardrails.py
│ └── wandb
│ │ ├── __init__.py
│ │ └── wandb_utils.py
├── llm
│ ├── __init__.py
│ ├── client
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── bedrock.py
│ │ ├── copilot.py
│ │ ├── gemini.py
│ │ ├── litellm.py
│ │ ├── logger.py
│ │ ├── mistral.py
│ │ └── openai.py
│ ├── config.py
│ ├── embeddings
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── bedrock.py
│ │ ├── fastembed.py
│ │ ├── litellm.py
│ │ └── openai.py
│ ├── errors.py
│ ├── evaluators
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── coherency.py
│ │ ├── correctness.py
│ │ ├── plausibility.py
│ │ ├── requirements.py
│ │ ├── string_matcher.py
│ │ └── utils.py
│ ├── generators
│ │ ├── __init__.py
│ │ ├── adversarial.py
│ │ ├── base.py
│ │ ├── implausible.py
│ │ ├── simple.py
│ │ └── sycophancy.py
│ ├── loaders
│ │ ├── __init__.py
│ │ ├── local
│ │ │ ├── giskard_meta_data.csv
│ │ │ └── prompt_injections.csv
│ │ └── prompt_injections.py
│ ├── talk
│ │ ├── config.py
│ │ ├── tools
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── metric.py
│ │ │ ├── predict.py
│ │ │ ├── scan.py
│ │ │ └── shap.py
│ │ └── utils
│ │ │ └── shap.py
│ ├── testcase.py
│ └── utils.py
├── models
│ ├── __init__.py
│ ├── _precooked.py
│ ├── automodel.py
│ ├── base
│ │ ├── __init__.py
│ │ ├── model.py
│ │ ├── model_prediction.py
│ │ ├── serialization.py
│ │ └── wrapper.py
│ ├── cache
│ │ ├── __init__.py
│ │ └── cache.py
│ ├── catboost.py
│ ├── function.py
│ ├── huggingface.py
│ ├── langchain.py
│ ├── model_explanation.py
│ ├── pytorch.py
│ ├── shap_result.py
│ ├── sklearn.py
│ ├── talk_result.py
│ ├── tensorflow.py
│ └── utils.py
├── path_utils.py
├── rag
│ ├── __init__.py
│ ├── base.py
│ ├── evaluate.py
│ ├── knowledge_base.py
│ ├── knowledge_base_plots.py
│ ├── metrics
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── correctness.py
│ │ └── ragas_metrics.py
│ ├── question_generators
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── complex_questions.py
│ │ ├── conversational_questions.py
│ │ ├── distracting_questions.py
│ │ ├── double_questions.py
│ │ ├── oos_questions.py
│ │ ├── prompt.py
│ │ ├── question_types.py
│ │ ├── simple_questions.py
│ │ ├── situational_questions.py
│ │ └── utils.py
│ ├── recommendation.py
│ ├── report.py
│ ├── testset.py
│ └── testset_generation.py
├── registry
│ ├── __init__.py
│ ├── decorators.py
│ ├── decorators_utils.py
│ ├── giskard_test.py
│ ├── registry.py
│ ├── slicing_function.py
│ ├── transformation_function.py
│ └── utils.py
├── scanner
│ ├── __init__.py
│ ├── calibration
│ │ ├── __init__.py
│ │ ├── overconfidence_detector.py
│ │ └── underconfidence_detector.py
│ ├── common
│ │ ├── examples.py
│ │ ├── loss_based_detector.py
│ │ └── utils.py
│ ├── correlation
│ │ ├── __init__.py
│ │ └── spurious_correlation_detector.py
│ ├── data_leakage
│ │ ├── __init__.py
│ │ └── data_leakage_detector.py
│ ├── decorators.py
│ ├── issues.py
│ ├── llm
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── llm_basic_sycophancy_detector.py
│ │ ├── llm_chars_injection_detector.py
│ │ ├── llm_faithfulness_detector.py
│ │ ├── llm_harmful_content_detector.py
│ │ ├── llm_implausible_output_detector.py
│ │ ├── llm_information_disclosure_detector.py
│ │ ├── llm_output_formatting_detector.py
│ │ ├── llm_prompt_injection_detector.py
│ │ └── llm_stereotypes_detector.py
│ ├── logger.py
│ ├── performance
│ │ ├── __init__.py
│ │ ├── metrics.py
│ │ └── performance_bias_detector.py
│ ├── registry.py
│ ├── report.py
│ ├── robustness
│ │ ├── __init__.py
│ │ ├── base_detector.py
│ │ ├── base_perturbation_function.py
│ │ ├── entity_swap.py
│ │ ├── ethical_bias_detector.py
│ │ ├── nationalities.json
│ │ ├── numerical_perturbation_detector.py
│ │ ├── numerical_transformations.py
│ │ ├── text_perturbation_detector.py
│ │ └── text_transformations.py
│ ├── scanner.py
│ ├── stochasticity
│ │ ├── __init__.py
│ │ └── stochasticity_detector.py
│ └── templates
│ │ └── static
│ │ ├── external.js
│ │ ├── internal.js
│ │ └── style.css
├── settings.py
├── slicing
│ ├── __init__.py
│ ├── base.py
│ ├── bruteforce_slicer.py
│ ├── category_slicer.py
│ ├── multiscale_slicer.py
│ ├── opt_slicer.py
│ ├── slice.py
│ ├── slice_finder.py
│ ├── stop_words.py
│ ├── text_slicer.py
│ ├── tree_slicer.py
│ └── utils.py
├── testing
│ ├── __init__.py
│ ├── tests
│ │ ├── __init__.py
│ │ ├── calibration.py
│ │ ├── data_quality.py
│ │ ├── debug_slicing_functions.py
│ │ ├── drift.py
│ │ ├── llm
│ │ │ ├── __init__.py
│ │ │ ├── correctness.py
│ │ │ ├── ground_truth.py
│ │ │ ├── hallucination.py
│ │ │ ├── injections.py
│ │ │ └── output_requirements.py
│ │ ├── metamorphic.py
│ │ ├── performance.py
│ │ ├── stability.py
│ │ └── statistic.py
│ └── utils
│ │ ├── stat_utils.py
│ │ └── utils.py
├── utils
│ ├── __init__.py
│ ├── analytics_collector.py
│ ├── artifacts.py
│ ├── display.py
│ ├── environment_detector.py
│ ├── file_utils.py
│ ├── iterables.py
│ ├── language_detection.py
│ ├── logging_utils.py
│ └── versions.py
└── visualization
│ ├── __init__.py
│ ├── custom_jinja.py
│ ├── templates
│ ├── rag_report
│ │ ├── rag_report.html
│ │ └── static
│ │ │ ├── internal.js
│ │ │ └── style.css
│ ├── scan_report
│ │ ├── html
│ │ │ ├── _code_snippet.html
│ │ │ ├── _issue.html
│ │ │ ├── _issues_table.html
│ │ │ ├── _main_content.html
│ │ │ ├── _tab_header.html
│ │ │ ├── base.html
│ │ │ ├── full.html
│ │ │ └── static
│ │ │ │ ├── external.js
│ │ │ │ ├── internal.js
│ │ │ │ └── style.css
│ │ └── markdown
│ │ │ ├── github.md
│ │ │ ├── huggingface.md
│ │ │ └── summary.md
│ └── suite_results
│ │ ├── _suite_results_cards.html
│ │ ├── _suite_results_header.html
│ │ └── suite_results.html
│ └── widget.py
├── gulpfile.js
├── package-lock.json
├── package.json
├── pdm.lock
├── postcss.config.js
├── pyproject.toml
├── readme
├── Discord.png
├── Give_feedback.jpeg
├── Logo_full_darkgreen.png
├── RAGET_updated.gif
├── architechture_giskard.png
├── catalog_example.png
├── catalog_slice.png
├── catalog_transfo.png
├── demo.png
├── design_partner.png
├── feedback.png
├── feedback1.png
├── giskard_logo.png
├── giskard_logo_green.png
├── inspect.png
├── perturbation.png
├── pipeline.png
├── scan_example.gif
├── scan_example.png
├── scan_results.png
├── scan_updates.gif
├── suite_example.png
├── test.png
├── test1.png
├── test_suite_example.png
├── tools.png
├── tools_updated.png
├── upload.png
└── workflow.png
├── sample_data
├── classification
│ ├── credit
│ │ ├── german_credit.csv
│ │ └── german_credit_prepared.csv
│ └── titanic
│ │ ├── titanic-train-big-duplicate.csv
│ │ └── titanic-train.csv
├── other
│ └── addresses.csv
└── regression
│ └── house-prices
│ ├── house_price_updated.csv
│ ├── test.csv
│ └── train.csv
├── scripts
├── install-giskard-client-dev.sh
└── make-release.sh
├── sonar-project.properties
├── src
└── scan-widget
│ ├── _highlight_theme.css
│ ├── _highlightjs_copy.css
│ ├── external-js
│ └── iframeResizer.min.js
│ ├── internal-js
│ ├── highlight.min.js
│ ├── highlightjs-copy.min.js
│ ├── iframeResizer.contentWindow.min.js
│ └── scan.js
│ └── style.css
├── tailwind.config.js
└── tests
├── __init__.py
├── conftest.py
├── core
├── __init__.py
├── test_core.py
├── test_test_result.py
└── test_validation.py
├── datasets
├── test_base_dataset.py
├── test_dataset_languages_extraction.py
├── test_dataset_row_hashes.py
├── test_dataset_serialization.py
├── test_metadata.py
└── test_metadata_loading.py
├── debug
├── test_calibration.py
├── test_drift.py
├── test_metamorphic.py
├── test_performance.py
└── test_statistic.py
├── fixtures
├── __init__.py
├── amazon_review__binary_classification.py
├── diabetes__regression.py
├── drug_classification__multiclass_classification.py
├── enron_multilabel_classification.py
├── fraud_detection__binary_classification.py
├── german_credit_scoring.py
├── hotel_text__regression.py
├── imdb.py
├── medical_transcript_multiclass_classification.py
├── pytorch_sst2.py
├── titanic.py
├── tripadvisor_text_classification_torch.py
├── utils.py
└── xboost_classification.py
├── functions
└── test_transformation.py
├── google_drive_utils.py
├── integrations
├── test_avid.py
├── test_mlflow.py
├── test_nemoguardrails.py
└── test_wandb.py
├── llm
├── evaluators
│ ├── test_coherency_evaluator.py
│ ├── test_correctness_evaluator.py
│ ├── test_llm_based_evaluators.py
│ ├── test_requirements_evaluator.py
│ └── utils.py
├── generators
│ ├── test_adversarial_generator.py
│ ├── test_base_llm_generators.py
│ └── test_sycophancy_generator.py
├── test_embedding_client.py
└── test_llm_client.py
├── models
├── automodel
│ ├── test_automodel.py
│ ├── test_infer_giskard_cls.py
│ └── test_loading.py
├── fixtures
│ ├── func
│ │ ├── 3.10
│ │ │ ├── giskard-model-meta.yaml
│ │ │ ├── giskard-model-wrapper-meta.yaml
│ │ │ └── model.pkl
│ │ ├── 3.11
│ │ │ ├── giskard-model-meta.yaml
│ │ │ ├── giskard-model-wrapper-meta.yaml
│ │ │ └── model.pkl
│ │ └── 3.9
│ │ │ ├── giskard-model-meta.yaml
│ │ │ ├── giskard-model-wrapper-meta.yaml
│ │ │ └── model.pkl
│ └── ipcc
│ │ ├── 3.10
│ │ ├── ModelClass.pkl
│ │ ├── giskard-model-meta.yaml
│ │ ├── giskard-model-wrapper-meta.yaml
│ │ └── model.json
│ │ └── 3.11
│ │ ├── ModelClass.pkl
│ │ ├── giskard-model-meta.yaml
│ │ ├── giskard-model-wrapper-meta.yaml
│ │ └── model.json
├── huggingface
│ ├── test_email_classification_bert.py
│ ├── test_email_classification_bert_custom_model.py
│ ├── test_sequence_classification_pytorch.py
│ ├── test_sequence_classification_pytorch_pipeline.py
│ └── test_sequence_classification_tensorflow.py
├── langchain
│ ├── state_of_the_union.txt
│ ├── test_llm_chain.py
│ └── test_qa_retreiver.py
├── pytorch
│ ├── test_dtypes.py
│ ├── test_error.py
│ ├── test_linear_regression_pytorch_dataframe.py
│ ├── test_newspaper_classification_pytorch_custom_model.py
│ ├── test_newspaper_classification_pytorch_dataset.py
│ └── test_sst2_pytorch.py
├── talk
│ ├── talk_test_resources.py
│ └── test_model_talk.py
├── tensorflow
│ ├── test_mnist.py
│ ├── test_tabular_titanic_binary_classification.py
│ ├── test_text_classification.py
│ ├── test_text_classification_tfhub.csv
│ ├── test_text_classification_tfhub.py
│ └── test_tf_auto_model_as_embedding_layer.py
├── test_base_model.py
├── test_catboost_wrapper.py
├── test_function_model.py
├── test_model.py
├── test_model_auto_inference.py
├── test_model_cache.py
├── test_model_explanation.py
├── test_model_postprocess.py
├── test_model_serialization.py
├── test_precooked_model.py
├── test_sklearn_wrapper.py
├── test_wrap_model.py
└── test_wrapper_model.py
├── rag
├── test_base_question_generator.py
├── test_document_creation.py
├── test_evaluate.py
├── test_knowledge_base.py
├── test_prompt.py
├── test_qa_testset.py
├── test_question_generators.py
├── test_ragas_metrics.py
├── test_report.py
├── test_testset_generator.py
└── test_testset_suite_conversion.py
├── registry
├── module_utils.py
└── test_giskard_test.py
├── scan
├── llm
│ ├── test_basic_sycophancy_detector.py
│ ├── test_chars_injection_detector.py
│ ├── test_implausible_output_detector.py
│ ├── test_prompt_injection_detector.py
│ └── test_requirement_based_detectors.py
├── test_data_leakage_detector.py
├── test_dataset_subsampling.py
├── test_detector_registry.py
├── test_example_extractor.py
├── test_numerical_perturbation_detector.py
├── test_overconfidence_detector.py
├── test_performance_bias_detector.py
├── test_performance_metrics.py
├── test_scan_report.py
├── test_scanner.py
├── test_slicers.py
├── test_spurious_correlation_detector.py
├── test_stochasticity_detector.py
├── test_suite_generation.py
├── test_text_perturbation_detector.py
├── test_text_transformations.py
└── test_underconfidence_detector.py
├── slicing
├── test_query_slicer.py
└── test_slicing_function.py
├── test_data
├── enron_data.csv
└── german_credit_prepared.csv
├── test_data_drift.py
├── test_data_processing_pipeline.py
├── test_dataset.py
├── test_import_giskard.py
├── test_metamorphic_direction.py
├── test_metamorphic_invariance.py
├── test_performance.py
├── test_programmatic.py
├── test_project_uploads.py
├── test_settings.py
├── test_statistical.py
├── test_suite.py
├── test_utils.py
├── testing
├── test_calibration_tests.py
├── test_data_quality.py
├── test_llm_chars_injector.py
├── test_llm_ground_truth.py
├── test_llm_output_requirement.py
├── test_side_effects.py
├── test_stability.py
└── test_test_metadata.py
├── url_utils.py
├── utils.py
└── utils
└── test_logging_utils.py
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | relative_files = True
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | extend-ignore =
3 | DAR003
4 | DAR102
5 | DAR201
6 | E501
7 | DAR201
8 | DAR101
9 | DAR401
10 | E203
11 | exclude =
12 | .git
13 | __pycache__
14 | giskard/models/vectorstore/__init__.py
15 | giskard/__init__.py
16 |
17 |
--------------------------------------------------------------------------------
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # Black
2 | 7e9ea13e0d06f6d0a1cf1821ee39a08511d02f03
3 | c75f43099c1fa1ee3863aa5d38eeaafa2f78d745
4 | # iSort
5 | f7bbe212aec81c3c4bd8aadff08080ab82d31cee
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto
3 | docs/** linguist-documentation
--------------------------------------------------------------------------------
/.github/.stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: false
18 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | ### Limit any modification to .github folder to have an owner review
2 | .github @Giskard-AI/giskard
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: Giskard-AI
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | # Configuration: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository
2 |
3 | blank_issues_enabled: true
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature request
3 | about: Suggest an idea for this project 🏖
4 | title: ''
5 | labels: enhancement
6 | assignees:
7 | ---
8 |
9 | ## 🚀 Feature Request
10 |
11 |
12 |
13 | ## 🔈 Motivation
14 |
15 |
16 |
17 | ## 🛰 Alternatives
18 |
19 |
20 |
21 | ## 📎 Additional context
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ❓ Question
3 | about: Ask a question about this project 🎓
4 | title: ''
5 | labels: question
6 | assignees:
7 | ---
8 |
9 | ## Checklist
10 |
11 |
12 |
13 | - [ ] I've searched the project's [`issues`](https://github.com/Giskard-AI/giskard/issues?q=is%3Aissue).
14 |
15 | ## ❓ Question
16 |
17 |
18 |
19 | How can I [...]?
20 |
21 | Is it possible to [...]?
22 |
23 | ## 📎 Additional context
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 | ## Related Issue
6 |
7 |
8 |
9 | ## Type of Change
10 |
11 |
12 |
13 | - [ ] 📚 Examples / docs / tutorials / dependencies update
14 | - [ ] 🔧 Bug fix (non-breaking change which fixes an issue)
15 | - [ ] 🥂 Improvement (non-breaking change which improves an existing feature)
16 | - [ ] 🚀 New feature (non-breaking change which adds functionality)
17 | - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change)
18 | - [ ] 🔐 Security fix
19 |
20 | ## Checklist
21 |
22 |
23 |
24 | - [ ] I've read the [`CODE_OF_CONDUCT.md`](https://github.com/Giskard-AI/ai-inspector/blob/master/CODE_OF_CONDUCT.md) document.
25 | - [ ] I've read the [`CONTRIBUTING.md`](https://github.com/Giskard-AI/ai-inspector/blob/master/CONTRIBUTING.md) guide.
26 | - [ ] I've written tests for all new methods and classes that I created.
27 | - [ ] I've written the docstring in Google format for all the methods and classes that I used.
28 | - [ ] I've updated the `pdm.lock` running `pdm update-lock` (only applicable when `pyproject.toml` has been
29 | modified)
30 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm"
9 | directory: "/"
10 | schedule:
11 | interval: "monthly"
12 |
13 | - package-ecosystem: "pip"
14 | directory: "/"
15 | schedule:
16 | interval: "monthly"
17 |
18 | - package-ecosystem: "github-actions"
19 | directory: "/"
20 | schedule:
21 | interval: "monthly"
22 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | # Release drafter configuration https://github.com/release-drafter/release-drafter#configuration
2 | # Emojis were chosen to match the https://gitmoji.carloscuesta.me/
3 |
4 | name-template: "v$NEXT_PATCH_VERSION"
5 | tag-template: "v$NEXT_PATCH_VERSION"
6 |
7 | categories:
8 | - title: ":rocket: Features"
9 | labels: [enhancement, feature]
10 | - title: ":wrench: Fixes & Refactoring"
11 | labels: [bug, refactoring, bugfix, fix]
12 | - title: ":package: Build System & CI/CD"
13 | labels: [build, ci, testing]
14 | - title: ":boom: Breaking Changes"
15 | labels: [breaking]
16 | - title: ":pencil: Documentation"
17 | labels: [documentation]
18 | - title: ":arrow_up: Dependencies updates"
19 | labels: [dependencies]
20 |
21 | template: |
22 | ## What’s Changed
23 |
24 | $CHANGES
25 |
26 | ## :busts_in_silhouette: List of contributors
27 |
28 | $CONTRIBUTORS
29 |
--------------------------------------------------------------------------------
/.github/workflows/clear-cache.yml:
--------------------------------------------------------------------------------
1 | name: Clear all caches
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: '0 0 * * 0' # Every week
6 |
7 | permissions:
8 | actions: write
9 |
10 | jobs:
11 | clear:
12 | name: Clear all cache
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout code
16 | uses: actions/checkout@v4
17 | with:
18 | fetch-depth: 1
19 | - name: Clear cache
20 | run: gh cache delete --all
21 | env:
22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 |
--------------------------------------------------------------------------------
/.github/workflows/nightly-test.yml:
--------------------------------------------------------------------------------
1 | name: Nightly test
2 | on:
3 | schedule:
4 | - cron: '0 1 * * *' # Always run at 1:00 a.m.
5 | workflow_dispatch:
6 |
7 | jobs:
8 | call-full-ci:
9 | uses: ./.github/workflows/build-python.yml
10 | with:
11 | run-integration-tests: true
12 | use-cache: false
--------------------------------------------------------------------------------
/.github/workflows/pre-commit-checks.yml:
--------------------------------------------------------------------------------
1 | name: Pre-commit checks
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 | workflow_dispatch:
8 |
9 | env:
10 | GSK_DISABLE_ANALYTICS: true
11 | SENTRY_ENABLED: false
12 | GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
13 | defaults:
14 | run:
15 | shell: bash
16 | jobs:
17 | pre-commit:
18 | name: Pre-commit checks
19 | runs-on: ubuntu-latest
20 | steps:
21 | - uses: actions/checkout@v4
22 | - uses: actions/setup-python@v5
23 | - uses: pre-commit/action@v3.0.1
24 | env:
25 | SKIP: ggshield
26 |
--------------------------------------------------------------------------------
/.github/workflows/retry-workflow.yml:
--------------------------------------------------------------------------------
1 | name: Retry workflow
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | run_id:
7 | required: true
8 | description: Id of the failed workflow to retry
9 | jobs:
10 | rerun:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: rerun ${{ inputs.run_id }}
14 | env:
15 | GH_REPO: ${{ github.repository }}
16 | GH_TOKEN: ${{ github.token }}
17 | run: |
18 | gh run watch ${{ inputs.run_id }} > /dev/null 2>&1
19 | gh run rerun ${{ inputs.run_id }} --failed
20 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pycqa/isort
3 | rev: 5.13.2
4 | hooks:
5 | - id: isort
6 | files: '^.*\.py$'
7 | args:
8 | - "--settings-path"
9 | - "pyproject.toml"
10 |
11 | - repo: https://github.com/ambv/black
12 | rev: 23.12.1
13 | hooks:
14 | - id: black
15 | files: '^.*\.py$'
16 | args:
17 | - "--config"
18 | - "pyproject.toml"
19 | stages: [pre-commit]
20 | - repo: https://github.com/astral-sh/ruff-pre-commit
21 | rev: v0.1.6
22 | hooks:
23 | - id: ruff
24 | files: '^.*\.py$'
25 | args:
26 | - "--config"
27 | - "pyproject.toml"
28 | - "--fix"
29 | - "--exit-non-zero-on-fix"
30 |
31 | - repo: https://github.com/gitguardian/ggshield
32 | rev: v1.23.0
33 | hooks:
34 | - id: ggshield
35 | language_version: python3
36 | stages: [pre-commit]
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: ubuntu-22.04
5 | tools:
6 | python: "3.10"
7 | jobs:
8 | post_create_environment:
9 | - pip install pdm
10 | - pdm export --without-hashes -G doc,llm -o requirements-sphinx.txt
11 |
12 | sphinx:
13 | configuration: docs/conf.py
14 |
15 | python:
16 | install:
17 | - requirements: requirements-sphinx.txt
18 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Python: Remote Attach",
9 | "type": "python",
10 | "request": "attach",
11 | "connect": {
12 | "host": "localhost",
13 | "port": 5678
14 | },
15 | "pathMappings": [
16 | {
17 | "localRoot": "${workspaceFolder}",
18 | "remoteRoot": "."
19 | }
20 | ],
21 | "justMyCode": true
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/ISSUES.md:
--------------------------------------------------------------------------------
1 | If you open a GitHub Issue, here is our policy:
2 |
3 | 1. It must be a bug/performance issue or a feature request or a build issue or
4 | a documentation issue (for small doc fixes please send a PR instead).
5 | 2. Make sure the Issue Template is filled out.
6 | 3. The issue should be related to the repo it is created in.
7 |
8 | **Here's why we have this policy:** We want to focus on the work that benefits
9 | the whole community, e.g., fixing bugs and adding features. Individual support
10 | should be sought on our [Discord](https://discord.com/invite/ABvfpbu69R) community. It helps us to
11 | address bugs and feature requests in a timely manner.
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | If you believe you have found a security vulnerability in Giskard, you can report it to us in two ways:
4 | - by privately submitting a report from this repository's [security advisories](https://github.com/Giskard-AI/giskard/security/advisories) page
5 | - by sending an email to security@giskard.ai
6 |
7 | Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.
8 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/_static/catalog_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/catalog_example.png
--------------------------------------------------------------------------------
/docs/_static/catalog_slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/catalog_slice.png
--------------------------------------------------------------------------------
/docs/_static/catalog_transfo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/catalog_transfo.png
--------------------------------------------------------------------------------
/docs/_static/debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/debug.png
--------------------------------------------------------------------------------
/docs/_static/giskard_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/giskard_logo.png
--------------------------------------------------------------------------------
/docs/_static/hey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/hey.png
--------------------------------------------------------------------------------
/docs/_static/js/reodev.js:
--------------------------------------------------------------------------------
1 | !function () {
2 | var e, t, n;
3 | e = "7f26c9419b1f16e", t = function () {
4 | Reo.init({clientID: "7f26c9419b1f16e"})
5 | }, (n = document.createElement("script")).src = "https://static.reo.dev/" + e + "/reo.js", n.async = !0, n.onload = t, document.head.appendChild(n)
6 | }();
--------------------------------------------------------------------------------
/docs/_static/js/sidebarKeepScroll.js:
--------------------------------------------------------------------------------
1 | document.addEventListener("DOMContentLoaded", () => {
2 | let sidebar = document.querySelector(".sidebar-scroll");
3 | let top = localStorage.getItem("sidebar-scroll");
4 | if (sidebar && top !== null) {
5 | sidebar.scrollTo({
6 | top: parseInt(top),
7 | behavior: "instant",
8 | });
9 | }
10 | window.addEventListener("beforeunload", () => {
11 | localStorage.setItem("sidebar-scroll", sidebar.scrollTop);
12 | });
13 | });
--------------------------------------------------------------------------------
/docs/_static/logo_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/logo_black.png
--------------------------------------------------------------------------------
/docs/_static/logo_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/logo_white.png
--------------------------------------------------------------------------------
/docs/_static/ragas_metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/ragas_metrics.png
--------------------------------------------------------------------------------
/docs/_static/raget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/raget.png
--------------------------------------------------------------------------------
/docs/_static/scan_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/scan_example.png
--------------------------------------------------------------------------------
/docs/_static/test_suite_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/_static/test_suite_example.png
--------------------------------------------------------------------------------
/docs/_templates/sidebar/brand.html:
--------------------------------------------------------------------------------
1 | {#-
2 |
3 | Hi there!
4 |
5 | You might be interested in https://pradyunsg.me/furo/customisation/sidebar/
6 |
7 | Although if you're reading this, chances are that you're either familiar
8 | enough with Sphinx that you know what you're doing, or landed here from that
9 | documentation page.
10 |
11 | Hope your day's going well. :)
12 |
13 | -#}
14 |
15 | {% block brand_content %}
16 | {%- if logo_url %}
17 |
20 | {%- endif %}
21 | {%- if theme_light_logo and theme_dark_logo %}
22 |
26 | {%- endif %}
27 | {% endblock brand_content %}
28 |
29 |
--------------------------------------------------------------------------------
/docs/assets/Architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/Architecture.jpg
--------------------------------------------------------------------------------
/docs/assets/RAG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/RAG.png
--------------------------------------------------------------------------------
/docs/assets/catalog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/catalog.png
--------------------------------------------------------------------------------
/docs/assets/comparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/comparison.png
--------------------------------------------------------------------------------
/docs/assets/create_project.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/create_project.gif
--------------------------------------------------------------------------------
/docs/assets/credit_scoring_comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/credit_scoring_comment.png
--------------------------------------------------------------------------------
/docs/assets/discussion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/discussion.png
--------------------------------------------------------------------------------
/docs/assets/feedback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/feedback.png
--------------------------------------------------------------------------------
/docs/assets/gh_discussion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/gh_discussion.png
--------------------------------------------------------------------------------
/docs/assets/gh_readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/gh_readme.png
--------------------------------------------------------------------------------
/docs/assets/image_(1)_(1)_(2).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/image_(1)_(1)_(2).png
--------------------------------------------------------------------------------
/docs/assets/image_(3).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/image_(3).png
--------------------------------------------------------------------------------
/docs/assets/integrations/avid/avid_taxonomy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/avid/avid_taxonomy.gif
--------------------------------------------------------------------------------
/docs/assets/integrations/dagshub/dagshub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/dagshub/dagshub.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/copy_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/copy_token.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/create_from_template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/create_from_template.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/create_new_space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/create_new_space.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/duplicate_this_space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/duplicate_this_space.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_copy_id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_copy_id.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_input_hf_access_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_input_hf_access_token.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_input_model_and_dataset_id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_input_model_and_dataset_id.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_job_id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_job_id.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_label_matched.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_label_matched.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_label_matching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_label_matching.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_label_unmatched.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_label_unmatched.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_logs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_logs.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_model_and_dataset_checking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_model_and_dataset_checking.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/eval_scan_conf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/eval_scan_conf.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/free_tier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/free_tier.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/generate_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/generate_token.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/giskard_client.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/giskard_client.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/hfs.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/input_hf_access_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/input_hf_access_token.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/mlworker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/mlworker.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/paid_tier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/paid_tier.png
--------------------------------------------------------------------------------
/docs/assets/integrations/hfs/where_to_create_access_token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/hfs/where_to_create_access_token.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/MLflow-logo-final-white-TM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/MLflow-logo-final-white-TM.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/artifact_comparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/artifact_comparison.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/scan-summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/scan-summary.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/table_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/table_view.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/text-davinci-001-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/text-davinci-001-metrics.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/text-davinci-001-scanresults.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/text-davinci-001-scanresults.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/llms/text-davinci-001-scanresults2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/llms/text-davinci-001-scanresults2.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/tabular/metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/tabular/metrics.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/tabular/scan-summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/tabular/scan-summary.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/tabular/scanresults.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/tabular/scanresults.png
--------------------------------------------------------------------------------
/docs/assets/integrations/mlflow/tabular/table_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/mlflow/tabular/table_view.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/categorical-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/categorical-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/dataset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/dataset.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/global-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/global-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/numerical-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/numerical-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/scanning-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/scanning-result.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/test-suite-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/test-suite-result.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-categorical-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-categorical-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-dataset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-dataset.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-global-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-global-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-logo-yellow-dots-black-wb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-logo-yellow-dots-black-wb.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-numerical-chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-numerical-chart.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-scanning-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-scanning-result.png
--------------------------------------------------------------------------------
/docs/assets/integrations/wandb/wandb-test-suite-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/integrations/wandb/wandb-test-suite-result.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_Computer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_Computer.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_Kungfu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_Kungfu.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_Lab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_Lab.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_SK8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_SK8.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_new_set_FINAL_05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_new_set_FINAL_05.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_new_set_FINAL_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_new_set_FINAL_06.png
--------------------------------------------------------------------------------
/docs/assets/intro/Giskard_Turtle_waving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/Giskard_Turtle_waving.png
--------------------------------------------------------------------------------
/docs/assets/intro/coffee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/coffee.png
--------------------------------------------------------------------------------
/docs/assets/intro/hey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/hey.png
--------------------------------------------------------------------------------
/docs/assets/intro/integrations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/integrations.png
--------------------------------------------------------------------------------
/docs/assets/intro/ninja.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/ninja.png
--------------------------------------------------------------------------------
/docs/assets/intro/slice.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/slice.jpg
--------------------------------------------------------------------------------
/docs/assets/intro/test_turtle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/intro/test_turtle.png
--------------------------------------------------------------------------------
/docs/assets/llm_debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/llm_debug.png
--------------------------------------------------------------------------------
/docs/assets/llm_monitoring_dashboard.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/llm_monitoring_dashboard.gif
--------------------------------------------------------------------------------
/docs/assets/model_insights_titanic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/model_insights_titanic.png
--------------------------------------------------------------------------------
/docs/assets/ngrok_aut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/ngrok_aut.png
--------------------------------------------------------------------------------
/docs/assets/ngrok_aut2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/ngrok_aut2.png
--------------------------------------------------------------------------------
/docs/assets/output_filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/output_filter.png
--------------------------------------------------------------------------------
/docs/assets/push.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/push.png
--------------------------------------------------------------------------------
/docs/assets/scan_llm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/scan_llm.png
--------------------------------------------------------------------------------
/docs/assets/scan_nlp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/scan_nlp.png
--------------------------------------------------------------------------------
/docs/assets/scan_results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/scan_results.png
--------------------------------------------------------------------------------
/docs/assets/scan_tabular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/scan_tabular.png
--------------------------------------------------------------------------------
/docs/assets/scan_vision.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/scan_vision.png
--------------------------------------------------------------------------------
/docs/assets/slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/slice.png
--------------------------------------------------------------------------------
/docs/assets/test_suite_scan_llm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/test_suite_scan_llm.png
--------------------------------------------------------------------------------
/docs/assets/test_suite_tabular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/assets/test_suite_tabular.png
--------------------------------------------------------------------------------
/docs/community/contribution_guidelines/giskard-architecture.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Giskard process architecture
3 | ---
4 |
5 | # Giskard architecture
6 | 
7 |
--------------------------------------------------------------------------------
/docs/community/discord/index.md:
--------------------------------------------------------------------------------
1 | # Discord community
2 |
3 | 🤖 Our discord community is an inclusive place where anyone interested in ML Quality is welcome! Leverage best practices from the community, contribute new tests, build the future of AI safety standards.
4 |
5 | 🤝 Use the following link to join the conversation: [Discord community link](https://discord.com/invite/ABvfpbu69R)
6 |
--------------------------------------------------------------------------------
/docs/community/github/index.md:
--------------------------------------------------------------------------------
1 | # GitHub community
2 |
3 | 💬 [Open a discussion](https://github.com/orgs/Giskard-AI/discussions) to interact with our contributing members and users!
4 |
5 | 🌟 You can also drop by to [leave us a star](https://github.com/Giskard-AI/giskard), it helps the project to get discovered by others and keeps us motivated to build awesome open-source tools! 🌟
6 |
7 | ❤️ Feel free to [sponsor us](https://github.com/sponsors/Giskard-AI) on GitHub. With a monthly sponsor subscription, you can get a sponsor badge and get your bug reports prioritized. We also offer one-time sponsoring if you want us to get involved in a consulting project, run a workshop, or give a talk at your company.
8 |
--------------------------------------------------------------------------------
/docs/community/index.md:
--------------------------------------------------------------------------------
1 | # Community
2 | ```{toctree}
3 | :caption: Community
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | discord/index
8 | github/index
9 | contribution_guidelines/index
10 | ```
11 |
12 | :::::{grid} 1 1 2 2
13 |
14 |
15 | ::::{grid-item-card}
Discord community
16 | :text-align: center
17 | :link: discord/index.html
18 | ::::
19 |
20 | ::::{grid-item-card}
Github community
21 | :text-align: center
22 | :link: github/index.html
23 | ::::
24 |
25 | ::::{grid-item-card}
Contribute to Giskard
26 | :text-align: center
27 | :link: contribution_guidelines/index.html
28 | ::::
29 |
30 | :::::
31 |
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/getting_started/quickstart/index.md:
--------------------------------------------------------------------------------
1 | # Quickstart
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 2
6 | :hidden:
7 |
8 | quickstart_llm
9 | quickstart_tabular
10 | quickstart_nlp
11 | quickstart_vision
12 | ```
13 |
14 | :::::{grid} 1 1 2 2
15 |
16 | ::::{grid-item-card}
📚 LLM Quickstart
17 | :text-align: center
18 | :link: quickstart_llm.ipynb
19 | ::::
20 |
21 | ::::{grid-item-card}
📊 Tabular Quickstart
22 | :text-align: center
23 | :link: quickstart_tabular.ipynb
24 | ::::
25 |
26 | ::::{grid-item-card}
🗣️ NLP Quickstart
27 | :text-align: center
28 | :link: quickstart_nlp.ipynb
29 | ::::
30 |
31 | ::::{grid-item-card}
📸 Vision Quickstart
32 | :text-align: center
33 | :link: quickstart_vision.ipynb
34 | ::::
35 |
36 | :::::
37 |
--------------------------------------------------------------------------------
/docs/integrations/huggingface/index.md:
--------------------------------------------------------------------------------
1 | # 🤗 Hugging Face
2 |
3 | **Leverage Hugging Face (HF) Spaces to easily scan, test & debug your own ML models.**
4 |
5 | ```{toctree}
6 | :caption: Table of Contents
7 | :maxdepth: 1
8 | :hidden:
9 |
10 | ./evaluator.md
11 |
12 | ```
13 |
14 | ::::::{grid} 1 1 1 1
15 |
16 | ::::{grid-item-card}
🔍 Giskard Evaluator
17 | :text-align: center
18 | :link: ./evaluator.md
19 | ::::
20 |
--------------------------------------------------------------------------------
/docs/integrations/index.md:
--------------------------------------------------------------------------------
1 | # Integrations
2 | ```{toctree}
3 | :caption: Integrations
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | cicd/index
8 | mlflow/index
9 | nemoguardrails/index
10 | wandb/index
11 | dagshub/index
12 | huggingface/index
13 | avid/index
14 | pytest/index
15 | ```
16 |
17 | ::::{grid} 1 1 2 2
18 |
19 |
20 | :::{grid-item-card}
🐙️ GitHub
21 | :text-align: center
22 | :link: cicd/index.html
23 | :::
24 |
25 | :::{grid-item-card}
🤗 HuggingFace
26 | :text-align: center
27 | :link: huggingface/index.html
28 | :::
29 |
30 | :::{grid-item-card}
🏃 MLflow
31 | :text-align: center
32 | :link: mlflow/index.html
33 | :::
34 |
35 | :::{grid-item-card}
🟩 NeMo Guardrails
36 | :text-align: center
37 | :link: nemoguardrails/index.html
38 | :::
39 |
40 | :::{grid-item-card}
🐝 Weights & Biases
41 | :text-align: center
42 | :link: wandb/index.html
43 | :::
44 |
45 | :::{grid-item-card}
🐶 DagsHub
46 | :text-align: center
47 | :link: dagshub/index.html
48 | :::
49 |
50 | :::{grid-item-card}
📒 AVID
51 | :text-align: center
52 | :link: avid/index.html
53 | :::
54 |
55 | :::{grid-item-card}
🧪 Pytest
56 | :text-align: center
57 | :link: pytest/index.html
58 | :::
59 |
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-evaluation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-evaluation.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-harmfulness.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-harmfulness.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-metrics.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-prompt-injection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-prompt-injection.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-runs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-runs.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow-scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow-scan.png
--------------------------------------------------------------------------------
/docs/integrations/mlflow/mlflow_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/docs/integrations/mlflow/mlflow_overview.png
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/index.md:
--------------------------------------------------------------------------------
1 | # Catalogs
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 2
6 | :hidden:
7 |
8 | test-catalog/index
9 | slicing-function-catalog/index
10 | transformation-function-catalog/index
11 | ```
12 |
13 | ::::::{grid} 1 1 2 2
14 |
15 |
16 | ::::{grid-item-card}
Tests
17 | :text-align: center
18 | :link: test-catalog/index.html
19 | ::::
20 |
21 | ::::{grid-item-card}
Slicing functions
22 | :text-align: center
23 | :link: slicing-function-catalog/index.html
24 | ::::
25 |
26 | ::::{grid-item-card}
Transformation functions
27 | :text-align: center
28 | :link: transformation-function-catalog/index.html
29 | ::::
30 | ::::::
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/slicing-function-catalog/index.rst:
--------------------------------------------------------------------------------
1 | Slicing functions
2 | =================
3 |
4 | - **Textual slicing function**
5 |
6 | - :func:`~.giskard.functions.slicing.short_comment_slicing_fn`
7 | - :func:`~.giskard.functions.slicing.keyword_lookup_slicing_fn`
8 | - :func:`~.giskard.functions.slicing.positive_sentiment_analysis`
9 | - :func:`~.giskard.functions.slicing.offensive_sentiment_analysis`
10 | - :func:`~.giskard.functions.slicing.irony_sentiment_analysis`
11 | - :func:`~.giskard.functions.slicing.hate_sentiment_analysis`
12 | - :func:`~.giskard.functions.slicing.emotion_sentiment_analysis`
13 |
14 | - **Numerical slicing function**
15 | - :func:`~.giskard.functions.slicing.outlier_filter`
16 |
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/test-catalog/index.rst:
--------------------------------------------------------------------------------
1 | Tests
2 | ============
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | classification/index
8 | regression/index
9 | text_generation/index
10 |
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/test-catalog/regression/index.rst:
--------------------------------------------------------------------------------
1 | Regression tests
2 | =================
3 |
4 | - **Metamorphic tests**
5 |
6 | - :func:`~.giskard.testing.test_metamorphic_invariance`
7 | - :func:`~.giskard.testing.test_metamorphic_increasing`
8 | - :func:`~.giskard.testing.test_metamorphic_decreasing`
9 |
10 | - **Statistical tests**
11 |
12 | - :func:`~.giskard.testing.test_output_in_range`
13 |
14 | - **Performance tests**
15 |
16 | - :func:`~.giskard.testing.test_mae`
17 | - :func:`~.giskard.testing.test_rmse`
18 | - :func:`~.giskard.testing.test_diff_rmse`
19 | - :func:`~.giskard.testing.test_r2`
20 |
21 | - **Drift tests**
22 |
23 | - :func:`~.giskard.testing.test_drift_prediction_psi`
24 | - :func:`~.giskard.testing.test_drift_prediction_chi_square`
25 | - :func:`~.giskard.testing.test_drift_prediction_ks`
26 | - :func:`~.giskard.testing.test_drift_prediction_earth_movers_distance`
27 |
28 | - **Stability tests**
29 | - :func:`~.giskard.testing.test_smoothness`
30 | - :func:`~.giskard.testing.test_monotonicity`
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/test-catalog/text_generation/index.rst:
--------------------------------------------------------------------------------
1 | Text generation tests
2 | =====================
3 |
4 | - **Injections**
5 |
6 | - :func:`~.giskard.testing.tests.llm.test_llm_char_injection`
7 | - :func:`~.giskard.testing.tests.llm.test_llm_single_output_against_strings`
8 | - :func:`~.giskard.testing.tests.llm.test_llm_output_against_strings`
9 |
10 | - **LLM-as-ajudge**
11 |
12 | - :func:`~.giskard.testing.tests.llm.test_llm_output_coherency`
13 | - :func:`~.giskard.testing.tests.llm.test_llm_output_plausibility`
14 | - :func:`~.giskard.testing.tests.llm.test_llm_output_against_requirement_per_row`
15 | - :func:`~.giskard.testing.tests.llm.test_llm_single_output_against_requirement`
16 | - :func:`~.giskard.testing.tests.llm.test_llm_output_against_requirement`
17 |
18 | - **Ground Truth**
19 |
20 | - :func:`~.giskard.testing.tests.llm.test_llm_ground_truth`
21 | - :func:`~.giskard.testing.tests.llm.test_llm_ground_truth_similarity`
22 | - :func:`~.giskard.testing.tests.llm.test_llm_as_a_judge_ground_truth_similarity`
23 |
24 |
--------------------------------------------------------------------------------
/docs/knowledge/catalogs/transformation-function-catalog/index.rst:
--------------------------------------------------------------------------------
1 | Transformation functions
2 | ========================
3 |
4 | - **Text transformation function**
5 |
6 | - :func:`~.giskard.functions.transformation.keyboard_typo_transformation`
7 | - :func:`~.giskard.functions.transformation.text_uppercase`
8 | - :func:`~.giskard.functions.transformation.text_lowercase`
9 | - :func:`~.giskard.functions.transformation.text_title_case`
10 | - :func:`~.giskard.functions.transformation.text_typo`
11 | - :func:`~.giskard.functions.transformation.text_typo_from_ocr`
12 | - :func:`~.giskard.functions.transformation.text_punctuation_removal`
13 | - :func:`~.giskard.functions.transformation.text_accent_removal`
14 | - :func:`~.giskard.functions.transformation.text_gender_switch`
15 | - :func:`~.giskard.functions.transformation.text_number_to_word`
16 | - :func:`~.giskard.functions.transformation.text_religion_switch`
17 | - :func:`~.giskard.functions.transformation.text_nationality_switch`
18 | - :func:`~.giskard.functions.transformation.text_typo_from_speech`
19 |
--------------------------------------------------------------------------------
/docs/knowledge/index.md:
--------------------------------------------------------------------------------
1 | # Knowledge
2 | ```{toctree}
3 | :caption: Knowledge
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | llm_vulnerabilities/index
8 | key_vulnerabilities/index
9 | catalogs/index
10 | ```
11 |
12 | ::::::{grid} 1 1 2 2
13 |
14 |
15 | ::::{grid-item-card}
📚 Catalogs
16 | :text-align: center
17 | :link: catalogs/index.html
18 | ::::
19 |
20 | ::::{grid-item-card}
📊 ML models vulnerabilities
21 | :text-align: center
22 | :link: key_vulnerabilities/index.html
23 | ::::
24 |
25 | ::::{grid-item-card}
🗣️ LLM vulnerabilities
26 | :text-align: center
27 | :link: llm_vulnerabilities/index.html
28 | ::::
29 |
--------------------------------------------------------------------------------
/docs/knowledge/key_vulnerabilities/index.rst:
--------------------------------------------------------------------------------
1 | ML Model Vulnerabilities
2 | ========================
3 |
4 | Before testing Machine Learning models, it's crucial to have a comprehensive understanding of the critical vulnerabilities that can impact your model. Giskard provides an `automatic scan functionality <../../open_source/scan/index.md>`_ that is designed to automatically detect a variety of risks associated with your ML model. You can learn more about the different vulnerabilities it can detect here:
5 |
6 | .. toctree::
7 | :maxdepth: 1
8 |
9 | performance_bias/index
10 | robustness/index
11 | overconfidence/index
12 | underconfidence/index
13 | ethics/index
14 | data_leakage/index
15 | stochasticity/index
16 | spurious/index
17 |
18 | By conducting a `Giskard Scan <../../open_source/scan/index.md>`_, you can proactively identify and address these vulnerabilities to ensure the reliability, fairness, and robustness of your Machine Learning models.
19 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/open_source/customize_tests/index.md:
--------------------------------------------------------------------------------
1 | # 🧪 Customize your tests
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 2
6 | :hidden:
7 |
8 | test_model/index
9 | data_slices/index
10 | data_transformations/index
11 | ```
12 |
13 | :::::{grid} 1 1 2 2
14 |
15 |
16 | ::::{grid-item-card}
👨🔬 Create tests
17 | :text-align: center
18 | :link: test_model/index.html
19 | ::::
20 |
21 | ::::{grid-item-card}
🔪 Create data slices
22 | :text-align: center
23 | :link: data_slices/index.html
24 | ::::
25 |
26 | ::::{grid-item-card}
🔄 Create data transformations
27 | :text-align: center
28 | :link: data_transformations/index.html
29 | ::::
30 |
31 | :::::
32 |
--------------------------------------------------------------------------------
/docs/open_source/index.md:
--------------------------------------------------------------------------------
1 | # Open Source
2 | ```{toctree}
3 | :caption: Open Source
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | installation_library/index
8 | setting_up/index
9 | scan/index
10 | testset_generation/index
11 | customize_tests/index
12 | integrate_tests/index
13 | ```
14 |
15 | ::::::{grid} 1 1 2 2
16 |
17 |
18 | ::::{grid-item-card}
📥 Install the Giskard Python Library
19 | :text-align: center
20 | :link: installation_library/index.html
21 | ::::
22 |
23 | ::::{grid-item-card}
🤖 Setting up the LLM Client
24 | :text-align: center
25 | :link: setting_up/index.html
26 | ::::
27 |
28 | ::::{grid-item-card}
🔍 Scan a model
29 | :text-align: center
30 | :link: scan/index.html
31 | ::::
32 |
33 | ::::{grid-item-card}
🧰 RAG Evaluation Toolkit
34 | :text-align: center
35 | :link: testset_generation/index.html
36 | ::::
37 |
38 | ::::{grid-item-card}
🤖 AI Quality Copilot
39 | :text-align: center
40 | :link: ai_quality_copilot/index.html
41 | ::::
42 |
43 | ::::{grid-item-card}
🧪 Customize your tests
44 | :text-align: center
45 | :link: customize_tests/index.html
46 | ::::
47 |
48 | ::::{grid-item-card}
🔁 Integrate your tests
49 | :text-align: center
50 | :link: integrate_tests/index.html
51 | ::::
--------------------------------------------------------------------------------
/docs/open_source/installation_library/index.md:
--------------------------------------------------------------------------------
1 | # 📥 Install the Giskard Python Library
2 |
3 | Giskard supports Python `3.9`, `3.10` and `3.11`.
4 |
5 | ## Install
6 |
7 | ::::{tab-set}
8 | :::{tab-item} LLMs
9 |
10 | ```sh
11 | pip install giskard[llm] -U
12 | ```
13 |
14 | :::
15 |
16 | :::{tab-item} Tabular and NLP
17 |
18 | ```sh
19 | pip install giskard -U
20 | ```
21 |
22 | :::
23 | ::::
24 |
25 | ## Upgrade
26 |
27 | ```sh
28 | pip uninstall giskard
29 | pip install giskard -U
30 | ```
31 |
32 | ## Dependency issues
33 |
34 | If you run into conflicts with Giskard dependencies, please uninstall the conflicting libraries and re-install Giskard.
35 |
36 | For instance, if you have dependency conflicts with `pandas`, you can run:
37 |
38 | ```sh
39 | pip uninstall giskard
40 | pip uninstall pandas
41 | pip install giskard -U
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/open_source/integrate_tests/index.md:
--------------------------------------------------------------------------------
1 | # 🔁 Integrate your tests
2 |
3 | Once you've created a test suite for a model, integrating it into existing workflows allow you to automate the testing and logging of your model quality. You will find a couple options on this page to do so.
4 |
5 | ```{toctree}
6 | :caption: Table of Contents
7 | :maxdepth: 2
8 | :hidden:
9 |
10 | ../../integrations/cicd/pipeline.ipynb
11 | ../../integrations/mlflow/index
12 | ../../integrations/wandb/index
13 | ../../integrations/pytest/index
14 |
15 | ```
16 |
17 | :::::{grid} 1 1 2 2
18 |
19 |
20 | ::::{grid-item-card}
🚀 Execute your test suite in your CI/CD pipeline
21 | :text-align: center
22 | :link: ../../integrations/cicd/pipeline.ipynb
23 | ::::
24 |
25 | ::::{grid-item-card}
🏃 Evaluate & log with MLflow
26 | :text-align: center
27 | :link: ../../integrations/mlflow/index.md
28 | ::::
29 |
30 | ::::{grid-item-card}
🐝 Evaluate & log with Weights & Biases
31 | :text-align: center
32 | :link: ../../integrations/wandb/index.md
33 | ::::
34 |
35 | ::::{grid-item-card}
🧪 Execute your test with pytest
36 | :text-align: center
37 | :link: ../../integrations/pytest/index.md
38 | ::::
39 |
40 | :::::
41 |
--------------------------------------------------------------------------------
/docs/open_source/scan/index.md:
--------------------------------------------------------------------------------
1 | # 🔍 Scan a model
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 2
6 | :hidden:
7 |
8 | scan_llm/index
9 | scan_tabular/index
10 | scan_nlp/index
11 | scan_vision/index
12 | advanced_scan/index
13 | ```
14 |
15 | ::::::{grid} 1 1 2 2
16 |
17 | ::::{grid-item-card}
📚 LLM scan
18 | :text-align: center
19 | :link: scan_llm/index.html
20 | ::::
21 |
22 | ::::{grid-item-card}
📊 Tabular model scan
23 | :text-align: center
24 | :link: scan_tabular/index.html
25 | ::::
26 |
27 | ::::{grid-item-card}
🗣️ NLP model scan
28 | :text-align: center
29 | :link: scan_nlp/index.html
30 | ::::
31 |
32 | ::::{grid-item-card}
📸 Vision model scan
33 | :text-align: center
34 | :link: scan_vision/index.html
35 | ::::
36 |
37 | ::::{grid-item-card}
Advanced scan usage
38 | :text-align: center
39 | :link: advanced_scan/index.rst
40 | ::::
41 |
--------------------------------------------------------------------------------
/docs/open_source/scan/scan_llm/html.rst:
--------------------------------------------------------------------------------
1 | .. raw:: html
2 | :file: scan_result_iframe.html
3 |
4 |
--------------------------------------------------------------------------------
/docs/open_source/testset_generation/index.md:
--------------------------------------------------------------------------------
1 | # 🧰 RAG Evaluation Toolkit
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 2
6 | :hidden:
7 |
8 | testset_generation/index
9 | rag_evaluation/index
10 | ```
11 |
12 | ::::::{grid} 1 1 2 2
13 |
14 |
15 | ::::{grid-item-card}
🎯 Testset Generation
16 | :text-align: center
17 | :link: testset_generation/index.html
18 | ::::
19 |
20 | ::::{grid-item-card}
🥇 Evaluate your RAG
21 | :text-align: center
22 | :link: rag_evaluation/index.html
23 | ::::
24 |
--------------------------------------------------------------------------------
/docs/reference/datasets/index.rst:
--------------------------------------------------------------------------------
1 | Dataset
2 | ============
3 |
4 | .. autoclass:: giskard.Dataset
5 |
6 | .. automethod:: __init__
7 | .. automethod:: _infer_column_types
8 | .. automethod:: add_slicing_function
9 | .. automethod:: add_transformation_function
10 | .. automethod:: slice
11 | .. automethod:: transform
12 | .. automethod:: process
--------------------------------------------------------------------------------
/docs/reference/index.rst:
--------------------------------------------------------------------------------
1 | API Reference
2 | =============
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | models/index
8 | datasets/index
9 | scan/index
10 | tests/index
11 | slicing-functions/index
12 | transformation-functions/index
13 | suite/index
14 | rag-toolset/index
15 |
--------------------------------------------------------------------------------
/docs/reference/models/index.rst:
--------------------------------------------------------------------------------
1 | Models
2 | ======
3 |
4 | .. automodule:: giskard.models
5 |
6 | Integrations
7 | ------------
8 |
9 | .. toctree::
10 | :glob:
11 | :maxdepth: 1
12 |
13 | integrations/*
14 |
15 |
16 | The :class:`giskard.Model` class
17 | --------------------------------
18 |
19 | .. autoclass:: giskard.Model
20 |
21 | .. automethod:: __new__
22 | .. automethod:: is_classification
23 | .. automethod:: is_binary_classification
24 | .. automethod:: is_regression
25 | .. automethod:: is_text_generation
26 | .. automethod:: model_predict
27 | .. automethod:: predict
28 | .. automethod:: save_model
29 | .. automethod:: load_model
30 |
31 |
32 |
33 |
34 |
35 | Model Prediction
36 | ----------------
37 | .. autoclass:: giskard.models.base.ModelPredictionResults
38 |
39 |
40 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/base_classes.rst:
--------------------------------------------------------------------------------
1 | Base model classes
2 | ==================
3 |
4 | .. automodule:: giskard.models.base
5 | :members: BaseModel, WrapperModel, MLFlowSerializableModel, CloudpickleSerializableModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/catboost.rst:
--------------------------------------------------------------------------------
1 | Catboost models
2 | ===============
3 |
4 | .. automodule:: giskard.models.catboost
5 | :members: CatboostModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/function.rst:
--------------------------------------------------------------------------------
1 | Prediction function
2 | ===================
3 |
4 | .. automodule:: giskard.models.function
5 | :members: PredictionFunctionModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/huggingface.rst:
--------------------------------------------------------------------------------
1 | HuggingFace models
2 | ==================
3 |
4 | .. automodule:: giskard.models.huggingface
5 | :members: HuggingFaceModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/langchain.rst:
--------------------------------------------------------------------------------
1 | Langchain models
2 | ================
3 |
4 | .. automodule:: giskard.models.langchain
5 | :members: LangchainModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/pytorch.rst:
--------------------------------------------------------------------------------
1 | Pytorch models
2 | ==============
3 |
4 | .. automodule:: giskard.models.pytorch
5 | :members: PyTorchModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/sklearn.rst:
--------------------------------------------------------------------------------
1 | Sklearn models
2 | ==============
3 |
4 | .. automodule:: giskard.models.sklearn
5 | :members: SKLearnModel
6 |
--------------------------------------------------------------------------------
/docs/reference/models/integrations/tensorflow.rst:
--------------------------------------------------------------------------------
1 | Tensorflow models
2 | =================
3 |
4 | .. automodule:: giskard.models.tensorflow
5 | :members: TensorFlowModel
6 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/evaluation.rst:
--------------------------------------------------------------------------------
1 | Evaluation
2 | ==========
3 |
4 | .. autofunction:: giskard.rag.evaluate
5 |
6 | .. autoclass:: giskard.llm.evaluators.CorrectnessEvaluator
7 | :members:
8 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/index.rst:
--------------------------------------------------------------------------------
1 | RAG Evaluation Toolkit
2 | ======================
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | testset_generation
8 | knowledge_base
9 | evaluation
10 | question_generation
11 | metrics
12 |
13 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/knowledge_base.rst:
--------------------------------------------------------------------------------
1 | Knowledge Base
2 | ==============
3 |
4 | .. autoclass:: giskard.rag.knowledge_base.KnowledgeBase
5 | :members:
6 |
7 | .. autoclass:: giskard.rag.knowledge_base.Document
8 | :members:
9 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/metrics.rst:
--------------------------------------------------------------------------------
1 |
2 | Available Metric functions
3 | ==========================
4 |
5 | Correctness
6 | -----------
7 | Using LLM as a judge strategy, the correctness metrics check if an answer is correct compared to the reference answer.
8 |
9 | .. autofunction:: giskard.rag.metrics.correctness.correctness_metric
10 |
11 | RAGAS Metrics
12 | -------------
13 | We provide wrappers for some RAGAS metrics. You can implement other RAGAS metrics using the `RAGASMetric` class.
14 | .. autofunction:: giskard.rag.metrics.ragas_metrics.ragas_context_precision
15 |
16 | .. autofunction:: giskard.rag.metrics.ragas_metrics.ragas_faithfulness
17 |
18 | .. autofunction:: giskard.rag.metrics.ragas_metrics.ragas_answer_relevancy
19 |
20 | .. autofunction:: giskard.rag.metrics.ragas_metrics.ragas_context_recall
21 |
22 | Base Metric
23 | -----------
24 | .. autoclass:: giskard.rag.metrics.Metric
25 | :members:
26 | :special-members: __call__
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/question_generation.rst:
--------------------------------------------------------------------------------
1 | Question Generation
2 | ===================
3 |
4 | .. autoclass:: giskard.rag.question_generators.SimpleQuestionsGenerator
5 | :members:
6 |
7 | .. autoclass:: giskard.rag.question_generators.ComplexQuestionsGenerator
8 | :members:
9 |
10 | .. autoclass:: giskard.rag.question_generators.DistractingQuestionsGenerator
11 | :members:
12 |
13 | .. autoclass:: giskard.rag.question_generators.SituationalQuestionsGenerator
14 | :members:
15 |
16 | .. autoclass:: giskard.rag.question_generators.DoubleQuestionsGenerator
17 | :members:
18 |
19 | .. autoclass:: giskard.rag.question_generators.ConversationalQuestionsGenerator
20 | :members:
21 |
22 | .. autoclass:: giskard.rag.question_generators.OutOfScopeGenerator
23 | :members:
24 |
--------------------------------------------------------------------------------
/docs/reference/rag-toolset/testset_generation.rst:
--------------------------------------------------------------------------------
1 | Testset Generation
2 | ==================
3 |
4 | .. autofunction:: giskard.rag.generate_testset
5 |
6 | .. autoclass:: giskard.rag.QATestset
7 | :members:
--------------------------------------------------------------------------------
/docs/reference/scan/detectors.rst:
--------------------------------------------------------------------------------
1 | Tabular & NLP Detectors
2 | =======================
3 |
4 | Performance
5 | -----------
6 | .. automodule:: giskard.scanner.performance
7 | :members:
8 | :show-inheritance:
9 |
10 | Robustness
11 | ----------
12 | .. automodule:: giskard.scanner.robustness
13 | :members:
14 | :show-inheritance:
15 |
16 | Calibration
17 | -----------
18 | .. automodule:: giskard.scanner.calibration
19 | :members:
20 | :show-inheritance:
21 |
22 | Data Leakage
23 | ------------
24 | .. automodule:: giskard.scanner.data_leakage
25 | :members:
26 | :show-inheritance:
27 |
28 | Stochasticity
29 | -------------
30 | .. automodule:: giskard.scanner.stochasticity
31 | :members:
32 | :show-inheritance:
33 |
34 |
--------------------------------------------------------------------------------
/docs/reference/scan/index.rst:
--------------------------------------------------------------------------------
1 | Model Scanner
2 | =============
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | report
8 | detectors
9 | llm_detectors
10 |
11 | .. automodule:: giskard.scanner
12 | :members:
--------------------------------------------------------------------------------
/docs/reference/scan/llm_detectors.rst:
--------------------------------------------------------------------------------
1 | Detectors for LLM models
2 | ========================
3 |
4 |
5 | Injection attacks
6 | -----------------
7 |
8 | .. autoclass :: giskard.scanner.llm.LLMCharsInjectionDetector
9 | :members:
10 | :show-inheritance:
11 |
12 | .. autoclass :: giskard.scanner.llm.LLMPromptInjectionDetector
13 | :members:
14 | :show-inheritance:
15 |
16 | Hallucination & misinformation
17 | ------------------------------
18 |
19 | .. autoclass :: giskard.scanner.llm.LLMBasicSycophancyDetector
20 | :members:
21 | :show-inheritance:
22 |
23 | .. autoclass :: giskard.scanner.llm.LLMImplausibleOutputDetector
24 | :members:
25 | :show-inheritance:
26 |
27 |
28 | Harmful content generation
29 | --------------------------
30 |
31 | .. autoclass :: giskard.scanner.llm.LLMHarmfulContentDetector
32 | :members:
33 | :show-inheritance:
34 |
35 | Stereotypes
36 | -----------
37 |
38 | .. autoclass :: giskard.scanner.llm.LLMStereotypesDetector
39 | :members:
40 | :show-inheritance:
41 |
42 |
43 | Information disclosure
44 | ----------------------
45 |
46 | .. autoclass :: giskard.scanner.llm.LLMInformationDisclosureDetector
47 | :members:
48 | :show-inheritance:
49 |
50 | Output formatting
51 | -----------------
52 |
53 | .. autoclass :: giskard.scanner.llm.LLMOutputFormattingDetector
54 | :members:
55 | :show-inheritance:
56 |
--------------------------------------------------------------------------------
/docs/reference/scan/report.rst:
--------------------------------------------------------------------------------
1 | Scan Report
2 | ===========
3 |
4 | .. autoclass:: giskard.scanner.report.ScanReport
5 | :members:
6 | :show-inheritance:
7 |
8 |
--------------------------------------------------------------------------------
/docs/reference/slicing-functions/index.rst:
--------------------------------------------------------------------------------
1 | Slicing functions
2 | =================
3 |
4 | .. autofunction:: giskard.slicing_function
5 |
6 | .. autoclass:: giskard.registry.slicing_function.SlicingFunction
7 |
8 | .. automethod:: execute
9 |
10 | Textual slicing
11 | ---------------
12 |
13 | .. autofunction:: giskard.functions.slicing.short_comment_slicing_fn
14 | .. autofunction:: giskard.functions.slicing.keyword_lookup_slicing_fn
15 | .. autofunction:: giskard.functions.slicing.positive_sentiment_analysis
16 | .. autofunction:: giskard.functions.slicing.offensive_sentiment_analysis
17 | .. autofunction:: giskard.functions.slicing.irony_sentiment_analysis
18 | .. autofunction:: giskard.functions.slicing.hate_sentiment_analysis
19 | .. autofunction:: giskard.functions.slicing.emotion_sentiment_analysis
20 |
21 | Numerical slicing functions
22 | ---------------------------
23 |
24 | .. autofunction:: giskard.functions.slicing.outlier_filter
25 |
--------------------------------------------------------------------------------
/docs/reference/suite/index.rst:
--------------------------------------------------------------------------------
1 | Test suite
2 | ==============
3 |
4 | .. autoclass:: giskard.Suite
5 |
6 | .. automethod:: __init__
7 | .. automethod:: run
8 | .. automethod:: add_test
9 | .. automethod:: add_test
10 | .. automethod:: remove_test
11 | .. automethod:: upgrade_test
12 | .. automethod:: update_test_params
13 |
14 | .. autoclass:: giskard.core.suite.SuiteInput
15 |
16 | .. autoclass:: giskard.core.suite.DatasetInput
17 |
18 | .. autoclass:: giskard.core.suite.ModelInput
19 |
20 | .. autoclass:: giskard.core.suite.TestSuiteResult
21 |
22 | .. autoclass:: giskard.core.test_result.TestResult
23 |
--------------------------------------------------------------------------------
/docs/reference/tests/data.rst:
--------------------------------------------------------------------------------
1 | Data quality tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 | .. autofunction:: giskard.testing.test_data_uniqueness
4 | .. autofunction:: giskard.testing.test_data_completeness
5 | .. autofunction:: giskard.testing.test_valid_range
6 | .. autofunction:: giskard.testing.test_valid_values
7 | .. autofunction:: giskard.testing.test_data_correlation
8 | .. autofunction:: giskard.testing.test_outlier_value
9 | .. autofunction:: giskard.testing.test_foreign_constraint
10 | .. autofunction:: giskard.testing.test_label_consistency
11 | .. autofunction:: giskard.testing.test_mislabeling
12 | .. autofunction:: giskard.testing.test_feature_importance
13 | .. autofunction:: giskard.testing.test_class_imbalance
14 |
--------------------------------------------------------------------------------
/docs/reference/tests/drift.rst:
--------------------------------------------------------------------------------
1 |
2 |
3 | Drift tests
4 | ^^^^^^^^^^^^^^^^^^^^^
5 | .. autofunction:: giskard.testing.test_drift_psi
6 | .. autofunction:: giskard.testing.test_drift_chi_square
7 | .. autofunction:: giskard.testing.test_drift_ks
8 | .. autofunction:: giskard.testing.test_drift_earth_movers_distance
9 | .. autofunction:: giskard.testing.test_drift_prediction_psi
10 | .. autofunction:: giskard.testing.test_drift_prediction_chi_square
11 | .. autofunction:: giskard.testing.test_drift_prediction_ks
12 | .. autofunction:: giskard.testing.test_drift_prediction_earth_movers_distance
--------------------------------------------------------------------------------
/docs/reference/tests/index.rst:
--------------------------------------------------------------------------------
1 | Tests
2 | ======
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | metamorphic
8 | statistic
9 | performance
10 | drift
11 | llm
12 | data
13 | stability
14 |
--------------------------------------------------------------------------------
/docs/reference/tests/llm.rst:
--------------------------------------------------------------------------------
1 | LLM tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 |
4 | Injections
5 | ----------
6 | .. autofunction:: giskard.testing.tests.llm.test_llm_char_injection
7 | .. autofunction:: giskard.testing.tests.llm.test_llm_single_output_against_strings
8 | .. autofunction:: giskard.testing.tests.llm.test_llm_output_against_strings
9 |
10 | LLM-as-a-judge
11 | --------------
12 | .. autofunction:: giskard.testing.tests.llm.test_llm_output_coherency
13 | .. autofunction:: giskard.testing.tests.llm.test_llm_output_plausibility
14 | .. autofunction:: giskard.testing.tests.llm.test_llm_output_against_requirement_per_row
15 | .. autofunction:: giskard.testing.tests.llm.test_llm_single_output_against_requirement
16 | .. autofunction:: giskard.testing.tests.llm.test_llm_output_against_requirement
17 | .. autofunction:: giskard.testing.tests.llm.test_llm_correctness
18 |
19 | Ground Truth
20 | --------------
21 | .. autofunction:: giskard.testing.tests.llm.test_llm_ground_truth
22 | .. autofunction:: giskard.testing.tests.llm.test_llm_ground_truth_similarity
23 | .. autofunction:: giskard.testing.tests.llm.test_llm_as_a_judge_ground_truth_similarity
24 |
--------------------------------------------------------------------------------
/docs/reference/tests/metamorphic.rst:
--------------------------------------------------------------------------------
1 | Metamorphic tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 | .. autofunction:: giskard.testing.test_metamorphic_invariance
4 | .. autofunction:: giskard.testing.test_metamorphic_increasing
5 | .. autofunction:: giskard.testing.test_metamorphic_decreasing
6 | .. autofunction:: giskard.testing.test_metamorphic_decreasing_t_test
7 | .. autofunction:: giskard.testing.test_metamorphic_increasing_t_test
8 | .. autofunction:: giskard.testing.test_metamorphic_invariance_t_test
9 | .. autofunction:: giskard.testing.test_metamorphic_decreasing_wilcoxon
10 | .. autofunction:: giskard.testing.test_metamorphic_increasing_wilcoxon
11 | .. autofunction:: giskard.testing.test_metamorphic_invariance_wilcoxon
12 |
--------------------------------------------------------------------------------
/docs/reference/tests/performance.rst:
--------------------------------------------------------------------------------
1 | Performance tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 | .. autofunction:: giskard.testing.test_mae
4 | .. autofunction:: giskard.testing.test_rmse
5 | .. autofunction:: giskard.testing.test_recall
6 | .. autofunction:: giskard.testing.test_auc
7 | .. autofunction:: giskard.testing.test_accuracy
8 | .. autofunction:: giskard.testing.test_precision
9 | .. autofunction:: giskard.testing.test_f1
10 | .. autofunction:: giskard.testing.test_r2
11 | .. autofunction:: giskard.testing.test_diff_recall
12 | .. autofunction:: giskard.testing.test_diff_accuracy
13 | .. autofunction:: giskard.testing.test_diff_precision
14 | .. autofunction:: giskard.testing.test_diff_rmse
15 | .. autofunction:: giskard.testing.test_diff_f1
16 | .. autofunction:: giskard.testing.test_brier
17 |
--------------------------------------------------------------------------------
/docs/reference/tests/stability.rst:
--------------------------------------------------------------------------------
1 | Stability tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 | .. autofunction:: giskard.testing.test_smoothness
4 | .. autofunction:: giskard.testing.test_monotonicity
5 |
--------------------------------------------------------------------------------
/docs/reference/tests/statistic.rst:
--------------------------------------------------------------------------------
1 | Statistical tests
2 | ^^^^^^^^^^^^^^^^^^^^^
3 | .. autofunction:: giskard.testing.test_right_label
4 | .. autofunction:: giskard.testing.test_output_in_range
5 | .. autofunction:: giskard.testing.test_disparate_impact
6 | .. autofunction:: giskard.testing.test_nominal_association
7 | .. autofunction:: giskard.testing.test_cramer_v
8 | .. autofunction:: giskard.testing.test_mutual_information
9 | .. autofunction:: giskard.testing.test_theil_u
10 |
--------------------------------------------------------------------------------
/docs/reference/transformation-functions/index.rst:
--------------------------------------------------------------------------------
1 | .. _transformation_functions:
2 |
3 | Transformation functions
4 | ========================
5 |
6 | .. autofunction:: giskard.transformation_function
7 |
8 | .. autoclass:: giskard.registry.transformation_function.TransformationFunction
9 |
10 | .. automethod:: execute
11 |
12 | Textual transformation functions
13 | --------------------------------
14 |
15 | .. autofunction:: giskard.functions.transformation.keyboard_typo_transformation
16 | .. autofunction:: giskard.functions.transformation.text_uppercase
17 | .. autofunction:: giskard.functions.transformation.text_lowercase
18 | .. autofunction:: giskard.functions.transformation.text_title_case
19 | .. autofunction:: giskard.functions.transformation.text_typo
20 | .. autofunction:: giskard.functions.transformation.text_typo_from_ocr
21 | .. autofunction:: giskard.functions.transformation.text_punctuation_removal
22 | .. autofunction:: giskard.functions.transformation.text_accent_removal
23 | .. autofunction:: giskard.functions.transformation.text_gender_switch
24 | .. autofunction:: giskard.functions.transformation.text_number_to_word
25 | .. autofunction:: giskard.functions.transformation.text_religion_switch
26 | .. autofunction:: giskard.functions.transformation.text_nationality_switch
27 | .. autofunction:: giskard.functions.transformation.text_typo_from_speech
28 |
29 |
30 | Special transformations used by the scan
31 | ----------------------------------------
32 |
33 | .. automodule:: giskard.scanner.robustness.text_transformations
34 | :members:
35 | :show-inheritance:
36 |
--------------------------------------------------------------------------------
/docs/tutorials/index.md:
--------------------------------------------------------------------------------
1 | # Tutorials
2 | ```{toctree}
3 | :caption: Tutorials
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | llm_tutorials/index
8 | rag_tutorials/index
9 | tabular_tutorials/index
10 | nlp_tutorials/index
11 | vision_tutorials/index
12 | ```
13 |
14 | ::::::{grid} 1 1 2 2
15 |
16 |
17 | ::::{grid-item-card}
📚 LLM tutorials
18 | :text-align: center
19 | :link: llm_tutorials/index.html
20 | ::::
21 |
22 | ::::{grid-item-card}
🗄️ RAG tutorials
23 | :text-align: center
24 | :link: rag_tutorials/index.html
25 | ::::
26 |
27 | ::::{grid-item-card}
📊 Tabular tutorials
28 | :text-align: center
29 | :link: tabular_tutorials/index.html
30 | ::::
31 |
32 | ::::{grid-item-card}
🗣️ NLP tutorials
33 | :text-align: center
34 | :link: nlp_tutorials/index.html
35 | ::::
36 |
37 | ::::{grid-item-card}
📸 Vision tutorials
38 | :text-align: center
39 | :link: vision_tutorials/index.html
40 | ::::
--------------------------------------------------------------------------------
/docs/tutorials/rag_tutorials/index.md:
--------------------------------------------------------------------------------
1 | # RAG Tutorials
2 |
3 | ```{toctree}
4 | :caption: Table of Contents
5 | :maxdepth: 1
6 | :hidden:
7 |
8 | ../../reference/notebooks/RAGET_IPCC.ipynb
9 | ../../reference/notebooks/RAGET_Banking_Supervision.ipynb
10 |
11 |
12 |
13 | ```
14 |
15 | :::::{grid} 1 1 2 2
16 |
17 | ::::{grid-item-card} IPCC Climate Change Report
RAGET Demo with LlamaIndex RAG
18 | :text-align: center
19 | :link: ../../reference/notebooks/RAGET_IPCC.ipynb
20 | ::::
21 |
22 | ::::{grid-item-card} ECB Banking Supervision Report
RAGET Demo with LlamaIndex RAG
23 | :text-align: center
24 | :link: ../../reference/notebooks/RAGET_Banking_Supervision.ipynb
25 | ::::
26 |
27 | :::::
28 |
--------------------------------------------------------------------------------
/docs/tutorials/vision_tutorials/index.md:
--------------------------------------------------------------------------------
1 | # Vision Tutorials
2 | ```{toctree}
3 | :caption: Table of Contents
4 | :maxdepth: 1
5 | :hidden:
6 |
7 | ../../reference/notebooks/vision_landmark_detection.ipynb
8 | ../../reference/notebooks/vision_object_detection.ipynb
9 | ```
10 |
11 | :::::{grid} 1 1 2 2
12 |
13 | ::::{grid-item-card} Face landmark detection on the FFHQ dataset
Landmark detection (Open CV)
14 | :text-align: center
15 | :link: ../../reference/notebooks/vision_landmark_detection.ipynb
16 | ::::
17 |
18 | ::::{grid-item-card} Detection of faces on the 300W dataset
Object detection (Hugging Face)
19 | :text-align: center
20 | :link: ../../reference/notebooks/vision_object_detection.ipynb
21 | ::::
22 |
23 | :::::
24 |
--------------------------------------------------------------------------------
/giskard/client/dtos.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, List, Optional
2 |
3 | from giskard.core.validation import ConfiguredBaseModel
4 |
5 |
6 | class ServerInfo(ConfiguredBaseModel):
7 | instanceId: Optional[str] = None
8 | serverVersion: Optional[str] = None
9 | instanceLicenseId: Optional[str] = None
10 | user: Optional[str] = None
11 |
12 |
13 | class ModelMetaInfo(ConfiguredBaseModel):
14 | id: str
15 | name: str
16 | modelType: str
17 | featureNames: List[str]
18 | threshold: Optional[float] = None
19 | description: Optional[str] = None
20 | classificationLabels: Optional[List[str]] = None
21 | classificationLabelsDtype: Optional[str] = None
22 | languageVersion: str
23 | language: str
24 | createdDate: str
25 | size: int
26 | projectId: int
27 |
28 |
29 | class DatasetMetaInfo(ConfiguredBaseModel):
30 | target: Optional[str] = None
31 | columnTypes: Dict[str, str]
32 | columnDtypes: Dict[str, str]
33 | numberOfRows: int
34 | categoryFeatures: Dict[str, List[str]]
35 | name: Optional[str] = None
36 | originalSizeBytes: int
37 | compressedSizeBytes: int
38 | createdDate: str
39 | id: str
40 |
--------------------------------------------------------------------------------
/giskard/client/python_utils.py:
--------------------------------------------------------------------------------
1 | """Various utility functions to manage Python environments"""
2 |
3 | import os
4 | import sys
5 | import warnings
6 | from platform import python_version
7 |
8 | import importlib_metadata
9 |
10 | # Libs to be excluded when create a kernel automatically from the current env
11 | EXCLUDED_PYLIBS = [
12 | "setuptools",
13 | "pip",
14 | ]
15 |
16 |
17 | def get_python_requirements() -> str:
18 | pip_requirements = os.popen(f"{sys.executable} -m pip list --format freeze").read()
19 | if pip_requirements:
20 | return pip_requirements
21 | else:
22 | raise RuntimeError(
23 | "Python requirements could not be resolved. "
24 | + "Please use one of the following Python package managers: "
25 | + "Poetry, Pipenv or Pip."
26 | )
27 |
28 |
29 | def get_python_version() -> str:
30 | return python_version()
31 |
32 |
33 | def warning(content: str):
34 | warnings.warn(content, stacklevel=2)
35 |
36 |
37 | def format_pylib_extras(name):
38 | extras = importlib_metadata.metadata(name).get_all("Provides-Extra")
39 | if not extras or len(extras) == 0:
40 | return ""
41 | else:
42 | return f"[{', '.join(extras)}]"
43 |
--------------------------------------------------------------------------------
/giskard/core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/core/__init__.py
--------------------------------------------------------------------------------
/giskard/core/errors.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 |
4 | class GiskardInstallationError(ImportError):
5 | functionality: Optional[str]
6 | flavor: Optional[str]
7 |
8 | def __init__(self, flavor: str = None, functionality: str = None, msg: str = None) -> None:
9 | self.msg = msg
10 | if not self.msg:
11 | self.flavor = flavor or self.flavor
12 | self.functionality = functionality or self.functionality
13 | assert self.flavor, "Either giskard package flavor or custom error message should be provided"
14 |
15 | self.msg = (
16 | f"It seems that you are using Giskard {self.functionality or self.flavor} functionality "
17 | "but you are missing some required package. Please install Giskard "
18 | f"with {self.functionality or self.flavor} support with `pip install giskard[{self.flavor}]`."
19 | )
20 |
21 |
22 | class GiskardImportError(ImportError):
23 | def __init__(self, missing_package: str) -> None:
24 | self.msg = f"The '{missing_package}' Python package is not installed; please execute 'pip install {missing_package}' to obtain it."
25 |
--------------------------------------------------------------------------------
/giskard/core/kwargs_utils.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, List, Optional, Set, Tuple, Union
2 |
3 | import inspect
4 | from collections import defaultdict
5 |
6 |
7 | def get_imports_code(obj):
8 | imports = _get_imports(obj)
9 | return "\n".join([f'from {module} import {", ".join(classes)}' for module, classes in imports.items()])
10 |
11 |
12 | def _get_imports(obj, imports: Optional[defaultdict] = None):
13 | imports = imports or defaultdict(set)
14 | module = inspect.getmodule(obj)
15 |
16 | if isinstance(obj, Dict):
17 | for i in obj.values():
18 | imports = _get_imports(i, imports)
19 | elif isinstance(obj, Union[List, Set, Tuple]):
20 | for i in obj:
21 | print(i)
22 | imports = _get_imports(i, imports)
23 | elif hasattr(obj, "__dict__"):
24 | imports = _get_imports(obj.__dict__.values(), imports)
25 |
26 | if module is None:
27 | return imports
28 |
29 | imports[module.__name__].add(obj.__class__.__name__)
30 | return imports
31 |
--------------------------------------------------------------------------------
/giskard/datasets/metadata/__init__.py:
--------------------------------------------------------------------------------
1 | from .indexing import ColumnMetadataMixin
2 | from .registry import MetadataProvider, MetadataProviderRegistry
3 |
4 | __all__ = [
5 | "MetadataProviderRegistry",
6 | "MetadataProvider",
7 | "ColumnMetadataMixin",
8 | ]
9 |
--------------------------------------------------------------------------------
/giskard/datasets/metadata/registry.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 |
3 | from abc import ABC, abstractmethod
4 |
5 | import pandas as pd
6 |
7 | from ...core.core import ColumnType
8 |
9 |
10 | class MetadataProvider(ABC):
11 | name: str
12 |
13 | def __init__(self, name):
14 | self.name = name
15 |
16 | @abstractmethod
17 | def generate_metadata(self, values: pd.Series) -> pd.DataFrame:
18 | ...
19 |
20 | @abstractmethod
21 | def supported_types(self) -> Sequence[ColumnType]:
22 | ...
23 |
24 |
25 | class MetadataProviderRegistry:
26 | _provider = dict()
27 |
28 | @classmethod
29 | def register(cls, provider):
30 | cls._provider[provider.name] = provider
31 |
32 | @classmethod
33 | def get_provider(cls, name) -> MetadataProvider:
34 | return cls._provider[name]
35 |
36 | @classmethod
37 | def get_available_providers(cls) -> Sequence[str]:
38 | return list(cls._provider.keys())
39 |
--------------------------------------------------------------------------------
/giskard/datasets/metadata/text_metadata_provider.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from langdetect import DetectorFactory
3 |
4 | from ...utils.language_detection import detect_lang
5 | from .registry import MetadataProvider
6 |
7 | DetectorFactory.seed = 0
8 |
9 |
10 | class TextMetadataProvider(MetadataProvider):
11 | def __init__(self, name="text"):
12 | self.name = name
13 |
14 | def generate_metadata(self, values: pd.Series):
15 | # Ensure this is text encoded as a string
16 | values = values.astype(str)
17 |
18 | return pd.DataFrame(
19 | {
20 | "text_length": values.map(len),
21 | "charset": pd.Categorical(values.map(_detect_charset)),
22 | "language": values.map(detect_lang),
23 | },
24 | index=values.index,
25 | )
26 |
27 | def supported_types(self):
28 | return ["text"]
29 |
30 |
31 | def _detect_charset(text: str):
32 | import chardet
33 |
34 | charset = chardet.detect(text.encode("utf-8", errors="ignore"))["encoding"]
35 | return charset or "undefined"
36 |
--------------------------------------------------------------------------------
/giskard/demo/__init__.py:
--------------------------------------------------------------------------------
1 | from . import linear_regression, titanic_classification
2 |
3 |
4 | def titanic_df():
5 | return titanic_classification.get_test_df()
6 |
7 |
8 | def titanic(model="LogisticRegression", max_iter=100):
9 | return titanic_classification.get_model_and_df(model=model, max_iter=max_iter)
10 |
11 |
12 | def titanic_pipeline():
13 | return titanic_classification.get_pipeline()
14 |
15 |
16 | def linear_df():
17 | return linear_regression.get_df()
18 |
19 |
20 | def linear():
21 | return linear_regression.get_model_and_df()
22 |
23 |
24 | def linear_pipeline():
25 | return linear_regression.get_pipeline()
26 |
27 |
28 | __all__ = [
29 | "titanic_df",
30 | "titanic",
31 | "titanic_pipeline",
32 | "linear_df",
33 | "linear",
34 | "linear_pipeline",
35 | ]
36 |
--------------------------------------------------------------------------------
/giskard/demo/linear_regression.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 |
5 | def get_df():
6 | df = pd.DataFrame({"x": np.arange(100), "y": np.arange(100)})
7 | return df
8 |
9 |
10 | def get_model_and_df():
11 | from sklearn.linear_model import LinearRegression
12 |
13 | df = get_df()
14 |
15 | reg = LinearRegression()
16 | reg.fit(df["x"].to_numpy().reshape(100, 1), df["y"].to_numpy().reshape(100, 1))
17 | return reg, df
18 |
19 |
20 | def get_pipeline():
21 | reg, _ = get_model_and_df()
22 |
23 | def preprocessor(df):
24 | return df["x"].to_numpy().reshape(len(df["x"]), 1)
25 |
26 | return preprocessor, reg
27 |
--------------------------------------------------------------------------------
/giskard/exceptions/IllegalArgumentError.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class StatusCode(str, Enum):
5 | NO_ERROR = "NO_ERROR"
6 | INTERNAL = "INTERNAL"
7 | INVALID_ARGUMENT = "INVALID_ARGUMENT"
8 |
9 |
10 | class CodedError(Exception):
11 | code: StatusCode = StatusCode.INTERNAL
12 |
13 | def __init__(self, code: StatusCode, *args: object) -> None:
14 | super().__init__(*args)
15 | self.code = code
16 |
17 |
18 | class IllegalArgumentError(CodedError):
19 | def __init__(self, *args: object) -> None:
20 | super().__init__(StatusCode.INVALID_ARGUMENT, *args)
21 |
--------------------------------------------------------------------------------
/giskard/exceptions/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/exceptions/__init__.py
--------------------------------------------------------------------------------
/giskard/functions/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ["slicing", "transformation"]
2 |
--------------------------------------------------------------------------------
/giskard/integrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/integrations/__init__.py
--------------------------------------------------------------------------------
/giskard/integrations/mlflow/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/integrations/mlflow/__init__.py
--------------------------------------------------------------------------------
/giskard/integrations/mlflow/evaluation_artifacts.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | from mlflow.models import EvaluationArtifact
3 | from zstandard import ZstdDecompressor
4 |
5 | from giskard.client.io_utils import save_df
6 |
7 |
8 | class GiskardDatasetEvaluationArtifact(EvaluationArtifact):
9 | def _save(self, output_artifact_path):
10 | with open(output_artifact_path, "wb") as fw:
11 | uncompressed_bytes = save_df(self._content)
12 | fw.write(uncompressed_bytes)
13 |
14 | def _load_content_from_file(self, local_artifact_path):
15 | with open(local_artifact_path, "rb") as ds_stream:
16 | return pd.read_csv(
17 | ZstdDecompressor().stream_reader(ds_stream),
18 | keep_default_na=False,
19 | na_values=["_GSK_NA_"],
20 | )
21 |
22 |
23 | class GiskardScanResultEvaluationArtifact(EvaluationArtifact):
24 | def _save(self, output_artifact_path):
25 | self._content.to_html(output_artifact_path)
26 |
27 | def _load_content_from_file(self, local_artifact_path):
28 | with open(local_artifact_path, "rb") as f:
29 | return f.read()
30 |
31 |
32 | class GiskardScanSummaryEvaluationArtifact(GiskardDatasetEvaluationArtifact):
33 | def _load_content_from_file(self, local_artifact_path):
34 | with open(local_artifact_path, "rb") as ds_stream:
35 | return pd.read_csv(
36 | ZstdDecompressor().stream_reader(ds_stream),
37 | keep_default_na=False,
38 | )
39 |
--------------------------------------------------------------------------------
/giskard/integrations/wandb/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/integrations/wandb/__init__.py
--------------------------------------------------------------------------------
/giskard/llm/__init__.py:
--------------------------------------------------------------------------------
1 | from .client import get_default_client, set_default_client, set_llm_api, set_llm_model
2 | from .embeddings import set_default_embedding, set_embedding_model
3 | from .errors import LLMImportError
4 |
5 | __all__ = [
6 | "LLMImportError",
7 | "get_default_client",
8 | "set_llm_model",
9 | "set_default_client",
10 | "set_llm_api",
11 | "set_default_embedding",
12 | "set_embedding_model",
13 | ]
14 |
--------------------------------------------------------------------------------
/giskard/llm/client/base.py:
--------------------------------------------------------------------------------
1 | from typing import Optional, Sequence
2 |
3 | from abc import ABC, abstractmethod
4 | from dataclasses import dataclass
5 |
6 | from .logger import LLMLogger
7 |
8 |
9 | @dataclass
10 | class ChatMessage:
11 | role: str
12 | content: Optional[str] = None
13 |
14 |
15 | _logger = LLMLogger()
16 |
17 |
18 | class LLMClient(ABC):
19 | @property
20 | def logger(self) -> LLMLogger:
21 | return _logger
22 |
23 | @abstractmethod
24 | def complete(
25 | self,
26 | messages: Sequence[ChatMessage],
27 | temperature: float = 1,
28 | max_tokens: Optional[int] = None,
29 | caller_id: Optional[str] = None,
30 | seed: Optional[int] = None,
31 | format=None,
32 | ) -> ChatMessage:
33 | ...
34 |
--------------------------------------------------------------------------------
/giskard/llm/client/logger.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 |
4 | class LLMLogger:
5 | def __init__(self):
6 | self.calls = []
7 | self.errors = []
8 |
9 | def log_call(
10 | self,
11 | prompt_tokens: int,
12 | sampled_tokens: int,
13 | model: Optional[str] = None,
14 | client_class: Optional[str] = None,
15 | caller_id: Optional[str] = None,
16 | ):
17 | self.calls.append(
18 | {
19 | "prompt_tokens": prompt_tokens,
20 | "sampled_tokens": sampled_tokens,
21 | "model": model,
22 | "client_class": client_class,
23 | "caller_id": caller_id,
24 | }
25 | )
26 |
27 | def log_error(self, error):
28 | self.errors.append(error)
29 |
30 | def reset(self):
31 | self.calls = []
32 |
33 | def get_num_calls(self):
34 | return len(self.calls)
35 |
36 | def get_num_prompt_tokens(self):
37 | return sum(c["prompt_tokens"] for c in self.calls)
38 |
39 | def get_num_sampled_tokens(self):
40 | return sum(c["sampled_tokens"] for c in self.calls)
41 |
--------------------------------------------------------------------------------
/giskard/llm/config.py:
--------------------------------------------------------------------------------
1 | class LLMConfigurationError(ValueError):
2 | """Raised when the LLM client is not configured properly."""
3 |
--------------------------------------------------------------------------------
/giskard/llm/embeddings/base.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 |
3 | from abc import ABC, abstractmethod
4 |
5 | import numpy as np
6 |
7 |
8 | class BaseEmbedding(ABC):
9 | @abstractmethod
10 | def embed(self, texts: Sequence[str]) -> np.ndarray:
11 | ...
12 |
--------------------------------------------------------------------------------
/giskard/llm/embeddings/bedrock.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 | from typing_extensions import deprecated
3 |
4 | import json
5 |
6 | import numpy as np
7 |
8 | from .base import BaseEmbedding
9 |
10 |
11 | @deprecated("BedrockEmbedding is deprecated: https://docs.giskard.ai/en/latest/open_source/setting_up/index.html")
12 | class BedrockEmbedding(BaseEmbedding):
13 | def __init__(self, client, model: str):
14 | """
15 | Parameters
16 | ----------
17 | client : Bedrock
18 | boto3 based Bedrock runtime client instance.
19 | model : str
20 | Model name.
21 | """
22 | self.model = model
23 | self.client = client
24 |
25 | def embed(self, texts: Sequence[str]) -> np.ndarray:
26 | if "titan" not in self.model:
27 | raise ValueError(f"Only titan embedding models are supported currently, got {self.model} instead")
28 |
29 | if isinstance(texts, str):
30 | texts = [texts]
31 |
32 | accept = "application/json"
33 | contentType = "application/json"
34 | embeddings = []
35 | for text in texts:
36 | body = json.dumps({"inputText": text})
37 | response = self.client.invoke_model(body=body, modelId=self.model, accept=accept, contentType=contentType)
38 | response_body = json.loads(response.get("body").read())
39 | embedding = response_body.get("embedding")
40 | embeddings.append(embedding)
41 |
42 | return np.array(embeddings)
43 |
--------------------------------------------------------------------------------
/giskard/llm/embeddings/fastembed.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING, Optional, Sequence
4 |
5 | import numpy as np
6 |
7 | from .base import BaseEmbedding
8 |
9 | if TYPE_CHECKING:
10 | from fastembed import TextEmbedding
11 |
12 |
13 | class FastEmbedEmbedding(BaseEmbedding):
14 | def __init__(self, text_embedding: TextEmbedding):
15 | """
16 | Parameters
17 | ----------
18 | text_embedding : TextEmbedding
19 | FastEmbed TextEmbedding model.
20 | """
21 | self.text_embedding = text_embedding
22 |
23 | def embed(self, texts: Sequence[str]) -> np.ndarray:
24 | if isinstance(texts, str):
25 | texts = [texts]
26 |
27 | return np.array(list(self.text_embedding.embed(texts)))
28 |
29 |
30 | def try_get_fastembed_embeddings() -> Optional[FastEmbedEmbedding]:
31 | try:
32 | from fastembed import TextEmbedding
33 |
34 | from .fastembed import FastEmbedEmbedding
35 |
36 | return FastEmbedEmbedding(
37 | text_embedding=TextEmbedding("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
38 | )
39 | except ImportError:
40 | return None
41 |
--------------------------------------------------------------------------------
/giskard/llm/embeddings/litellm.py:
--------------------------------------------------------------------------------
1 | from typing import Any, Dict, Optional, Sequence
2 |
3 | import numpy as np
4 |
5 | from ...utils.iterables import batched
6 | from .. import LLMImportError
7 | from .base import BaseEmbedding
8 |
9 | try:
10 | import litellm
11 | except ImportError as err:
12 | raise LLMImportError(flavor="litellm") from err
13 |
14 |
15 | class LiteLLMEmbedding(BaseEmbedding):
16 | def __init__(self, model: str, embedding_params: Optional[Dict[str, Any]] = None, batch_size=40):
17 | """Initialize a LiteLLM embedding client
18 |
19 | Parameters
20 | ----------
21 | model : str
22 | Model name.
23 | embedding_params : dict, optional)
24 | A dictionary containing params for the completion.
25 | batch_size : int, optional
26 | Batch size for embeddings, by default 40.
27 | """
28 | self.model = model
29 | self.embedding_params = embedding_params or dict()
30 | self.batch_size = batch_size
31 |
32 | def embed(self, texts: Sequence[str]) -> np.ndarray:
33 | if isinstance(texts, str):
34 | texts = [texts]
35 |
36 | embeddings = []
37 | for batch in batched(texts, self.batch_size):
38 | response = litellm.embedding(model=self.model, input=batch, **self.embedding_params)
39 | embeddings.extend([item["embedding"] for item in response.data])
40 |
41 | return np.array(embeddings)
42 |
--------------------------------------------------------------------------------
/giskard/llm/errors.py:
--------------------------------------------------------------------------------
1 | from ..core.errors import GiskardInstallationError
2 |
3 |
4 | class LLMImportError(GiskardInstallationError):
5 | flavor = "llm"
6 | functionality = "LLM"
7 |
8 |
9 | class LLMGenerationError(RuntimeError):
10 | """Indicates a failure in LLM-based generation"""
11 |
--------------------------------------------------------------------------------
/giskard/llm/evaluators/__init__.py:
--------------------------------------------------------------------------------
1 | from .coherency import CoherencyEvaluator
2 | from .correctness import CorrectnessEvaluator
3 | from .plausibility import PlausibilityEvaluator
4 | from .requirements import RequirementEvaluator
5 |
6 | __all__ = [
7 | "CoherencyEvaluator",
8 | "RequirementEvaluator",
9 | "PlausibilityEvaluator",
10 | "CorrectnessEvaluator",
11 | ]
12 |
--------------------------------------------------------------------------------
/giskard/llm/evaluators/utils.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, Sequence
2 |
3 |
4 | def format_conversation(conversation: Sequence[Dict]):
5 | return "\n\n".join([f"<{msg['role'].lower()}>{msg['content']}{msg['role'].lower()}>" for msg in conversation])
6 |
--------------------------------------------------------------------------------
/giskard/llm/generators/__init__.py:
--------------------------------------------------------------------------------
1 | from .adversarial import AdversarialDataGenerator
2 | from .base import LLMBasedDataGenerator
3 | from .implausible import ImplausibleDataGenerator
4 | from .sycophancy import SycophancyDataGenerator
5 |
6 | __all__ = [
7 | "LLMBasedDataGenerator",
8 | "SycophancyDataGenerator",
9 | "ImplausibleDataGenerator",
10 | "AdversarialDataGenerator",
11 | ]
12 |
--------------------------------------------------------------------------------
/giskard/llm/loaders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/llm/loaders/__init__.py
--------------------------------------------------------------------------------
/giskard/llm/talk/tools/__init__.py:
--------------------------------------------------------------------------------
1 | from giskard.llm.talk.tools.base import BaseTool
2 | from giskard.llm.talk.tools.metric import MetricTool
3 | from giskard.llm.talk.tools.predict import PredictTool
4 | from giskard.llm.talk.tools.scan import IssuesScannerTool
5 | from giskard.llm.talk.tools.shap import SHAPExplanationTool
6 |
7 | __all__ = ["BaseTool", "PredictTool", "MetricTool", "IssuesScannerTool", "SHAPExplanationTool"]
8 |
--------------------------------------------------------------------------------
/giskard/models/base/__init__.py:
--------------------------------------------------------------------------------
1 | from .model import BaseModel
2 | from .model_prediction import ModelPredictionResults
3 | from .serialization import CloudpickleSerializableModel, MLFlowSerializableModel
4 | from .wrapper import WrapperModel
5 |
6 | __all__ = [
7 | "BaseModel",
8 | "ModelPredictionResults",
9 | "WrapperModel",
10 | "MLFlowSerializableModel",
11 | "CloudpickleSerializableModel",
12 | ]
13 |
--------------------------------------------------------------------------------
/giskard/models/cache/__init__.py:
--------------------------------------------------------------------------------
1 | from contextlib import AbstractContextManager
2 |
3 | from .cache import ModelCache
4 |
5 | # This is a global switch that controls model prediction cache.
6 | _cache_enabled = True
7 |
8 |
9 | def set_cache_enabled(value: bool):
10 | global _cache_enabled
11 | _cache_enabled = value
12 |
13 |
14 | def get_cache_enabled():
15 | global _cache_enabled
16 | return _cache_enabled
17 |
18 |
19 | def enable_cache():
20 | set_cache_enabled(True)
21 |
22 |
23 | def disable_cache():
24 | set_cache_enabled(False)
25 |
26 |
27 | class no_cache(AbstractContextManager):
28 | def __init__(self):
29 | self.prev = get_cache_enabled()
30 |
31 | def __enter__(self):
32 | set_cache_enabled(False)
33 |
34 | def __exit__(self, exc_type, exc_val, exc_tb):
35 | set_cache_enabled(self.prev)
36 |
37 |
38 | __all__ = ["set_cache_enabled", "get_cache_enabled", "enable_cache", "disable_cache", "no_cache", "ModelCache"]
39 |
--------------------------------------------------------------------------------
/giskard/models/catboost.py:
--------------------------------------------------------------------------------
1 | from typing import Optional, Tuple
2 |
3 | import mlflow
4 |
5 | from .sklearn import SKLearnModel
6 |
7 |
8 | class CatboostModel(SKLearnModel):
9 | """Automatically wraps ``catboost`` models for use with Giskard."""
10 |
11 | _feature_names_attr = "feature_names_"
12 |
13 | def save_model(self, local_path, mlflow_meta: mlflow.models.Model, *args, **kwargs):
14 | mlflow.catboost.save_model(self.model, path=local_path, mlflow_model=mlflow_meta)
15 |
16 | @classmethod
17 | def load_model(cls, local_dir, model_py_ver: Optional[Tuple[str, str, str]] = None, *args, **kwargs):
18 | return mlflow.catboost.load_model(local_dir)
19 |
20 | def to_mlflow(self, artifact_path: str = "catboost-model-from-giskard", **kwargs):
21 | return mlflow.catboost.log_model(self.model, artifact_path, **kwargs)
22 |
--------------------------------------------------------------------------------
/giskard/models/function.py:
--------------------------------------------------------------------------------
1 | from typing import Any, Callable, Iterable, Optional
2 |
3 | import numpy
4 | import pandas as pd
5 |
6 | from ..core.core import ModelType
7 | from ..core.validation import configured_validate_arguments
8 | from .base.serialization import CloudpickleSerializableModel
9 |
10 |
11 | class PredictionFunctionModel(CloudpickleSerializableModel):
12 | @configured_validate_arguments
13 | def __init__(
14 | self,
15 | model: Callable,
16 | model_type: ModelType,
17 | data_preprocessing_function: Optional[Callable[[pd.DataFrame], Any]] = None,
18 | model_postprocessing_function: Optional[Callable[[Any], Any]] = None,
19 | name: Optional[str] = None,
20 | feature_names: Optional[Iterable] = None,
21 | classification_threshold: Optional[float] = 0.5,
22 | classification_labels: Optional[Iterable] = None,
23 | id: Optional[str] = None,
24 | **kwargs,
25 | ) -> None:
26 | super().__init__(
27 | model,
28 | model_type,
29 | data_preprocessing_function,
30 | model_postprocessing_function,
31 | name,
32 | feature_names,
33 | classification_threshold,
34 | classification_labels,
35 | id=id,
36 | **kwargs,
37 | )
38 |
39 | def model_predict(self, df: pd.DataFrame) -> numpy.ndarray:
40 | return self.model(df)
41 |
--------------------------------------------------------------------------------
/giskard/models/talk_result.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 |
3 | from giskard.llm.client import ChatMessage
4 |
5 |
6 | @dataclass
7 | class TalkResult:
8 | """The dataclass containing the result of the 'talk' call.
9 |
10 | Attributes
11 | ----------
12 | response : ChatMessage
13 | The response to the user's query.
14 | summary : ChatMessage
15 | The summary of the conversation between the user and the LLM agent.
16 | tool_errors : list[Exception]
17 | The list of errors raised during tools execution.
18 | """
19 |
20 | response: ChatMessage
21 | summary: ChatMessage
22 | tool_errors: list[Exception]
23 |
24 | def __repr__(self) -> str:
25 | """Return the 'talk' result.
26 |
27 | Returns
28 | -------
29 | str
30 | The 'Talk' result, containing an answer and a conversation summary.
31 | """
32 | return (
33 | f"LLM Response:\n"
34 | f"-------------\n"
35 | f"{self.response.content}\n\n"
36 | f"Full Conversation Summary:\n"
37 | f"--------------------------\n"
38 | f"{self.summary.content}\n\n"
39 | f"Tool Errors Raised: {len(self.tool_errors)}"
40 | )
41 |
--------------------------------------------------------------------------------
/giskard/models/utils.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 | import itertools
4 | import random
5 | from collections.abc import Iterator
6 | from functools import lru_cache
7 |
8 | import numpy as np
9 |
10 |
11 | def map_to_tuples(data: Iterator):
12 | item = next(data)
13 | data = itertools.chain([item], data)
14 |
15 | if isinstance(item, tuple): # nothing to do
16 | return data
17 |
18 | return map(lambda x: (x,), data)
19 |
20 |
21 | def np_types_to_native(some_list: List):
22 | if some_list is not None:
23 | return [np_type_to_native(i) for i in some_list]
24 | return some_list
25 |
26 |
27 | def np_type_to_native(i):
28 | return i.item() if isinstance(i, np.generic) else i
29 |
30 |
31 | def fix_seed(seed=1337):
32 | random.seed(seed)
33 | np.random.seed(seed)
34 | try:
35 | import torch
36 |
37 | torch.manual_seed(seed)
38 | torch.cuda.manual_seed_all(seed)
39 | except ImportError:
40 | pass
41 |
42 |
43 | @lru_cache(None)
44 | def warn_once(logger, msg: str):
45 | logger.warning(msg)
46 |
--------------------------------------------------------------------------------
/giskard/path_utils.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | from giskard.settings import settings
4 |
5 | run_dir = settings.home_dir / "run"
6 | artifacts_dir = settings.home_dir / "artifacts"
7 |
8 |
9 | def get_size(path: str):
10 | size = 0
11 |
12 | for file_ in Path(path).rglob("*"):
13 | size += file_.stat().st_size
14 |
15 | return size
16 |
--------------------------------------------------------------------------------
/giskard/rag/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import AgentAnswer
2 | from .evaluate import evaluate
3 | from .knowledge_base import KnowledgeBase
4 | from .report import RAGReport
5 | from .testset import QATestset, QuestionSample
6 | from .testset_generation import generate_testset
7 |
8 | __all__ = [
9 | "QATestset",
10 | "QuestionSample",
11 | "generate_testset",
12 | "KnowledgeBase",
13 | "evaluate",
14 | "RAGReport",
15 | "AgentAnswer",
16 | ]
17 |
--------------------------------------------------------------------------------
/giskard/rag/base.py:
--------------------------------------------------------------------------------
1 | from typing import Optional, Sequence
2 |
3 | from dataclasses import dataclass
4 |
5 |
6 | @dataclass
7 | class AgentAnswer:
8 | message: str
9 | documents: Optional[Sequence[str]] = None
10 |
--------------------------------------------------------------------------------
/giskard/rag/metrics/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import Metric
2 | from .correctness import CorrectnessMetric, correctness_metric
3 |
4 | __all__ = ["Metric", "correctness_metric", "CorrectnessMetric"]
5 |
--------------------------------------------------------------------------------
/giskard/rag/metrics/base.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 | from ...llm.client.base import LLMClient
4 | from ..base import AgentAnswer
5 |
6 |
7 | class Metric(ABC):
8 | """
9 | Metric base class. All metrics should inherit from this class and implement the __call__ method.
10 | The instances of this class can be passed to the evaluate method.
11 | """
12 |
13 | def __init__(self, name: str, llm_client: LLMClient = None) -> None:
14 | self.name = name
15 | self._llm_client = llm_client
16 |
17 | @abstractmethod
18 | def __call__(self, question_sample: dict, answer: AgentAnswer):
19 | """
20 | Compute the metric on a single question and its associated answer.
21 |
22 | Parameters
23 | ----------
24 | question_sample : dict
25 | A question sample from a QATestset.
26 | answer : AgentAnswer
27 | The agent answer on that question.
28 |
29 | Returns
30 | -------
31 | dict
32 | The result of the metric computation. The keys should be the names of the metrics computed.
33 | """
34 | pass
35 |
--------------------------------------------------------------------------------
/giskard/rag/question_generators/__init__.py:
--------------------------------------------------------------------------------
1 | from .base import QuestionGenerator
2 | from .complex_questions import ComplexQuestionsGenerator, complex_questions
3 | from .conversational_questions import ConversationalQuestionsGenerator, conversational_questions
4 | from .distracting_questions import DistractingQuestionsGenerator, distracting_questions
5 | from .double_questions import DoubleQuestionsGenerator, double_questions
6 | from .oos_questions import OutOfScopeGenerator, oos_questions
7 | from .question_types import COMPONENT_DESCRIPTIONS, QUESTION_ATTRIBUTION, RAGComponents
8 | from .simple_questions import SimpleQuestionsGenerator, simple_questions
9 | from .situational_questions import SituationalQuestionsGenerator, situational_questions
10 |
11 | __all__ = [
12 | "RAGComponents",
13 | "QuestionGenerator",
14 | "QUESTION_ATTRIBUTION",
15 | "COMPONENT_DESCRIPTIONS",
16 | "SimpleQuestionsGenerator",
17 | "ComplexQuestionsGenerator",
18 | "ConversationalQuestionsGenerator",
19 | "DistractingQuestionsGenerator",
20 | "SituationalQuestionsGenerator",
21 | "DoubleQuestionsGenerator",
22 | "OutOfScopeGenerator",
23 | "simple_questions",
24 | "complex_questions",
25 | "conversational_questions",
26 | "distracting_questions",
27 | "situational_questions",
28 | "double_questions",
29 | "oos_questions",
30 | ]
31 |
--------------------------------------------------------------------------------
/giskard/rag/question_generators/prompt.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from dataclasses import dataclass
4 |
5 | from ...llm.client import ChatMessage
6 |
7 |
8 | @dataclass
9 | class QAGenerationPrompt:
10 | system_prompt: str
11 | user_input_template: Optional[str] = None
12 | example_input: Optional[str] = None
13 | example_output: Optional[str] = None
14 |
15 | def _format_example_prompt(self, examples):
16 | if examples is not None:
17 | return examples
18 |
19 | examples = []
20 | if self.example_input is not None:
21 | examples.append(ChatMessage(role="user", content=self.example_input))
22 | if self.example_output is not None:
23 | examples.append(ChatMessage(role="assistant", content=self.example_output))
24 | return examples
25 |
26 | def to_messages(
27 | self,
28 | system_prompt_input,
29 | user_input,
30 | add_examples=True,
31 | examples=None,
32 | ):
33 | messages = [
34 | ChatMessage(
35 | role="system",
36 | content=self.system_prompt.format(**system_prompt_input),
37 | )
38 | ]
39 | if add_examples:
40 | messages.extend(self._format_example_prompt(examples))
41 |
42 | if self.user_input_template is None:
43 | messages.append(ChatMessage(role="user", content=user_input))
44 | else:
45 | messages.append(ChatMessage(role="user", content=self.user_input_template.format(**user_input)))
46 |
47 | return messages
48 |
--------------------------------------------------------------------------------
/giskard/rag/question_generators/question_types.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class RAGComponents(int, Enum):
5 | GENERATOR = 1
6 | RETRIEVER = 2
7 | REWRITER = 3
8 | ROUTING = 4
9 | KNOWLEDGE_BASE = 5
10 |
11 |
12 | QUESTION_ATTRIBUTION = {
13 | RAGComponents.GENERATOR: [
14 | "simple",
15 | "complex",
16 | "distracting element",
17 | "situational",
18 | "double",
19 | ],
20 | RAGComponents.RETRIEVER: ["simple", "distracting element", "multi-context"],
21 | RAGComponents.REWRITER: [
22 | "distracting element",
23 | "double",
24 | "conversational",
25 | "multi-context",
26 | ],
27 | RAGComponents.ROUTING: ["out of scope"],
28 | RAGComponents.KNOWLEDGE_BASE: ["out of scope"],
29 | }
30 |
31 | COMPONENT_DESCRIPTIONS = {
32 | "GENERATOR": "The Generator is the LLM inside the RAG to generate the answers.",
33 | "RETRIEVER": "The Retriever fetches relevant documents from the knowledge base according to a user query.",
34 | "REWRITER": "The Rewriter modifies the user query to match a predefined format or to include the context from the chat history.",
35 | "ROUTING": "The Router filters the query of the user based on his intentions (intentions detection).",
36 | "KNOWLEDGE_BASE": "The knowledge base is the set of documents given to the RAG to generate the answers. Its scores is computed differently from the other components: it is the difference between the maximum and minimum correctness score across all the topics of the knowledge base.",
37 | }
38 |
--------------------------------------------------------------------------------
/giskard/registry/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/registry/__init__.py
--------------------------------------------------------------------------------
/giskard/scanner/calibration/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package provides detectors for potential problems related to model calibration.
3 | """
4 | from .overconfidence_detector import OverconfidenceDetector
5 | from .underconfidence_detector import UnderconfidenceDetector
6 |
7 | __all__ = ["OverconfidenceDetector", "UnderconfidenceDetector"]
8 |
--------------------------------------------------------------------------------
/giskard/scanner/common/utils.py:
--------------------------------------------------------------------------------
1 | from ...datasets.base import Dataset
2 | from ...models.base import BaseModel
3 |
4 |
5 | def get_dataset_subsample(dataset: Dataset, model: BaseModel, max_data_size: int):
6 | if max_data_size <= 0 or len(dataset) <= max_data_size: # just double checking
7 | return dataset
8 | if not model.is_classification:
9 | return dataset.slice(lambda df: df.sample(max_data_size, random_state=42), row_level=False)
10 |
11 | # Slice the dataset while keeping the class proportions
12 | keep_ratio = max_data_size / len(dataset)
13 | dataset = dataset.slice(
14 | lambda df: df.groupby(dataset.target, group_keys=False, sort=False).sample(frac=keep_ratio, random_state=42),
15 | row_level=False,
16 | )
17 | return dataset
18 |
--------------------------------------------------------------------------------
/giskard/scanner/correlation/__init__.py:
--------------------------------------------------------------------------------
1 | from .spurious_correlation_detector import SpuriousCorrelationDetector
2 |
3 | __all__ = ["SpuriousCorrelationDetector"]
4 |
--------------------------------------------------------------------------------
/giskard/scanner/data_leakage/__init__.py:
--------------------------------------------------------------------------------
1 | from .data_leakage_detector import DataLeakageDetector
2 |
3 | __all__ = ["DataLeakageDetector"]
4 |
--------------------------------------------------------------------------------
/giskard/scanner/decorators.py:
--------------------------------------------------------------------------------
1 | import inspect
2 | import re
3 |
4 | from .registry import DetectorRegistry
5 |
6 |
7 | def detector(name=None, tags=None):
8 | if inspect.isclass(name):
9 | # If the decorator is used without arguments, the first argument is the class
10 | cls = name
11 | DetectorRegistry.register(_to_snake_case(cls.__name__), cls)
12 | return cls
13 |
14 | def inner(cls):
15 | DetectorRegistry.register(name or _to_snake_case(cls.__name__), cls, tags)
16 | return cls
17 |
18 | return inner
19 |
20 |
21 | def _to_snake_case(string) -> str:
22 | s = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", string)
23 | return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s).lower()
24 |
--------------------------------------------------------------------------------
/giskard/scanner/llm/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This package provides LLM-specific detectors for the automatic model scan.
3 | """
4 | from .llm_basic_sycophancy_detector import LLMBasicSycophancyDetector
5 | from .llm_chars_injection_detector import LLMCharsInjectionDetector
6 | from .llm_harmful_content_detector import LLMHarmfulContentDetector
7 | from .llm_implausible_output_detector import LLMImplausibleOutputDetector
8 | from .llm_information_disclosure_detector import LLMInformationDisclosureDetector
9 | from .llm_output_formatting_detector import LLMOutputFormattingDetector
10 | from .llm_prompt_injection_detector import LLMPromptInjectionDetector
11 | from .llm_stereotypes_detector import LLMStereotypesDetector
12 |
13 | __all__ = [
14 | "LLMBasicSycophancyDetector",
15 | "LLMCharsInjectionDetector",
16 | "LLMHarmfulContentDetector",
17 | "LLMImplausibleOutputDetector",
18 | "LLMInformationDisclosureDetector",
19 | "LLMOutputFormattingDetector",
20 | "LLMPromptInjectionDetector",
21 | "LLMStereotypesDetector",
22 | ]
23 |
--------------------------------------------------------------------------------
/giskard/scanner/logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logger = logging.getLogger(__name__)
4 | logger.setLevel(logging.INFO)
5 |
--------------------------------------------------------------------------------
/giskard/scanner/performance/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This module contains detectors that measure the performance of a model to spot potential performance problems. In
3 | particular, we aim at detecting performance problems affecting specific subpopulations of the data (data slices).
4 |
5 | For example, consider a census model that performs well on the overall population but performs poorly on a specific
6 | subpopulation (e.g. age < 30). This is a performance problem that we want to detect.
7 | """
8 | from .performance_bias_detector import PerformanceBiasDetector
9 |
10 | __all__ = ["PerformanceBiasDetector"]
11 |
--------------------------------------------------------------------------------
/giskard/scanner/registry.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, Optional, Sequence
2 |
3 | from abc import ABC, abstractmethod
4 | from collections import defaultdict
5 |
6 | from ..datasets.base import Dataset
7 | from ..models.base import BaseModel
8 | from .issues import Issue
9 |
10 |
11 | class Detector(ABC):
12 | @abstractmethod
13 | def run(self, model: BaseModel, dataset: Dataset, features: Sequence[str]) -> Sequence[Issue]:
14 | ...
15 |
16 |
17 | class DetectorRegistry:
18 | _detectors: Dict[str, Detector] = dict()
19 | _tags = defaultdict(set)
20 |
21 | @classmethod
22 | def register(cls, name: str, detector: Detector, tags: Optional[Sequence[str]] = None):
23 | cls._detectors[name] = detector
24 | if tags is not None:
25 | cls._tags[name] = set(tags)
26 |
27 | @classmethod
28 | def get_detector_classes(cls, tags: Optional[Sequence[str]] = None) -> dict:
29 | if tags is None:
30 | return {n: d for n, d in cls._detectors.items()}
31 |
32 | return {n: d for n, d in cls._detectors.items() if cls._tags[n].intersection(tags)}
33 |
--------------------------------------------------------------------------------
/giskard/scanner/robustness/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This module contains detectors that measure the robustness of a model to spot potential robustness problems. For
3 | classification models, this means detecting a change in the predicted class as a result of a small change in the input
4 | data. For regression models, this means detecting a significant variation in the predicted value as a result of a small
5 | change in the input features.
6 |
7 | These detectors are generally based on some form of metamorphic invariance testing, e.g. by applying a transformation
8 | to the input data that is not supposed to affect the output significantly, and compare the output of the model before
9 | and after the transformation.
10 | """
11 | from .base_detector import BaseTextPerturbationDetector
12 | from .ethical_bias_detector import EthicalBiasDetector
13 | from .text_perturbation_detector import TextPerturbationDetector
14 |
15 | __all__ = ["EthicalBiasDetector", "TextPerturbationDetector", "BaseTextPerturbationDetector"]
16 |
--------------------------------------------------------------------------------
/giskard/scanner/robustness/base_perturbation_function.py:
--------------------------------------------------------------------------------
1 | from typing import Any
2 |
3 | import pandas as pd
4 |
5 | from ...core.core import DatasetProcessFunctionMeta
6 | from ...registry.registry import get_object_uuid
7 | from ...registry.transformation_function import TransformationFunction
8 |
9 |
10 | class PerturbationFunction(TransformationFunction):
11 | name: str
12 |
13 | def __init__(self, column: str, needs_dataset: bool = False) -> None:
14 | super().__init__(None, row_level=False, cell_level=False, needs_dataset=needs_dataset)
15 | self.column = column
16 | self.meta = DatasetProcessFunctionMeta(type="TRANSFORMATION")
17 | self.meta.uuid = get_object_uuid(self)
18 | self.meta.code = self.name
19 | self.meta.name = self.name
20 | self.meta.display_name = self.name
21 | self.meta.tags = ["pickle", "scan"]
22 | self.meta.doc = self.meta.default_doc("Automatically generated transformation function")
23 |
24 | def __str__(self) -> str:
25 | return self.name
26 |
27 | def make_perturbation(self, data_or_series: Any) -> Any:
28 | raise NotImplementedError()
29 |
30 | def execute(self, data: pd.DataFrame) -> pd.DataFrame:
31 | raise NotImplementedError()
32 |
--------------------------------------------------------------------------------
/giskard/scanner/robustness/numerical_perturbation_detector.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 |
3 | from ..decorators import detector
4 | from .base_detector import BaseNumericalPerturbationDetector
5 | from .numerical_transformations import NumericalTransformation
6 |
7 |
8 | class BoundClassWrapper:
9 | def __init__(self, cls, **bound_kwargs):
10 | self.cls = cls
11 | self.bound_kwargs = bound_kwargs
12 |
13 | def __call__(self, *args, **kwargs):
14 | return self.cls(*args, **self.bound_kwargs, **kwargs)
15 |
16 | def __getattr__(self, attr):
17 | # Forward attribute access to the wrapped class
18 | return getattr(self.cls, attr)
19 |
20 |
21 | @detector(
22 | name="numerical_perturbation",
23 | tags=[
24 | "numerical_perturbation",
25 | "robustness",
26 | "classification",
27 | "regression",
28 | ],
29 | )
30 | class NumericalPerturbationDetector(BaseNumericalPerturbationDetector):
31 | """Detects robustness problems in a model by applying numerical perturbations to the numerical features."""
32 |
33 | def _get_default_transformations(self) -> Sequence[NumericalTransformation]:
34 | from .numerical_transformations import AddGaussianNoise, MultiplyByFactor
35 |
36 | return [
37 | BoundClassWrapper(MultiplyByFactor, factor=1.01),
38 | BoundClassWrapper(MultiplyByFactor, factor=0.99),
39 | BoundClassWrapper(AddGaussianNoise, mean=0, std=0.01),
40 | ]
41 |
--------------------------------------------------------------------------------
/giskard/scanner/stochasticity/__init__.py:
--------------------------------------------------------------------------------
1 | from .stochasticity_detector import StochasticityDetector
2 |
3 | __all__ = ["StochasticityDetector"]
4 |
--------------------------------------------------------------------------------
/giskard/settings.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | import os
4 | from pathlib import Path
5 |
6 | import pydantic
7 | from packaging import version
8 | from pydantic import BaseModel
9 |
10 | # See https://linear.app/giskard/issue/GSK-1745/upgrade-pydantic-to-20
11 | IS_PYDANTIC_V2 = version.parse(pydantic.version.VERSION) >= version.parse("2.0")
12 |
13 | if IS_PYDANTIC_V2:
14 | FIELD_ATTR = "model_fields"
15 | else:
16 | FIELD_ATTR = "__fields__"
17 |
18 |
19 | def expand_env_var(env_var: Optional[str]) -> Optional[str]:
20 | current = env_var
21 | previous = None
22 | while current != previous:
23 | previous = current
24 | current = os.path.expandvars(current)
25 | return current
26 |
27 |
28 | class Settings(BaseModel):
29 | home: str = "~/giskard-home"
30 | ws_port: int = 9000
31 | ws_path: str = "/websocket"
32 | host: str = "localhost"
33 | max_workers: int = 10
34 | loglevel: str = "INFO"
35 | cache_dir: str = "cache"
36 | disable_analytics: bool = False
37 | force_asyncio_event_loop: bool = False
38 | min_workers: int = 2
39 | use_pool: bool = True # For testing/debugging only, do not disable
40 |
41 | class Config:
42 | env_prefix = "GSK_"
43 |
44 | @property
45 | def home_dir(self) -> Path:
46 | return Path(expand_env_var(self.home)).expanduser().resolve()
47 |
48 | @classmethod
49 | def build_from_env(cls) -> "Settings":
50 | return Settings(
51 | **{k: os.getenv(cls.Config.env_prefix + k.upper(), v.default) for k, v in getattr(cls, FIELD_ATTR).items()}
52 | )
53 |
54 |
55 | settings = Settings.build_from_env()
56 |
--------------------------------------------------------------------------------
/giskard/slicing/__init__.py:
--------------------------------------------------------------------------------
1 | from .slice import QueryBasedSliceFunction
2 |
3 | __all__ = ["QueryBasedSliceFunction"]
4 |
--------------------------------------------------------------------------------
/giskard/slicing/base.py:
--------------------------------------------------------------------------------
1 | from typing import List, Optional, Sequence
2 |
3 | from abc import ABC, abstractmethod
4 |
5 | from ..datasets.base import Dataset
6 | from .slice import QueryBasedSliceFunction
7 |
8 |
9 | class BaseSlicer(ABC):
10 | def __init__(
11 | self,
12 | dataset: Dataset,
13 | features: Optional[Sequence[str]] = None,
14 | target: Optional[str] = None,
15 | min_deviation: float = 0.05,
16 | abs_deviation: bool = False,
17 | ):
18 | self.dataset = dataset
19 | self.features = features
20 | self.target = target
21 | self.min_deviation = min_deviation
22 | self.abs_deviation = abs_deviation
23 |
24 | @abstractmethod
25 | def find_slices(self, features, target=None) -> List[QueryBasedSliceFunction]:
26 | ...
27 |
--------------------------------------------------------------------------------
/giskard/slicing/bruteforce_slicer.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 | from ..datasets import Dataset
4 | from .base import BaseSlicer
5 | from .slice import GreaterThan, LowerThan, Query, QueryBasedSliceFunction
6 |
7 |
8 | class BruteForceSlicer(BaseSlicer):
9 | def __init__(self, dataset: Dataset, features=None, target=None):
10 | self.dataset = dataset
11 | self.features = features
12 | self.target = target
13 |
14 | def find_slices(self, features, target=None):
15 | target = target or self.target
16 | data = self.dataset.df
17 |
18 | if len(features) > 1:
19 | raise NotImplementedError("Only single-feature slicing is implemented for now.")
20 | (feature,) = features
21 |
22 | # Quantile-based binning
23 | _, cut_bin = pd.qcut(data[feature], q=4, retbins=True, duplicates="drop", labels=False)
24 |
25 | result_df = []
26 | for i in range(len(cut_bin) - 1):
27 | result_df.append([cut_bin[i], cut_bin[i + 1]])
28 |
29 | clauses = []
30 | for interval in result_df:
31 | clauses.append([GreaterThan(feature, interval[0], True), LowerThan(feature, interval[1], True)])
32 |
33 | slice_candidates = [QueryBasedSliceFunction(Query(clause)) for clause in clauses]
34 |
35 | # Filter by relevance
36 | # filt = SignificanceFilter(target)
37 | # slices = filt.filter(slice_candidates)
38 |
39 | return slice_candidates
40 |
--------------------------------------------------------------------------------
/giskard/slicing/category_slicer.py:
--------------------------------------------------------------------------------
1 | from .base import BaseSlicer
2 | from .slice import EqualTo, Query, QueryBasedSliceFunction
3 |
4 |
5 | class CategorySlicer(BaseSlicer):
6 | def find_slices(self, features, target=None):
7 | data = self.dataset.df
8 | target = target or self.target
9 |
10 | if len(features) > 1:
11 | raise NotImplementedError("Only single-feature slicing is implemented for now.")
12 | (feature,) = features
13 |
14 | # Make slices
15 | values = data[feature].dropna().unique().tolist()
16 | slice_candidates = [QueryBasedSliceFunction(Query([EqualTo(feature, val)])) for val in values]
17 |
18 | return slice_candidates
19 |
--------------------------------------------------------------------------------
/giskard/slicing/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from .bruteforce_slicer import BruteForceSlicer
4 | from .multiscale_slicer import MultiscaleSlicer
5 | from .opt_slicer import OptSlicer
6 | from .slice import GreaterThan, LowerThan
7 | from .tree_slicer import DecisionTreeSlicer
8 |
9 |
10 | def get_slice_feature_interval(data_slice, feature, min_value=None, max_value=None):
11 | clauses = data_slice.query.clauses[feature]
12 | try:
13 | low = next(c for c in clauses if isinstance(c, GreaterThan)).threshold
14 | except StopIteration:
15 | low = min_value or -float("inf")
16 |
17 | try:
18 | high = next(c for c in clauses if isinstance(c, LowerThan)).threshold
19 | except StopIteration:
20 | high = max_value or float("inf")
21 |
22 | return low, high
23 |
24 |
25 | def get_slice_feature_intervals(slices, *args, **kwargs):
26 | return np.array([get_slice_feature_interval(s, *args, **kwargs) for s in slices])
27 |
28 |
29 | def get_slicer(slicer_name, dataset, target):
30 | if slicer_name == "optimized":
31 | return OptSlicer(dataset, target=target)
32 | if slicer_name == "tree":
33 | return DecisionTreeSlicer(dataset, target=target)
34 | if slicer_name == "multiscale":
35 | return MultiscaleSlicer(dataset, target=target)
36 | if slicer_name == "bruteforce":
37 | return BruteForceSlicer(dataset, target=target)
38 |
39 | raise ValueError(f"Invalid slicer `{slicer_name}`.")
40 |
--------------------------------------------------------------------------------
/giskard/testing/tests/__init__.py:
--------------------------------------------------------------------------------
1 | debug_prefix = "Debug: "
2 | debug_description_prefix = "This debugging session opens one by one all the examples "
3 |
--------------------------------------------------------------------------------
/giskard/testing/tests/debug_slicing_functions.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 | from giskard.registry.slicing_function import slicing_function
5 |
6 |
7 | # Performance tests: Classification
8 | @slicing_function(name="Incorrect rows", row_level=False)
9 | def incorrect_rows_slicing_fn(df: pd.DataFrame, target: str, prediction: np.ndarray) -> pd.DataFrame:
10 | """
11 | Filter the rows where the ground truth (target) does not match the model predictions.
12 | """
13 | return df[df[target] != prediction]
14 |
15 |
16 | # Performance tests: Regression
17 | @slicing_function(name="nlargest abs err rows", row_level=False)
18 | def nlargest_abs_err_rows_slicing_fn(
19 | df: pd.DataFrame, target: str, prediction: np.ndarray, debug_percent_rows: float = 0.3
20 | ) -> pd.DataFrame:
21 | """
22 | Filter the largest debug_percent_rows of rows based on the absolute error between
23 | the ground truth (target) and the model predictions.
24 | """
25 | df["metric"] = abs(df[target] - prediction)
26 | top_n = round(debug_percent_rows * len(df))
27 | return df.nlargest(top_n, "metric").drop("metric", axis=1)
28 |
29 |
30 | # Miscellaneous: Monotonicity
31 | @slicing_function(name="Rows failing monotonicity", row_level=False)
32 | def row_failing_slicing_fn(df: pd.DataFrame, index_failure: pd.Index) -> pd.DataFrame:
33 | """
34 | Filter the dataset by index
35 | """
36 | return df.loc[index_failure]
37 |
--------------------------------------------------------------------------------
/giskard/testing/tests/llm/__init__.py:
--------------------------------------------------------------------------------
1 | from .correctness import test_llm_correctness
2 | from .ground_truth import (
3 | test_llm_as_a_judge_ground_truth_similarity,
4 | test_llm_ground_truth,
5 | test_llm_ground_truth_similarity,
6 | )
7 | from .hallucination import test_llm_output_coherency, test_llm_output_plausibility
8 | from .injections import (
9 | LLMCharInjector,
10 | test_llm_char_injection,
11 | test_llm_output_against_strings,
12 | test_llm_single_output_against_strings,
13 | )
14 | from .output_requirements import (
15 | test_llm_output_against_requirement,
16 | test_llm_output_against_requirement_per_row,
17 | test_llm_single_output_against_requirement,
18 | )
19 |
20 | __all__ = [
21 | "test_llm_char_injection",
22 | "LLMCharInjector",
23 | "test_llm_output_against_requirement",
24 | "test_llm_single_output_against_requirement",
25 | "test_llm_output_against_requirement_per_row",
26 | "test_llm_output_coherency",
27 | "test_llm_output_plausibility",
28 | "test_llm_single_output_against_strings",
29 | "test_llm_output_against_strings",
30 | "test_llm_ground_truth_similarity",
31 | "test_llm_ground_truth",
32 | "test_llm_correctness",
33 | "test_llm_as_a_judge_ground_truth_similarity",
34 | ]
35 |
--------------------------------------------------------------------------------
/giskard/utils/__init__.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from threading import Thread
3 |
4 | LOGGER = logging.getLogger(__name__)
5 |
6 |
7 | def threaded(fn):
8 | def wrapper(*args, **kwargs):
9 | thread = Thread(target=fn, daemon=True, args=args, kwargs=kwargs)
10 | thread.start()
11 | return thread
12 |
13 | return wrapper
14 |
15 |
16 | def fullname(o):
17 | klass = o.__class__
18 | module = klass.__module__
19 | if module == "__builtin__":
20 | return klass.__name__
21 | return module + "." + klass.__name__
22 |
--------------------------------------------------------------------------------
/giskard/utils/display.py:
--------------------------------------------------------------------------------
1 | def format_number(value, n=3):
2 | if isinstance(value, float):
3 | if value > 1e6 or value < 1e-3:
4 | return f"{value:.{n}e}"
5 | else:
6 | return f"{value:.{3}f}"
7 |
8 | if isinstance(value, int) and abs(value) > 1e4:
9 | return f"{value:.{n}e}"
10 |
11 | return value
12 |
13 |
14 | def truncate(text, max_length=240, ellipsis="…"):
15 | """Truncates a text to the given length, adding an ellipsis at the end if needed."""
16 | if len(text) > max_length:
17 | return text[: max_length - len(ellipsis)] + ellipsis
18 | return text
19 |
--------------------------------------------------------------------------------
/giskard/utils/file_utils.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from uuid import UUID
3 |
4 | from giskard.settings import settings
5 |
6 |
7 | def get_file_name(name: str, extension: str, sample: bool):
8 | return f"{name}.sample.{extension}" if sample else f"{name}.{extension}"
9 |
10 |
11 | def job_logs_path(job_id: UUID) -> Path:
12 | return settings.home_dir / "run" / "jobs" / (str(job_id) + ".log")
13 |
--------------------------------------------------------------------------------
/giskard/utils/iterables.py:
--------------------------------------------------------------------------------
1 | import itertools
2 |
3 |
4 | def batched(iterable, batch_size):
5 | """Batches an iterable into chunks of size batch_size."""
6 | it = iter(iterable)
7 | while True:
8 | chunk = list(itertools.islice(it, batch_size))
9 | if not chunk:
10 | break
11 | yield chunk
12 |
--------------------------------------------------------------------------------
/giskard/utils/language_detection.py:
--------------------------------------------------------------------------------
1 | import langdetect
2 | import pandas as pd
3 |
4 |
5 | def detect_lang(text: str):
6 | if len(text.split()) <= 5:
7 | return pd.NA
8 | try:
9 | detected = langdetect.detect_langs(text)
10 | language = detected[0].lang
11 | except langdetect.lang_detect_exception.LangDetectException:
12 | language = "unknown"
13 | return language
14 |
--------------------------------------------------------------------------------
/giskard/visualization/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/giskard/visualization/__init__.py
--------------------------------------------------------------------------------
/giskard/visualization/custom_jinja.py:
--------------------------------------------------------------------------------
1 | from typing import Sequence
2 |
3 | import markdown
4 | from jinja2 import nodes
5 | from jinja2.ext import Extension
6 | from markupsafe import Markup
7 |
8 | from ..utils.display import format_number
9 |
10 |
11 | class IncludeRawExtension(Extension):
12 | tags = {"include_raw"}
13 |
14 | def parse(self, parser):
15 | lineno = next(parser.stream).lineno
16 | template = parser.parse_expression()
17 | result = self.call_method("_render", [template], lineno=lineno)
18 | return nodes.Output([result], lineno=lineno)
19 |
20 | def _render(self, filename):
21 | return Markup(self.environment.loader.get_source(self.environment, filename)[0])
22 |
23 |
24 | def markdown_to_html(md_text):
25 | html = markdown.markdown(md_text)
26 | return Markup(html)
27 |
28 |
29 | def pluralize(count, singular="", plural="s"):
30 | if isinstance(count, Sequence):
31 | count = len(count)
32 | return singular if count == 1 else plural
33 |
34 |
35 | def format_metric(value, n=3):
36 | return format_number(value, n)
37 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/rag_report/static/internal.js:
--------------------------------------------------------------------------------
1 | function opentab(evt, name) {
2 | // Declare all variables
3 | let i, tabcontent, tablinks;
4 |
5 | // Get all elements with class="tabcontent" and hide them
6 | tabcontent = document.getElementsByClassName("tabcontent");
7 | for (i = 0; i < tabcontent.length; i++) {
8 | tabcontent[i].style.display = "none";
9 | }
10 |
11 | // Get all elements with class="tablinks" and remove the class "active"
12 | tablinks = document.getElementsByClassName("tablinks");
13 | for (i = 0; i < tablinks.length; i++) {
14 | tablinks[i].className = tablinks[i].className.replace(" active", "");
15 | }
16 |
17 | // Show the current tab, and add an "active" class to the button that opened the tab
18 | document.getElementById(name).style.display = "block";
19 | evt.currentTarget.className += " active";
20 | }
21 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/html/_code_snippet.html:
--------------------------------------------------------------------------------
1 |
2 |
What's next?
3 |
4 |
5 | 1. Generate a test suite from your scan results
6 |
7 |
{% raw %}test_suite = results.generate_test_suite("My first test suite"){% endraw %}
8 |
9 |
2. Run your test suite
10 |
{% raw %}test_suite.run(){% endraw %}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/html/_issues_table.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% for issue in issues %}
4 |
5 | {% include "scan_report/html/_issue.html" %}
6 |
7 | {% endfor %}
8 |
9 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/html/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Giskard Scan Results
6 |
7 |
8 | {% block head %}{% endblock %}
9 |
10 |
11 |
12 | {% block content %}{% endblock %}
13 | {% block javascript %}{% endblock %}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/html/full.html:
--------------------------------------------------------------------------------
1 | {% extends "scan_report/html/base.html" %}
2 |
3 | {% block head %}
4 |
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 |
10 | {% include "scan_report/html/_tab_header.html" %}
11 | {% include "scan_report/html/_main_content.html" %}
12 | {% if issues|length > 0 and not issues[0].model.is_text_generation and issues[0].display_footer_info %}
13 | {% include "scan_report/html/_code_snippet.html" %}
14 | {% endif %}
15 |
16 |
17 | {% endblock %}
18 |
19 | {% block javascript %}
20 |
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/markdown/github.md:
--------------------------------------------------------------------------------
1 | {% for view in groups -%}
2 |
3 | {{ view.group.name }} issues ({{ view.issues|length }})
4 |
5 | | Vulnerability | Level | Data slice | Metric | Transformation | Deviation | Description |
6 | |---------------|-------|------------|--------|----------------|-----------|-------------|
7 | {% for issue in view.issues -%}
8 | | {{ view.group.name }} | {{ issue.level.value }} | {{ issue.slicing_fn if issue.slicing_fn else "—" }} | {% if "metric" in issue.meta %}{{ issue.meta.metric }} = {{ issue.meta.metric_value|format_metric }}{% else %} "—" {% endif %} | {{ issue.transformation_fn if issue.transformation_fn else "—" }} | {{ issue.meta["deviation"] if "deviation" in issue.meta else "—" }} | {{ issue.description }} |
9 | {% endfor %}
10 |
11 |
12 | {% endfor -%}
--------------------------------------------------------------------------------
/giskard/visualization/templates/scan_report/markdown/summary.md:
--------------------------------------------------------------------------------
1 | | Vulnerability | Level | Data slice | Metric | Transformation | Deviation | Description |
2 | |---------------|-------|------------|--------|----------------|-----------|-------------|
3 | {%- for view in groups -%}
4 | {% for issue in view.issues %}
5 | | {{ view.group.name }} | {{ issue.level.value }} | {{ issue.slicing_fn if issue.slicing_fn else "—" }} | {% if "metric" in issue.meta %}{{ issue.meta.metric }} = {{ issue.meta.metric_value|format_metric }}{% else %} "—" {% endif %} | {{ issue.transformation_fn if issue.transformation_fn else "—" }} | {{ issue.meta["deviation"] if "deviation" in issue.meta else "—" }} | {{ issue.description }} |
6 | {%- endfor -%}
7 | {%- endfor -%}
8 |
--------------------------------------------------------------------------------
/giskard/visualization/templates/suite_results/_suite_results_header.html:
--------------------------------------------------------------------------------
1 |
2 | {% if passed %}
3 |
7 |
Test suite passed.
8 |
9 | {% else %}
10 |
16 |
Test suite failed.
17 | {% endif %}
18 |
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "build": "tailwindcss -i ./src/scan-widget/style.css -o ./giskard/scanner/templates/static/style.css",
4 | "watch": "tailwindcss -i ./src/scan-widget/style.css -o ./giskard/scanner/templates/static/style.css --watch"
5 | },
6 | "devDependencies": {
7 | "@babel/core": "^7.26.9",
8 | "@babel/preset-env": "^7.26.9",
9 | "autoprefixer": "^10.4.21",
10 | "cssnano": "^7.0.6",
11 | "gulp": "^5.0.0",
12 | "gulp-babel": "^8.0.0",
13 | "gulp-concat": "^2.6.1",
14 | "gulp-minify": "^3.1.0",
15 | "gulp-postcss": "^10.0.0",
16 | "postcss": "^8.5.3",
17 | "postcss-import": "^16.1.0",
18 | "tailwindcss": "^4.1.0",
19 | "uglify": "^0.1.5"
20 | },
21 | "dependencies": {
22 | "alpinejs": "^3.14.9"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | "postcss-import": {},
4 | tailwindcss: {},
5 | autoprefixer: {},
6 | cssnano: {},
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/readme/Discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/Discord.png
--------------------------------------------------------------------------------
/readme/Give_feedback.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/Give_feedback.jpeg
--------------------------------------------------------------------------------
/readme/Logo_full_darkgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/Logo_full_darkgreen.png
--------------------------------------------------------------------------------
/readme/RAGET_updated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/RAGET_updated.gif
--------------------------------------------------------------------------------
/readme/architechture_giskard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/architechture_giskard.png
--------------------------------------------------------------------------------
/readme/catalog_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/catalog_example.png
--------------------------------------------------------------------------------
/readme/catalog_slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/catalog_slice.png
--------------------------------------------------------------------------------
/readme/catalog_transfo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/catalog_transfo.png
--------------------------------------------------------------------------------
/readme/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/demo.png
--------------------------------------------------------------------------------
/readme/design_partner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/design_partner.png
--------------------------------------------------------------------------------
/readme/feedback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/feedback.png
--------------------------------------------------------------------------------
/readme/feedback1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/feedback1.png
--------------------------------------------------------------------------------
/readme/giskard_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/giskard_logo.png
--------------------------------------------------------------------------------
/readme/giskard_logo_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/giskard_logo_green.png
--------------------------------------------------------------------------------
/readme/inspect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/inspect.png
--------------------------------------------------------------------------------
/readme/perturbation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/perturbation.png
--------------------------------------------------------------------------------
/readme/pipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/pipeline.png
--------------------------------------------------------------------------------
/readme/scan_example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/scan_example.gif
--------------------------------------------------------------------------------
/readme/scan_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/scan_example.png
--------------------------------------------------------------------------------
/readme/scan_results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/scan_results.png
--------------------------------------------------------------------------------
/readme/scan_updates.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/scan_updates.gif
--------------------------------------------------------------------------------
/readme/suite_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/suite_example.png
--------------------------------------------------------------------------------
/readme/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/test.png
--------------------------------------------------------------------------------
/readme/test1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/test1.png
--------------------------------------------------------------------------------
/readme/test_suite_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/test_suite_example.png
--------------------------------------------------------------------------------
/readme/tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/tools.png
--------------------------------------------------------------------------------
/readme/tools_updated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/tools_updated.png
--------------------------------------------------------------------------------
/readme/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/upload.png
--------------------------------------------------------------------------------
/readme/workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/readme/workflow.png
--------------------------------------------------------------------------------
/sample_data/other/addresses.csv:
--------------------------------------------------------------------------------
1 | Name,Last,Address,City,State,PostalCode
2 | John,Doe,120 jefferson st.,Riverside, NJ, 08075
3 | Jack,McGinnis,220 hobo Av.,Phila, PA,09119
4 | "John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075
5 | Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234
6 | ,Blankman,,SomeTown, SD, 00298
7 | "Joan ""the bone"", Anne",Jet,"9th, at Terrace plc",Desert City,CO,00123
8 |
--------------------------------------------------------------------------------
/scripts/install-giskard-client-dev.sh:
--------------------------------------------------------------------------------
1 | pip="${1:-pip}"
2 | rm -f /tmp/giskard*whl* || true
3 | wget https://nightly.link/Giskard-AI/giskard/workflows/build/main/giskard-dev.whl.zip -P /tmp
4 | unzip -o /tmp/giskard-dev.whl.zip -d /tmp
5 | $pip install --upgrade "$(ls /tmp/giskard*whl)"
6 | rm -f /tmp/giskard*whl*
--------------------------------------------------------------------------------
/scripts/make-release.sh:
--------------------------------------------------------------------------------
1 | set -e
2 |
3 | DIR="$(dirname $(readlink -f $0))"
4 |
5 | die () {
6 | echo >&2 "$@"
7 | exit 1
8 | }
9 |
10 | [ "$#" -eq 1 ] || die "1 argument required, $# provided"
11 | echo $1 | grep -E -q '^[0-9]+\.[0-9]+\.[0-9]+([ab]\d+)?$' ||
12 | die "Version should match '^[0-9]+\.[0-9]+\.[0-9]+([ab]\d+)?$', $1 provided"
13 |
14 | if [ -n "$1" ]; then
15 | git stash || true
16 | git pull
17 | pyprojpath="$DIR/../pyproject.toml"
18 | echo "Setting version to $1 in $pyprojpath"
19 | sed -i '' "s/^version = \".*$/version = \"$1\"/" "$pyprojpath"
20 | git add "$pyprojpath"
21 | git commit -m "Version $1"
22 | git tag -a "python-client-v$1" -m "v$1"
23 | git push
24 | git push origin "python-client-$1"
25 | else
26 | echo "New version is not specified"
27 | fi
28 |
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | sonar.sources=giskard
2 | sonar.tests=tests
3 | sonar.language=python
4 | sonar.python.version=3
5 | sonar.dynamicAnalysis=reuseReports
6 | sonar.core.codeCoveragePlugin=cobertura
7 | sonar.python.coverage.reportPaths=coverage.xml
8 |
9 | sonar.verbose=true
10 | sonar.projectKey=giskard
11 | sonar.organization=giskard
12 |
13 | sonar.host.url=https://sonarcloud.io
14 | sonar.sourceEncoding=UTF-8
15 |
16 | sonar.issue.ignore.multicriteria.S2245.resourceKey=**/*
17 | sonar.issue.ignore.multicriteria.S2245.ruleKey=python:S2245
--------------------------------------------------------------------------------
/src/scan-widget/internal-js/highlightjs-copy.min.js:
--------------------------------------------------------------------------------
1 | class CopyButtonPlugin{constructor(options={}){self.hook=options.hook;self.callback=options.callback}"after:highlightElement"({el,text}){let button=Object.assign(document.createElement("button"),{innerHTML:"Copy",className:"hljs-copy-button"});button.dataset.copied=false;el.parentElement.classList.add("hljs-copy-wrapper");el.parentElement.appendChild(button);el.parentElement.style.setProperty("--hljs-theme-background",window.getComputedStyle(el).backgroundColor);button.onclick=function(){if(!navigator.clipboard)return;let newText=text;if(hook&&typeof hook==="function"){newText=hook(text,el)||text}navigator.clipboard.writeText(newText).then(function(){button.innerHTML=" Copied! ";button.dataset.copied=true;let alert=Object.assign(document.createElement("div"),{role:"status",className:"hljs-copy-alert",innerHTML:"Copied to clipboard"});el.parentElement.appendChild(alert);setTimeout(()=>{button.innerHTML="Copy";button.dataset.copied=false;el.parentElement.removeChild(alert);alert=null},2e3)}).then(function(){if(typeof callback==="function")return callback(newText,el)})}}}
--------------------------------------------------------------------------------
/src/scan-widget/internal-js/scan.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | // HighlightJS
3 | hljs.addPlugin(new CopyButtonPlugin());
4 | hljs.highlightAll();
5 |
6 | // Tabs
7 | let rows = document.querySelectorAll("#gsk-scan .gsk-issue")
8 | rows.forEach(rowEl => {
9 | rowEl.addEventListener("click", (event) => {
10 | {
11 | event.preventDefault()
12 | rowEl.classList.toggle("open")
13 | rowEl.classList.toggle("bg-zinc-700")
14 | }
15 | })
16 | });
17 |
18 | const tabs = document.querySelectorAll("#gsk-scan [role='tabpanel']")
19 | const tabHeaders = document.querySelectorAll("#gsk-scan [data-tab-target]")
20 | tabHeaders.forEach(tabHeader => {
21 | tabHeader.addEventListener("click", (event) => {
22 | event.preventDefault()
23 | const tabId = tabHeader.getAttribute("data-tab-target")
24 |
25 | tabs.forEach(tab => {
26 | tab.classList.add("hidden")
27 | })
28 | tabHeaders.forEach(tabh => {
29 | tabh.classList.remove("active")
30 | })
31 |
32 | tabHeader.classList.add("active")
33 | document.getElementById(tabId).classList.remove("hidden")
34 |
35 | })
36 | })
37 | })()
--------------------------------------------------------------------------------
/src/scan-widget/style.css:
--------------------------------------------------------------------------------
1 | /* Imports */
2 | @import "_highlight_theme.css";
3 | @import "_highlightjs_copy.css";
4 |
5 | /* Main styles */
6 | @tailwind base;
7 | @tailwind components;
8 | @tailwind utilities;
9 |
10 |
11 | p a {
12 | text-decoration: underline;
13 | }
14 |
15 | /* Special styles for tab headers */
16 | .tab-header {
17 | min-width: 3rem;
18 | }
19 |
20 | .active.tab-header {
21 | min-width: fit-content;
22 | }
23 |
24 | /* Pandas DataFrame table */
25 | table.dataframe {
26 | width: 100%;
27 | max-width: 100%;
28 | overflow: auto;
29 | }
30 |
31 | .dataframe tr {
32 | border-bottom: 1px solid #555;
33 | vertical-align: top;
34 | }
35 |
36 | .dataframe td,
37 | .dataframe th {
38 | padding: 0.5rem;
39 | }
40 |
41 | .dataframe th {
42 | text-align: left !important;
43 | }
44 |
45 | .prose p {
46 | @apply my-1;
47 | }
48 |
49 | .prose ul {
50 | @apply list-disc ml-4 my-1;
51 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | darkMode: "class",
4 | content: [
5 | "./giskard/visualization/templates/**/*.{html,js}"
6 | ],
7 | theme: {
8 | extend: {},
9 | },
10 | plugins: [],
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 |
4 | def path(p):
5 | return Path(__file__).parent / p
6 |
--------------------------------------------------------------------------------
/tests/core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/core/__init__.py
--------------------------------------------------------------------------------
/tests/core/test_validation.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | import pydantic
4 | import pytest
5 | from packaging import version
6 | from pydantic import ValidationError
7 |
8 | from giskard.core.validation import ConfiguredBaseModel
9 |
10 | IS_PYDANTIC_V2 = version.parse(pydantic.version.VERSION) >= version.parse("2.0")
11 |
12 |
13 | def test_model_forbid_extra():
14 | class TestModel(ConfiguredBaseModel):
15 | a: str
16 | b: int
17 |
18 | TestModel(a="toot", b=5)
19 | with pytest.raises(ValidationError) as exc_info:
20 | TestModel(a="toto", b=5, c=True)
21 |
22 | with pytest.raises(ValidationError) as exc_info:
23 | TestModel.parse_obj({"a": "toto", "b": 5, "c": True})
24 | if IS_PYDANTIC_V2:
25 | assert "Extra inputs are not permitted" in str(exc_info)
26 | else:
27 | assert "extra fields not permitted" in str(exc_info)
28 |
29 |
30 | @pytest.mark.skip(reason="GSK-2057, restore after proper handing of NaN in tests metrics")
31 | def test_model_forbid_inf_nan():
32 | class TestModel(ConfiguredBaseModel):
33 | a: float
34 |
35 | TestModel(a=5.0)
36 | with pytest.raises(ValidationError) as exc_info:
37 | TestModel(a=math.inf)
38 |
39 | if IS_PYDANTIC_V2:
40 | assert "Input should be a finite number" in str(exc_info)
41 | else:
42 | assert "ensure this value is a finite number" in str(exc_info)
43 |
--------------------------------------------------------------------------------
/tests/datasets/test_base_dataset.py:
--------------------------------------------------------------------------------
1 | import uuid
2 |
3 | import pandas as pd
4 | import pytest
5 |
6 | from giskard import Dataset
7 |
8 |
9 | @pytest.fixture
10 | def df() -> pd.DataFrame:
11 | return pd.DataFrame({"a": range(10), "b": ["x", "y"] * 5})
12 |
13 |
14 | def test_named_and_IDed_dataset_str(df: pd.DataFrame):
15 | uid = uuid.uuid4()
16 | dataset = Dataset(name="foo", id=uid, df=df)
17 | assert str(dataset) == f"foo({uid})"
18 |
19 |
20 | def test_named_dataset_str(df: pd.DataFrame):
21 | dataset = Dataset(name="bar", df=df)
22 | assert str(dataset).split("(")[0] == "bar"
23 |
24 |
25 | def test_unnamed_dataset_str(df: pd.DataFrame):
26 | dataset = Dataset(df=df)
27 | assert hex(id(dataset)).lower()[2:] in str(dataset).lower()
28 | assert " pd.DataFrame:
16 | return df[TEXT_COLUMN_NAME].apply(lambda x: self.model.run({"query": x}))
17 |
18 | def save_model(self, path: str, *args, **kwargs):
19 | out_dest = Path(path)
20 | # Save the chain object
21 | self.model.save(out_dest.joinpath("model.json"))
22 |
23 | @classmethod
24 | def load_model(cls, path: str, **kwargs) -> Chain:
25 | src = Path(path)
26 |
27 | # Load the chain, passing the retriever
28 | chain = load_chain(src.joinpath("model.json"))
29 | return chain
30 |
31 |
32 | def test_load():
33 | llm = FakeListLLM(responses=["foo", "bar", "baz"])
34 | chain = LLMChain.from_string(llm=llm, template="{query}")
35 |
36 | model = MyModel(
37 | chain,
38 | "text_generation",
39 | name="Foo",
40 | description="Model that reply foo, bar, baz",
41 | feature_names=[TEXT_COLUMN_NAME],
42 | )
43 |
44 | with tempfile.TemporaryDirectory() as f:
45 | model.save(f)
46 | giskard.Model.load(f)
47 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.10/giskard-model-meta.yaml:
--------------------------------------------------------------------------------
1 | classification_labels:
2 | - 0
3 | - 1
4 | description: No description
5 | feature_names: null
6 | id: 54a90cbf-3b44-43d4-8070-8926c8339791
7 | language: PYTHON
8 | language_version: 3.10.13
9 | loader_class: PredictionFunctionModel
10 | loader_module: giskard.models.function
11 | model_type: CLASSIFICATION
12 | name: PredictionFunctionModel
13 | size: 0
14 | threshold: 0.5
15 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.10/giskard-model-wrapper-meta.yaml:
--------------------------------------------------------------------------------
1 | batch_size: null
2 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.10/model.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/models/fixtures/func/3.10/model.pkl
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.11/giskard-model-meta.yaml:
--------------------------------------------------------------------------------
1 | classification_labels:
2 | - 0
3 | - 1
4 | description: No description
5 | feature_names: null
6 | id: 01297928-e182-4b50-b9aa-57058dcbadbd
7 | language: PYTHON
8 | language_version: 3.11.5
9 | loader_class: PredictionFunctionModel
10 | loader_module: giskard.models.function
11 | model_type: CLASSIFICATION
12 | name: PredictionFunctionModel
13 | size: 0
14 | threshold: 0.5
15 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.11/giskard-model-wrapper-meta.yaml:
--------------------------------------------------------------------------------
1 | batch_size: null
2 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.11/model.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/models/fixtures/func/3.11/model.pkl
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.9/giskard-model-meta.yaml:
--------------------------------------------------------------------------------
1 | classification_labels:
2 | - 0
3 | - 1
4 | feature_names: null
5 | id: 592e6f31-5d04-4915-9d26-798f21277a28
6 | language: PYTHON
7 | language_version: 3.9.6
8 | loader_class: PredictionFunctionModel
9 | loader_module: giskard.models.function
10 | model_type: CLASSIFICATION
11 | name: PredictionFunctionModel
12 | size: 0
13 | threshold: 0.5
14 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.9/giskard-model-wrapper-meta.yaml:
--------------------------------------------------------------------------------
1 | batch_size: null
2 |
--------------------------------------------------------------------------------
/tests/models/fixtures/func/3.9/model.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/models/fixtures/func/3.9/model.pkl
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.10/ModelClass.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/models/fixtures/ipcc/3.10/ModelClass.pkl
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.10/giskard-model-meta.yaml:
--------------------------------------------------------------------------------
1 | classification_labels: null
2 | description: Model that reply foo, bar, baz
3 | feature_names:
4 | - query
5 | id: 172f1497-fb87-4484-8dcc-c01ca4197509
6 | language: PYTHON
7 | language_version: 3.10.9
8 | loader_class: MyModel
9 | loader_module: __main__
10 | model_type: TEXT_GENERATION
11 | name: Foo
12 | size: 1608
13 | threshold: 0.5
14 |
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.10/giskard-model-wrapper-meta.yaml:
--------------------------------------------------------------------------------
1 | batch_size: null
2 |
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.10/model.json:
--------------------------------------------------------------------------------
1 | {
2 | "memory": null,
3 | "verbose": false,
4 | "tags": null,
5 | "metadata": null,
6 | "prompt": {
7 | "input_variables": [
8 | "query"
9 | ],
10 | "output_parser": null,
11 | "partial_variables": {},
12 | "template": "{query}",
13 | "template_format": "f-string",
14 | "validate_template": true,
15 | "_type": "prompt"
16 | },
17 | "llm": {
18 | "responses": [
19 | "foo",
20 | "bar",
21 | "baz"
22 | ],
23 | "_type": "fake-list"
24 | },
25 | "output_key": "text",
26 | "output_parser": {
27 | "_type": "default"
28 | },
29 | "return_final_only": true,
30 | "llm_kwargs": {},
31 | "_type": "llm_chain"
32 | }
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.11/ModelClass.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Giskard-AI/giskard/6808a562cc1c565e6cf88aeb1fd1f77d28fe76ba/tests/models/fixtures/ipcc/3.11/ModelClass.pkl
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.11/giskard-model-meta.yaml:
--------------------------------------------------------------------------------
1 | classification_labels: null
2 | description: Model that reply foo, bar, baz
3 | feature_names:
4 | - query
5 | id: 9a6c36df-390c-4b13-81de-e7f310a909c0
6 | language: PYTHON
7 | language_version: 3.11.3
8 | loader_class: MyModel
9 | loader_module: __main__
10 | model_type: TEXT_GENERATION
11 | name: Foo
12 | size: 2067
13 | threshold: 0.5
14 |
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.11/giskard-model-wrapper-meta.yaml:
--------------------------------------------------------------------------------
1 | batch_size: null
2 |
--------------------------------------------------------------------------------
/tests/models/fixtures/ipcc/3.11/model.json:
--------------------------------------------------------------------------------
1 | {
2 | "memory": null,
3 | "verbose": false,
4 | "tags": null,
5 | "metadata": null,
6 | "prompt": {
7 | "input_variables": [
8 | "query"
9 | ],
10 | "input_types": {},
11 | "output_parser": null,
12 | "partial_variables": {},
13 | "template": "{query}",
14 | "template_format": "f-string",
15 | "validate_template": false,
16 | "_type": "prompt"
17 | },
18 | "llm": {
19 | "responses": [
20 | "foo",
21 | "bar",
22 | "baz"
23 | ],
24 | "_type": "fake-list"
25 | },
26 | "output_key": "text",
27 | "output_parser": {
28 | "_type": "default"
29 | },
30 | "return_final_only": true,
31 | "llm_kwargs": {},
32 | "_type": "llm_chain"
33 | }
--------------------------------------------------------------------------------
/tests/models/langchain/test_llm_chain.py:
--------------------------------------------------------------------------------
1 | import tempfile
2 |
3 | import pandas as pd
4 | from langchain.chains import LLMChain
5 | from langchain.llms.fake import FakeListLLM
6 | from langchain.prompts import PromptTemplate
7 |
8 | from giskard import Dataset, Model
9 | from giskard.models.langchain import LangchainModel
10 |
11 |
12 | def test_llm_chain():
13 | responses = ["\n\nHueFoots.", "\n\nEcoDrive Motors."]
14 | llm = FakeListLLM(responses=responses)
15 | prompt = PromptTemplate(
16 | input_variables=["product"],
17 | template="What is a good name for a company that makes {product}?",
18 | )
19 | chain = LLMChain(llm=llm, prompt=prompt)
20 |
21 | wrapped_model = Model(
22 | chain, model_type="text_generation", name="test", description="fake", feature_names=["product"]
23 | )
24 |
25 | df = pd.DataFrame(["colorful socks", "electric car"], columns=["product"])
26 |
27 | wrapped_dataset = Dataset(df, cat_columns=[])
28 |
29 | results = wrapped_model.predict(wrapped_dataset)
30 |
31 | assert list(results.raw) == responses[:2], f"{results.raw}"
32 | assert list(results.raw_prediction) == responses[:2]
33 |
34 | with tempfile.TemporaryDirectory() as tmpdirname:
35 | wrapped_model.save(tmpdirname)
36 | loaded_model = LangchainModel.load(tmpdirname)
37 |
38 | assert list(results.raw) == list(loaded_model.predict(wrapped_dataset).raw)
39 |
--------------------------------------------------------------------------------
/tests/models/pytorch/test_dtypes.py:
--------------------------------------------------------------------------------
1 | from typing import get_args
2 |
3 | from giskard.models.pytorch import TorchDType, string_to_torch_dtype
4 |
5 |
6 | def test_dtypes():
7 | for t in get_args(TorchDType):
8 | assert string_to_torch_dtype(t)
9 |
--------------------------------------------------------------------------------
/tests/models/pytorch/test_error.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import pytest
4 | import torch
5 | import torch.nn as nn
6 |
7 | from giskard import Dataset
8 | from giskard.core.model_validation import validate_model
9 | from giskard.models.pytorch import PyTorchModel
10 |
11 |
12 | class ManualLinearRegression(nn.Module):
13 | def __init__(self):
14 | super().__init__()
15 | self.linear = nn.Linear(1, 1)
16 |
17 | def forward(self, x):
18 | return self.linear(x)
19 |
20 |
21 | def test_error():
22 | device = "cuda" if torch.cuda.is_available() else "cpu"
23 |
24 | model = ManualLinearRegression().to(device)
25 |
26 | df = pd.DataFrame({"x": np.array([1]), "y": np.array([2])})
27 |
28 | def preproc_func(df):
29 | return df.values.tolist()
30 |
31 | my_model = PyTorchModel(
32 | name="my_linear_model",
33 | model=model,
34 | feature_names=["x"],
35 | model_type="regression",
36 | data_preprocessing_function=preproc_func,
37 | )
38 |
39 | my_test_dataset = Dataset(df.head(), name="test dataset", target="y")
40 |
41 | with pytest.raises(Exception) as e:
42 | validate_model(my_model, validate_ds=my_test_dataset)
43 | assert e.match(
44 | f"The output of data_preprocessing_function is of type={type(df.values.tolist())}.\n \
45 | Make sure that your data_preprocessing_function outputs one of the following: \n \
46 | - pandas.DataFrame \n \
47 | - torch.Dataset \n \
48 | - torch.DataLoader"
49 | )
50 |
--------------------------------------------------------------------------------
/tests/models/pytorch/test_sst2_pytorch.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from giskard.core.model_validation import validate_model
4 |
5 |
6 | @pytest.mark.memory_expensive
7 | @pytest.mark.skip(reason="Too memory expensive, to be replaced with smaller one")
8 | def test_sst2_pytorch_upload(sst2_model, sst2_data):
9 | validate_model(sst2_model, validate_ds=sst2_data)
10 |
--------------------------------------------------------------------------------
/tests/models/tensorflow/test_tabular_titanic_binary_classification.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from giskard import Dataset
4 | from giskard.core.model_validation import validate_model
5 | from giskard.demo import titanic_classification
6 | from giskard.models.tensorflow import TensorFlowModel
7 |
8 | tf = pytest.importorskip("tensorflow")
9 |
10 |
11 | def test_tabular_titanic_binary_classification():
12 | df = titanic_classification.get_test_df()
13 | preprocess, _ = titanic_classification.get_pipeline()
14 |
15 | input_shape = (preprocess(df).shape[-1],)
16 |
17 | model = tf.keras.models.Sequential(
18 | [
19 | tf.keras.layers.Dense(128, input_shape=input_shape, activation="relu"),
20 | tf.keras.layers.Dropout(0.2),
21 | tf.keras.layers.Dense(2, activation="softmax"),
22 | ]
23 | )
24 |
25 | my_model = TensorFlowModel(
26 | model,
27 | feature_names=df.columns.drop("Survived"),
28 | model_type="classification",
29 | classification_labels=["no", "yes"],
30 | data_preprocessing_function=preprocess,
31 | )
32 |
33 | my_test_dataset = Dataset(df, target="Survived", name="test dataset")
34 |
35 | assert my_model.predict(my_test_dataset)
36 | assert my_model.predict(my_test_dataset).raw.shape == (len(df), 2)
37 |
38 | validate_model(my_model, validate_ds=my_test_dataset)
39 |
--------------------------------------------------------------------------------
/tests/models/test_catboost_wrapper.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from catboost import CatBoostClassifier
4 |
5 | from giskard.models.catboost import CatboostModel
6 |
7 |
8 | def test_catboost_model_detects_feature_names():
9 | df = pd.DataFrame({"feature_1": np.random.normal(size=100), "feature_2": ["cat1"] * 10 + ["cat2"] * 90})
10 | classifier = CatBoostClassifier(cat_features=["feature_2"])
11 | classifier.fit(df, ["target1"] * 90 + ["target2"] * 10)
12 |
13 | model = CatboostModel(
14 | model=classifier,
15 | model_type="classification",
16 | feature_names=None, # we are not passing feature names here
17 | classification_labels=None, # we are not passing labels here
18 | )
19 |
20 | assert model.meta.feature_names == ["feature_1", "feature_2"]
21 | assert model.meta.classification_labels == ["target1", "target2"]
22 |
--------------------------------------------------------------------------------
/tests/models/test_precooked_model.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import pytest
4 |
5 | from giskard import slicing_function
6 | from giskard.models._precooked import PrecookedModel
7 |
8 |
9 | @slicing_function(name="random", row_level=False)
10 | def random_slice(df: pd.DataFrame) -> pd.DataFrame:
11 | return df.sample(100)
12 |
13 |
14 | @pytest.mark.parametrize(
15 | "model,dataset",
16 | [("german_credit_model", "german_credit_data")],
17 | )
18 | def test_precooked_model(model, dataset, request):
19 | model = request.getfixturevalue(model)
20 | dataset = request.getfixturevalue(dataset)
21 | precooked_model = PrecookedModel.from_model(model, dataset)
22 | data_slice = dataset.slice(random_slice())
23 | # assert np.all(data_slice.df.columns == dataset.df.columns)
24 | # assert np.all(precooked_model.predict(dataset).raw == model.predict(dataset).raw)
25 |
26 | assert np.all(precooked_model.predict(data_slice).raw == model.predict(data_slice).raw)
27 |
--------------------------------------------------------------------------------
/tests/models/test_sklearn_wrapper.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import pytest
4 | from sklearn.linear_model import LinearRegression
5 |
6 | from giskard.models.sklearn import SKLearnModel
7 |
8 |
9 | def test_must_provide_feature_names_if_has_preprocessing():
10 | df = pd.DataFrame({"a": np.random.normal(size=100), "b": np.random.normal(size=100)})
11 | reg = LinearRegression()
12 | reg.fit(df, np.ones(100))
13 |
14 | with pytest.raises(ValueError):
15 | SKLearnModel(reg, model_type="regression", data_preprocessing_function=lambda df: df)
16 |
17 | assert SKLearnModel(reg, model_type="regression", feature_names=["test"], data_preprocessing_function=lambda df: df)
18 |
19 |
20 | def test_raises_save_error_if_unknown_model_type():
21 | reg = LinearRegression()
22 | gsk_model = SKLearnModel(reg, model_type="regression")
23 |
24 | with pytest.raises(ValueError):
25 | gsk_model.meta.model_type = "unknown"
26 | gsk_model.save_model("test_path", None)
27 |
--------------------------------------------------------------------------------
/tests/registry/module_utils.py:
--------------------------------------------------------------------------------
1 | from typing import List, Union
2 |
3 | import importlib.util
4 | import os
5 | import sys
6 | import tempfile
7 | from dataclasses import dataclass
8 | from pathlib import Path
9 |
10 |
11 | @dataclass
12 | class PythonFile:
13 | relative_path: Path
14 | content: str
15 |
16 |
17 | @dataclass
18 | class PythonModule:
19 | module_name: str
20 | init_content: str
21 | files: List[PythonFile]
22 |
23 |
24 | def _write_file(dir: Path, file: Union[str, Path], content: str):
25 | os.makedirs(os.path.dirname(dir / file), exist_ok=True)
26 | with open(dir / file, "w", encoding="utf-8") as f:
27 | f.write(content)
28 |
29 |
30 | class TmpModule(object):
31 | def __init__(self, module_def: PythonModule):
32 | self.temp_dir = tempfile.TemporaryDirectory()
33 | self.module_def = module_def
34 |
35 | def __enter__(self):
36 | dir = Path(self.temp_dir.__enter__())
37 |
38 | _write_file(dir, "__init__.py", self.module_def.init_content)
39 | for file_def in self.module_def.files:
40 | _write_file(dir, file_def.relative_path, file_def.content)
41 |
42 | spec = importlib.util.spec_from_file_location(self.module_def.module_name, dir / "__init__.py")
43 | loaded_module = importlib.util.module_from_spec(spec)
44 | sys.modules[self.module_def.module_name] = loaded_module
45 | spec.loader.exec_module(loaded_module)
46 |
47 | return loaded_module
48 |
49 | def __exit__(self, type, value, traceback):
50 | del sys.modules[self.module_def.module_name]
51 | self.temp_dir.__exit__(type, value, traceback)
52 |
--------------------------------------------------------------------------------
/tests/scan/test_data_leakage_detector.py:
--------------------------------------------------------------------------------
1 | from giskard.scanner.data_leakage.data_leakage_detector import DataLeakageDetector
2 | from giskard.scanner.issues import DataLeakage
3 |
4 |
5 | def test_data_leakage_is_detected(enron_data, enron_model):
6 | detector = DataLeakageDetector()
7 | issues = detector.run(enron_model, enron_data)
8 |
9 | # should detect no issue
10 | assert len(issues) == 0
11 |
12 | # Now we add normalization problems
13 | ll = len(enron_data)
14 |
15 | def renormalize_df(df):
16 | numeric_cols = df.select_dtypes("number").columns
17 | df.loc[:, numeric_cols] /= ll / len(df)
18 | return df
19 |
20 | _prev_func = enron_model.data_preprocessing_function
21 | enron_model.data_preprocessing_function = renormalize_df
22 | issues = detector.run(enron_model, enron_data)
23 |
24 | assert len(issues) == 1
25 | assert issues[0].group == DataLeakage
26 |
27 | enron_model.data_preprocessing_function = _prev_func
28 |
29 |
30 | def test_data_leakage_works_on_small_dataset(enron_data, enron_model):
31 | test_data_leakage_is_detected(enron_data.slice(lambda df: df.sample(10), row_level=False), enron_model)
32 |
--------------------------------------------------------------------------------
/tests/scan/test_dataset_subsampling.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 | from giskard import Dataset, Model
5 | from giskard.scanner.common.utils import get_dataset_subsample
6 |
7 |
8 | def test_get_dataset_subsample():
9 | # Create dummy dataset with 20% of samples having label 1, 20% label 2, and the rest label 0
10 | data = {"feature": np.arange(1000), "target": np.zeros(1000)}
11 | data["target"][0:200] = 1
12 | data["target"][200:400] = 2
13 | np.random.shuffle(data["target"])
14 | df = pd.DataFrame(data)
15 | dataset = Dataset(df, target="target")
16 |
17 | # Create dummy model
18 | model = Model(lambda df: np.ones(len(df)), model_type="classification", classification_labels=[0, 1, 2])
19 |
20 | # Test new dataset size
21 | max_data_size = len(dataset) // 10
22 | result = get_dataset_subsample(dataset, model, max_data_size)
23 | assert len(result) == max_data_size
24 |
25 | # For each label, check that the proportion of samples is preserved
26 | label_counts = dataset.df.target.value_counts()
27 | for label in label_counts.index:
28 | assert result.df.target.tolist().count(label) == label_counts[label] // 10
29 |
30 | # Edge case: max size larger than original size (should return the original dataset)
31 | large_max_data_size = len(dataset) * 2
32 | result_large = get_dataset_subsample(dataset, model, large_max_data_size)
33 | assert len(result_large) == len(dataset)
34 |
35 | # Edge case: max size 0 (should return the original dataset)
36 | result_zero = get_dataset_subsample(dataset, model, 0)
37 | assert len(result_zero) == len(dataset)
38 |
--------------------------------------------------------------------------------
/tests/scan/test_detector_registry.py:
--------------------------------------------------------------------------------
1 | from giskard.scanner.decorators import detector
2 | from giskard.scanner.registry import DetectorRegistry
3 |
4 |
5 | def test_detector_registry():
6 | class MyTestDetector:
7 | def run(self, model, dataset, features=None):
8 | return []
9 |
10 | DetectorRegistry.register("test_detector", MyTestDetector, tags=["tag_1", "tag_2", "classification"])
11 |
12 | assert "test_detector" in DetectorRegistry.get_detector_classes().keys()
13 | assert DetectorRegistry.get_detector_classes()["test_detector"] == MyTestDetector
14 | assert DetectorRegistry.get_detector_classes(tags=["tag_1"])["test_detector"] == MyTestDetector
15 | assert "test_detector" not in DetectorRegistry.get_detector_classes(tags=["regression"]).keys()
16 |
17 |
18 | def test_detector_decorator():
19 | @detector
20 | class MyDecoratedDetector:
21 | def run(self, model, dataset):
22 | return []
23 |
24 | assert "my_decorated_detector" in DetectorRegistry.get_detector_classes().keys()
25 |
26 | @detector(name="other_detector", tags=["tag_1", "tag_2"])
27 | class MyOtherDecoratedDetector:
28 | def run(self, model, dataset):
29 | return []
30 |
31 | assert "other_detector" in DetectorRegistry.get_detector_classes().keys()
32 | assert "other_detector" in DetectorRegistry.get_detector_classes(tags=["tag_2"]).keys()
33 | assert "other_detector" not in DetectorRegistry.get_detector_classes(tags=["regression"]).keys()
34 |
--------------------------------------------------------------------------------
/tests/scan/test_suite_generation.py:
--------------------------------------------------------------------------------
1 | from giskard import slicing_function
2 | from giskard.core.suite import Suite
3 | from giskard.scanner.issues import Issue, IssueLevel, Performance
4 | from giskard.scanner.performance.metrics import Accuracy, MetricResult
5 | from giskard.scanner.performance.performance_bias_detector import _generate_performance_tests
6 | from giskard.scanner.report import ScanReport
7 |
8 |
9 | def test_generate_test_suite_from_scan_result(german_credit_data, german_credit_model):
10 | @slicing_function
11 | def slice_fn(x):
12 | return True
13 |
14 | issues = [
15 | Issue(
16 | model=german_credit_model,
17 | dataset=german_credit_data,
18 | group=Performance,
19 | level=IssueLevel.MAJOR,
20 | description="Description",
21 | meta={
22 | "metric": "Accuracy",
23 | "metric_value": 0.2,
24 | "metric_reference_value": 1.0,
25 | "slice_metric": MetricResult(Accuracy(), 0.2, 100),
26 | "reference_metric": MetricResult(Accuracy(), 1, 100),
27 | "threshold": 0.95,
28 | "p_value": 1e-6,
29 | },
30 | slicing_fn=slice_fn,
31 | tests=_generate_performance_tests,
32 | )
33 | ]
34 |
35 | result = ScanReport(issues, model=german_credit_model, dataset=german_credit_data)
36 | test_suite = result.generate_test_suite("Custom name")
37 |
38 | assert isinstance(test_suite, Suite)
39 | assert test_suite.name == "Custom name"
40 | assert len(test_suite.tests) == 1
41 |
42 | test_suite.run()
43 |
--------------------------------------------------------------------------------
/tests/slicing/test_slicing_function.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 | from giskard import slicing_function
5 |
6 |
7 | def test_slicing_function(german_credit_data):
8 | # Define a slicing function
9 | @slicing_function(row_level=False)
10 | def head_slice(df: pd.DataFrame) -> pd.DataFrame:
11 | return df.head(10)
12 |
13 | # Slice the dataset
14 | data_slice = german_credit_data.slice(head_slice)
15 |
16 | assert np.all(data_slice.df.values == german_credit_data.df.head(10).values)
17 |
--------------------------------------------------------------------------------
/tests/test_import_giskard.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | from time import time
3 |
4 | # As of 17.01.2024. The import of giskard takes about 2.5-3 seconds on a 2021 MacBook Pro.
5 | IMPORT_TIME_THRESHOLD_SECOND = 7
6 |
7 |
8 | def test_import_giskard():
9 | start = time()
10 |
11 | # Start subprocess to ensure that giskard is not already imported
12 | # Average of 10 imports to avoid random issues
13 | for _ in range(10):
14 | subprocess.run(["python", "-c", "import giskard"])
15 |
16 | end = time()
17 | assert (
18 | end - start
19 | ) / 10 < IMPORT_TIME_THRESHOLD_SECOND, f"Import of Giskard took {(end - start) / 10} seconds on average (maximum threshold is set to {IMPORT_TIME_THRESHOLD_SECOND} second)"
20 |
--------------------------------------------------------------------------------
/tests/test_settings.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pathlib import Path
3 |
4 | from giskard.settings import Settings
5 |
6 |
7 | def test_default_obj_equals_static_built():
8 | assert Settings(disable_analytics=os.getenv("GSK_DISABLE_ANALYTICS", "false")) == Settings.build_from_env()
9 |
10 |
11 | def test_override_env():
12 | os.environ["GSK_DISABLE_ANALYTICS"] = "true"
13 | os.environ["GSK_WS_PORT"] = "4444"
14 | os.environ["GSK_HOST"] = "toto"
15 |
16 | settings = Settings.build_from_env()
17 | assert settings.disable_analytics
18 | assert settings.ws_port == 4444
19 | assert settings.host == "toto"
20 |
21 |
22 | def test_expand_path():
23 | os.environ["ENV1"] = "~/toto/../${ENV2}"
24 | os.environ["ENV2"] = "${ENV3}/${ENV4}"
25 | os.environ["ENV3"] = "tutu"
26 | os.environ["ENV4"] = "tata"
27 |
28 | settings = Settings(home="${ENV1}")
29 | print(settings.home_dir.as_posix())
30 | assert settings.home_dir.as_posix() == (Path("~").expanduser().resolve() / "tutu/tata").as_posix()
31 |
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | from numpy.testing import assert_array_equal
2 |
3 | from giskard.utils.analytics_collector import anonymize
4 |
5 |
6 | def test_anonymize_simple():
7 | assert anonymize("clear text") == "3ede875cc56517b8"
8 | assert anonymize(123) == "40bd001563085fc3"
9 | assert anonymize(1.23) == "1ee00eff570301a5"
10 | assert anonymize(None) is None
11 |
12 |
13 | def test_anonymize_complex():
14 | assert_array_equal(anonymize(["hello", "world"]), ["aaf4c61ddcc5e8a2", "7c211433f0207159"])
15 |
--------------------------------------------------------------------------------
/tests/testing/test_side_effects.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 |
4 | from giskard import Dataset
5 | from giskard.testing import test_accuracy
6 |
7 |
8 | def test_dataset_index_is_preserved(german_credit_data, german_credit_model):
9 | dataset = german_credit_data
10 | model = german_credit_model
11 |
12 | # Permute the index to make it non banal, otherwise reset_index will produce,
13 | # by change, the same sequence.
14 | dataset.df.set_index(dataset.df.index.values[np.random.permutation(len(dataset.df))], inplace=True)
15 | original_idx = dataset.df.index.copy()
16 |
17 | _ = test_accuracy(dataset=dataset, model=model, threshold=0.8).execute()
18 |
19 | assert (dataset.df.index == original_idx).all()
20 |
21 | # Try with an index that is not a sequence of integers
22 | dataset = Dataset(
23 | dataset.df.set_index(pd.to_datetime(dataset.df.index)), column_types=dataset.column_types, target=dataset.target
24 | )
25 | original_idx = dataset.df.index.copy()
26 |
27 | _ = test_accuracy(dataset=dataset, model=model, threshold=0.8).execute()
28 |
29 | assert (dataset.df.index == original_idx).all()
30 |
--------------------------------------------------------------------------------
/tests/url_utils.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from urllib.request import urlretrieve
3 |
4 |
5 | def fetch_test_data(url: str, file: Path) -> None:
6 | if not file.parent.exists():
7 | file.parent.mkdir(parents=True, exist_ok=True)
8 |
9 | if not file.exists():
10 | urlretrieve(url, file)
11 |
--------------------------------------------------------------------------------
/tests/utils/test_logging_utils.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | import giskard
4 |
5 |
6 | def test_giskard_log_level():
7 | assert (
8 | logging.getLogger(giskard.__name__).level == logging.INFO
9 | ), "giskard log level should be set to INFO when importing giskard"
10 |
11 |
12 | def test_other_package_log_level_unset():
13 | assert (
14 | logging.getLogger(giskard.llm.client.__name__).level == logging.NOTSET
15 | ), "Non giskard package log level should't be touched by giskard (NOTSET)"
16 |
17 |
18 | def test_root_log_level_default_warning():
19 | assert logging.getLogger().level == logging.WARNING, "Root package log level should be set to WARNING by default"
20 |
--------------------------------------------------------------------------------