completion-kit 0.27.9 → 0.28.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c963af7241cc97480aa462a422e3c34fb2f25ea813a380083443e68678f724b
4
- data.tar.gz: 8a20da4fd8a0fac0e6395816cd65a4bc79ebf48756439414a343467f41ab2c2b
3
+ metadata.gz: 49de7d9ec92e8fb633cebd08ad79baeb32158864beeb06796321b909f862dcfe
4
+ data.tar.gz: 47a798af3557ca3e95dc0f0897e032aa121f0014824cc71bbd71dace49437bdd
5
5
  SHA512:
6
- metadata.gz: a9575cfcb4ef088a9e34c92d9852341f69eff3130f2d0e7845fc6517ce939dd9f8252c7c7722946b106de72dc2ad281388a0fc4a63134d8d8e69b9d037506825
7
- data.tar.gz: 4050b952aea1c85a1871de868218fb9637cd662d30e4b1508f47ef2920f5d7e57c12b21b8a09c6cc7d0bc6e718f05032938ae6b47733767fcb458d3ccf374949
6
+ metadata.gz: 4a94dae22a11aa716352e8b5f44109479ad87af5a7928ea1d98ce095beccc46468fb02c79fe5afc7c044616eba4b260931c2a309ea15bbb916aa44bbc5bc3f56
7
+ data.tar.gz: a9a8920af149a4aad600ce8b95635fd89abf678d76e8bd84e69a462e73ec1588c29cb71a82f4159928e058f671487fe21c109f2cf7026eebde57a41c6ea94af4
@@ -286,6 +286,13 @@ form.button_to {
286
286
  margin-top: 0.45rem;
287
287
  }
288
288
 
289
+ .ck-pagination {
290
+ display: flex;
291
+ align-items: center;
292
+ gap: 1rem;
293
+ margin-top: 1rem;
294
+ }
295
+
289
296
  .ck-title,
290
297
  .ck-section-title,
291
298
  .ck-card-title,
@@ -10,8 +10,18 @@ module CompletionKit
10
10
  @runs = apply_tag_filter(scope)
11
11
  end
12
12
 
13
+ RESPONSES_PER_PAGE = 100
14
+
13
15
  def show
14
- @responses = ordered_responses_relation(@run, params[:sort]).includes(:reviews)
16
+ @responses_total = @run.responses.count
17
+ @responses_per_page = RESPONSES_PER_PAGE
18
+ @responses_total_pages = [(@responses_total.to_f / RESPONSES_PER_PAGE).ceil, 1].max
19
+ @responses_page = params[:page].to_i.clamp(1, @responses_total_pages)
20
+ @responses_offset = (@responses_page - 1) * RESPONSES_PER_PAGE
21
+ @responses = ordered_responses_relation(@run, params[:sort])
22
+ .includes(:reviews)
23
+ .limit(RESPONSES_PER_PAGE)
24
+ .offset(@responses_offset)
15
25
  end
16
26
 
17
27
  def new
@@ -29,16 +29,15 @@ module CompletionKit
29
29
  "#{base} #{styles}"
30
30
  end
31
31
 
32
- def ck_delete_trigger(form_id:, label:, confirm: nil, disabled: false, title: nil)
32
+ def ck_delete_trigger(form_id:, label:, confirm: nil)
33
33
  content_tag(
34
34
  :button,
35
35
  type: "submit",
36
- form: (disabled ? nil : form_id),
36
+ form: form_id,
37
37
  class: "ck-icon-btn",
38
- title: title || label,
38
+ title: label,
39
39
  "aria-label": label,
40
- disabled: disabled,
41
- data: (disabled ? {} : {turbo_confirm: confirm, ck_confirm_label: "Delete", ck_confirm_tone: "danger"})
40
+ data: {turbo_confirm: confirm, ck_confirm_label: "Delete", ck_confirm_tone: "danger"}
42
41
  ) do
43
42
  heroicon_tag "trash", variant: :outline, size: 16, "aria-hidden": "true"
44
43
  end
