Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add report tags #643

Merged
merged 3 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/evidently/experimental/report_set.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import os
import uuid
from collections import defaultdict
from typing import Dict
from typing import List
Expand All @@ -24,15 +25,15 @@ def load_metric_report_set(
reports = load_report_set(path, Report, date_from, date_to)
result: Dict[Metric, Dict[datetime.datetime, MetricResult]] = defaultdict(dict)
if metrics is None:
for timestamp, report in reports.items():
for _, report in reports.items():
for metric in report._first_level_metrics:
result[metric][timestamp] = metric.get_result()
result[metric][report.timestamp] = metric.get_result()
return result
for metric in metrics:
for timestamp, report in reports.items():
for _, report in reports.items():
if metric in report._first_level_metrics:
metric.set_context(report._inner_suite.context)
result[metric][timestamp] = metric.get_result()
result[metric][report.timestamp] = metric.get_result()
return result


Expand All @@ -45,7 +46,7 @@ def load_report_set(
date_from: Optional[datetime.datetime] = None,
date_to: Optional[datetime.datetime] = None,
skip_errors: bool = False,
) -> Dict[datetime.datetime, T]:
) -> Dict[uuid.UUID, T]:
result = {}
for file in os.listdir(path):
filepath = os.path.join(path, file)
Expand All @@ -59,5 +60,5 @@ def load_report_set(
continue
if date_to is not None and suite.timestamp > date_to:
continue
result[suite.timestamp] = suite
result[suite.id] = suite
return result
8 changes: 5 additions & 3 deletions src/evidently/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ class Report(Display):
_inner_suite: Suite
_columns_info: DatasetColumns
_first_level_metrics: List[Union[Metric]]
id: uuid.UUID
metrics: List[Union[Metric, MetricPreset, BaseGenerator]]
metadata: Dict[str, str] = {}

def __init__(
self,
Expand All @@ -46,6 +44,7 @@ def __init__(
timestamp: Optional[datetime.datetime] = None,
id: uuid.UUID = None,
metadata: Dict[str, str] = None,
tags: List[str] = None,
):
super().__init__(options, timestamp)
# just save all metrics and metric presets
Expand All @@ -54,6 +53,7 @@ def __init__(
self._first_level_metrics = []
self.id = id or uuid.uuid4()
self.metadata = metadata or {}
self.tags = tags or []

def run(
self,
Expand Down Expand Up @@ -210,6 +210,7 @@ def _get_payload(self) -> BaseModel:
metrics_ids=[suite.metrics.index(m) for m in self._first_level_metrics],
timestamp=self.timestamp,
metadata=self.metadata,
tags=self.tags,
)

@classmethod
Expand All @@ -223,11 +224,12 @@ class _ReportPayload(BaseModel):
metrics_ids: List[int]
timestamp: datetime.datetime
metadata: Dict[str, str]
tags: List[str]

def load(self):
ctx = self.suite.to_context()
metrics = [ctx.metrics[i] for i in self.metrics_ids]
report = Report(metrics=metrics, timestamp=self.timestamp, id=self.id, metadata=self.metadata)
report = Report(metrics=metrics, timestamp=self.timestamp, id=self.id, metadata=self.metadata, tags=self.tags)
report._first_level_metrics = metrics
report._inner_suite.context = ctx

Expand Down
4 changes: 4 additions & 0 deletions src/evidently/suite/base_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dataclasses
import json
import logging
import uuid
from datetime import datetime
from typing import Dict
from typing import Iterator
Expand Down Expand Up @@ -148,7 +149,10 @@ class ExecutionError(Exception):
class Display:
# collection of all possible common options
options: Options
id: uuid.UUID
timestamp: datetime
metadata: Dict[str, str] = {}
tags: List[str] = []

def __init__(self, options: AnyOptions = None, timestamp: Optional[datetime] = None):
self.options = Options.from_any_options(options)
Expand Down
8 changes: 7 additions & 1 deletion src/evidently_service/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import datetime
import json
import uuid
from contextlib import asynccontextmanager
from typing import Annotated
from typing import List
from typing import Optional

import uvicorn
from fastapi import APIRouter
Expand Down Expand Up @@ -156,13 +158,17 @@ async def list_project_dashboard_panels(
@api_router.get("/projects/{project_id}/dashboard")
async def project_dashboard(
project_id: Annotated[uuid.UUID, PROJECT_ID],
timestamp_start: Optional[datetime.datetime] = None,
timestamp_end: Optional[datetime.datetime] = None,
) -> Response:
workspace: Workspace = app.state.workspace
project = workspace.get_project(project_id)
if project is None:
raise HTTPException(status_code=404, detail="Project not found")

info = DashboardInfoModel.from_dashboard_info(project.build_dashboard_info())
info = DashboardInfoModel.from_dashboard_info(
project.build_dashboard_info(timestamp_start=timestamp_start, timestamp_end=timestamp_end)
)
# todo: add numpy encoder to fastapi
# return info
json_str = json.dumps(info.dict(), cls=NumpyEncoder).encode("utf-8")
Expand Down
5 changes: 4 additions & 1 deletion src/evidently_service/dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@

class ReportFilter(BaseModel):
metadata_values: Dict[str, str]
tag_values: List[str]

def filter(self, report: Report):
return all(report.metadata.get(key) == value for key, value in self.metadata_values.items())
return all(report.metadata.get(key) == value for key, value in self.metadata_values.items()) and all(
tag in report.tags for tag in self.tag_values
)


class PanelValue(BaseModel):
Expand Down
15 changes: 9 additions & 6 deletions src/evidently_service/generate_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
adult_cur.iloc[:2000, 3:5] = np.nan


def create_report(metric, date: datetime.datetime):
data_drift_report = Report(metrics=[metric], metadata={"type": metric.__class__.__name__}, timestamp=date)
def create_report(metric, date: datetime.datetime, tag: str):
data_drift_report = Report(
metrics=[metric], metadata={"type": metric.__class__.__name__}, tags=[tag], timestamp=date
)

data_drift_report.run(reference_data=adult_ref, current_data=adult_cur)
data_drift_report._save(f"workspace/project1/reports/{uuid.uuid4()}")
Expand All @@ -54,17 +56,17 @@ def create_project_config():
name="sample_dashboard",
panels=[
DashboardPanelCounter(
filter=ReportFilter(metadata_values={}), agg=CounterAgg.NONE, title="My beatifule panels"
filter=ReportFilter(metadata_values={}, tag_values=["drift"]), agg=CounterAgg.NONE, title="My beatifule panels"
),
DashboardPanelCounter(
filter=ReportFilter(metadata_values={"type": "DataDriftPreset"}),
filter=ReportFilter(metadata_values={"type": "DataDriftPreset"}, tag_values=["drift"]),
agg=CounterAgg.SUM,
value=PanelValue(metric_id="DatasetDriftMetric", field_path="number_of_columns"),
title="sum of number_of_columns",
),
DashboardPanelPlot(
title="sample_panel",
filter=ReportFilter(metadata_values={"type": "DataDriftPreset"}),
filter=ReportFilter(metadata_values={"type": "DataDriftPreset"}, tag_values=["drift"]),
values=[
PanelValue(metric_id="DatasetDriftMetric", field_path="share_of_drifted_columns", legend="Share"),
PanelValue(metric_id="DatasetDriftMetric", field_path="number_of_drifted_columns", legend="Count"),
Expand Down Expand Up @@ -93,8 +95,9 @@ def main():
num_stattest="ks", cat_stattest="psi", num_stattest_threshold=0.2, cat_stattest_threshold=0.2
),
ts,
"drift",
)
create_report(DatasetCorrelationsMetric(), ts)
create_report(DatasetCorrelationsMetric(), ts, "correlation")

create_test_suite()

Expand Down
12 changes: 10 additions & 2 deletions src/evidently_service/workspace.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import json
import os
import uuid
Expand Down Expand Up @@ -83,9 +84,16 @@ def get_item(self, report_id: uuid.UUID) -> Optional[ProjectItem]:
return None
return self._items.get(item.id)

def build_dashboard_info(self) -> DashboardInfo:
def build_dashboard_info(
self, timestamp_start: Optional[datetime.datetime], timestamp_end: Optional[datetime.datetime]
) -> DashboardInfo:
self.reload()
return self.dashboard.build_dashboard_info(self.reports.values())
return self.dashboard.build_dashboard_info(
r
for r in self.reports.values()
if (timestamp_start is None or r.timestamp >= timestamp_start)
and (timestamp_end is None or r.timestamp < timestamp_end)
)


class Workspace:
Expand Down