Generate HTML report from loop output data. If auto_refresh is True, adds a meta refresh tag.
(data: dict, auto_refresh: bool = False, skill_name: str = "")
| 14 | |
| 15 | |
| 16 | def generate_html(data: dict, auto_refresh: bool = False, skill_name: str = "") -> str: |
| 17 | """Generate HTML report from loop output data. If auto_refresh is True, adds a meta refresh tag.""" |
| 18 | history = data.get("history", []) |
| 19 | holdout = data.get("holdout", 0) |
| 20 | title_prefix = html.escape(skill_name + " \u2014 ") if skill_name else "" |
| 21 | |
| 22 | # Get all unique queries from train and test sets, with should_trigger info |
| 23 | train_queries: list[dict] = [] |
| 24 | test_queries: list[dict] = [] |
| 25 | if history: |
| 26 | for r in history[0].get("train_results", history[0].get("results", [])): |
| 27 | train_queries.append({"query": r["query"], "should_trigger": r.get("should_trigger", True)}) |
| 28 | if history[0].get("test_results"): |
| 29 | for r in history[0].get("test_results", []): |
| 30 | test_queries.append({"query": r["query"], "should_trigger": r.get("should_trigger", True)}) |
| 31 | |
| 32 | refresh_tag = ' <meta http-equiv="refresh" content="5">\n' if auto_refresh else "" |
| 33 | |
| 34 | html_parts = ["""<!DOCTYPE html> |
| 35 | <html> |
| 36 | <head> |
| 37 | <meta charset="utf-8"> |
| 38 | """ + refresh_tag + """ <title>""" + title_prefix + """Skill Description Optimization</title> |
| 39 | <link rel="preconnect" href="https://fonts.googleapis.com"> |
| 40 | <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| 41 | <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet"> |
| 42 | <style> |
| 43 | body { |
| 44 | font-family: 'Lora', Georgia, serif; |
| 45 | max-width: 100%; |
| 46 | margin: 0 auto; |
| 47 | padding: 20px; |
| 48 | background: #faf9f5; |
| 49 | color: #141413; |
| 50 | } |
| 51 | h1 { font-family: 'Poppins', sans-serif; color: #141413; } |
| 52 | .explainer { |
| 53 | background: white; |
| 54 | padding: 15px; |
| 55 | border-radius: 6px; |
| 56 | margin-bottom: 20px; |
| 57 | border: 1px solid #e8e6dc; |
| 58 | color: #b0aea5; |
| 59 | font-size: 0.875rem; |
| 60 | line-height: 1.6; |
| 61 | } |
| 62 | .summary { |
| 63 | background: white; |
| 64 | padding: 15px; |
| 65 | border-radius: 6px; |
| 66 | margin-bottom: 20px; |
| 67 | border: 1px solid #e8e6dc; |
| 68 | } |
| 69 | .summary p { margin: 5px 0; } |
| 70 | .best { color: #788c5d; font-weight: bold; } |
| 71 | .table-container { |
| 72 | overflow-x: auto; |
| 73 | width: 100%; |
no test coverage detected