Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
b0a277e
update: add dependency
dalestee May 4, 2026
5792aae
update: add import
dalestee May 4, 2026
3e60b95
fix: pandas object
dalestee May 4, 2026
5221565
dev: first demo
dalestee May 5, 2026
eeff637
delete: remove legacy
dalestee May 7, 2026
02667c8
change name
dalestee May 7, 2026
3e23d33
re organized code
dalestee May 7, 2026
701dde8
create test
dalestee May 7, 2026
48d9218
move to correct place
dalestee May 7, 2026
d1e2c3c
ruff mod
dalestee May 7, 2026
0b28917
adding docstring
dalestee May 7, 2026
e66f450
using bokeh instead of ploty
dalestee May 7, 2026
49e0ec4
Revert "using bokeh instead of ploty"
dalestee May 7, 2026
a2b9ea2
v2 report working
dalestee May 11, 2026
ffef9fd
ruff mod
dalestee May 11, 2026
b050feb
removing unecessary files and adding blocks
dalestee May 11, 2026
e8a6854
default report good
dalestee May 11, 2026
cc25d35
ruff mod
dalestee May 11, 2026
7f9ba24
stable version
dalestee May 13, 2026
5dc14f9
refactoring
dalestee May 13, 2026
32b937b
ruff
dalestee May 13, 2026
e39629e
fix test
dalestee May 13, 2026
abab2f2
update: change logo and update color sheme
dalestee May 19, 2026
fa07dc6
add: more detailled documentation in blocks
dalestee May 19, 2026
622196a
add: change the notebook for tutorial
dalestee May 19, 2026
c4ab917
add: change tutorial
dalestee May 20, 2026
88e2baf
delete: remove legacy code
dalestee May 21, 2026
04cf41c
add: responsivenes
dalestee May 27, 2026
99a4abd
delete: removing old files and functions
dalestee May 29, 2026
987b030
BIG MODS: refactoring and using pane now
dalestee Jun 2, 2026
6dd73a7
nav bar
dalestee Jun 3, 2026
e0d69f2
ruff mods and docstring
dalestee Jun 3, 2026
59d0f0a
del: removing color
dalestee Jun 3, 2026
da51c4f
indicator and other additions
dalestee Jun 4, 2026
79705ad
ruff
dalestee Jun 4, 2026
e9ec087
update: améliorer lisibilité
dalestee Jun 8, 2026
d14950c
fix: fixing test error missing yaml
dalestee Jun 8, 2026
2afbf8b
add: adding logo on the top left
dalestee Jun 9, 2026
1a612c6
format: ruff
dalestee Jun 9, 2026
47caec5
verification: check if objects returned by blocks are correct
dalestee Jun 9, 2026
09610d4
remove: runtime
dalestee Jun 9, 2026
531b112
add: example with more detailed plots
dalestee Jun 10, 2026
683c131
add: complete tutorials
dalestee Jun 10, 2026
78c3fff
update: keep only usefull dependencies
dalestee Jun 17, 2026
12316cd
remove: delete unused parameters
dalestee Jun 17, 2026
779baf4
update: improve code readability
dalestee Jun 17, 2026
5a1f19a
readability: add typings
dalestee Jun 17, 2026
8df4563
refactor: put block render inside block mixin
dalestee Jun 18, 2026
5d50030
remove: remove unused arguments + removing edge case
dalestee Jun 18, 2026
21f1281
refactor: fuse css supporters
dalestee Jun 18, 2026
49722ca
add: custom css path can be configured in yaml
dalestee Jun 18, 2026
863cf04
style: changing the header of the tables
dalestee Jun 18, 2026
0f5a300
ruff
dalestee Jun 18, 2026
7fcaab6
refactor: make_plotly_pane inside decorator
dalestee Jun 18, 2026
a97abad
fix: pyarrow free test pkl
guerinclement Jul 1, 2026
6f66480
chore: remove obsolete test
guerinclement Jul 1, 2026
ce78bb5
chore: clean generate_report
guerinclement Jul 1, 2026
d1a1b00
chore: remove unused check
guerinclement Jul 1, 2026
c36f594
chore: move assets
guerinclement Jul 1, 2026
fc4327d
fix: tests
guerinclement Jul 1, 2026
fb8347a
feat: adds report yml export function
guerinclement Aug 26, 2026
47c05a2
fix: move support functions to appropriate modules
guerinclement Aug 26, 2026
e01f064
feat: handle list of tuples in block decorator
guerinclement Aug 26, 2026
7275d83
fix: type checker
guerinclement Aug 26, 2026
eeba52b
fix: imports and typing
guerinclement Aug 28, 2026
da1ec43
chore: phik dependency
guerinclement Aug 28, 2026
65eb365
chore: clean report examples + Tabular widget support
guerinclement Aug 28, 2026
2586606
feat: Tabulator on df.cols > 10
guerinclement Aug 28, 2026
decb96a
fix: correct usage of block decorator
guerinclement Aug 28, 2026
9b691c4
fix: contribution plot stretch_width
guerinclement Aug 31, 2026
4effdc3
feat: block_text accept dict
guerinclement Aug 31, 2026
6889f9e
fix: enable classification template
guerinclement Aug 31, 2026
cd0a24e
feat: top_interaction_plot in report
guerinclement Sep 1, 2026
e032faf
doc: update report tutorial
guerinclement Sep 2, 2026
1eb3c83
feat: utf-8 export
guerinclement Sep 4, 2026
7cbebfa
Merge branch 'develop' into feature/report
guerinclement Sep 4, 2026
677a0fa
chore: revert plot changes
guerinclement Sep 4, 2026
d4eb6ff
doc: fix
guerinclement Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
recursive-include shapash/webapp/assets *
recursive-include shapash/report/html *
recursive-include shapash/report/template *

