completion-kit 0.28.20 → 0.28.21
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8242f60832e3c23d204132839a832e082eb5115c26afd46eb2082ca4e342f908
|
|
4
|
+
data.tar.gz: 5798c4e0f853e3aa5a2ae20291a7909cc5f70dd7baaa5e9bd2765cb5cbbe5f4f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec13a779260638ccd8968c9c3be4bd250780fdda06f01ea13b9963553756329cb0c092603a7ee66118e854227bcdb68b2b360e66a1e7830c2cfeffc879bf35d3
|
|
7
|
+
data.tar.gz: 92dd2c71fd38a9cc31638c77927a21a9a53f6ba8a4f4b81dc876f652dbf91c3d601722b402dd71f108d7530ab96442d1d2c113aadf60684ab767902c1e3ec1c9
|
|
@@ -6,8 +6,9 @@ module CompletionKit
|
|
|
6
6
|
before_action :load_form_collections, only: [:new, :edit, :create, :update]
|
|
7
7
|
|
|
8
8
|
def index
|
|
9
|
-
scope = Run.includes(:prompt, :dataset, :tags
|
|
10
|
-
@runs = apply_tag_filter(scope)
|
|
9
|
+
scope = Run.includes(:prompt, :dataset, :tags).order(created_at: :desc).display_scoped
|
|
10
|
+
@runs = apply_tag_filter(scope).load
|
|
11
|
+
Run.preload_summaries(@runs)
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
RESPONSES_PER_PAGE = 100
|
|
@@ -14,6 +14,8 @@ module CompletionKit
|
|
|
14
14
|
has_many :suggestions, dependent: :destroy
|
|
15
15
|
has_many :dashboard_dismissals, as: :dismissable, dependent: :destroy
|
|
16
16
|
|
|
17
|
+
attr_writer :avg_score, :check_pass_rate, :metric_averages, :response_count
|
|
18
|
+
|
|
17
19
|
validates :name, presence: true
|
|
18
20
|
validates :status, inclusion: { in: STATUSES }
|
|
19
21
|
validate :dataset_supplies_prompt_variables
|
|
@@ -34,6 +36,58 @@ module CompletionKit
|
|
|
34
36
|
display_scoped.select(:id)
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
# Batch-compute the list-view summaries (response count, avg score, check
|
|
40
|
+
# pass rate, per-metric averages) for a set of runs in a constant number of
|
|
41
|
+
# grouped queries, injecting the results so the index never loads a single
|
|
42
|
+
# response or review object. Mirrors the per-run reader methods exactly.
|
|
43
|
+
def self.preload_summaries(runs)
|
|
44
|
+
runs = runs.to_a
|
|
45
|
+
return runs if runs.empty?
|
|
46
|
+
|
|
47
|
+
run_ids = runs.map(&:id)
|
|
48
|
+
counts = Response.where(run_id: run_ids).group(:run_id).count
|
|
49
|
+
|
|
50
|
+
run_col = Arel.sql("completion_kit_responses.run_id")
|
|
51
|
+
base = Review.joins(:response).where(completion_kit_responses: {run_id: run_ids})
|
|
52
|
+
|
|
53
|
+
run_rows = base.group(run_col).pluck(
|
|
54
|
+
run_col,
|
|
55
|
+
Arel.sql("AVG(ai_score)"),
|
|
56
|
+
Arel.sql("COUNT(passed)"),
|
|
57
|
+
Arel.sql("SUM(CASE WHEN passed THEN 1 ELSE 0 END)")
|
|
58
|
+
)
|
|
59
|
+
run_stats = run_rows.each_with_object({}) do |(rid, avg, resolved, passed), h|
|
|
60
|
+
h[rid] = {avg: avg, resolved: resolved.to_i, passed: passed.to_i}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
metric_rows = base.group(run_col, :metric_name).pluck(
|
|
64
|
+
run_col,
|
|
65
|
+
:metric_name,
|
|
66
|
+
Arel.sql("AVG(ai_score)"),
|
|
67
|
+
Arel.sql("COUNT(ai_score)"),
|
|
68
|
+
Arel.sql("COUNT(passed)"),
|
|
69
|
+
Arel.sql("SUM(CASE WHEN passed THEN 1 ELSE 0 END)")
|
|
70
|
+
)
|
|
71
|
+
metrics_by_run = metric_rows.group_by(&:first)
|
|
72
|
+
|
|
73
|
+
runs.each do |run|
|
|
74
|
+
run.response_count = counts.fetch(run.id, 0)
|
|
75
|
+
|
|
76
|
+
stats = run_stats[run.id]
|
|
77
|
+
run.avg_score = stats && stats[:avg] ? stats[:avg].to_f.round(2) : nil
|
|
78
|
+
run.check_pass_rate = stats && stats[:resolved] > 0 ? (stats[:passed].to_f / stats[:resolved]).round(2) : nil
|
|
79
|
+
|
|
80
|
+
run.metric_averages = (metrics_by_run[run.id] || []).filter_map do |(_rid, name, avg, scored, resolved, passed)|
|
|
81
|
+
if scored.to_i > 0
|
|
82
|
+
{name: name, avg: avg.to_f.round(1)}
|
|
83
|
+
elsif resolved.to_i > 0
|
|
84
|
+
{name: name, kind: "check", pass_rate: (passed.to_i.to_f / resolved.to_i).round(2)}
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
runs
|
|
89
|
+
end
|
|
90
|
+
|
|
37
91
|
# A scoring-only run grades a pre-existing column on the dataset instead of
|
|
38
92
|
# generating new outputs. No prompt is attached; the response text is read
|
|
39
93
|
# from row[output_column]; no LLM generation happens.
|
|
@@ -126,7 +180,15 @@ module CompletionKit
|
|
|
126
180
|
end
|
|
127
181
|
end
|
|
128
182
|
|
|
183
|
+
def response_count
|
|
184
|
+
return @response_count if defined?(@response_count)
|
|
185
|
+
|
|
186
|
+
responses.size
|
|
187
|
+
end
|
|
188
|
+
|
|
129
189
|
def avg_score
|
|
190
|
+
return @avg_score if defined?(@avg_score)
|
|
191
|
+
|
|
130
192
|
scores = reviews_for_summary.map(&:ai_score).compact.map(&:to_f)
|
|
131
193
|
return nil if scores.empty?
|
|
132
194
|
|
|
@@ -134,6 +196,8 @@ module CompletionKit
|
|
|
134
196
|
end
|
|
135
197
|
|
|
136
198
|
def metric_averages
|
|
199
|
+
return @metric_averages if defined?(@metric_averages)
|
|
200
|
+
|
|
137
201
|
reviews_for_summary.group_by(&:metric_name).filter_map do |name, reviews|
|
|
138
202
|
scored = reviews.select { |r| r.ai_score.present? }
|
|
139
203
|
if scored.any?
|
|
@@ -150,6 +214,8 @@ module CompletionKit
|
|
|
150
214
|
end
|
|
151
215
|
|
|
152
216
|
def check_pass_rate
|
|
217
|
+
return @check_pass_rate if defined?(@check_pass_rate)
|
|
218
|
+
|
|
153
219
|
resolved = reviews_for_summary.reject { |r| r.passed.nil? }
|
|
154
220
|
return nil if resolved.empty?
|
|
155
221
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</td>
|
|
28
28
|
<td>
|
|
29
29
|
<span class="ck-runs-table__count">
|
|
30
|
-
<%= run.
|
|
30
|
+
<%= run.response_count %><% if run.dataset %><span class="ck-runs-table__count-of">/<%= run.dataset.row_count %></span><% end %>
|
|
31
31
|
</span>
|
|
32
32
|
</td>
|
|
33
33
|
<td>
|