@@ -99,7 +99,7 @@ module CompletionKit
99
99
  parts = []
100
100
  parts << "#{prompt_count} #{'prompt'.pluralize(prompt_count)}" if prompt_count.positive?
101
101
  parts << "#{judge_count} judge #{'run'.pluralize(judge_count)}" if judge_count.positive?
102
- "#{display_provider} is still in use by #{parts.to_sentence}. Remove those references before deleting it."
102
+ "#{display_provider} is in use by #{parts.to_sentence} and can't be deleted."
103
103
  end
104
104
 
105
105
  def broadcast_discovery_progress
@@ -201,7 +201,6 @@ module CompletionKit
201
201
  end
202
202
  end
203
203
 
204
- failed_row = nil
205
204
  begin
206
205
  transaction do
207
206
  responses.destroy_all
@@ -212,37 +211,46 @@ module CompletionKit
212
211
  failure_summary: nil,
213
212
  error_message: nil
214
213
  )
215
- rows.each_with_index do |row, index|
216
- failed_row = index
217
- input = row.empty? ? nil : row.to_json
218
- attrs = {
219
- status: "pending",
220
- row_index: index,
221
- input_data: input,
222
- expected_output: row[expected_column.presence || "expected_output"]
223
- }
224
- if judge_only?
225
- attrs[:status] = "succeeded"
226
- column = output_column.presence || "actual_output"
227
- attrs[:response_text] = row[column].to_s if dataset && dataset.headers.include?(column)
228
- end
229
214
 
230
- response = responses.create!(attrs)
231
-
232
- if judge_only?
233
- llm_metrics.each { |m| JudgeReviewJob.perform_later(response.id, m.id, id) } if llm_judge_configured?
234
- check_metrics.each { |m| CheckReviewJob.perform_later(response.id, m.id, id) }
235
- else
236
- GenerateRowJob.perform_later(id, response.id)
215
+ now = Time.current
216
+ out_col = output_column.presence || "actual_output"
217
+ exp_col = expected_column.presence || "expected_output"
218
+ judge = judge_only?
219
+ has_output = judge && dataset && dataset.headers.include?(out_col)
220
+ scope_defaults = Response.all.where_values_hash.symbolize_keys
221
+
222
+ response_attrs = rows.each_with_index.map do |row, index|
223
+ {
224
+ run_id: id,
225
+ status: judge ? "succeeded" : "pending",
226
+ row_index: index,
227
+ input_data: row.empty? ? nil : row.to_json,
228
+ expected_output: row[exp_col],
229
+ response_text: (judge && has_output ? row[out_col].to_s : nil),
230
+ attempts: 0,
231
+ created_at: now,
232
+ updated_at: now
233
+ }.merge(scope_defaults)
234
+ end
235
+ Response.insert_all(response_attrs)
236
+ responses.reset
237
+
238
+ response_ids = responses.order(:row_index).pluck(:id)
239
+ if judge
240
+ judge_metrics = llm_judge_configured? ? llm_metrics.to_a : []
241
+ chk_metrics = check_metrics.to_a
242
+ response_ids.each do |rid|
243
+ judge_metrics.each { |m| JudgeReviewJob.perform_later(rid, m.id, id) }
244
+ chk_metrics.each { |m| CheckReviewJob.perform_later(rid, m.id, id) }
237
245
  end
246
+ RunCompletionCheckJob.perform_later(id)
247
+ else
248
+ response_ids.each { |rid| GenerateRowJob.perform_later(id, rid) }
238
249
  end
239
-
240
- RunCompletionCheckJob.perform_later(id) if judge_only?
241
250
  end
242
251
  rescue ActiveRecord::RecordInvalid => e
243
252
  reload
244
- detail = e.record.errors.full_messages.to_sentence
245
- return fail_with_summary!(failed_row ? "Row #{failed_row + 1}: #{detail}" : detail)
253
+ return fail_with_summary!(e.record.errors.full_messages.to_sentence)
246
254
  end
247
255
 
248
256
  safely_broadcast do
@@ -1,6 +1,5 @@
1
1
  <% if provider_credential.persisted? %>