include LICENSE
include README.md
include shapash/report/base_report.ipynb
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ app = xpl.run_app()
[Live Demo Shapash-Monitor](https://shapash-demo.ossbymaif.fr/)

- Step 4: Generate the Shapash Report
> This step allows to generate a standalone html report of your project using the different splits
of your dataset and also the metrics you used:
> This step generates a standalone HTML report from a block-based layout.
You can optionally provide a YAML file to customize report sections and blocks.

```python
xpl.generate_report(
Expand All @@ -208,6 +208,7 @@ xpl.generate_report(
x_train=xtrain,
y_train=ytrain,
y_test=ytest,
yaml_path="path/to/report_config.yml", # Optional: custom block configuration
title_story="House prices report",
title_description="""This document is a data science report of the kaggle house prices tutorial project.
It was generated using the Shapash library.""",
Expand Down
Binary file added docs/assets/images/logos/shapash-fond-clair.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 3 additions & 6 deletions docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ The 4 steps to display results:
app = xpl.run_app()

- Step 4: Generate the Shapash Report
> This step allows to generate a standalone html report of your project using the different splits
of your dataset and also the metrics you used:
> This step generates a standalone HTML report from a configurable block-based layout.
> You can provide a YAML configuration file to customize sections and blocks.

.. code:: ipython

Expand All @@ -101,10 +101,7 @@ The 4 steps to display results:
x_train=Xtrain,
y_train=ytrain,
y_test=ytest,
title_story="House prices report",
title_description="""This document is a data science report of the kaggle house prices tutorial project.
It was generated using the Shapash library.""",
metrics=[{'name': 'MSE', 'path': 'sklearn.metrics.mean_squared_error'}]
yaml_path='path/to/report_config.yml', # Optional: custom block configuration
)

- Step 5: From training to deployment : SmartPredictor Object
Expand Down
10 changes: 3 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies = [
"numpy>=2.0.0",
# 3.0.4 yanked upstream: segfaults in datetime ops (pandas #66083)
"pandas>=2.2.2,!=3.0.4,<4.0.0",
"phik>=0.12.4",
"plotly>=5.0.0,<6.0.0",
"scikit-learn>=1.8.0,<1.9.0",
"scipy>=1.13.0",
Expand All @@ -51,13 +52,8 @@ dependencies = [

[project.optional-dependencies] # Optional
report = [
"Jinja2>=3.1.0",
"jupyter-client>=8.3.0",
"nbconvert>=7.2.0",
"notebook>=7.0.0",
"papermill>=2.5.0",
"phik>=0.12.4",
"pyarrow>=17.0.0",
"panel>=1.8.10",

]
xgboost = ["xgboost>=2.1.0"]
catboost = ["catboost>=1.2.8"]
Expand Down
157 changes: 62 additions & 95 deletions shapash/explainer/smart_explainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

import copy
import logging
import shutil
import tempfile
from pathlib import Path
from typing import Any

import numpy as np
Expand All @@ -17,7 +16,6 @@
from shapash.backend.shap_backend import get_shap_interaction_values
from shapash.manipulation.select_lines import keep_right_contributions
from shapash.manipulation.summarize import create_grouped_features_values
from shapash.report import check_report_requirements
from shapash.style.style_utils import colors_loading, select_palette
from shapash.utils.check import (
check_additional_data,
Expand All @@ -36,6 +34,14 @@
from shapash.utils.utils import get_host_name
from shapash.webapp.smart_app import SmartApp

try:
from shapash.report import ReportTemplate
from shapash.report.blocks import ReportBlockMixin
from shapash.report.core import generate_report as generate_smart_report
except ImportError:
# [report] optional dependencies may not be installed
...

from .smart_plotter import SmartPlotter

logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -1654,74 +1660,44 @@ def check_x_y_attributes(self, x_str, y_str):

def generate_report(
self,
output_file,
project_info_file,
x_train=None,
y_train=None,
y_test=None,
title_story=None,
title_description=None,
metrics=None,
working_dir=None,
notebook_path=None,
kernel_name=None,
max_points=200,
display_interaction_plot=False,
nb_top_interactions=5,
):
output_file: str,
x_train: pd.DataFrame | None = None,
y_train: pd.Series | pd.DataFrame | list | None = None,
y_test: pd.Series | pd.DataFrame | list | None = None,
yaml_path: str | Path | None = None,
max_points: int = 200,
block_instance: ReportBlockMixin | None = None,
) -> None:
"""
Generate an interactive HTML report summarizing the model and its explainability.

This method produces a comprehensive HTML report containing visual and textual
insights about the project, dataset, and model performance.
It leverages a predefined or custom Jupyter notebook template to analyze
the model, generate plots, compute metrics, and export the final report.
insights about the project, dataset, and model performance using the
smart_report block-based HTML renderer.

A project information YAML file is required to describe key project details
(e.g., model name, author, date, context).
A report configuration is provided through a YAML file. If no YAML file is
specified, a default configuration is generated automatically.

Parameters
----------
output_file : str
Path to the output HTML file where the report will be saved.
project_info_file : str
Path to a YAML file containing project metadata to be displayed in the report
(e.g., project name, author, date, description).
x_train : pandas.DataFrame, optional
Training dataset used to fit the model.
Used for generating feature summaries and training-related analyses.
y_train : pandas.Series or pandas.DataFrame, optional
Target values corresponding to `x_train`.
y_test : pandas.Series or pandas.DataFrame, optional
Target values for the test dataset.
title_story : str, optional
Title displayed at the top of the report.
title_description : str, optional
Short descriptive text displayed below the main title.
metrics : list of dict, optional
List of metrics to compute and display in the performance section.
Each dictionary should include:
- `'path'`: str — import path to the metric function (e.g., `"sklearn.metrics.f1_score"`)
- `'name'`: str, optional — display name for the metric
- `'use_proba_values'`: bool, optional — if True, use predicted probabilities instead of labels
Example:
`metrics=[{'name': 'F1 score', 'path': 'sklearn.metrics.f1_score'}]`
working_dir : str, optional
Directory used to temporarily store generated files (e.g., notebook, outputs).
If `None`, a temporary directory is automatically created and deleted after report generation.
notebook_path : str, optional
Path to a custom notebook used as a template for generating the report.
If `None`, the default Shapash report notebook is used.
kernel_name : str, optional
Name of the Jupyter kernel to use for report execution.
Useful when multiple kernels are available and the default one is incorrect.
yaml_path : str, optional
Path to a custom YAML configuration file used to generate the report.
If `None`, a default YAML configuration is generated.
max_points : int, optional, default=200
Maximum number of points displayed in contribution plots.
display_interaction_plot : bool, optional, default=False
If True, includes interaction plots in the report.
(Note: this can increase computation time.)
nb_top_interactions : int, optional, default=5
Number of top feature interactions to include in the report.
block_instance : object, optional
Optional custom block runtime used to resolve block methods during report generation.
The instance must already be fully initialized by the user and should implement
methods named `block_<type>` for YAML block entries.

Returns
-------
Expand All @@ -1737,77 +1713,68 @@ def generate_report(

Notes
-----
- The method internally executes a notebook that generates the report content.
- The method renders the report from block definitions in a YAML configuration.
- Temporary files are automatically cleaned up unless a custom `working_dir` is provided.
- Interaction plots can be disabled to optimize runtime performance.

Example
-------
>>> xpl.generate_report(
... output_file="report.html",
... project_info_file="utils/project_info.yml",
... x_train=x_train,
... y_train=y_train,
... y_test=y_test,
... title_story="House Prices Project Report",
... title_description="Comprehensive interpretability analysis for the Kaggle house prices dataset.",
... metrics=[
... {"path": "sklearn.metrics.mean_squared_error", "name": "Mean Squared Error"},
... {"path": "sklearn.metrics.mean_absolute_error", "name": "Mean Absolute Error"},
... ],
... display_interaction_plot=True,
... nb_top_interactions=5,
... )
"""
check_report_requirements()
if x_train is not None:
x_train = handle_categorical_missing(x_train)
# Avoid Import Errors with requirements specific to the Shapash Report
from shapash.report.generation import execute_report, export_and_save_report # noqa: PLC0415

rm_working_dir = False
if not working_dir:
working_dir = tempfile.mkdtemp()
rm_working_dir = True

# input checks
if not hasattr(self, "model"):
raise AssertionError(
"Explainer object was not compiled. Please compile the explainer "
"object using .compile(...) method before generating the report."
)

try:
execute_report(
working_dir=working_dir,
if block_instance is not None:
if (x_train is not None) and (block_instance.x_train_init is not x_train):
logging.warning("block_instance's x_train is different from provided x_train. Latter is ignored.")
if (y_train is not None) and (block_instance.y_train is not y_train):
logging.warning("block_instance's y_train is different from provided y_train. Latter is ignored.")
if (y_test is not None) and (block_instance.y_test is not y_test):
logging.warning("block_instance's y_test is different from provided y_test. Latter is ignored.")
if max_points != block_instance.max_points:
logging.warning("block_instance's max_points is different from provided max_points. Latter is ignored.")

report_runtime = block_instance

else:
if x_train is not None:
x_train = handle_categorical_missing(x_train)

report_runtime = ReportBlockMixin(
explainer=self,
project_info_file=project_info_file,
x_train=x_train,
y_train=y_train,
y_test=y_test,
config={
k: v
for k, v in dict(
title_story=title_story,
title_description=title_description,
metrics=metrics,
max_points=max_points,
display_interaction_plot=display_interaction_plot,
nb_top_interactions=nb_top_interactions,
).items()
if v is not None
},
notebook_path=notebook_path,
kernel_name=kernel_name,
max_points=max_points,
)
export_and_save_report(working_dir=working_dir, output_file=output_file)
if self._case == "classification":
default_report = ReportTemplate.DEFAULT_CLASSIFICATION
else:
default_report = ReportTemplate.DEFAULT_REGRESSION

if rm_working_dir:
shutil.rmtree(working_dir)
config_file = (
Path(yaml_path)
if yaml_path is not None
else Path(__file__).resolve().parent.parent / "report" / "assets" / str(default_report)
)

except Exception as e:
if rm_working_dir:
shutil.rmtree(working_dir)
raise e
generate_smart_report(
runtime=report_runtime,
config_file=config_file,
output_file=output_file,
)

def _local_pred(self, index, label=None):
"""
Expand Down
21 changes: 2 additions & 19 deletions shapash/report/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
import importlib
from .common import ReportTemplate, export_report_yml

# This list should be identical to the list in setup.py
report_requirements = ["nbconvert==6.0.7", "papermill", "matplotlib", "notebook", "Jinja2"]


def check_report_requirements():
"""
Checks that all required packages for the report are installed.
This function should be called before executing the report.
"""
for req in report_requirements:
pkg = req.split("=")[0]
try:
importlib.import_module(pkg.lower())
except ImportError as err:
raise ModuleNotFoundError(
f"The following package is necessary to generate the Shapash Report : {pkg}. "
f"Try 'pip install shapash[report]' to install all required packages."
) from err
__all__ = ["ReportTemplate", "export_report_yml"]
Loading