completion-kit 0.26.5 → 0.26.6

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: 870c7454b6181023648742b79a1682b09137cdd8480074b8c10c9382c1e0eb4c
4
- data.tar.gz: b4faee283f8da861406d36c90ef201ea7bf35d4d725ec3103b42f9025d6b3beb
3
+ metadata.gz: a1d7db0abdd990413e60ba5ef164580ef34485396f02598336ddca4e2ce39f4d
4
+ data.tar.gz: 7a8563ba729f30c7296fefd6aab9b3de6b6aee8c1b7823739ed96d545424f96c
5
5
  SHA512:
6
- metadata.gz: 0f20cad2387e3c95fa2a00b6caebde697de4c10d21eb7b44f71b2a47bfcfa60100dc5a94041aa435a5de470cff2a7b9a214e976c4c6a4f2a6d83f0f4baf71b4f
7
- data.tar.gz: a713d5273431e17b145a14f85645aa437c143f2d86e93f6401ddd0bd7d6ade437004870aa5c03da39967003ec5d4429d5977df19b1ea981bf70db3c042475a5b
6
+ metadata.gz: e3b52c0043a89ae3fdf78735291fa4caffdd043c98f5ad35c99ea2d9969ba8c3b284ae50d24cde31f528e35cf4a51172b946d150116bc525e71fe02658528108
7
+ data.tar.gz: 946d48be8c7d204cc94d47f97cc0c71856199226e8602d3e94df293204d4cfe87dff50a70d2b71f672e0df0cf82dc7d061de4908ba2dd3599e87cc5640eb59e1
@@ -12,12 +12,21 @@ module CompletionKit
12
12
  model = options[:model]
13
13
  max_tokens = options[:max_tokens] || 1000
14
14
  temperature = options[:temperature] || 0.7
15
-
16
- response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature)
17
-
18
- if response.status == 400 && temperature_unsupported?(response.body)
19
- @temperature_dropped = true
20
- response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: nil)
15
+ max_completion = false
16
+
17
+ response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature, max_completion: max_completion)
18
+
19
+ 2.times do
20
+ break unless response.status == 400
21
+ if !max_completion && max_tokens_unsupported?(response.body)
22
+ max_completion = true
23
+ elsif !temperature.nil? && temperature_unsupported?(response.body)
24
+ @temperature_dropped = true
25
+ temperature = nil
26
+ else
27
+ break
28
+ end
29
+ response = post_chat(model: model, prompt: prompt, max_tokens: max_tokens, temperature: temperature, max_completion: max_completion)
21
30
  end
22
31
 
23
32
  if response.status == 429
@@ -49,12 +58,12 @@ module CompletionKit
49
58
  return [] unless configured?
50
59
  return [] unless ProviderEndpoint.safe?(api_endpoint)
51
60
 
52
- response = build_connection(azure_base_url).get(models_path) do |req|
61
+ response = build_connection(azure_base_url).get(models_url) do |req|
53
62
  req.headers["api-key"] = api_key
54
63
  end
55
64
  return [] unless response.success?
56
65
 
57
- JSON.parse(response.body).fetch("data", []).map { |entry| { id: entry["id"], name: entry["id"] } }
66
+ parse_models(response.body)
58
67
  rescue StandardError
59
68
  []
60
69
  end
@@ -92,13 +101,33 @@ module CompletionKit
92
101
  api_version.blank?
93
102
  end
94
103
 
95
- def models_path
96
- v1_mode? ? "/openai/v1/models" : "/openai/deployments?api-version=#{api_version}"
104
+ def foundry_project?
105
+ api_endpoint.to_s.include?("/api/projects/")
97
106
  end
98
107
 
99
- def post_chat(model:, prompt:, max_tokens:, temperature:)
100
- body = { messages: [{ role: "user", content: prompt }], max_tokens: max_tokens }
108
+ def models_url
109
+ if foundry_project?
110
+ "#{azure_base_url}/deployments?api-version=v1"
111
+ elsif v1_mode?
112
+ "/openai/v1/models"
113
+ else
114
+ "/openai/deployments?api-version=#{api_version}"
115
+ end
116
+ end
117
+
118
+ def parse_models(body)
119
+ json = JSON.parse(body)
120
+ if foundry_project?
121
+ json.fetch("value", []).map { |d| { id: d["name"], name: d["name"] } }
122
+ else
123
+ json.fetch("data", []).map { |e| { id: e["id"], name: e["id"] } }
124
+ end
125
+ end
126
+
127
+ def post_chat(model:, prompt:, max_tokens:, temperature:, max_completion: false)
128
+ body = { messages: [{ role: "user", content: prompt }] }
101
129
  body[:model] = model if v1_mode?
130
+ body[max_completion ? :max_completion_tokens : :max_tokens] = max_tokens
102
131
  body[:temperature] = temperature unless temperature.nil?
103
132
 
104
133
  build_connection(azure_base_url, timeout: 30, open_timeout: 5).post do |req|
@@ -113,5 +142,10 @@ module CompletionKit
113
142
  s = body.to_s
114
143
  s.include?("temperature") && (s.include?("deprecated") || s.include?("not supported") || s.include?("Unsupported parameter"))
115
144
  end
145
+
146
+ def max_tokens_unsupported?(body)
147
+ s = body.to_s
148
+ s.include?("max_tokens") && (s.include?("max_completion_tokens") || s.include?("not supported") || s.include?("Unsupported parameter"))
149
+ end
116
150
  end
