|
14 | 14 | # |
15 | 15 | """Visualization utilities for GenAI Evaluation SDK.""" |
16 | 16 |
|
| 17 | +import base64 |
17 | 18 | import json |
18 | 19 | import logging |
| 20 | +import textwrap |
19 | 21 | from typing import Any, Optional |
20 | 22 |
|
21 | 23 | import pandas as pd |
@@ -78,9 +80,16 @@ def stringify_cell(cell: Any) -> Optional[str]: |
78 | 80 | return df_copy |
79 | 81 |
|
80 | 82 |
|
| 83 | +def _encode_to_base64(data: str) -> str: |
| 84 | + """Encodes a string to a web-safe Base64 string.""" |
| 85 | + return base64.b64encode(data.encode("utf-8")).decode("utf-8") |
| 86 | + |
| 87 | + |
81 | 88 | def _get_evaluation_html(eval_result_json: str) -> str: |
82 | 89 | """Returns a self-contained HTML for single evaluation visualization.""" |
83 | | - return f""" |
| 90 | + payload_b64 = _encode_to_base64(eval_result_json) |
| 91 | + return textwrap.dedent( |
| 92 | + f""" |
84 | 93 | <!DOCTYPE html> |
85 | 94 | <html> |
86 | 95 | <head> |
@@ -249,12 +258,11 @@ def _get_evaluation_html(eval_result_json: str) -> str: |
249 | 258 | <body> |
250 | 259 | <div class="container"> |
251 | 260 | <h1>Evaluation Report</h1> |
252 | | - <div id="summary-section"></div> |
253 | | - <div id="agent-info-section"></div> |
254 | | - <div id="details-section"></div> |
255 | | - </div> |
| 261 | + < <div id="summary-section"></div> |
| 262 | + <div id="agent-info-section"></div> |
| 263 | + <div id="details-section"></div> |
256 | 264 | <script> |
257 | | - var vizData_vertex_eval_sdk = {eval_result_json}; |
| 265 | + var vizData_vertex_eval_sdk = JSON.parse(new TextDecoder().decode(Uint8Array.from(atob("{payload_b64}"), c => c.charCodeAt(0)))); |
258 | 266 | function formatDictVals(obj) {{ |
259 | 267 | if (typeof obj === 'string') return obj; |
260 | 268 | if (obj === undefined || obj === null) return ''; |
@@ -552,11 +560,14 @@ def _get_evaluation_html(eval_result_json: str) -> str: |
552 | 560 | </body> |
553 | 561 | </html> |
554 | 562 | """ |
| 563 | + ) |
555 | 564 |
|
556 | 565 |
|
557 | 566 | def _get_comparison_html(eval_result_json: str) -> str: |
558 | 567 | """Returns a self-contained HTML for a side-by-side eval comparison.""" |
559 | | - return f""" |
| 568 | + payload_b64 = _encode_to_base64(eval_result_json) |
| 569 | + return textwrap.dedent( |
| 570 | + f""" |
560 | 571 | <!DOCTYPE html> |
561 | 572 | <html> |
562 | 573 | <head> |
@@ -612,11 +623,10 @@ def _get_comparison_html(eval_result_json: str) -> str: |
612 | 623 | <body> |
613 | 624 | <div class="container"> |
614 | 625 | <h1>Eval Comparison Report</h1> |
615 | | - <div id="summary-section"></div> |
616 | | - <div id="details-section"></div> |
617 | | - </div> |
| 626 | + < <div id="summary-section"></div> |
| 627 | + <div id="details-section"></div> |
618 | 628 | <script> |
619 | | - var vizData_vertex_eval_sdk = {eval_result_json}; |
| 629 | + var vizData_vertex_eval_sdk = JSON.parse(new TextDecoder().decode(Uint8Array.from(atob("{payload_b64}"), c => c.charCodeAt(0)))); |
620 | 630 | function renderSummary(summaryMetrics, metadata) {{ |
621 | 631 | const container = document.getElementById('summary-section'); |
622 | 632 | if (!summaryMetrics || summaryMetrics.length === 0) {{ container.innerHTML = '<h2>Summary Metrics</h2><p>No summary metrics.</p>'; return; }} |
@@ -692,11 +702,14 @@ def _get_comparison_html(eval_result_json: str) -> str: |
692 | 702 | </body> |
693 | 703 | </html> |
694 | 704 | """ |
| 705 | + ) |
695 | 706 |
|
696 | 707 |
|
697 | 708 | def _get_inference_html(dataframe_json: str) -> str: |
698 | 709 | """Returns a self-contained HTML for displaying inference results.""" |
699 | | - return f""" |
| 710 | + payload_b64 = _encode_to_base64(dataframe_json) |
| 711 | + return textwrap.dedent( |
| 712 | + f""" |
700 | 713 | <!DOCTYPE html> |
701 | 714 | <html> |
702 | 715 | <head> |
@@ -741,12 +754,12 @@ def _get_inference_html(dataframe_json: str) -> str: |
741 | 754 | </style> |
742 | 755 | </head> |
743 | 756 | <body> |
744 | | - <div class="container"> |
| 757 | + < <div class="container"> |
745 | 758 | <h1>Evaluation Dataset</h1> |
746 | 759 | <div id="results-table"></div> |
747 | 760 | </div> |
748 | 761 | <script> |
749 | | - var vizData_vertex_eval_sdk = {dataframe_json}; |
| 762 | + var vizData_vertex_eval_sdk = JSON.parse(new TextDecoder().decode(Uint8Array.from(atob("{payload_b64}"), c => c.charCodeAt(0)))); |
750 | 763 | var container_vertex_eval_sdk = document.getElementById('results-table'); |
751 | 764 |
|
752 | 765 | function renderRubrics(cellValue) {{ |
@@ -822,6 +835,7 @@ def _get_inference_html(dataframe_json: str) -> str: |
822 | 835 | </body> |
823 | 836 | </html> |
824 | 837 | """ |
| 838 | + ) |
825 | 839 |
|
826 | 840 |
|
827 | 841 | def _extract_text_and_raw_json(content: Any) -> dict[str, str]: |
@@ -1086,12 +1100,14 @@ def _get_status_html(status: str, error_message: Optional[str] = None) -> str: |
1086 | 1100 | </p> |
1087 | 1101 | """ |
1088 | 1102 |
|
1089 | | - return f""" |
| 1103 | + return textwrap.dedent( |
| 1104 | + f""" |
1090 | 1105 | <div> |
1091 | 1106 | <p><b>Status:</b> {status}</p> |
1092 | 1107 | {error_html} |
1093 | 1108 | </div> |
1094 | 1109 | """ |
| 1110 | + ) |
1095 | 1111 |
|
1096 | 1112 |
|
1097 | 1113 | def display_evaluation_run_status(eval_run_obj: "types.EvaluationRun") -> None: |
|
0 commit comments