completion-kit 0.28.34 → 0.28.36
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/app/controllers/completion_kit/runs_controller.rb +5 -1
- data/app/jobs/completion_kit/judge_review_job.rb +4 -0
- data/app/models/completion_kit/run.rb +6 -3
- data/app/services/completion_kit/anthropic_client.rb +2 -9
- data/app/services/completion_kit/azure_foundry_client.rb +1 -8
- data/app/services/completion_kit/judge_service.rb +4 -0
- data/app/services/completion_kit/llm_client.rb +47 -0
- data/app/services/completion_kit/mcp_tools/runs.rb +6 -2
- data/app/services/completion_kit/ollama_client.rb +2 -9
- data/app/services/completion_kit/open_ai_client.rb +3 -10
- data/app/services/completion_kit/open_router_client.rb +2 -9
- data/app/views/completion_kit/runs/_form.html.erb +12 -3
- data/app/views/completion_kit/runs/_run_config.html.erb +53 -0
- data/app/views/completion_kit/runs/show.html.erb +1 -51
- data/db/migrate/20260804000001_add_judge_temperature_ignored_to_runs.rb +5 -0
- data/lib/completion_kit/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9c91a74066fe93a6df18e5e02a8fc8277bb93f4f15f3d4aed392ab911e88febc
|
|
4
|
+
data.tar.gz: 4d193ac02c79e75763aa97fcc528ab21521ce2ddbf290350818c539746601633
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8cbeba6b6a76455b23c4c9f45c88e77c73995e1dfa29bbc4be3acce814633977cd4a00af594df92f77e4740640907cdff520373582d19688aa2aec897bcf84b5
|
|
7
|
+
data.tar.gz: bd564daac0efe50d01a1b0850af2ca452f427ab6496b22a1af88865f4dc01917bb32f50d9b2371be88dbfe56e75acff0adfcd0e5b42f34c32d1ffd3b5f035f81
|
|
@@ -130,6 +130,7 @@ module CompletionKit
|
|
|
130
130
|
format.turbo_stream do
|
|
131
131
|
render turbo_stream: [
|
|
132
132
|
turbo_stream.replace("run_status_header", partial: "completion_kit/runs/status_header", locals: { run: @run }),
|
|
133
|
+
turbo_stream.replace("run_config", partial: "completion_kit/runs/run_config", locals: { run: @run }),
|
|
133
134
|
turbo_stream.replace("run_status_panel", partial: "completion_kit/runs/status_panel", locals: { run: @run }),
|
|
134
135
|
turbo_stream.replace("run_responses_region", partial: "completion_kit/runs/responses_region",
|
|
135
136
|
locals: { run: @run, responses: @responses, responses_offset: @responses_offset })
|
|
@@ -222,7 +223,10 @@ module CompletionKit
|
|
|
222
223
|
end
|
|
223
224
|
|
|
224
225
|
def run_params
|
|
225
|
-
params.require(:run).permit(:name, :prompt_id, :dataset_id, :judge_model, :temperature, :max_tokens, :judge_temperature, :output_column, :expected_column, metric_ids: [], tag_names: [])
|
|
226
|
+
permitted = params.require(:run).permit(:name, :prompt_id, :dataset_id, :judge_model, :temperature, :max_tokens, :judge_temperature, :output_column, :expected_column, :omit_temperature, metric_ids: [], tag_names: [])
|
|
227
|
+
omit = permitted.delete(:omit_temperature)
|
|
228
|
+
permitted[:temperature] = nil if omit == "1"
|
|
229
|
+
permitted
|
|
226
230
|
end
|
|
227
231
|
|
|
228
232
|
# Editing a run that already has results forks a new run — but only when a
|
|
@@ -75,6 +75,10 @@ module CompletionKit
|
|
|
75
75
|
record_terminal_failure!(e)
|
|
76
76
|
enqueue_completion_check
|
|
77
77
|
return
|
|
78
|
+
ensure
|
|
79
|
+
if judge.temperature_dropped? && !run.judge_temperature_ignored?
|
|
80
|
+
run.update_columns(judge_temperature_ignored: true)
|
|
81
|
+
end
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
review = response.reviews.find_or_initialize_by(metric_id: metric.id)
|
|
@@ -337,7 +337,9 @@ module CompletionKit
|
|
|
337
337
|
progress_current: 0,
|
|
338
338
|
progress_total: 0,
|
|
339
339
|
failure_summary: nil,
|
|
340
|
-
error_message: nil
|
|
340
|
+
error_message: nil,
|
|
341
|
+
temperature_ignored: false,
|
|
342
|
+
judge_temperature_ignored: false
|
|
341
343
|
)
|
|
342
344
|
end
|
|
343
345
|
rescue ActiveRecord::RecordInvalid => e
|
|
@@ -436,7 +438,7 @@ module CompletionKit
|
|
|
436
438
|
error_status: nil,
|
|
437
439
|
error_message: nil
|
|
438
440
|
)
|
|
439
|
-
update!(status: "running", failure_summary: nil, error_message: nil)
|
|
441
|
+
update!(status: "running", failure_summary: nil, error_message: nil, judge_temperature_ignored: false)
|
|
440
442
|
|
|
441
443
|
response_ids.each do |rid|
|
|
442
444
|
llm_metrics.each { |m| JudgeReviewJob.perform_later(rid, m.id, id) } if llm_judge_configured?
|
|
@@ -467,7 +469,7 @@ module CompletionKit
|
|
|
467
469
|
end
|
|
468
470
|
|
|
469
471
|
def nondeterministic_judge?
|
|
470
|
-
judge_temperature.to_f > 0
|
|
472
|
+
judge_temperature.to_f > 0 || judge_temperature_ignored?
|
|
471
473
|
end
|
|
472
474
|
|
|
473
475
|
def rerun!
|
|
@@ -559,6 +561,7 @@ module CompletionKit
|
|
|
559
561
|
expected_column: expected_column,
|
|
560
562
|
created_at: created_at, updated_at: updated_at,
|
|
561
563
|
max_tokens: max_tokens, judge_temperature: judge_temperature,
|
|
564
|
+
temperature_ignored: temperature_ignored, judge_temperature_ignored: judge_temperature_ignored,
|
|
562
565
|
responses_count: responses.count, avg_score: avg_score,
|
|
563
566
|
check_pass_rate: check_pass_rate,
|
|
564
567
|
metric_averages: metric_averages,
|
|
@@ -5,9 +5,6 @@ module CompletionKit
|
|
|
5
5
|
{ id: "claude-3-5-haiku-latest", name: "Claude 3.5 Haiku" }
|
|
6
6
|
].freeze
|
|
7
7
|
|
|
8
|
-
def temperature_dropped?
|
|
9
|
-
@temperature_dropped == true
|
|
10
|
-
end
|
|
11
8
|
|
|
12
9
|
def generate_completion(prompt, options = {})
|
|
13
10
|
@temperature_dropped = false
|
|
@@ -15,11 +12,11 @@ module CompletionKit
|
|
|
15
12
|
|
|
16
13
|
model = options[:model] || "claude-3-7-sonnet-latest"
|
|
17
14
|
max_tokens = options[:max_tokens] || 1000
|
|
18
|
-
temperature = options
|
|
15
|
+
temperature = resolve_temperature(options)
|
|
19
16
|
|
|
20
17
|
response = post_messages(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature)
|
|
21
18
|
|
|
22
|
-
if response.status == 400 && temperature_unsupported?(response.body)
|
|
19
|
+
if response.status == 400 && !temperature.nil? && temperature_unsupported?(response.body)
|
|
23
20
|
@temperature_dropped = true
|
|
24
21
|
response = post_messages(model: model, prompt: prompt, max_tokens: max_tokens, temperature: nil)
|
|
25
22
|
end
|
|
@@ -97,9 +94,5 @@ module CompletionKit
|
|
|
97
94
|
end
|
|
98
95
|
end
|
|
99
96
|
|
|
100
|
-
def temperature_unsupported?(body)
|
|
101
|
-
s = body.to_s
|
|
102
|
-
s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported"))
|
|
103
|
-
end
|
|
104
97
|
end
|
|
105
98
|
end
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
module CompletionKit
|
|
2
2
|
class AzureFoundryClient < LlmClient
|
|
3
|
-
def temperature_dropped?
|
|
4
|
-
@temperature_dropped == true
|
|
5
|
-
end
|
|
6
3
|
|
|
7
4
|
def generate_completion(prompt, options = {})
|
|
8
5
|
@temperature_dropped = false
|
|
@@ -11,7 +8,7 @@ module CompletionKit
|
|
|
11
8
|
|
|
12
9
|
model = options[:model]
|
|
13
10
|
max_tokens = options[:max_tokens] || 1000
|
|
14
|
-
temperature = options
|
|
11
|
+
temperature = resolve_temperature(options)
|
|
15
12
|
max_completion = false
|
|
16
13
|
|
|
17
14
|
response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature, max_completion: max_completion)
|
|
@@ -129,10 +126,6 @@ module CompletionKit
|
|
|
129
126
|
end
|
|
130
127
|
end
|
|
131
128
|
|
|
132
|
-
def temperature_unsupported?(body)
|
|
133
|
-
s = body.to_s
|
|
134
|
-
s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported") || s.include?("Unsupported parameter"))
|
|
135
|
-
end
|
|
136
129
|
|
|
137
130
|
def max_tokens_unsupported?(body)
|
|
138
131
|
s = body.to_s
|
|
@@ -13,6 +13,10 @@ module CompletionKit
|
|
|
13
13
|
@judge_client = LlmClient.for_model(@judge_model, ApiConfig.for_model(@judge_model))
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def temperature_dropped?
|
|
17
|
+
@judge_client.temperature_dropped?
|
|
18
|
+
end
|
|
19
|
+
|
|
16
20
|
def evaluate(output, expected_output = nil, prompt = nil, criteria: nil, rubric_text: nil, input_data: nil, human_examples: nil, **_extras)
|
|
17
21
|
raise CompletionKit::ConfigurationError, "Judge not configured" unless @judge_client.configured?
|
|
18
22
|
|
|
@@ -4,10 +4,46 @@ require "json"
|
|
|
4
4
|
|
|
5
5
|
module CompletionKit
|
|
6
6
|
class LlmClient
|
|
7
|
+
DEFAULT_TEMPERATURE = 0.7
|
|
8
|
+
|
|
9
|
+
# Providers phrase a temperature refusal every which way. OpenAI's current
|
|
10
|
+
# reasoning models say "Unsupported value: 'temperature' does not support
|
|
11
|
+
# 0.7 with this model. Only the default (1) value is supported.", which
|
|
12
|
+
# shares no wording with Azure's "Unsupported parameter" or Anthropic's
|
|
13
|
+
# "not supported". Matching on any one phrasing silently turns a
|
|
14
|
+
# recoverable refusal into a failed row.
|
|
15
|
+
#
|
|
16
|
+
# The wording can sit on either side of the parameter name, so both orders
|
|
17
|
+
# carry the same phrase set, and a provider that names the offending field
|
|
18
|
+
# outright gets a branch of its own.
|
|
19
|
+
#
|
|
20
|
+
# Neither gap may cross a brace, which stops a refusal aimed at some other
|
|
21
|
+
# parameter from matching a temperature echoed back in a neighbouring
|
|
22
|
+
# object of the same body. The phrase-first gap additionally bars commas,
|
|
23
|
+
# because "unsupported parameter: logprobs. Supported: model, prompt,
|
|
24
|
+
# temperature" is a list of what IS allowed and must not read as a refusal.
|
|
25
|
+
# The temperature-first gap has to allow commas, since "temperature, top_p
|
|
26
|
+
# and top_k are not supported" is a genuine refusal.
|
|
27
|
+
REFUSAL_PHRASE = /
|
|
28
|
+
deprecated | not\s+supported | does\s+not\s+support |
|
|
29
|
+
only\s+the\s+default | unsupported\s+(?:parameter|value)
|
|
30
|
+
/xi
|
|
31
|
+
TEMPERATURE_REFUSAL = /
|
|
32
|
+
temperature [^{}]{0,80}? #{REFUSAL_PHRASE}
|
|
33
|
+
|
|
|
34
|
+
#{REFUSAL_PHRASE} [^{},]{0,80}? temperature
|
|
35
|
+
|
|
|
36
|
+
"param" \s*:\s* "temperature"
|
|
37
|
+
/xi
|
|
38
|
+
|
|
7
39
|
def initialize(config = {})
|
|
8
40
|
@config = config
|
|
9
41
|
end
|
|
10
42
|
|
|
43
|
+
def temperature_dropped?
|
|
44
|
+
@temperature_dropped == true
|
|
45
|
+
end
|
|
46
|
+
|
|
11
47
|
def generate_completion(prompt, options = {})
|
|
12
48
|
raise NotImplementedError, "Subclasses must implement generate_completion"
|
|
13
49
|
end
|
|
@@ -50,6 +86,17 @@ module CompletionKit
|
|
|
50
86
|
|
|
51
87
|
protected
|
|
52
88
|
|
|
89
|
+
# An explicit nil means the caller wants no temperature sent at all, which
|
|
90
|
+
# is the only request many current models accept. An absent key still gets
|
|
91
|
+
# the historical default.
|
|
92
|
+
def resolve_temperature(options)
|
|
93
|
+
options.key?(:temperature) ? options[:temperature] : DEFAULT_TEMPERATURE
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def temperature_unsupported?(body)
|
|
97
|
+
TEMPERATURE_REFUSAL.match?(body.to_s)
|
|
98
|
+
end
|
|
99
|
+
|
|
53
100
|
def build_connection(url, timeout: nil, open_timeout: nil)
|
|
54
101
|
Faraday.new(url: url) do |f|
|
|
55
102
|
f.options.timeout = timeout if timeout
|
|
@@ -4,7 +4,9 @@ module CompletionKit
|
|
|
4
4
|
extend Base
|
|
5
5
|
|
|
6
6
|
TEMPERATURE_DESCRIPTION = "Sampling temperature for generation, 0 to 1. Defaults to the column default. " \
|
|
7
|
-
"Reasoning models ignore it and the run is flagged temperature_ignored."
|
|
7
|
+
"Reasoning models ignore it and the run is flagged temperature_ignored. " \
|
|
8
|
+
"Pass null to send no temperature at all, which is what models that refuse " \
|
|
9
|
+
"the parameter require.".freeze
|
|
8
10
|
|
|
9
11
|
MAX_TOKENS_DESCRIPTION = "Cap on generated tokens per row. Leave unset to use the provider client's default, " \
|
|
10
12
|
"which is what silently truncates long outputs and makes the judge score malformed " \
|
|
@@ -181,7 +183,9 @@ module CompletionKit
|
|
|
181
183
|
if run.metric_ids.empty?
|
|
182
184
|
warnings << "No metrics are attached, so this run judges nothing. Attach metric_ids or a metric_group_id before generating."
|
|
183
185
|
end
|
|
184
|
-
if run.
|
|
186
|
+
if run.judge_temperature_ignored?
|
|
187
|
+
warnings << "The judge model refused the temperature parameter, so it was re-sent without one and the provider applied its own default. judge_temperature reads #{run.judge_temperature} but was never applied, and these scores are not reproducible. Pick a judge model that accepts temperature if you need reproducible scoring."
|
|
188
|
+
elsif run.nondeterministic_judge?
|
|
185
189
|
warnings << "Judge temperature is #{run.judge_temperature}. Judging above 0 makes scores irreproducible: the same output can get a different score on a re-judge. Set judge_temperature to 0 unless you are deliberately measuring judge variance."
|
|
186
190
|
end
|
|
187
191
|
return json if warnings.empty?
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
module CompletionKit
|
|
2
2
|
class OllamaClient < LlmClient
|
|
3
|
-
def temperature_dropped?
|
|
4
|
-
@temperature_dropped == true
|
|
5
|
-
end
|
|
6
3
|
|
|
7
4
|
def generate_completion(prompt, options = {})
|
|
8
5
|
@temperature_dropped = false
|
|
@@ -11,11 +8,11 @@ module CompletionKit
|
|
|
11
8
|
|
|
12
9
|
model = options[:model]
|
|
13
10
|
max_tokens = options[:max_tokens] || 1000
|
|
14
|
-
temperature = options
|
|
11
|
+
temperature = resolve_temperature(options)
|
|
15
12
|
|
|
16
13
|
response = post_completion(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature)
|
|
17
14
|
|
|
18
|
-
if response.status == 400 && temperature_unsupported?(response.body)
|
|
15
|
+
if response.status == 400 && !temperature.nil? && temperature_unsupported?(response.body)
|
|
19
16
|
@temperature_dropped = true
|
|
20
17
|
response = post_completion(model: model, prompt: prompt, max_tokens: max_tokens, temperature: nil)
|
|
21
18
|
end
|
|
@@ -97,9 +94,5 @@ module CompletionKit
|
|
|
97
94
|
end
|
|
98
95
|
end
|
|
99
96
|
|
|
100
|
-
def temperature_unsupported?(body)
|
|
101
|
-
s = body.to_s
|
|
102
|
-
s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported") || s.include?("Unsupported parameter"))
|
|
103
|
-
end
|
|
104
97
|
end
|
|
105
98
|
end
|
|
@@ -6,9 +6,6 @@ module CompletionKit
|
|
|
6
6
|
{ id: "gpt-4o-mini", name: "GPT-4o Mini" }
|
|
7
7
|
].freeze
|
|
8
8
|
|
|
9
|
-
def temperature_dropped?
|
|
10
|
-
@temperature_dropped == true
|
|
11
|
-
end
|
|
12
9
|
|
|
13
10
|
def generate_completion(prompt, options = {})
|
|
14
11
|
@temperature_dropped = false
|
|
@@ -16,11 +13,11 @@ module CompletionKit
|
|
|
16
13
|
|
|
17
14
|
model = options[:model] || "gpt-4.1-mini"
|
|
18
15
|
max_tokens = options[:max_tokens] || 8192
|
|
19
|
-
temperature = options
|
|
16
|
+
temperature = resolve_temperature(options)
|
|
20
17
|
|
|
21
18
|
response = post_responses(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature)
|
|
22
19
|
|
|
23
|
-
if response.status == 400 && temperature_unsupported?(response.body)
|
|
20
|
+
if response.status == 400 && !temperature.nil? && temperature_unsupported?(response.body)
|
|
24
21
|
@temperature_dropped = true
|
|
25
22
|
response = post_responses(model: model, prompt: prompt, max_tokens: max_tokens, temperature: nil)
|
|
26
23
|
end
|
|
@@ -38,7 +35,7 @@ module CompletionKit
|
|
|
38
35
|
data = JSON.parse(response.body)
|
|
39
36
|
if data["status"] == "incomplete"
|
|
40
37
|
reason = data.dig("incomplete_details", "reason") || "unknown"
|
|
41
|
-
return "Error: response incomplete (#{reason})
|
|
38
|
+
return "Error: response incomplete (#{reason}). Increase max_tokens=#{max_tokens} or pick a non-reasoning judge model"
|
|
42
39
|
end
|
|
43
40
|
message = Array(data["output"]).find { |o| o["type"] == "message" }
|
|
44
41
|
content = message&.dig("content", 0, "text").to_s.strip
|
|
@@ -93,9 +90,5 @@ module CompletionKit
|
|
|
93
90
|
end
|
|
94
91
|
end
|
|
95
92
|
|
|
96
|
-
def temperature_unsupported?(body)
|
|
97
|
-
s = body.to_s
|
|
98
|
-
s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported") || s.include?("Unsupported parameter"))
|
|
99
|
-
end
|
|
100
93
|
end
|
|
101
94
|
end
|
|
@@ -4,9 +4,6 @@ module CompletionKit
|
|
|
4
4
|
REFERER = "https://completionkit.com".freeze
|
|
5
5
|
APP_TITLE = "CompletionKit".freeze
|
|
6
6
|
|
|
7
|
-
def temperature_dropped?
|
|
8
|
-
@temperature_dropped == true
|
|
9
|
-
end
|
|
10
7
|
|
|
11
8
|
def generate_completion(prompt, options = {})
|
|
12
9
|
@temperature_dropped = false
|
|
@@ -14,11 +11,11 @@ module CompletionKit
|
|
|
14
11
|
|
|
15
12
|
model = options[:model] || "openai/gpt-4o-mini"
|
|
16
13
|
max_tokens = options[:max_tokens] || 8192
|
|
17
|
-
temperature = options
|
|
14
|
+
temperature = resolve_temperature(options)
|
|
18
15
|
|
|
19
16
|
response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature)
|
|
20
17
|
|
|
21
|
-
if response.status == 400 && temperature_unsupported?(response.body)
|
|
18
|
+
if response.status == 400 && !temperature.nil? && temperature_unsupported?(response.body)
|
|
22
19
|
@temperature_dropped = true
|
|
23
20
|
response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: nil)
|
|
24
21
|
end
|
|
@@ -90,9 +87,5 @@ module CompletionKit
|
|
|
90
87
|
end
|
|
91
88
|
end
|
|
92
89
|
|
|
93
|
-
def temperature_unsupported?(body)
|
|
94
|
-
s = body.to_s
|
|
95
|
-
s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported") || s.include?("Unsupported parameter"))
|
|
96
|
-
end
|
|
97
90
|
end
|
|
98
91
|
end
|
|
@@ -85,12 +85,21 @@
|
|
|
85
85
|
|
|
86
86
|
<div class="ck-field">
|
|
87
87
|
<label class="ck-label" for="run_temperature" style="position: relative;">
|
|
88
|
-
Temperature<span class="ck-info-toggle" tabindex="0">?</span><span class="ck-info-popup">Controls how random the model's output is. Lower values are more focused and deterministic
|
|
88
|
+
Temperature<span class="ck-info-toggle" tabindex="0">?</span><span class="ck-info-popup">Controls how random the model's output is. Lower values are more focused and deterministic, so the model picks the most likely words. Higher values are more varied and creative, with more risk of odd phrasing. Most LLMs default to 1.0; for evaluation, try a few values and see how your prompt holds up. Newer reasoning models (Claude Opus 4.7, GPT-5 family, etc.) refuse temperature outright. CompletionKit detects that and re-sends without the parameter, and flags the run so you know the value was never applied. Tick the box below to skip sending it in the first place.</span>
|
|
89
89
|
</label>
|
|
90
90
|
<div class="ck-slider-row">
|
|
91
|
-
<%= form.range_field :temperature, min: 0, max: 1, step: 0.1, class: "ck-slider", id: "run_temperature", oninput: "document.getElementById('temp-value').textContent = this.value" %>
|
|
92
|
-
<span class="ck-slider-value" id="temp-value"><%= run.temperature
|
|
91
|
+
<%= form.range_field :temperature, min: 0, max: 1, step: 0.1, class: "ck-slider", id: "run_temperature", disabled: run.temperature.nil?, oninput: "document.getElementById('temp-value').textContent = this.value" %>
|
|
92
|
+
<span class="ck-slider-value" id="temp-value"><%= run.temperature.nil? ? "off" : run.temperature %></span>
|
|
93
93
|
</div>
|
|
94
|
+
<label class="ck-checkbox-label">
|
|
95
|
+
<%= check_box_tag "run[omit_temperature]", "1", run.temperature.nil?, id: "run_omit_temperature", class: "ck-checkbox",
|
|
96
|
+
onchange: "document.getElementById('run_temperature').disabled = this.checked; document.getElementById('temp-value').textContent = this.checked ? 'off' : document.getElementById('run_temperature').value;" %>
|
|
97
|
+
<span class="ck-checkbox-label__box" aria-hidden="true"></span>
|
|
98
|
+
<span class="ck-checkbox-label__body">
|
|
99
|
+
<span class="ck-checkbox-label__text">Send no temperature</span>
|
|
100
|
+
<span class="ck-checkbox-label__hint">The model applies its own default. Required by models that refuse the parameter, which most current frontier models do.</span>
|
|
101
|
+
</span>
|
|
102
|
+
</label>
|
|
94
103
|
</div>
|
|
95
104
|
|
|
96
105
|
<div class="ck-field">
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<div class="ck-run-config" id="run_config">
|
|
2
|
+
<div class="ck-run-config__row">
|
|
3
|
+
<span class="ck-run-config__key">Created</span>
|
|
4
|
+
<time datetime="<%= run.created_at.iso8601 %>" data-local-time><%= run.created_at.utc.strftime("%Y-%m-%d %H:%M UTC") %></time>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="ck-run-config__row">
|
|
7
|
+
<span class="ck-run-config__key">Dataset</span>
|
|
8
|
+
<% if run.dataset %>
|
|
9
|
+
<span class="ck-run-config__dataset">
|
|
10
|
+
<%= link_to run.dataset.name, dataset_path(run.dataset), class: "ck-link" %>
|
|
11
|
+
<span class="ck-run-config__dataset-meta"><%= run.dataset.row_count %> rows</span>
|
|
12
|
+
<button type="button" class="ck-run-config__dataset-preview" onclick="document.getElementById('dataset-preview-<%= run.id %>').showModal()">Preview</button>
|
|
13
|
+
</span>
|
|
14
|
+
<% else %>
|
|
15
|
+
<span class="ck-run-config__none">None</span>
|
|
16
|
+
<% end %>
|
|
17
|
+
</div>
|
|
18
|
+
<% if run.judge_model.present? %>
|
|
19
|
+
<div class="ck-run-config__row">
|
|
20
|
+
<span class="ck-run-config__key">Judge</span>
|
|
21
|
+
<span style="text-transform: none;"><%= run.judge_model %></span>
|
|
22
|
+
<% unless run.judge_configured? %>
|
|
23
|
+
<span class="ck-run-config__warn">provider not configured</span>
|
|
24
|
+
<% end %>
|
|
25
|
+
</div>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% if run.metrics.any? %>
|
|
28
|
+
<div class="ck-run-config__row">
|
|
29
|
+
<span class="ck-run-config__key">Metrics</span>
|
|
30
|
+
<span><%= run.metrics.map { |m| link_to(m.name, metric_path(m), class: "ck-link") }.join(", ").html_safe %></span>
|
|
31
|
+
</div>
|
|
32
|
+
<% end %>
|
|
33
|
+
<div class="ck-run-config__row">
|
|
34
|
+
<span class="ck-run-config__key">Temperature</span>
|
|
35
|
+
<span><%= run.temperature.nil? ? "Not sent, provider default" : run.temperature %></span>
|
|
36
|
+
<% if run.temperature_ignored? %>
|
|
37
|
+
<span class="ck-run-config__warn" style="color: var(--ck-dim);" title="The model rejected the temperature parameter, so CompletionKit re-sent the request without it.">ignored by model</span>
|
|
38
|
+
<% end %>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="ck-run-config__row">
|
|
41
|
+
<span class="ck-run-config__key">Max tokens</span>
|
|
42
|
+
<span><%= run.max_tokens || "Provider default" %></span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="ck-run-config__row">
|
|
45
|
+
<span class="ck-run-config__key">Judge temperature</span>
|
|
46
|
+
<span><%= run.judge_temperature %></span>
|
|
47
|
+
<% if run.judge_temperature_ignored? %>
|
|
48
|
+
<span class="ck-run-config__warn" style="color: var(--ck-warning);" title="The judge model refused the temperature parameter, so CompletionKit re-sent the request without it and the provider applied its own default. The scores are not reproducible despite the setting above.">refused by judge, not reproducible</span>
|
|
49
|
+
<% elsif run.nondeterministic_judge? %>
|
|
50
|
+
<span class="ck-run-config__warn" style="color: var(--ck-warning);" title="Judging above temperature 0 makes scores irreproducible. The same output can get a different score on a re-judge.">scores not reproducible</span>
|
|
51
|
+
<% end %>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
@@ -50,57 +50,7 @@
|
|
|
50
50
|
<% end %>
|
|
51
51
|
<% end %>
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
<div class="ck-run-config__row">
|
|
55
|
-
<span class="ck-run-config__key">Created</span>
|
|
56
|
-
<time datetime="<%= @run.created_at.iso8601 %>" data-local-time><%= @run.created_at.utc.strftime("%Y-%m-%d %H:%M UTC") %></time>
|
|
57
|
-
</div>
|
|
58
|
-
<div class="ck-run-config__row">
|
|
59
|
-
<span class="ck-run-config__key">Dataset</span>
|
|
60
|
-
<% if @run.dataset %>
|
|
61
|
-
<span class="ck-run-config__dataset">
|
|
62
|
-
<%= link_to @run.dataset.name, dataset_path(@run.dataset), class: "ck-link" %>
|
|
63
|
-
<span class="ck-run-config__dataset-meta"><%= @run.dataset.row_count %> rows</span>
|
|
64
|
-
<button type="button" class="ck-run-config__dataset-preview" onclick="document.getElementById('dataset-preview-<%= @run.id %>').showModal()">Preview</button>
|
|
65
|
-
</span>
|
|
66
|
-
<% else %>
|
|
67
|
-
<span class="ck-run-config__none">None</span>
|
|
68
|
-
<% end %>
|
|
69
|
-
</div>
|
|
70
|
-
<% if @run.judge_model.present? %>
|
|
71
|
-
<div class="ck-run-config__row">
|
|
72
|
-
<span class="ck-run-config__key">Judge</span>
|
|
73
|
-
<span style="text-transform: none;"><%= @run.judge_model %></span>
|
|
74
|
-
<% unless @run.judge_configured? %>
|
|
75
|
-
<span class="ck-run-config__warn">provider not configured</span>
|
|
76
|
-
<% end %>
|
|
77
|
-
</div>
|
|
78
|
-
<% end %>
|
|
79
|
-
<% if @run.metrics.any? %>
|
|
80
|
-
<div class="ck-run-config__row">
|
|
81
|
-
<span class="ck-run-config__key">Metrics</span>
|
|
82
|
-
<span><%= @run.metrics.map { |m| link_to(m.name, metric_path(m), class: "ck-link") }.join(", ").html_safe %></span>
|
|
83
|
-
</div>
|
|
84
|
-
<% end %>
|
|
85
|
-
<div class="ck-run-config__row">
|
|
86
|
-
<span class="ck-run-config__key">Temperature</span>
|
|
87
|
-
<span><%= @run.temperature %></span>
|
|
88
|
-
<% if @run.temperature_ignored? %>
|
|
89
|
-
<span class="ck-run-config__warn" style="color: var(--ck-dim);" title="The model rejected the temperature parameter, so CompletionKit re-sent the request without it.">ignored by model</span>
|
|
90
|
-
<% end %>
|
|
91
|
-
</div>
|
|
92
|
-
<div class="ck-run-config__row">
|
|
93
|
-
<span class="ck-run-config__key">Max tokens</span>
|
|
94
|
-
<span><%= @run.max_tokens || "Provider default" %></span>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="ck-run-config__row">
|
|
97
|
-
<span class="ck-run-config__key">Judge temperature</span>
|
|
98
|
-
<span><%= @run.judge_temperature %></span>
|
|
99
|
-
<% if @run.nondeterministic_judge? %>
|
|
100
|
-
<span class="ck-run-config__warn" style="color: var(--ck-warning);" title="Judging above temperature 0 makes scores irreproducible. The same output can get a different score on a re-judge.">scores not reproducible</span>
|
|
101
|
-
<% end %>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
53
|
+
<%= render "run_config", run: @run %>
|
|
104
54
|
|
|
105
55
|
<% if @run.prompt %>
|
|
106
56
|
<div class="ck-prompt-preview">
|
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.28.
|
|
4
|
+
version: 0.28.36
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Damien Bastin
|
|
@@ -373,6 +373,7 @@ files:
|
|
|
373
373
|
- app/views/completion_kit/runs/_response_row.html.erb
|
|
374
374
|
- app/views/completion_kit/runs/_responses_region.html.erb
|
|
375
375
|
- app/views/completion_kit/runs/_row.html.erb
|
|
376
|
+
- app/views/completion_kit/runs/_run_config.html.erb
|
|
376
377
|
- app/views/completion_kit/runs/_sort_toolbar.html.erb
|
|
377
378
|
- app/views/completion_kit/runs/_status_header.html.erb
|
|
378
379
|
- app/views/completion_kit/runs/_status_panel.html.erb
|
|
@@ -447,6 +448,7 @@ files:
|
|
|
447
448
|
- db/migrate/20260728000001_add_max_tokens_to_completion_kit_runs.rb
|
|
448
449
|
- db/migrate/20260730000001_add_judge_temperature_to_completion_kit_runs.rb
|
|
449
450
|
- db/migrate/20260730000002_create_completion_kit_prompt_serves.rb
|
|
451
|
+
- db/migrate/20260804000001_add_judge_temperature_ignored_to_runs.rb
|
|
450
452
|
- lib/completion-kit.rb
|
|
451
453
|
- lib/completion_kit.rb
|
|
452
454
|
- lib/completion_kit/concurrency_check.rb
|