Class: Legion::Extensions::Llm::AzureFoundry::Provider
- Inherits:
-
Provider
- Object
- Provider
- Legion::Extensions::Llm::AzureFoundry::Provider
- Includes:
- Provider::OpenAICompatible
- Defined in:
- lib/legion/extensions/llm/azure_foundry/provider.rb
Overview
Azure AI Foundry and Azure OpenAI hosted provider surface.
Defined Under Namespace
Modules: Capabilities
Constant Summary collapse
- DEFAULT_API_VERSION =
'2024-05-01-preview'- MODEL_INFERENCE_SURFACE =
:model_inference- OPENAI_V1_SURFACE =
:openai_v1
Class Method Summary collapse
- .capabilities ⇒ Object
- .configuration_options ⇒ Object
- .configuration_requirements ⇒ Object
- .deployment_config(model_id, config:) ⇒ Object
- .normalize_deployments(deployments) ⇒ Object
- .resolve_model_id(model_id, config: nil) ⇒ Object
- .slug ⇒ Object
Instance Method Summary collapse
- #api_base ⇒ Object
-
#chat(messages, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}) ⇒ Object
rubocop:disable Metrics/ParameterLists.
- #chat_url ⇒ Object
- #completion_url ⇒ Object
- #count_tokens(messages, model:) ⇒ Object
- #discover_offerings(live: false, **filters) ⇒ Object
- #embed(text, model:, dimensions: nil, input_type: nil) ⇒ Object
- #embedding_url ⇒ Object
- #headers ⇒ Object
- #health(live: false) ⇒ Object
- #health_url ⇒ Object
- #list_models ⇒ Object
- #models_url ⇒ Object
-
#offering_for(model:, model_family: nil, canonical_model_alias: nil, instance_id: :default, usage_type: nil, **metadata) ⇒ Object
rubocop:disable Metrics/ParameterLists.
- #readiness(live: false) ⇒ Object
-
#stream(messages, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}) ⇒ Object
rubocop:disable Metrics/ParameterLists.
- #stream_url ⇒ Object
Class Method Details
.capabilities ⇒ Object
35 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 35 def capabilities = Capabilities |
.configuration_options ⇒ Object
24 25 26 27 28 29 30 31 32 33 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 24 def %i[ azure_foundry_endpoint azure_foundry_api_key azure_foundry_bearer_token azure_foundry_api_version azure_foundry_surface azure_foundry_deployments ] end |
.configuration_requirements ⇒ Object
22 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 22 def configuration_requirements = %i[azure_foundry_endpoint] |
.deployment_config(model_id, config:) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 42 def deployment_config(model_id, config:) deployments = config&.azure_foundry_deployments entries = normalize_deployments(deployments) entries.find do |entry| [value_for(entry, :deployment), value_for(entry, :model), value_for(entry, :canonical_model_alias)] .compact.map(&:to_s).include?(model_id.to_s) end end |
.normalize_deployments(deployments) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 51 def normalize_deployments(deployments) case deployments when Hash deployments.map do |name, | value = .to_h value[:deployment] ||= name value end else Array(deployments).map { |deployment| normalize_deployment_entry(deployment) } end end |
.resolve_model_id(model_id, config: nil) ⇒ Object
37 38 39 40 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 37 def resolve_model_id(model_id, config: nil) deployment = deployment_config(model_id, config:) value_for(deployment, :deployment) || value_for(deployment, :model) || model_id.to_s end |
.slug ⇒ Object
21 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 21 def slug = 'azure_foundry' |
Instance Method Details
#api_base ⇒ Object
117 118 119 120 121 122 123 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 117 def api_base endpoint = config.azure_foundry_endpoint.to_s.sub(%r{/*\z}, '') return "#{endpoint}/openai/v1" if surface == OPENAI_V1_SURFACE && !endpoint.end_with?('/openai/v1') return endpoint.delete_suffix('/models') if surface == MODEL_INFERENCE_SURFACE endpoint end |
#chat(messages, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}) ⇒ Object
rubocop:disable Metrics/ParameterLists
202 203 204 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 202 def chat(, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}) # rubocop:disable Metrics/ParameterLists complete(, tools:, temperature:, model: model_info(model, max_tokens:), params:, tool_prefs:) end |
#chat_url ⇒ Object
133 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 133 def chat_url = completion_url |
#completion_url ⇒ Object
132 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 132 def completion_url = path_for('chat/completions') |
#count_tokens(messages, model:) ⇒ Object
217 218 219 220 221 222 223 224 225 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 217 def count_tokens(, model:, **) { provider_family: :azure_foundry, model: model_id(model), supported: false, reason: 'Azure AI Foundry REST docs do not define a portable token-counting endpoint for this surface.', estimated_input_characters: .sum { || .content.to_s.length } } end |
#discover_offerings(live: false, **filters) ⇒ Object
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 139 def discover_offerings(live: false, **filters) offerings = configured_deployments.filter_map { |deployment| offering_from_config(deployment) } return filter_offerings(offerings, **filters) unless live filter_offerings(offerings, **filters).map do |offering| (offering) rescue StandardError => e with_health(offering, ready: false, checked: true, error: e) end end |
#embed(text, model:, dimensions: nil, input_type: nil) ⇒ Object
210 211 212 213 214 215 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 210 def (text, model:, dimensions: nil, input_type: nil) payload = (text, model: model_id(model), dimensions:) payload[:input_type] = input_type if input_type response = connection.post((model:), payload) (response, model: model_id(model), text:) end |
#embedding_url ⇒ Object
136 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 136 def (**) = path_for('embeddings') |
#headers ⇒ Object
125 126 127 128 129 130 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 125 def headers { 'api-key' => config.azure_foundry_api_key, 'Authorization' => bearer_header }.compact end |
#health(live: false) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 167 def health(live: false) baseline = { provider: :azure_foundry, configured: configured?, ready: configured?, live: live, api_base: api_base, surface: surface } return baseline.merge(checked: false) unless live response = connection.get(health_url) baseline.merge(checked: true, model_info: response.body) rescue StandardError => e baseline.merge(checked: true, ready: false, error: e.class.name, message: e.) end |
#health_url ⇒ Object
137 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 137 def health_url = models_url |
#list_models ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 188 def list_models discover_offerings(live: false).map do |offering| Legion::Extensions::Llm::Model::Info.new( id: offering.model, name: offering.[:canonical_model_alias] || offering.model, provider: :azure_foundry, family: offering.[:model_family], capabilities: offering.capabilities.map(&:to_s), modalities: modalities_for_capabilities(offering.capabilities.map(&:to_s)), metadata: offering.to_h ) end end |
#models_url ⇒ Object
135 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 135 def models_url = path_for('info') |
#offering_for(model:, model_family: nil, canonical_model_alias: nil, instance_id: :default, usage_type: nil, **metadata) ⇒ Object
rubocop:disable Metrics/ParameterLists
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 150 def offering_for(model:, model_family: nil, canonical_model_alias: nil, instance_id: :default, # rubocop:disable Metrics/ParameterLists usage_type: nil, **) deployment = self.class.deployment_config(model, config:) model_id = self.class.resolve_model_id(model, config:) configured_family = value_for(deployment, :model_family) configured_alias = value_for(deployment, :canonical_model_alias) build_offering( model: model_id, instance_id: instance_id, model_family: normalize_family(model_family || configured_family || infer_model_family(model_id)), canonical_model_alias: canonical_model_alias || configured_alias, usage_type: usage_type || value_for(deployment, :usage_type) || usage_type_for(model_id), metadata: .merge((deployment)) ) end |
#readiness(live: false) ⇒ Object
184 185 186 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 184 def readiness(live: false) health(live: live).merge(local: false, remote: true, endpoints: endpoint_manifest) end |
#stream(messages, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}) ⇒ Object
rubocop:disable Metrics/ParameterLists
206 207 208 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 206 def stream(, model:, temperature: nil, max_tokens: nil, tools: {}, tool_prefs: nil, params: {}, &) # rubocop:disable Metrics/ParameterLists complete(, tools:, temperature:, model: model_info(model, max_tokens:), params:, tool_prefs:, &) end |
#stream_url ⇒ Object
134 |
# File 'lib/legion/extensions/llm/azure_foundry/provider.rb', line 134 def stream_url = completion_url |