completion-kit 0.26.3 → 0.26.4
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/models/completion_kit/provider_credential.rb +0 -1
- data/app/services/completion_kit/azure_foundry_client.rb +11 -3
- data/app/services/completion_kit/model_discovery_service.rb +17 -6
- data/app/views/completion_kit/provider_credentials/_form.html.erb +1 -0
- data/lib/completion_kit/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c296e624ff4313d1e4f4804cf902cce88ac7e5eee95deccefec8ff69241ff89d
|
|
4
|
+
data.tar.gz: 6f0c48e6efaa5fd65c23e07656687de56031f6c3634593d1a44cf9b40b560c11
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4d0c20a2c591456cb9d7def96f8bd01ea143b66c3cbb678a10e6a68c5310e40a6bf8b69cc547b3c5e802905b31e4b741dcff5c2a6fb110d652ceb363a03548b
|
|
7
|
+
data.tar.gz: 58a03c4e699a33193dfe2cfaed23a3913cd0b1b2819a79beaca2559d38016c0c131e0cf0817b97a9c50651dc92a717d0146986d015065f588327cc63d075c7dc
|
|
@@ -26,7 +26,6 @@ module CompletionKit
|
|
|
26
26
|
validates :provider, presence: true, inclusion: { in: PROVIDERS }
|
|
27
27
|
validates :provider, tenant_scoped_uniqueness: true
|
|
28
28
|
validates :api_endpoint, presence: true, if: :azure_foundry?
|
|
29
|
-
validates :api_version, presence: true, if: :azure_foundry?
|
|
30
29
|
validate :api_endpoint_not_internal
|
|
31
30
|
|
|
32
31
|
after_save :enqueue_discovery
|
|
@@ -49,7 +49,7 @@ module CompletionKit
|
|
|
49
49
|
return [] unless configured?
|
|
50
50
|
return [] unless ProviderEndpoint.safe?(api_endpoint)
|
|
51
51
|
|
|
52
|
-
response = build_connection(azure_base_url).get(
|
|
52
|
+
response = build_connection(azure_base_url).get(models_path) do |req|
|
|
53
53
|
req.headers["api-key"] = api_key
|
|
54
54
|
end
|
|
55
55
|
return [] unless response.success?
|
|
@@ -67,7 +67,6 @@ module CompletionKit
|
|
|
67
67
|
errors = []
|
|
68
68
|
errors << "Azure endpoint is not configured" if api_endpoint.blank?
|
|
69
69
|
errors << "Azure API key is not configured" if api_key.blank?
|
|
70
|
-
errors << "Azure api-version is not configured" if api_version.blank?
|
|
71
70
|
errors
|
|
72
71
|
end
|
|
73
72
|
|
|
@@ -89,12 +88,21 @@ module CompletionKit
|
|
|
89
88
|
api_endpoint.to_s.strip.delete_suffix("/")
|
|
90
89
|
end
|
|
91
90
|
|
|
91
|
+
def v1_mode?
|
|
92
|
+
api_version.blank?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def models_path
|
|
96
|
+
v1_mode? ? "/openai/v1/models" : "/openai/deployments?api-version=#{api_version}"
|
|
97
|
+
end
|
|
98
|
+
|
|
92
99
|
def post_chat(model:, prompt:, max_tokens:, temperature:)
|
|
93
100
|
body = { messages: [{ role: "user", content: prompt }], max_tokens: max_tokens }
|
|
101
|
+
body[:model] = model if v1_mode?
|
|
94
102
|
body[:temperature] = temperature unless temperature.nil?
|
|
95
103
|
|
|
96
104
|
build_connection(azure_base_url, timeout: 30, open_timeout: 5).post do |req|
|
|
97
|
-
req.url "/openai/deployments/#{model}/chat/completions?api-version=#{api_version}"
|
|
105
|
+
req.url(v1_mode? ? "/openai/v1/chat/completions" : "/openai/deployments/#{model}/chat/completions?api-version=#{api_version}")
|
|
98
106
|
req.headers["Content-Type"] = "application/json"
|
|
99
107
|
req.headers["api-key"] = api_key
|
|
100
108
|
req.body = body.to_json
|
|
@@ -133,7 +133,7 @@ module CompletionKit
|
|
|
133
133
|
def custom_endpoint_404_message
|
|
134
134
|
message = "No OpenAI-compatible model list was found at #{custom_endpoint_host}/v1/models (404). Check that the base URL is correct."
|
|
135
135
|
return message unless azure_custom_host?
|
|
136
|
-
"#{message} This looks like an Azure endpoint; add it with the Azure AI Foundry provider
|
|
136
|
+
"#{message} This looks like an Azure endpoint; add it with the Azure AI Foundry provider."
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def with_detail(message, detail)
|
|
@@ -155,22 +155,31 @@ module CompletionKit
|
|
|
155
155
|
|
|
156
156
|
def fetch_azure_foundry_models
|
|
157
157
|
raise DiscoveryError, "An Azure endpoint URL is required." if @api_endpoint.blank?
|
|
158
|
-
raise DiscoveryError, "An Azure api-version is required." if @api_version.blank?
|
|
159
158
|
|
|
160
|
-
response = fetch_connection(azure_base_url).get(
|
|
159
|
+
response = fetch_connection(azure_base_url).get(azure_models_path) do |req|
|
|
161
160
|
req.headers["api-key"] = @api_key
|
|
162
161
|
end
|
|
163
162
|
raise DiscoveryError, azure_error_message(response) unless response.success?
|
|
164
163
|
JSON.parse(response.body).fetch("data", []).map { |e| { id: e["id"], display_name: e["id"] } }
|
|
165
164
|
end
|
|
166
165
|
|
|
166
|
+
def azure_v1_mode?
|
|
167
|
+
@api_version.blank?
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def azure_models_path
|
|
171
|
+
azure_v1_mode? ? "/openai/v1/models" : "/openai/deployments?api-version=#{@api_version}"
|
|
172
|
+
end
|
|
173
|
+
|
|
167
174
|
def azure_base_url
|
|
168
175
|
@api_endpoint.to_s.strip.delete_suffix("/")
|
|
169
176
|
end
|
|
170
177
|
|
|
171
178
|
def azure_error_message(response)
|
|
172
179
|
detail = extract_provider_error_message(response.body)
|
|
173
|
-
|
|
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"
|
|
182
|
+
with_detail("Azure did not return a model list at #{path} (#{response.status}). #{hint}", detail)
|
|
174
183
|
end
|
|
175
184
|
|
|
176
185
|
def reconcile(discovered)
|
|
@@ -428,11 +437,13 @@ module CompletionKit
|
|
|
428
437
|
f.request :retry, max: 1, interval: 0.5
|
|
429
438
|
f.adapter Faraday.default_adapter
|
|
430
439
|
end
|
|
440
|
+
body = { messages: [{ role: "user", content: input }], max_tokens: max_tokens }
|
|
441
|
+
body[:model] = model_id if azure_v1_mode?
|
|
431
442
|
conn.post do |req|
|
|
432
|
-
req.url "/openai/deployments/#{model_id}/chat/completions?api-version=#{@api_version}"
|
|
443
|
+
req.url(azure_v1_mode? ? "/openai/v1/chat/completions" : "/openai/deployments/#{model_id}/chat/completions?api-version=#{@api_version}")
|
|
433
444
|
req.headers["Content-Type"] = "application/json"
|
|
434
445
|
req.headers["api-key"] = @api_key
|
|
435
|
-
req.body =
|
|
446
|
+
req.body = body.to_json
|
|
436
447
|
end
|
|
437
448
|
end
|
|
438
449
|
end
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
<%= form.label :api_version, "API version", class: "ck-label" %>
|
|
38
38
|
<%= form.text_field :api_version, class: "ck-input", placeholder: "e.g. 2024-10-21", **ck_field_aria(form, :api_version) %>
|
|
39
39
|
<%= 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>
|
|
40
41
|
</div>
|
|
41
42
|
|
|
42
43
|
<div class="ck-actions">
|