2
2
  <% pc_delete_id = "ck_delete_provider_#{provider_credential.id}" %>
3
- <% pc_delete_blocked = provider_credential.in_use? %>
4
3
  <% pc_delete_confirm = "Delete the #{provider_credential.display_provider} provider and its discovered models? This can't be undone." %>
5
4
  <% end %>
6
5
  <%= form_with(model: provider_credential, local: true) do |form| %>
@@ -37,24 +36,21 @@
37
36
  <%= form.label :api_version, "API version", class: "ck-label" %>
38
37
  <%= form.text_field :api_version, class: "ck-input", placeholder: "e.g. 2024-10-21", **ck_field_aria(form, :api_version) %>
39
38
  <%= ck_field_error(form, :api_version) %>
40
- <p class="ck-field-hint">Optional. Leave blank to use Azure's v1 API, or set a dated version for the legacy API (which also lists your deployments during discovery).</p>
39
+ <p class="ck-field-hint">Optional. Leave blank to use Azure's v1 API.</p>
41
40
  </div>
42
41
 
43
42
  <div class="ck-actions">
44
43
  <% if provider_credential.persisted? %>
45
- <%= ck_delete_trigger(form_id: pc_delete_id, label: "Delete provider", confirm: pc_delete_confirm, disabled: pc_delete_blocked, title: (pc_delete_blocked ? provider_credential.in_use_message : "Delete provider")) %>
44
+ <%= ck_delete_trigger(form_id: pc_delete_id, label: "Delete provider", confirm: pc_delete_confirm) %>
46
45
  <% end %>
47
46
  <%= link_to "Cancel", provider_credentials_path, class: ck_button_classes(:light, variant: :outline), tabindex: "0" %>
48
47
  <%= form.submit(provider_credential.persisted? ? "Save provider" : "Create provider", class: ck_button_classes(:dark)) %>
49
48
  </div>
50
- <% if provider_credential.persisted? && pc_delete_blocked %>
51
- <p class="ck-field-hint"><%= provider_credential.in_use_message %></p>
52
- <% end %>
53
49
 
54
50
  </div>
55
51
  <% end %>
56
52
 
57
- <% if provider_credential.persisted? && !pc_delete_blocked %>
53
+ <% if provider_credential.persisted? %>
58
54
  <%= render "completion_kit/shared/delete_form", form_id: pc_delete_id, path: provider_credential_path(provider_credential) %>
59
55
  <% end %>
60
56
 
@@ -197,11 +197,23 @@
197
197
  </thead>
198
198
  <tbody id="run_responses">
199
199
  <% @responses.each_with_index do |response, idx| %>
200
- <%= render "response_row", run: @run, response: response, index: idx + 1 %>
200
+ <%= render "response_row", run: @run, response: response, index: @responses_offset + idx + 1 %>
201
201
  <% end %>
202
202
  </tbody>
203
203
  </table>
204
204
 
205
+ <% if @responses_total_pages > 1 %>
206
+ <nav class="ck-pagination" aria-label="Response pages">
207
+ <% if @responses_page > 1 %>
208
+ <%= link_to run_path(@run, page: @responses_page - 1, sort: params[:sort]), class: ck_button_classes(:light, variant: :outline) do %>&larr; Prev<% end %>
209
+ <% end %>
210
+ <span class="ck-meta-copy">Page <%= @responses_page %> of <%= @responses_total_pages %> &middot; <%= pluralize(@responses_total, "response") %></span>
211
+ <% if @responses_page < @responses_total_pages %>
212
+ <%= link_to run_path(@run, page: @responses_page + 1, sort: params[:sort]), class: ck_button_classes(:light, variant: :outline) do %>Next &rarr;<% end %>
213
+ <% end %>
214
+ </nav>
215
+ <% end %>
216
+
205
217
  <% if @run.status.in?(%w[pending running]) %>
206
218
  <script>
207
219
  (function() {
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.27.9"
2
+ VERSION = "0.28.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completion-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.9
4
+ version: 0.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin