Setting the file. One moment. Eval Review · Skill Creator · anthropics/skills · Skills Docs14.11
Eval Review
(opens in a new tab)
assets/eval_review.html
HTML·146 lines·7 KB
<
link
rel
=
"preconnect"
href
=
"https://fonts.googleapis.com"
>
8 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9 <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet">
10 <style>
11 * { box-sizing: border-box; margin: 0; padding: 0; }
12 body { font-family: 'Lora', Georgia, serif; background: #faf9f5; padding: 2rem; color: #141413; }
13 h1 { font-family: 'Poppins', sans-serif; margin-bottom: 0.5rem; font-size: 1.5rem; }
14 .description { color: #b0aea5; margin-bottom: 1.5rem; font-style: italic; max-width: 900px; }
15 .controls { margin-bottom: 1rem; display: flex; gap: 0.5rem; }
16 .btn { font-family: 'Poppins', sans-serif; padding: 0.5rem 1rem; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem; font-weight: 500; }
17 .btn-add { background: #6a9bcc; color: white; }
18 .btn-add:hover { background: #5889b8; }
19 .btn-export { background: #d97757; color: white; }
20 .btn-export:hover { background: #c4613f; }
21 table { width: 100%; max-width: 1100px; border-collapse: collapse; background: white; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
22 th { font-family: 'Poppins', sans-serif; background: #141413; color: #faf9f5; padding: 0.75rem 1rem; text-align: left; font-size: 0.875rem; }
23 td { padding: 0.75rem 1rem; border-bottom: 1px solid #e8e6dc; vertical-align: top; }
24 tr:nth-child(even) td { background: #faf9f5; }
25 tr:hover td { background: #f3f1ea; }
26 .section-header td { background: #e8e6dc; font-family: 'Poppins', sans-serif; font-weight: 500; font-size: 0.8rem; color: #141413; text-transform: uppercase; letter-spacing: 0.05em; }
27 .query-input { width: 100%; padding: 0.4rem; border: 1px solid #e8e6dc; border-radius: 4px; font-size: 0.875rem; font-family: 'Lora', Georgia, serif; resize: vertical; min-height: 60px; }
28 .query-input:focus { outline: none; border-color: #d97757; box-shadow: 0 0 0 2px rgba(217,119,87,0.15); }
29 .toggle { position: relative; display: inline-block; width: 44px; height: 24px; }
30 .toggle input { opacity: 0; width: 0; height: 0; }
31 .toggle .slider { position: absolute; inset: 0; background: #b0aea5; border-radius: 24px; cursor: pointer; transition: 0.2s; }
32 .toggle .slider::before { content: ""; position: absolute; width: 18px; height: 18px; left: 3px; bottom: 3px; background: white; border-radius: 50%; transition: 0.2s; }
33 .toggle input:checked + .slider { background: #d97757; }
34 .toggle input:checked + .slider::before { transform: translateX(20px); }
35 .btn-delete { background: #c44; color: white; padding: 0.3rem 0.6rem; border: none; border-radius: 4px; cursor: pointer; font-size: 0.75rem; font-family: 'Poppins', sans-serif; }
36 .btn-delete:hover { background: #a33; }
37 .summary { margin-top: 1rem; color: #b0aea5; font-size: 0.875rem; }
38 </style>
39</head>
40<body>
41 <h1>Eval Set Review: <span id="skill-name">__SKILL_NAME_PLACEHOLDER__</span></h1>
42 <p class="description">Current description: <span id="skill-desc">__SKILL_DESCRIPTION_PLACEHOLDER__</span></p>
43
44 <div class="controls">
45 <button class="btn btn-add" onclick="addRow()">+ Add Query</button>
46 <button class="btn btn-export" onclick="exportEvalSet()">Export Eval Set</button>
47 </div>
48
49 <table>
50 <thead>
51 <tr>
52 <th style="width:65%">Query</th>
53 <th style="width:18%">Should Trigger</th>
54 <th style="width:10%">Actions</th>
55 </tr>
56 </thead>
57 <tbody id="eval-body"></tbody>
58 </table>
59
60 <p class="summary" id="summary"></p>
61
62 <script>
63 const EVAL_DATA = __EVAL_DATA_PLACEHOLDER__;
64
65 let evalItems = [...EVAL_DATA];
66
67 function render() {
68 const tbody = document.getElementById('eval-body');
69 tbody.innerHTML = '';
70
71 // Sort: should-trigger first, then should-not-trigger
72 const sorted = evalItems
73 .map((item, origIdx) => ({ ...item, origIdx }))
74 .sort((a, b) => (b.should_trigger ? 1 : 0) - (a.should_trigger ? 1 : 0));
75
76 let lastGroup = null;
77 sorted.forEach(item => {
78 const group = item.should_trigger ? 'trigger' : 'no-trigger';
79 if (group !== lastGroup) {
80 const headerRow = document.createElement('tr');
81 headerRow.className = 'section-header';
82 headerRow.innerHTML = `<td colspan="3">${item.should_trigger ? 'Should Trigger' : 'Should NOT Trigger'}</td>`;
83 tbody.appendChild(headerRow);
84 lastGroup = group;
85 }
86
87 const idx = item.origIdx;
88 const tr = document.createElement('tr');
89 tr.innerHTML = `
90 <td><textarea class="query-input" onchange="updateQuery(${idx}, this.value)">${escapeHtml(item.query)}</textarea></td>
91 <td>
92 <label class="toggle">
93 <input type="checkbox" ${item.should_trigger ? 'checked' : ''} onchange="updateTrigger(${idx}, this.checked)">
94 <span class="slider"></span>
95 </label>
96 <span style="margin-left:8px;font-size:0.8rem;color:#b0aea5">${item.should_trigger ? 'Yes' : 'No'}</span>
97 </td>
98 <td><button class="btn-delete" onclick="deleteRow(${idx})">Delete</button></td>
99 `;
100 tbody.appendChild(tr);
101 });
102 updateSummary();
103 }
104
105 function escapeHtml(text) {
106 const div = document.createElement('div');
107 div.textContent = text;
108 return div.innerHTML;
109 }
110
111 function updateQuery(idx, value) { evalItems[idx].query = value; updateSummary(); }
112 function updateTrigger(idx, value) { evalItems[idx].should_trigger = value; render(); }
113 function deleteRow(idx) { evalItems.splice(idx, 1); render(); }
114
115 function addRow() {
116 evalItems.push({ query: '', should_trigger: true });
117 render();
118 const inputs = document.querySelectorAll('.query-input');
119 inputs[inputs.length - 1].focus();
120 }
121
122 function updateSummary() {
123 const trigger = evalItems.filter(i => i.should_trigger).length;
124 const noTrigger = evalItems.filter(i => !i.should_trigger).length;
125 document.getElementById('summary').textContent =
126 `${evalItems.length} queries total: ${trigger} should trigger, ${noTrigger} should not trigger`;
127 }
128
129 function exportEvalSet() {
130 const valid = evalItems.filter(i => i.query.trim() !== '');
131 const data = valid.map(i => ({ query: i.query.trim(), should_trigger: i.should_trigger }));
132 const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
133 const url = URL.createObjectURL(blob);
134 const a = document.createElement('a');
135 a.href = url;
136 a.download = 'eval_set.json';
137 document.body.appendChild(a);
138 a.click();
139 document.body.removeChild(a);
140 URL.revokeObjectURL(url);
141 }
142
143 render();
144 </script>
145</body>
146</html>