completion-kit 0.4.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/app/assets/stylesheets/completion_kit/application.css +375 -0
- data/app/controllers/completion_kit/api/v1/datasets_controller.rb +2 -2
- data/app/controllers/completion_kit/api/v1/metric_groups_controller.rb +2 -2
- data/app/controllers/completion_kit/api/v1/metrics_controller.rb +3 -2
- data/app/controllers/completion_kit/api/v1/prompts_controller.rb +5 -4
- data/app/controllers/completion_kit/api/v1/runs_controller.rb +3 -2
- data/app/controllers/completion_kit/api/v1/tags_controller.rb +51 -0
- data/app/controllers/completion_kit/datasets_controller.rb +3 -2
- data/app/controllers/completion_kit/metric_groups_controller.rb +7 -6
- data/app/controllers/completion_kit/metrics_controller.rb +4 -2
- data/app/controllers/completion_kit/prompts_controller.rb +7 -4
- data/app/controllers/completion_kit/runs_controller.rb +4 -3
- data/app/controllers/completion_kit/tags_controller.rb +50 -0
- data/app/controllers/concerns/completion_kit/tag_filtering.rb +22 -0
- data/app/helpers/completion_kit/application_helper.rb +11 -0
- data/app/models/completion_kit/dataset.rb +5 -2
- data/app/models/completion_kit/metric.rb +4 -1
- data/app/models/completion_kit/metric_group.rb +4 -1
- data/app/models/completion_kit/prompt.rb +4 -1
- data/app/models/completion_kit/run.rb +3 -1
- data/app/models/completion_kit/tag.rb +39 -0
- data/app/models/completion_kit/tagging.rb +12 -0
- data/app/models/concerns/completion_kit/taggable.rb +24 -0
- data/app/services/completion_kit/mcp_dispatcher.rb +3 -1
- data/app/services/completion_kit/mcp_tools/datasets.rb +6 -4
- data/app/services/completion_kit/mcp_tools/metric_groups.rb +6 -2
- data/app/services/completion_kit/mcp_tools/metrics.rb +8 -4
- data/app/services/completion_kit/mcp_tools/prompts.rb +10 -5
- data/app/services/completion_kit/mcp_tools/runs.rb +7 -3
- data/app/services/completion_kit/mcp_tools/tags.rb +74 -0
- data/app/views/completion_kit/api_reference/index.html.erb +38 -0
- data/app/views/completion_kit/datasets/_form.html.erb +20 -1
- data/app/views/completion_kit/datasets/index.html.erb +17 -1
- data/app/views/completion_kit/datasets/show.html.erb +6 -0
- data/app/views/completion_kit/metric_groups/_form.html.erb +74 -19
- data/app/views/completion_kit/metric_groups/index.html.erb +30 -4
- data/app/views/completion_kit/metrics/_form.html.erb +19 -1
- data/app/views/completion_kit/metrics/index.html.erb +18 -2
- data/app/views/completion_kit/metrics/show.html.erb +6 -0
- data/app/views/completion_kit/prompts/_form.html.erb +20 -1
- data/app/views/completion_kit/prompts/index.html.erb +17 -1
- data/app/views/completion_kit/prompts/show.html.erb +6 -0
- data/app/views/completion_kit/provider_credentials/_form.html.erb +1 -1
- data/app/views/completion_kit/provider_credentials/index.html.erb +3 -1
- data/app/views/completion_kit/runs/_form.html.erb +25 -3
- data/app/views/completion_kit/runs/_row.html.erb +5 -0
- data/app/views/completion_kit/runs/index.html.erb +9 -0
- data/app/views/completion_kit/runs/show.html.erb +6 -0
- data/app/views/completion_kit/shared/_settings_nav.html.erb +9 -0
- data/app/views/completion_kit/tags/_filter_bar.html.erb +15 -0
- data/app/views/completion_kit/tags/_form.html.erb +39 -0
- data/app/views/completion_kit/tags/_marks.html.erb +3 -0
- data/app/views/completion_kit/tags/_picker.html.erb +20 -0
- data/app/views/completion_kit/tags/edit.html.erb +20 -0
- data/app/views/completion_kit/tags/index.html.erb +45 -0
- data/app/views/completion_kit/tags/new.html.erb +20 -0
- data/app/views/layouts/completion_kit/application.html.erb +38 -1
- data/config/routes.rb +2 -0
- data/db/migrate/20260509000001_create_completion_kit_tags.rb +10 -0
- data/db/migrate/20260509000002_create_completion_kit_taggings.rb +16 -0
- data/lib/completion_kit/version.rb +1 -1
- metadata +18 -1
|
@@ -64,6 +64,7 @@ end %>
|
|
|
64
64
|
<input type="radio" name="ck-api-tab" id="ck-tab-datasets" class="ck-api-tabs__radio">
|
|
65
65
|
<input type="radio" name="ck-api-tab" id="ck-tab-metrics" class="ck-api-tabs__radio">
|
|
66
66
|
<input type="radio" name="ck-api-tab" id="ck-tab-metric-groups" class="ck-api-tabs__radio">
|
|
67
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-tags" class="ck-api-tabs__radio">
|
|
67
68
|
<input type="radio" name="ck-api-tab" id="ck-tab-providers" class="ck-api-tabs__radio">
|
|
68
69
|
|
|
69
70
|
<nav class="ck-api-tabs__nav">
|
|
@@ -74,6 +75,7 @@ end %>
|
|
|
74
75
|
<label for="ck-tab-datasets" class="ck-api-tabs__label">Datasets <span class="ck-api-tabs__count">5</span></label>
|
|
75
76
|
<label for="ck-tab-metrics" class="ck-api-tabs__label">Metrics <span class="ck-api-tabs__count">5</span></label>
|
|
76
77
|
<label for="ck-tab-metric-groups" class="ck-api-tabs__label">Metric Groups <span class="ck-api-tabs__count">5</span></label>
|
|
78
|
+
<label for="ck-tab-tags" class="ck-api-tabs__label">Tags <span class="ck-api-tabs__count">5</span></label>
|
|
77
79
|
<label for="ck-tab-providers" class="ck-api-tabs__label">Providers <span class="ck-api-tabs__count">5</span></label>
|
|
78
80
|
</nav>
|
|
79
81
|
|
|
@@ -254,6 +256,42 @@ end %>
|
|
|
254
256
|
</div>
|
|
255
257
|
</div>
|
|
256
258
|
|
|
259
|
+
<div class="ck-api-tabs__panel">
|
|
260
|
+
<h2 class="ck-section-title">Tags</h2>
|
|
261
|
+
<p class="ck-copy">Domain labels you can attach to metrics, prompts, runs, and datasets. Tags are auto-assigned a color from a 10-color palette. Each index page can be filtered by one or more tags using <code>?tag[]=name</code> query params (OR semantics).</p>
|
|
262
|
+
<div class="ck-api-endpoint">
|
|
263
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/tags</p>
|
|
264
|
+
<p class="ck-meta-copy">List all tags with name and color.</p>
|
|
265
|
+
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl #{@base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="ck-api-endpoint">
|
|
268
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/tags</p>
|
|
269
|
+
<p class="ck-meta-copy">Create a tag.</p>
|
|
270
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code></p>
|
|
271
|
+
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"real estate\"}'" %>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="ck-api-endpoint">
|
|
274
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/tags/:id</p>
|
|
275
|
+
<p class="ck-meta-copy">Get, update, or delete a tag. PATCH accepts <code>name</code>. DELETE returns 204 No Content and removes all taggings for this tag.</p>
|
|
276
|
+
</div>
|
|
277
|
+
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
278
|
+
<p class="ck-kicker" style="margin-bottom: 0.5rem;">Tagging resources</p>
|
|
279
|
+
<p class="ck-meta-copy">Metrics, prompts, runs, and datasets accept a <code>tag_names</code> array on their create and update endpoints. Passing a name that does not yet exist silently creates the tag. On PATCH, the list replaces all existing tags for that record (omit the field to leave tags unchanged).</p>
|
|
280
|
+
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/metrics \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"Accuracy\", \"tag_names\": [\"real estate\"]}'" %>
|
|
281
|
+
</div>
|
|
282
|
+
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
283
|
+
<p class="ck-kicker" style="margin-bottom: 0.5rem;">MCP tools</p>
|
|
284
|
+
<div class="ck-mcp-tools">
|
|
285
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_list</code><span class="ck-mcp-tool__desc">List all tags</span></div>
|
|
286
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_get</code><span class="ck-mcp-tool__desc">Get a tag by ID</span></div>
|
|
287
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_create</code><span class="ck-mcp-tool__desc">Create a tag (name required)</span></div>
|
|
288
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_update</code><span class="ck-mcp-tool__desc">Update a tag's name</span></div>
|
|
289
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_delete</code><span class="ck-mcp-tool__desc">Delete a tag and remove all its taggings</span></div>
|
|
290
|
+
</div>
|
|
291
|
+
<p class="ck-meta-copy" style="margin-top: 0.75rem;">The existing <code>metrics_create</code>, <code>metrics_update</code>, <code>prompts_create</code>, <code>prompts_update</code>, <code>runs_create</code>, <code>runs_update</code>, <code>datasets_create</code>, and <code>datasets_update</code> tools all accept a <code>tag_names</code> parameter with the same auto-create and replace semantics as the REST API.</p>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
257
295
|
<div class="ck-api-tabs__panel">
|
|
258
296
|
<h2 class="ck-section-title">Provider Credentials</h2>
|
|
259
297
|
<p class="ck-copy">LLM provider API keys. The <code>api_key</code> field is write-only and never returned in responses.</p>
|
|
@@ -21,8 +21,27 @@
|
|
|
21
21
|
<%= form.text_area :csv_data, rows: 12, class: "ck-input ck-input--area ck-input--code", placeholder: "content,audience\nFirst ticket text,internal\nSecond ticket text,customer" %>
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
|
+
<%= render "completion_kit/tags/picker", record: dataset, param_namespace: :dataset %>
|
|
25
|
+
|
|
24
26
|
<div class="ck-actions">
|
|
25
|
-
|
|
27
|
+
<% if dataset.persisted? %>
|
|
28
|
+
<% runs_n = dataset.runs.count %>
|
|
29
|
+
<% responses_n = CompletionKit::Response.where(run_id: dataset.runs.select(:id)).count %>
|
|
30
|
+
<% confirm = if runs_n.zero?
|
|
31
|
+
"Delete \"#{dataset.name}\"? It has no runs."
|
|
32
|
+
else
|
|
33
|
+
"Delete \"#{dataset.name}\"? Cascades through #{pluralize(runs_n, 'run')} and #{pluralize(responses_n, 'response')} (and their reviews) that used this dataset."
|
|
34
|
+
end %>
|
|
35
|
+
<%= button_to dataset_path(dataset), method: :delete,
|
|
36
|
+
form_class: "inline-block",
|
|
37
|
+
class: "ck-icon-btn",
|
|
38
|
+
title: "Delete dataset",
|
|
39
|
+
"aria-label": "Delete dataset",
|
|
40
|
+
data: { turbo_confirm: confirm } do %>
|
|
41
|
+
<%= heroicon_tag "trash", variant: :outline, size: 16, "aria-hidden": "true" %>
|
|
42
|
+
<% end %>
|
|
43
|
+
<% end %>
|
|
44
|
+
<%= link_to "Cancel", datasets_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
26
45
|
<%= form.submit(dataset.persisted? ? "Save dataset" : "Create dataset", class: ck_button_classes(:dark)) %>
|
|
27
46
|
</div>
|
|
28
47
|
</div>
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</section>
|
|
10
10
|
|
|
11
|
+
<%= render "completion_kit/tags/filter_bar",
|
|
12
|
+
available: @available_tags,
|
|
13
|
+
selected: @selected_tags,
|
|
14
|
+
base_path: datasets_path %>
|
|
15
|
+
|
|
11
16
|
<% if @datasets.any? %>
|
|
12
17
|
<table class="ck-results-table">
|
|
13
18
|
<thead>
|
|
@@ -22,7 +27,14 @@
|
|
|
22
27
|
<tbody>
|
|
23
28
|
<% @datasets.each do |dataset| %>
|
|
24
29
|
<tr onclick="window.location='<%= dataset_path(dataset) %>'" style="cursor: pointer;">
|
|
25
|
-
<td
|
|
30
|
+
<td>
|
|
31
|
+
<strong><%= dataset.name %></strong>
|
|
32
|
+
<% if dataset.tags.any? %>
|
|
33
|
+
<div class="tag-marks-row">
|
|
34
|
+
<%= render "completion_kit/tags/marks", tags: dataset.tags %>
|
|
35
|
+
</div>
|
|
36
|
+
<% end %>
|
|
37
|
+
</td>
|
|
26
38
|
<td><%= dataset.row_count %></td>
|
|
27
39
|
<td><%= dataset.runs.count %></td>
|
|
28
40
|
<td class="ck-meta-copy"><time datetime="<%= dataset.created_at.iso8601 %>"><%= dataset.created_at.strftime("%b %-d, %Y") %></time></td>
|
|
@@ -31,6 +43,10 @@
|
|
|
31
43
|
<% end %>
|
|
32
44
|
</tbody>
|
|
33
45
|
</table>
|
|
46
|
+
<% elsif @selected_tags.any? %>
|
|
47
|
+
<div class="ck-empty">
|
|
48
|
+
<p>No datasets match these tags. <%= link_to "Clear filters", datasets_path, class: "ck-link" %>.</p>
|
|
49
|
+
</div>
|
|
34
50
|
<% else %>
|
|
35
51
|
<div class="ck-empty">
|
|
36
52
|
No datasets yet. Create one to use with your prompts.
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
</section>
|
|
14
14
|
|
|
15
|
+
<% if @dataset.tags.any? %>
|
|
16
|
+
<div class="tag-marks-row tag-marks-row--header">
|
|
17
|
+
<%= render "completion_kit/tags/marks", tags: @dataset.tags %>
|
|
18
|
+
</div>
|
|
19
|
+
<% end %>
|
|
20
|
+
|
|
15
21
|
<section>
|
|
16
22
|
<p class="ck-kicker">CSV preview</p>
|
|
17
23
|
<%
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
<%= form_with(model: metric_group, url: metric_group.persisted? ? metric_group_path(metric_group) : metric_groups_path, local: true) do |form| %>
|
|
2
|
-
<%
|
|
3
|
-
<div class="ck-flash ck-flash--alert">
|
|
4
|
-
<p class="ck-flash__title"><%= pluralize(metric_group.errors.count, "problem") %> prevented this metric group from being saved.</p>
|
|
5
|
-
<ul class="ck-error-list">
|
|
6
|
-
<% metric_group.errors.full_messages.each do |message| %>
|
|
7
|
-
<li><%= message %></li>
|
|
8
|
-
<% end %>
|
|
9
|
-
</ul>
|
|
10
|
-
</div>
|
|
11
|
-
<% end %>
|
|
2
|
+
<% name_error = metric_group.errors[:name].first %>
|
|
12
3
|
|
|
13
4
|
<div class="ck-card ck-form-card">
|
|
14
5
|
<div class="ck-field">
|
|
15
6
|
<%= form.label :name, "Metric group name", class: "ck-label" %>
|
|
16
|
-
<%= form.text_field :name,
|
|
7
|
+
<%= form.text_field :name,
|
|
8
|
+
class: ["ck-input", ("ck-input--error" if name_error)].compact.join(" "),
|
|
9
|
+
placeholder: "Support quality",
|
|
10
|
+
autofocus: !metric_group.persisted?,
|
|
11
|
+
"aria-invalid": name_error ? "true" : nil %>
|
|
12
|
+
<% if name_error %>
|
|
13
|
+
<p class="ck-field-error" role="alert"><%= name_error %></p>
|
|
14
|
+
<% end %>
|
|
17
15
|
</div>
|
|
18
16
|
|
|
19
17
|
<div class="ck-field">
|
|
@@ -21,16 +19,41 @@
|
|
|
21
19
|
<%= form.text_area :description, rows: 3, class: "ck-input ck-input--area", placeholder: "When this metric group should be used." %>
|
|
22
20
|
</div>
|
|
23
21
|
|
|
22
|
+
<%= render "completion_kit/tags/picker", record: metric_group, param_namespace: :metric_group %>
|
|
23
|
+
|
|
24
24
|
<div class="ck-field">
|
|
25
25
|
<p class="ck-label">Metrics in this group</p>
|
|
26
|
-
<p class="ck-hint">Pick the metrics to include.</p>
|
|
27
|
-
|
|
26
|
+
<p class="ck-hint">Pick the metrics to include. Filter the list by tag to narrow it down.</p>
|
|
27
|
+
|
|
28
|
+
<% available_filter_tags = @metrics.flat_map(&:tags).uniq.sort_by(&:name) %>
|
|
29
|
+
<% if available_filter_tags.any? %>
|
|
30
|
+
<div class="ck-metric-tag-filter" data-metric-tag-filter>
|
|
31
|
+
<span class="ck-metric-tag-filter__label">Filter metrics by tag</span>
|
|
32
|
+
<% available_filter_tags.each do |tag| %>
|
|
33
|
+
<button type="button"
|
|
34
|
+
class="tag-mark tag-mark--off ck-metric-tag-filter__chip"
|
|
35
|
+
style="--mark-color: var(--tag-<%= tag.color %>);"
|
|
36
|
+
data-filter-tag="<%= tag.name %>"
|
|
37
|
+
onclick="ckToggleMetricGroupFilter(this)"><%= tag.name %></button>
|
|
38
|
+
<% end %>
|
|
39
|
+
</div>
|
|
40
|
+
<% end %>
|
|
41
|
+
|
|
42
|
+
<div class="ck-metric-checkboxes" data-metric-checkboxes>
|
|
28
43
|
<% @metrics.each do |metric| %>
|
|
29
|
-
<label class="ck-
|
|
30
|
-
<%= check_box_tag "metric_group[metric_ids][]", metric.id, metric_group.metrics.exists?(metric.id), class: "ck-checkbox" %>
|
|
31
|
-
<span>
|
|
32
|
-
|
|
33
|
-
<span class="ck-
|
|
44
|
+
<label class="ck-checkbox-label" data-metric-tags="<%= metric.tag_names.join(",") %>">
|
|
45
|
+
<%= check_box_tag "metric_group[metric_ids][]", metric.id, metric_group.metrics.exists?(metric.id), class: "ck-checkbox", id: "metric_group_metric_#{metric.id}" %>
|
|
46
|
+
<span class="ck-checkbox-label__box" aria-hidden="true"></span>
|
|
47
|
+
<span class="ck-checkbox-label__body">
|
|
48
|
+
<span class="ck-checkbox-label__text"><%= metric.name %></span>
|
|
49
|
+
<% if metric.instruction.present? %>
|
|
50
|
+
<span class="ck-checkbox-label__hint"><%= truncate(metric.instruction.to_s, length: 90) %></span>
|
|
51
|
+
<% end %>
|
|
52
|
+
<% if metric.tags.any? %>
|
|
53
|
+
<div class="tag-marks-row">
|
|
54
|
+
<%= render "completion_kit/tags/marks", tags: metric.tags %>
|
|
55
|
+
</div>
|
|
56
|
+
<% end %>
|
|
34
57
|
</span>
|
|
35
58
|
</label>
|
|
36
59
|
<% end %>
|
|
@@ -38,8 +61,40 @@
|
|
|
38
61
|
<%= hidden_field_tag "metric_group[metric_ids][]", "" %>
|
|
39
62
|
</div>
|
|
40
63
|
|
|
64
|
+
<script>
|
|
65
|
+
function ckToggleMetricGroupFilter(btn) {
|
|
66
|
+
btn.classList.toggle("tag-mark--off");
|
|
67
|
+
var bar = btn.closest("[data-metric-tag-filter]");
|
|
68
|
+
var grid = bar && bar.parentElement.querySelector("[data-metric-checkboxes]");
|
|
69
|
+
if (!grid) return;
|
|
70
|
+
var active = Array.prototype.map.call(
|
|
71
|
+
bar.querySelectorAll(".ck-metric-tag-filter__chip:not(.tag-mark--off)"),
|
|
72
|
+
function(b) { return b.getAttribute("data-filter-tag"); }
|
|
73
|
+
);
|
|
74
|
+
grid.querySelectorAll(".ck-checkbox-label").forEach(function(lbl) {
|
|
75
|
+
var tags = (lbl.getAttribute("data-metric-tags") || "").split(",").filter(Boolean);
|
|
76
|
+
var visible = active.length === 0 || tags.some(function(t) { return active.indexOf(t) !== -1; });
|
|
77
|
+
lbl.style.display = visible ? "" : "none";
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
</script>
|
|
81
|
+
|
|
41
82
|
<div class="ck-actions">
|
|
42
|
-
|
|
83
|
+
<% if metric_group.persisted? %>
|
|
84
|
+
<% members_n = metric_group.metrics.count %>
|
|
85
|
+
<% confirm = members_n.zero? ?
|
|
86
|
+
"Delete \"#{metric_group.name}\"? It has no members." :
|
|
87
|
+
"Delete \"#{metric_group.name}\"? Removes this grouping. #{pluralize(members_n, 'member metric')} #{members_n == 1 ? 'is' : 'are'} kept." %>
|
|
88
|
+
<%= button_to metric_group_path(metric_group), method: :delete,
|
|
89
|
+
form_class: "inline-block",
|
|
90
|
+
class: "ck-icon-btn",
|
|
91
|
+
title: "Delete metric group",
|
|
92
|
+
"aria-label": "Delete metric group",
|
|
93
|
+
data: { turbo_confirm: confirm } do %>
|
|
94
|
+
<%= heroicon_tag "trash", variant: :outline, size: 16, "aria-hidden": "true" %>
|
|
95
|
+
<% end %>
|
|
96
|
+
<% end %>
|
|
97
|
+
<%= link_to "Cancel", metrics_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
43
98
|
<%= form.submit(metric_group.persisted? ? "Save metric group" : "Create metric group", class: ck_button_classes(:dark)) %>
|
|
44
99
|
</div>
|
|
45
100
|
</div>
|
|
@@ -13,27 +13,53 @@
|
|
|
13
13
|
</div>
|
|
14
14
|
</section>
|
|
15
15
|
|
|
16
|
+
<%= render "completion_kit/tags/filter_bar",
|
|
17
|
+
available: @available_tags,
|
|
18
|
+
selected: @selected_tags,
|
|
19
|
+
base_path: metric_groups_path %>
|
|
20
|
+
|
|
16
21
|
<% if @metric_groups.any? %>
|
|
17
22
|
<table class="ck-results-table">
|
|
18
23
|
<thead>
|
|
19
24
|
<tr>
|
|
20
25
|
<th>Name</th>
|
|
21
26
|
<th>Description</th>
|
|
22
|
-
<th>
|
|
27
|
+
<th>Members</th>
|
|
23
28
|
<th></th>
|
|
24
29
|
</tr>
|
|
25
30
|
</thead>
|
|
26
31
|
<tbody>
|
|
27
32
|
<% @metric_groups.each do |metric_group| %>
|
|
28
33
|
<tr onclick="window.location='<%= metric_group_path(metric_group) %>'" style="cursor: pointer;">
|
|
29
|
-
<td
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
<td>
|
|
35
|
+
<strong><%= metric_group.name %></strong>
|
|
36
|
+
<% if metric_group.tags.any? %>
|
|
37
|
+
<div class="tag-marks-row">
|
|
38
|
+
<%= render "completion_kit/tags/marks", tags: metric_group.tags %>
|
|
39
|
+
</div>
|
|
40
|
+
<% end %>
|
|
41
|
+
</td>
|
|
42
|
+
<td class="ck-meta-copy"><div class="ck-clamp-2"><%= metric_group.description.presence || "—" %></div></td>
|
|
43
|
+
<td>
|
|
44
|
+
<% if metric_group.metrics.any? %>
|
|
45
|
+
<div class="ck-mg-members">
|
|
46
|
+
<% metric_group.metrics.each do |m| %>
|
|
47
|
+
<span class="ck-mg-member"><%= m.name %></span>
|
|
48
|
+
<% end %>
|
|
49
|
+
</div>
|
|
50
|
+
<% else %>
|
|
51
|
+
<span class="ck-metrics-table__dim">empty</span>
|
|
52
|
+
<% end %>
|
|
53
|
+
</td>
|
|
32
54
|
<td class="ck-results-table__arrow">→</td>
|
|
33
55
|
</tr>
|
|
34
56
|
<% end %>
|
|
35
57
|
</tbody>
|
|
36
58
|
</table>
|
|
59
|
+
<% elsif @selected_tags.any? %>
|
|
60
|
+
<div class="ck-empty">
|
|
61
|
+
<p>No metric groups match these tags. <%= link_to "Clear filters", metric_groups_path, class: "ck-link" %>.</p>
|
|
62
|
+
</div>
|
|
37
63
|
<% else %>
|
|
38
64
|
<div class="ck-empty">
|
|
39
65
|
<p>No metric groups yet. <%= link_to "Create one", new_metric_group_path, class: "ck-link" %> if you want to group multiple metrics and apply them together.</p>
|
|
@@ -43,8 +43,26 @@
|
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
|
+
<%= render "completion_kit/tags/picker", record: metric, param_namespace: :metric %>
|
|
47
|
+
|
|
46
48
|
<div class="ck-actions">
|
|
47
|
-
|
|
49
|
+
<% if metric.persisted? %>
|
|
50
|
+
<% groups_n = metric.metric_groups.count %>
|
|
51
|
+
<% reviews_n = metric.reviews.count %>
|
|
52
|
+
<% parts = [] %>
|
|
53
|
+
<% parts << "in #{pluralize(groups_n, 'metric group')} (removed from each)" if groups_n > 0 %>
|
|
54
|
+
<% parts << "scored in #{pluralize(reviews_n, 'review')} (scores kept, link cleared)" if reviews_n > 0 %>
|
|
55
|
+
<% confirm = parts.empty? ? "Delete \"#{metric.name}\"? It's not in use." : "Delete \"#{metric.name}\"? It's #{parts.to_sentence}." %>
|
|
56
|
+
<%= button_to metric_path(metric), method: :delete,
|
|
57
|
+
form_class: "inline-block",
|
|
58
|
+
class: "ck-icon-btn",
|
|
59
|
+
title: "Delete metric",
|
|
60
|
+
"aria-label": "Delete metric",
|
|
61
|
+
data: { turbo_confirm: confirm } do %>
|
|
62
|
+
<%= heroicon_tag "trash", variant: :outline, size: 16, "aria-hidden": "true" %>
|
|
63
|
+
<% end %>
|
|
64
|
+
<% end %>
|
|
65
|
+
<%= link_to "Cancel", metrics_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
48
66
|
<%= form.submit(metric.persisted? ? "Save metric" : "Create metric", class: ck_button_classes(:dark)) %>
|
|
49
67
|
</div>
|
|
50
68
|
</div>
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</section>
|
|
10
10
|
|
|
11
|
+
<%= render "completion_kit/tags/filter_bar",
|
|
12
|
+
available: @available_tags,
|
|
13
|
+
selected: @selected_tags,
|
|
14
|
+
base_path: metrics_path %>
|
|
15
|
+
|
|
11
16
|
<% if @metrics.any? %>
|
|
12
17
|
<table class="ck-results-table ck-metrics-table">
|
|
13
18
|
<thead>
|
|
@@ -21,8 +26,15 @@
|
|
|
21
26
|
<tbody>
|
|
22
27
|
<% @metrics.each do |metric| %>
|
|
23
28
|
<tr onclick="window.location='<%= metric_path(metric) %>'" style="cursor: pointer;">
|
|
24
|
-
<td
|
|
25
|
-
|
|
29
|
+
<td>
|
|
30
|
+
<strong><%= metric.name %></strong>
|
|
31
|
+
<% if metric.tags.any? %>
|
|
32
|
+
<div class="tag-marks-row">
|
|
33
|
+
<%= render "completion_kit/tags/marks", tags: metric.tags %>
|
|
34
|
+
</div>
|
|
35
|
+
<% end %>
|
|
36
|
+
</td>
|
|
37
|
+
<td class="ck-meta-copy"><div class="ck-clamp-2"><%= metric.instruction.presence || "—" %></div></td>
|
|
26
38
|
<td>
|
|
27
39
|
<% groups = metric.metric_groups %>
|
|
28
40
|
<% if groups.any? %>
|
|
@@ -48,6 +60,10 @@
|
|
|
48
60
|
Use the same metrics on multiple runs? <%= link_to "Group them →", metric_groups_path, class: "ck-link" %>
|
|
49
61
|
</p>
|
|
50
62
|
<% end %>
|
|
63
|
+
<% elsif @selected_tags.any? %>
|
|
64
|
+
<div class="ck-empty">
|
|
65
|
+
<p>No metrics match these tags. <%= link_to "Clear filters", metrics_path, class: "ck-link" %>.</p>
|
|
66
|
+
</div>
|
|
51
67
|
<% else %>
|
|
52
68
|
<div class="ck-empty">
|
|
53
69
|
<p>No metrics yet. <%= link_to "Create your first metric", new_metric_path, class: "ck-link" %> to start scoring prompt outputs.</p>
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
</section>
|
|
14
14
|
|
|
15
|
+
<% if @metric.tags.any? %>
|
|
16
|
+
<div class="tag-marks-row tag-marks-row--header">
|
|
17
|
+
<%= render "completion_kit/tags/marks", tags: @metric.tags %>
|
|
18
|
+
</div>
|
|
19
|
+
<% end %>
|
|
20
|
+
|
|
15
21
|
<% if @metric.instruction.present? %>
|
|
16
22
|
<section class="ck-card">
|
|
17
23
|
<p class="ck-kicker">Instruction</p>
|
|
@@ -47,8 +47,27 @@
|
|
|
47
47
|
<p class="ck-field-hint" id="refresh-status" style="min-height: 1.2em; margin-top: -0.25rem; font-size: 0.75rem;"> </p>
|
|
48
48
|
</div>
|
|
49
49
|
|
|
50
|
+
<%= render "completion_kit/tags/picker", record: prompt, param_namespace: :prompt %>
|
|
51
|
+
|
|
50
52
|
<div class="ck-actions">
|
|
51
|
-
|
|
53
|
+
<% if prompt.persisted? %>
|
|
54
|
+
<% runs_n = prompt.runs.count %>
|
|
55
|
+
<% responses_n = prompt.responses.count %>
|
|
56
|
+
<% confirm = if runs_n.zero?
|
|
57
|
+
"Delete \"#{prompt.display_name}\"? This version has no runs."
|
|
58
|
+
else
|
|
59
|
+
"Delete \"#{prompt.display_name}\"? Cascades through #{pluralize(runs_n, 'run')} and #{pluralize(responses_n, 'response')} (and their reviews). Other versions of this prompt are untouched."
|
|
60
|
+
end %>
|
|
61
|
+
<%= button_to prompt_path(prompt), method: :delete,
|
|
62
|
+
form_class: "inline-block",
|
|
63
|
+
class: "ck-icon-btn",
|
|
64
|
+
title: "Delete prompt",
|
|
65
|
+
"aria-label": "Delete prompt",
|
|
66
|
+
data: { turbo_confirm: confirm } do %>
|
|
67
|
+
<%= heroicon_tag "trash", variant: :outline, size: 16, "aria-hidden": "true" %>
|
|
68
|
+
<% end %>
|
|
69
|
+
<% end %>
|
|
70
|
+
<%= link_to "Cancel", prompts_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
52
71
|
<%= form.submit(prompt.persisted? ? "Save prompt" : "Create prompt", class: ck_button_classes(:dark), disabled: available.empty?) %>
|
|
53
72
|
</div>
|
|
54
73
|
</div>
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</section>
|
|
10
10
|
|
|
11
|
+
<%= render "completion_kit/tags/filter_bar",
|
|
12
|
+
available: @available_tags,
|
|
13
|
+
selected: @selected_tags,
|
|
14
|
+
base_path: prompts_path %>
|
|
15
|
+
|
|
11
16
|
<% if @prompts.any? %>
|
|
12
17
|
<table class="ck-results-table ck-prompts-table">
|
|
13
18
|
<thead>
|
|
@@ -23,7 +28,14 @@
|
|
|
23
28
|
<tbody>
|
|
24
29
|
<% @prompts.each do |prompt| %>
|
|
25
30
|
<tr onclick="window.location='<%= prompt_path(prompt) %>'" style="cursor: pointer;">
|
|
26
|
-
<td
|
|
31
|
+
<td>
|
|
32
|
+
<strong><%= prompt.name %></strong>
|
|
33
|
+
<% if prompt.tags.any? %>
|
|
34
|
+
<div class="tag-marks-row">
|
|
35
|
+
<%= render "completion_kit/tags/marks", tags: prompt.tags %>
|
|
36
|
+
</div>
|
|
37
|
+
<% end %>
|
|
38
|
+
</td>
|
|
27
39
|
<% latest_version = prompt.family_versions.maximum(:version_number) %>
|
|
28
40
|
<td>
|
|
29
41
|
<span class="ck-chip ck-chip--soft"><%= prompt.version_label %></span>
|
|
@@ -58,6 +70,10 @@
|
|
|
58
70
|
<% end %>
|
|
59
71
|
</tbody>
|
|
60
72
|
</table>
|
|
73
|
+
<% elsif @selected_tags.any? %>
|
|
74
|
+
<div class="ck-empty">
|
|
75
|
+
<p>No prompts match these tags. <%= link_to "Clear filters", prompts_path, class: "ck-link" %>.</p>
|
|
76
|
+
</div>
|
|
61
77
|
<% else %>
|
|
62
78
|
<div class="ck-empty">
|
|
63
79
|
No prompts yet. Create one to get started.
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
</section>
|
|
27
27
|
|
|
28
|
+
<% if @prompt.tags.any? %>
|
|
29
|
+
<div class="tag-marks-row tag-marks-row--header">
|
|
30
|
+
<%= render "completion_kit/tags/marks", tags: @prompt.tags %>
|
|
31
|
+
</div>
|
|
32
|
+
<% end %>
|
|
33
|
+
|
|
28
34
|
<section>
|
|
29
35
|
<div class="ck-prompt-preview__header">
|
|
30
36
|
<p class="ck-kicker">Prompt</p>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
29
|
<div class="ck-actions">
|
|
30
|
-
<%= link_to "Cancel", provider_credentials_path, class: ck_button_classes(:light, variant: :outline) %>
|
|
30
|
+
<%= link_to "Cancel", provider_credentials_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
31
31
|
<%= form.submit(provider_credential.persisted? ? "Save provider" : "Create provider", class: ck_button_classes(:dark)) %>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
<%= turbo_stream_from "completion_kit_provider_#{pc.id}" %>
|
|
3
3
|
<% end %>
|
|
4
4
|
|
|
5
|
+
<%= render "completion_kit/shared/settings_nav", section_label: "Providers" %>
|
|
6
|
+
|
|
5
7
|
<section class="ck-page-header">
|
|
6
8
|
<div>
|
|
7
|
-
<h1 class="ck-title">
|
|
9
|
+
<h1 class="ck-title">Providers</h1>
|
|
8
10
|
<p class="ck-lead">API keys for LLM providers. These are used for both generating prompt completions and running judge evaluations.</p>
|
|
9
11
|
</div>
|
|
10
12
|
<div class="ck-actions">
|
|
@@ -115,9 +115,24 @@
|
|
|
115
115
|
</div>
|
|
116
116
|
<div class="ck-metric-divider"><span>or pick individually</span></div>
|
|
117
117
|
<% end %>
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
<% available_filter_tags = @all_metrics.flat_map(&:tags).uniq.sort_by(&:name) %>
|
|
120
|
+
<% if available_filter_tags.any? %>
|
|
121
|
+
<div class="ck-metric-tag-filter" data-metric-tag-filter>
|
|
122
|
+
<span class="ck-metric-tag-filter__label">Filter metrics by tag</span>
|
|
123
|
+
<% available_filter_tags.each do |tag| %>
|
|
124
|
+
<button type="button"
|
|
125
|
+
class="tag-mark tag-mark--off ck-metric-tag-filter__chip"
|
|
126
|
+
style="--mark-color: var(--tag-<%= tag.color %>);"
|
|
127
|
+
data-filter-tag="<%= tag.name %>"
|
|
128
|
+
onclick="ckToggleMetricGroupFilter(this)"><%= tag.name %></button>
|
|
129
|
+
<% end %>
|
|
130
|
+
</div>
|
|
131
|
+
<% end %>
|
|
132
|
+
|
|
133
|
+
<div class="ck-metric-checkboxes" data-metric-checkboxes>
|
|
119
134
|
<% @all_metrics.each do |metric| %>
|
|
120
|
-
<label class="ck-checkbox-label">
|
|
135
|
+
<label class="ck-checkbox-label" data-metric-tags="<%= metric.tag_names.join(",") %>">
|
|
121
136
|
<%= check_box_tag "run[metric_ids][]", metric.id, run.metric_ids.include?(metric.id), class: "ck-checkbox", id: "run_metric_#{metric.id}" %>
|
|
122
137
|
<span class="ck-checkbox-label__box" aria-hidden="true"></span>
|
|
123
138
|
<span class="ck-checkbox-label__body">
|
|
@@ -125,6 +140,11 @@
|
|
|
125
140
|
<% if metric.instruction.present? %>
|
|
126
141
|
<span class="ck-checkbox-label__hint"><%= truncate(metric.instruction.to_s, length: 90) %></span>
|
|
127
142
|
<% end %>
|
|
143
|
+
<% if metric.tags.any? %>
|
|
144
|
+
<div class="tag-marks-row">
|
|
145
|
+
<%= render "completion_kit/tags/marks", tags: metric.tags %>
|
|
146
|
+
</div>
|
|
147
|
+
<% end %>
|
|
128
148
|
</span>
|
|
129
149
|
</label>
|
|
130
150
|
<% end %>
|
|
@@ -248,8 +268,10 @@ document.querySelectorAll('input[name="run[metric_ids][]"]').forEach(function(cb
|
|
|
248
268
|
updateRunForm();
|
|
249
269
|
</script>
|
|
250
270
|
|
|
271
|
+
<%= render "completion_kit/tags/picker", record: run, param_namespace: :run %>
|
|
272
|
+
|
|
251
273
|
<div class="ck-actions">
|
|
252
|
-
<%= link_to "Cancel", run.persisted? ? run_path(run) : runs_path, class: ck_button_classes(:light, variant: :outline) %>
|
|
274
|
+
<%= link_to "Cancel", run.persisted? ? run_path(run) : runs_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
|
|
253
275
|
<%= form.submit(run.persisted? ? "Save run" : "Create run", class: ck_button_classes(:dark), id: "run-submit") %>
|
|
254
276
|
</div>
|
|
255
277
|
</div>
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
<%= link_to run.dataset.name, dataset_path(run.dataset), class: "ck-runs-table__config-link", onclick: "event.stopPropagation();" %>
|
|
14
14
|
<% end %>
|
|
15
15
|
</div>
|
|
16
|
+
<% if run.tags.any? %>
|
|
17
|
+
<div class="tag-marks-row">
|
|
18
|
+
<%= render "completion_kit/tags/marks", tags: run.tags %>
|
|
19
|
+
</div>
|
|
20
|
+
<% end %>
|
|
16
21
|
</div>
|
|
17
22
|
</td>
|
|
18
23
|
<td>
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</section>
|
|
10
10
|
|
|
11
|
+
<%= render "completion_kit/tags/filter_bar",
|
|
12
|
+
available: @available_tags,
|
|
13
|
+
selected: @selected_tags,
|
|
14
|
+
base_path: runs_path %>
|
|
15
|
+
|
|
11
16
|
<% if @runs.any? %>
|
|
12
17
|
<table class="ck-results-table ck-runs-table">
|
|
13
18
|
<thead>
|
|
@@ -26,6 +31,10 @@
|
|
|
26
31
|
<% end %>
|
|
27
32
|
</tbody>
|
|
28
33
|
</table>
|
|
34
|
+
<% elsif @selected_tags.any? %>
|
|
35
|
+
<div class="ck-empty">
|
|
36
|
+
<p>No runs match these tags. <%= link_to "Clear filters", runs_path, class: "ck-link" %>.</p>
|
|
37
|
+
</div>
|
|
29
38
|
<% else %>
|
|
30
39
|
<div class="ck-empty">No runs yet. <%= link_to "Create your first run →", new_run_path, class: "ck-link" %></div>
|
|
31
40
|
<% end %>
|
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
<%= render "status_header", run: @run %>
|
|
9
9
|
|
|
10
|
+
<% if @run.tags.any? %>
|
|
11
|
+
<div class="tag-marks-row tag-marks-row--header">
|
|
12
|
+
<%= render "completion_kit/tags/marks", tags: @run.tags %>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
10
16
|
<% if @run.dataset %>
|
|
11
17
|
<% dataset_lines = @run.dataset.csv_data.to_s.lines %>
|
|
12
18
|
<% dataset_preview_lines = dataset_lines.first(50) %>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<p class="ck-settings-kicker">
|
|
2
|
+
Settings <span class="ck-settings-kicker__sep">/</span>
|
|
3
|
+
<% link = local_assigns[:section_link] %>
|
|
4
|
+
<%= link ? link_to(section_label, link, class: "ck-settings-kicker__link") : section_label %>
|
|
5
|
+
<% if local_assigns[:trail].present? %>
|
|
6
|
+
<span class="ck-settings-kicker__sep">/</span>
|
|
7
|
+
<%= trail.html_safe %>
|
|
8
|
+
<% end %>
|
|
9
|
+
</p>
|