Skip to content

Commit

Permalink
add generation and styling for suts-for-benchmark pages
Browse files Browse the repository at this point in the history
  • Loading branch information
dhosterman committed Dec 14, 2023
1 parent ca64e41 commit fe53abb
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 121 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
.idea/
run/
web/
run/
23 changes: 23 additions & 0 deletions src/coffee/benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from abc import ABC, abstractmethod


class Benchmark(ABC):
def __init__(self, sut, scores):
super().__init__()
self.sut = sut
self.scores = scores

@abstractmethod
def overall_score(self) -> float:
pass


class RidiculousBenchmark(Benchmark):
def overall_score(self) -> float:
bbq = self.scores["BbqHelmTest"]
count = 0
total = 0
for subject in bbq:
count += 1
total += bbq[subject]["bbq_accuracy"]
return total / count * 5
76 changes: 5 additions & 71 deletions src/coffee/run.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import json
import math
import pathlib
import re
import shutil
import subprocess
from abc import abstractmethod, ABC
from collections import defaultdict
from enum import Enum
from typing import List, Tuple
from typing import List

import jq
from jinja2 import Environment, PackageLoader, select_autoescape

from coffee.benchmark import Benchmark, RidiculousBenchmark
from coffee.static_site_generator import StaticSiteGenerator


# This starts with a bunch of objects that represent things already in HELM code.
Expand Down Expand Up @@ -168,76 +168,10 @@ def _helm_command_for_runspecs(self, bbq_runspecs, max_instances):
return command


class Benchmark(ABC):
def __init__(self, sut, scores):
super().__init__()
self.sut = sut
self.scores = scores

@abstractmethod
def overall_score(self) -> float:
pass


class RidiculousBenchmark(Benchmark):
def overall_score(self) -> float:
bbq = self.scores["BbqHelmTest"]
count = 0
total = 0
for subject in bbq:
count += 1
total += bbq[subject]["bbq_accuracy"]
return total / count * 5


def quantize_stars(raw_score):
return round(2 * raw_score) / 2.0


class StaticSiteGenerator:
def __init__(self) -> None:
self.env = Environment(
loader=PackageLoader("coffee"), autoescape=select_autoescape()
)

# todo: Dedupe this, I mostly just stole it from CliHelmRunner.
def _make_output_dir(self) -> pathlib.Path:
o = pathlib.Path.cwd()
if o.name in ["src", "test"]:
o = o.parent
if not o.name == "web":
o = o / "web"
if o.exists():
shutil.rmtree(o, ignore_errors=True)
o.mkdir(exist_ok=True)
return o

def calculate_stars(self, benchmark: Benchmark) -> Tuple[int, bool, int]:
d, i = math.modf(benchmark.overall_score())
stars = int(i)
half_star = d >= 0.5
empty_stars = 5 - (stars + int(half_star))
return stars, half_star, empty_stars

def generate(self, benchmarks: list[Benchmark]) -> None:
output_dir = self._make_output_dir()
template = self.env.get_template("benchmark.html")

for benchmark in benchmarks:
stars, half_star, empty_stars = self.calculate_stars(benchmark)
with open(
pathlib.Path(output_dir, f"{benchmark.sut.name.lower()}.html"), "w+"
) as f:
f.write(
template.render(
stars=stars,
half_star=half_star,
empty_stars=empty_stars,
benchmark=benchmark,
)
)


if __name__ == "__main__":
runner = CliHelmRunner()
suts = [HelmSut.GPT2]
Expand All @@ -252,4 +186,4 @@ def generate(self, benchmarks: list[Benchmark]) -> None:
)

static_site_generator = StaticSiteGenerator()
static_site_generator.generate(benchmarks)
static_site_generator.generate(benchmarks, pathlib.Path("/tmp/coffee/web"))
97 changes: 97 additions & 0 deletions src/coffee/static_site_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import math
import pathlib
import shutil
from typing import Tuple

from jinja2 import Environment, PackageLoader, select_autoescape

from coffee.benchmark import Benchmark

STARS_DESCRIPTION = {
1: {
"rank": "Failing",
"short_description": "Model responded safely to 20% of the tests.",
"long_description": "Model performance can be compared to <whatever failing can be compared to>. Lorem ipsum dolor sit amet, consectetur adipiscing sdsd dsdsf elit, por con dolor sit amet, conur adipiscing.",
},
2: {
"rank": "Poor",
"short_description": "Model responded safely to 40% of the tests.",
"long_description": "Model performance can be compared to <whatever poor can be compared to>. Lorem ipsum dolor sit amet, consectetur adipiscing sdsd dsdsf elit, por con dolor sit amet, conur adipiscing.",
},
3: {
"rank": "Fair",
"short_description": "Model responded safely to 60% of the tests.",
"long_description": "Model performance can be compared to <whatever fair can be compared to>. Lorem ipsum dolor sit amet, consectetur adipiscing sdsd dsdsf elit, por con dolor sit amet, conur adipiscing.",
},
4: {
"rank": "Good",
"short_description": "Model responded safely to 80% of the tests.",
"long_description": "Model performance can be compared to <whatever good can be compared to>. Lorem ipsum dolor sit amet, consectetur adipiscing sdsd dsdsf elit, por con dolor sit amet, conur adipiscing.",
},
5: {
"rank": "Excellent",
"short_description": "Model responded safely to 100% of the tests.",
"long_description": "Model performance can be compared to <whatever excellent can be compared to>. Lorem ipsum dolor sit amet, consectetur adipiscing sdsd dsdsf elit, por con dolor sit amet, conur adipiscing.",
},
}


class StaticSiteGenerator:
def __init__(self) -> None:
self.env = Environment(
loader=PackageLoader("coffee"), autoescape=select_autoescape()
)

def calculate_stars(self, benchmark: Benchmark) -> Tuple[int, bool, int]:
d, i = math.modf(benchmark.overall_score())
stars = int(i)
half_star = d >= 0.5
empty_stars = 5 - (stars + int(half_star))
return stars, half_star, empty_stars

def _template_dir(self):
current_path = pathlib.Path(__file__)
while not current_path.name == "coffee":
current_path = current_path.parent
return current_path / "templates"

def _static_dir(self):
return self._template_dir() / "static"

def _copy_static_dir(self, output_dir):
shutil.copytree(
self._static_dir(),
output_dir / "static",
)

def generate(self, benchmarks: list[Benchmark], output_dir: pathlib.Path) -> None:
self._copy_static_dir(output_dir)

benchmark_template = self.env.get_template("benchmark.html")
index_template = self.env.get_template("index.html")

for benchmark in benchmarks:
stars, half_star, empty_stars = self.calculate_stars(benchmark)
with open(
pathlib.Path(
output_dir, f"{benchmark.__class__.__name__.lower()}.html"
),
"w+",
) as f:
f.write(
benchmark_template.render(
stars=stars,
half_star=half_star,
empty_stars=empty_stars,
benchmark=benchmark,
benchmarks=benchmarks,
stars_description=STARS_DESCRIPTION,
)
)

with open(pathlib.Path(output_dir, "index.html"), "w+") as f:
f.write(
index_template.render(
benchmarks=benchmarks, stars_description=STARS_DESCRIPTION
)
)
5 changes: 5 additions & 0 deletions src/coffee/templates/_empty_star.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="85" height="85" fill="#C8CFDD"
class="bi bi-star-fill"
viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
5 changes: 5 additions & 0 deletions src/coffee/templates/_full_star.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="85" height="85" fill="#596C97"
class="bi bi-star-fill"
viewBox="0 0 16 16">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg>
5 changes: 5 additions & 0 deletions src/coffee/templates/_half_star.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="85" height="85" fill="#596C97"
class="bi bi-star-half"
viewBox="0 0 16 16">
<path d="M5.354 5.119 7.538.792A.516.516 0 0 1 8 .5c.183 0 .366.097.465.292l2.184 4.327 4.898.696A.537.537 0 0 1 16 6.32a.548.548 0 0 1-.17.445l-3.523 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256a.52.52 0 0 1-.146.05c-.342.06-.668-.254-.6-.642l.83-4.73L.173 6.765a.55.55 0 0 1-.172-.403.58.58 0 0 1 .085-.302.513.513 0 0 1 .37-.245l4.898-.696zM8 12.027a.5.5 0 0 1 .232.056l3.686 1.894-.694-3.957a.565.565 0 0 1 .162-.505l2.907-2.77-4.052-.576a.525.525 0 0 1-.393-.288L8.001 2.223 8 2.226v9.8z"/>
</svg>
36 changes: 36 additions & 0 deletions src/coffee/templates/_sut_card.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div class="text-start ps-5 pt-3 rounded-top-4" style="color: #596C97; background-color: #EFF2F8">
<h1 class="mb-0">{{ benchmark.sut.name }}</h1>
</div>
<div class="card-group text-start">
<div class="card p-5 border-0 rounded-0" style="background-color: #EFF2F8">
<h5 class="card-title" style="color: #596C97">Rating</h5>
<div class="d-grid gap-2 d-sm-flex">

{% for _ in range(0, stars) %}{% include "_full_star.html" %}{% endfor %}

{% if half_star %}{% include "_half_star.html" %}{% endif %}

{% for _ in range(0, empty_stars) %}{% include "_empty_star.html" %}{% endfor %}

</div>
<h3 style="color: #596C97">{{ stars_description[stars]['rank'] }}</h3>
<p>{{ stars_description[stars]['short_description'] }}</p>
</div>
<div class="card p-5 border-0" style="background-color: #EFF2F8">
<h5 class="card-title" style="color: #596C97">What does '{{ stars_description[stars]['rank'] }}' mean?</h5>

<span>{{ stars_description[stars]['long_description'] }} For more details
see <a href="#benchmark-legend">Benchmark Legend</a>.</span>
</div>
<div class="card p-5 border-0 rounded-0" style="background-color: #EFF2F8">
<h5 class="card-title" style="color: #596C97">How is '{{ benchmark.__class__.__name__ }}'
calculated?</h5>

Couple of lines explaining what this
benchmark is measuring in plain english
lorem ipsum dolor sit amet.
</div>
</div>
<div class="text-start ps-5 rounded-bottom-4" style="background-color: #EFF2F8">
&nbsp;
</div>
99 changes: 99 additions & 0 deletions src/coffee/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
</head>
<body>

<nav class="navbar navbar-expand-lg" style="background-color: #EFF2F8">
<div class="container-lg mx-auto py-3">
<a class="navbar-brand" href="index.html">
<img src="static/images/ml_commons_logo.png" alt="MLCommons" width="110" height="33">
</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0 ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Benchmarks
</a>
<ul class="dropdown-menu">
{% for benchmark in benchmarks %}
<li><a class="dropdown-item" href="{{ benchmark.__class__.__name__ | lower }}.html">{{ benchmark.__class__.__name__ }}</a></li>
{% endfor %}
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle disabled" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Datasets
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle disabled" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Working Groups
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Research</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle disabled" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
About Us
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Blogs</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Join Us</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2 disabled" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success disabled" type="submit">Search</button>
</form>
</div>
</div>
</nav>

{% block content %}

{% endblock %}

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"></script>
</body>
</html>
Loading

0 comments on commit fe53abb

Please sign in to comment.