117
151
  end
@@ -156,17 +156,26 @@ module CompletionKit
156
156
  def fetch_azure_foundry_models
157
157
  raise DiscoveryError, "An Azure endpoint URL is required." if @api_endpoint.blank?
158
158
 
159
- response = fetch_connection(azure_base_url).get(azure_models_path) do |req|
159
+ response = fetch_connection(azure_base_url).get(azure_foundry_project? ? "#{azure_base_url}/deployments?api-version=v1" : azure_models_path) do |req|
160
160
  req.headers["api-key"] = @api_key
161
161
  end
162
162
  raise DiscoveryError, azure_error_message(response) unless response.success?
163
- JSON.parse(response.body).fetch("data", []).map { |e| { id: e["id"], display_name: e["id"] } }
163
+ body = JSON.parse(response.body)
164
+ if azure_foundry_project?
165
+ body.fetch("value", []).map { |d| { id: d["name"], display_name: d["name"] } }
166
+ else
167
+ body.fetch("data", []).map { |e| { id: e["id"], display_name: e["id"] } }
168
+ end
164
169
  end
165
170
 
166
171
  def azure_v1_mode?
167
172
  @api_version.blank?
168
173
  end
169
174
 
175
+ def azure_foundry_project?
176
+ @api_endpoint.to_s.include?("/api/projects/")
177
+ end
178
+
170
179
  def azure_models_path
171
180
  azure_v1_mode? ? "/openai/v1/models" : "/openai/deployments?api-version=#{@api_version}"
172
181
  end
@@ -177,8 +186,16 @@ module CompletionKit
177
186
 
178
187
  def azure_error_message(response)
179
188
  detail = extract_provider_error_message(response.body)
180
- hint = azure_v1_mode? ? "Check the endpoint base URL." : "Check the endpoint base URL and api-version."
181
- path = azure_v1_mode? ? "/openai/v1/models" : "/openai/deployments"
189
+ if azure_foundry_project?
190
+ path = "/deployments"
191
+ hint = "Check the project endpoint URL."
192
+ elsif azure_v1_mode?
193
+ path = "/openai/v1/models"
194
+ hint = "Check the endpoint base URL."
195
+ else
196
+ path = "/openai/deployments"
197
+ hint = "Check the endpoint base URL and api-version."
198
+ end
182
199
  with_detail("Azure did not return a model list at #{path} (#{response.status}). #{hint}", detail)
183
200
  end
184
201
 
@@ -437,8 +454,17 @@ module CompletionKit
437
454
  f.request :retry, max: 1, interval: 0.5
438
455
  f.adapter Faraday.default_adapter
439
456
  end
440
- body = { messages: [{ role: "user", content: input }], max_tokens: max_tokens }
457
+ response = azure_probe_post(conn, model_id, input, max_tokens, max_completion: false)
458
+ if response.status == 400 && azure_max_tokens_unsupported?(response.body)
459
+ response = azure_probe_post(conn, model_id, input, max_tokens, max_completion: true)
460
+ end
461
+ response
462
+ end
463
+
464
+ def azure_probe_post(conn, model_id, input, max_tokens, max_completion:)
465
+ body = { messages: [{ role: "user", content: input }] }
441
466
  body[:model] = model_id if azure_v1_mode?
467
+ body[max_completion ? :max_completion_tokens : :max_tokens] = max_tokens
442
468
  conn.post do |req|
443
469
  req.url(azure_v1_mode? ? "/openai/v1/chat/completions" : "/openai/deployments/#{model_id}/chat/completions?api-version=#{@api_version}")
444
470
  req.headers["Content-Type"] = "application/json"
@@ -446,5 +472,10 @@ module CompletionKit
446
472
  req.body = body.to_json
447
473
  end
448
474
  end
475
+
476
+ def azure_max_tokens_unsupported?(body)
477
+ s = body.to_s
478
+ s.include?("max_tokens") && (s.include?("max_completion_tokens") || s.include?("not supported") || s.include?("Unsupported parameter"))
479
+ end
449
480
  end
450
481
  end
@@ -1,5 +1,5 @@
1
1
  <ol class="ck-breadcrumb">
2
- <li><%= link_to "Settings", provider_credentials_path %></li>
2
+ <li><%= link_to "Providers", provider_credentials_path %></li>
3
3
  <li>Edit</li>
4
4
  </ol>
5
5
 
@@ -1,5 +1,5 @@
1
1
  <ol class="ck-breadcrumb">
2
- <li><%= link_to "Settings", provider_credentials_path %></li>
2
+ <li><%= link_to "Providers", provider_credentials_path %></li>
3
3
  <li>New</li>
4
4
  </ol>
5
5
 
@@ -64,6 +64,12 @@
64
64
  <span class="ck-run-config__none">None</span>
65
65
  <% end %>
66
66
  </div>
67
+ <% if @run.prompt&.llm_model.present? %>
68
+ <div class="ck-run-config__row">
69
+ <span class="ck-run-config__key">Model</span>
70
+ <span style="text-transform: none;"><%= @run.prompt.llm_model %></span>
71
+ </div>
72
+ <% end %>
67
73
  <% if @run.judge_model.present? %>
68
74
  <div class="ck-run-config__row">
69
75
  <span class="ck-run-config__key">Judge</span>
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.26.5"
2
+ VERSION = "0.26.6"
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.26.5
4
+ version: 0.26.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin