diff --git a/ee/app/models/ai/feature_setting.rb b/ee/app/models/ai/feature_setting.rb index 10b0bfbc32db4921be1b6205de269b1154675705..9bccbf341852d4261172dd014334dfb22c4e9428 100644 --- a/ee/app/models/ai/feature_setting.rb +++ b/ee/app/models/ai/feature_setting.rb @@ -4,12 +4,6 @@ module Ai class FeatureSetting < ApplicationRecord self.table_name = "ai_feature_settings" - PROVIDER_TITLES = HashWithIndifferentAccess.new({ - disabled: 'Disabled', - vendored: 'GitLab AI Vendor', - self_hosted: 'Self-Hosted Model' - }).freeze - belongs_to :self_hosted_model, foreign_key: :ai_self_hosted_model_id, inverse_of: :feature_settings validates :self_hosted_model, presence: true, if: :self_hosted? @@ -32,8 +26,16 @@ def self.code_suggestions_self_hosted? exists?(feature: [:code_generations, :code_completions], provider: :self_hosted) end + def self.provider_titles + { + disabled: s_('AdminAiPoweredFeatures|Disabled'), + vendored: s_('AdminAiPoweredFeatures|AI vendor'), + self_hosted: s_('AdminAiPoweredFeatures|Self-hosted model') + }.with_indifferent_access.freeze + end + def provider_title - title = PROVIDER_TITLES[provider] + title = self.class.provider_titles[provider] return title unless self_hosted? "#{title} (#{self_hosted_model.name})" diff --git a/ee/app/views/admin/ai/feature_settings/_feature_setting.html.haml b/ee/app/views/admin/ai/feature_settings/_feature_setting.html.haml index b56769a1a94a95b1a871e66c53f16c31ea404865..3ff1ca68c3b358a0df7cadfba4ccecb910e59f2d 100644 --- a/ee/app/views/admin/ai/feature_settings/_feature_setting.html.haml +++ b/ee/app/views/admin/ai/feature_settings/_feature_setting.html.haml @@ -3,7 +3,7 @@ %li.gl-list-none.gl-py-3.gl-border-b.gl-last-of-type-border-b-0{ id: feature } .label-content.gl-px-3.gl-py-2 .label-name.gl-flex-shrink-0.gl-mr-5 - = feature.titleize + = feature == "duo_chat" ? feature.titleize : feature.humanize.singularize .label-description.gl-w-full .gl-flex-wrap .gl-mr-5 diff --git a/ee/app/views/admin/ai/feature_settings/_form.html.haml b/ee/app/views/admin/ai/feature_settings/_form.html.haml index 0c582c441a073e4bd2e2c1f47fdf5524672319b9..4c780050796dccbdb1ce0c636bce560d36e69848 100644 --- a/ee/app/views/admin/ai/feature_settings/_form.html.haml +++ b/ee/app/views/admin/ai/feature_settings/_form.html.haml @@ -1,6 +1,6 @@ - add_page_specific_style 'page_bundles/labels' - options = Ai::SelfHostedModel.all.map { |model| ["#{model.name} (#{model.model.humanize})", model.id] } -- feature_name = feature.titleize +- feature_name = feature.humanize.downcase.singularize - provider_field_name = 'feature_setting[provider]' = gitlab_ui_form_for @feature_setting, as: :feature_setting, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f| @@ -10,33 +10,33 @@ %fieldset.form-group.gl-form-group %legend.col-form-label - = s_('AdminAiPoweredFeatures|Model Provider') + = s_('AdminAiPoweredFeatures|Model provider') .gl-font-normal.form-text.text-gl-muted - = s_("AdminAiPoweredFeatures|Choose the AI model for %{feature_name} feature") % { feature_name: feature_name } + = s_("AdminAiPoweredFeatures|Choose the AI model to use with %{feature_name}.") % { feature_name: feature_name } = render Pajamas::RadioTagComponent.new(name: provider_field_name, - label: ::Ai::FeatureSetting::PROVIDER_TITLES[:disabled], + label: s_('AdminAiPoweredFeatures|Turn off'), value: :disabled, radio_options: { class: 'js-self-hosted-model-setting' }, checked: @feature_setting.disabled?) do |c| = c.with_help_text do - = s_("AdminAiPoweredFeatures|Disables %{feature_name} for the instance.") % { feature_name: feature_name } + = s_("AdminAiPoweredFeatures|Turn off %{feature_name} for the instance.") % { feature_name: feature_name } = render Pajamas::RadioTagComponent.new(name: provider_field_name, - label: ::Ai::FeatureSetting::PROVIDER_TITLES[:vendored], + label: ::Ai::FeatureSetting.provider_titles[:vendored], radio_options: { class: 'js-self-hosted-model-setting' }, value: :vendored, checked: @feature_setting.vendored?) do |c| = c.with_help_text do - = s_("AdminAiPoweredFeatures|Enables %{feature_name} empowered by a GitLab AI Vendor. The model must be configured for the instance.") % { feature_name: feature_name } + = s_("AdminAiPoweredFeatures|Turn on %{feature_name}, powered by a GitLab-selected AI Vendor. The model must be configured for the instance.") % { feature_name: feature_name } = render Pajamas::RadioTagComponent.new(name: provider_field_name, radio_options: { class: 'js-self-hosted-model-setting' }, value: :self_hosted, checked: @feature_setting.self_hosted?) do |c| = c.with_help_text do - = s_("AdminAiPoweredFeatures|Enables %{feature_name} empowered by a Self-Hosted model") % { feature_name: feature_name } + = s_("AdminAiPoweredFeatures|Turn on %{feature_name}, powered by a self-hosted model.") % { feature_name: feature_name } = c.with_label do - = ::Ai::FeatureSetting::PROVIDER_TITLES[:self_hosted] - = f.select(:ai_self_hosted_model_id, options_for_select(options, @feature_setting.ai_self_hosted_model_id), {}, { class: 'custom-select gl-form-select gl-form-select-lg gl-ml-6 js-self-hosted-model-select', data: { testid: 'ai-feature-settings-model' }, disabled: !@feature_setting.self_hosted?, 'aria-label': ::Ai::FeatureSetting::PROVIDER_TITLES[:self_hosted] }) + = ::Ai::FeatureSetting.provider_titles[:self_hosted] + = f.select(:ai_self_hosted_model_id, options_for_select(options, @feature_setting.ai_self_hosted_model_id), {}, { class: 'custom-select gl-form-select gl-form-select-lg gl-ml-6 js-self-hosted-model-select', data: { testid: 'ai-feature-settings-model' }, disabled: !@feature_setting.self_hosted?, 'aria-label': ::Ai::FeatureSetting.provider_titles[:self_hosted] }) .gl-mt-2 %div diff --git a/ee/app/views/admin/ai/feature_settings/edit.html.haml b/ee/app/views/admin/ai/feature_settings/edit.html.haml index 2bc825bae71739fc59aa32e6faa3f37fb6cdfee6..e5b4678dd79dd21146f84f01b18e0d62f32af955 100644 --- a/ee/app/views/admin/ai/feature_settings/edit.html.haml +++ b/ee/app/views/admin/ai/feature_settings/edit.html.haml @@ -1,5 +1,5 @@ - feature = @feature_setting.feature -- edit_feature_title = s_("AdminAiPoweredFeatures|Edit %{feature_name}") % { feature_name: feature.titleize } +- edit_feature_title = s_("AdminAiPoweredFeatures|%{feature_name}") % { feature_name: feature.humanize.singularize } - add_to_breadcrumbs s_("AdminAiPoweredFeatures|AI-powered features"), admin_ai_feature_settings_path - breadcrumb_title edit_feature_title - page_title edit_feature_title diff --git a/ee/app/views/admin/ai/feature_settings/index.html.haml b/ee/app/views/admin/ai/feature_settings/index.html.haml index 286e56f57de725912ad7623216a6af0d31a8efed..2708662692d0da24a7a5d61a61c2156a62fa1041 100644 --- a/ee/app/views/admin/ai/feature_settings/index.html.haml +++ b/ee/app/views/admin/ai/feature_settings/index.html.haml @@ -7,7 +7,7 @@ .gl-new-card-title = s_('AdminAIPoweredFeatures|AI-powered features') .gl-new-card-description - = s_('AdminAIPoweredFeatures|AI-powered features that can be enabled, disabled or linked to a cloud-based or self-hosted model.') + = s_('AdminAIPoweredFeatures|AI-powered features that can be enabled, disabled, or linked to a cloud-based or self-hosted model.') - c.with_body do %ul.manage-labels-list.gl-px-3 = render partial: 'feature_setting', collection: @feature_settings, as: :feature_setting diff --git a/ee/spec/models/ai/feature_setting_spec.rb b/ee/spec/models/ai/feature_setting_spec.rb index 5e581bc05b9b9aea607c27dae6c27a1e49763d3c..2bb9f42897e8d8155bc9881b4f4ebefb2d9eafbe 100644 --- a/ee/spec/models/ai/feature_setting_spec.rb +++ b/ee/spec/models/ai/feature_setting_spec.rb @@ -14,13 +14,13 @@ let(:feature_setting) { build(:ai_feature_setting) } it { expect(feature_setting).to validate_presence_of(:self_hosted_model) } - it { expect(feature_setting.provider_title).to eq('Self-Hosted Model (mistral-7b-ollama-api)') } + it { expect(feature_setting.provider_title).to eq('Self-hosted model (mistral-7b-ollama-api)') } end context 'when feature setting is vendored' do let(:feature_setting) { build(:ai_feature_setting, provider: :vendored) } - it { expect(feature_setting.provider_title).to eq('GitLab AI Vendor') } + it { expect(feature_setting.provider_title).to eq('AI vendor') } end context 'when feature setting is disabled' do diff --git a/ee/spec/requests/admin/ai/feature_settings_controller_spec.rb b/ee/spec/requests/admin/ai/feature_settings_controller_spec.rb index 78d23d71d08f4526e28510683138982ad1f3d80a..df6a411fc2a8e1828745bdab933c97d65ebc4064 100644 --- a/ee/spec/requests/admin/ai/feature_settings_controller_spec.rb +++ b/ee/spec/requests/admin/ai/feature_settings_controller_spec.rb @@ -55,10 +55,10 @@ expect(response).to have_gitlab_http_status(:ok) expect(response.body).to match( - /Code Generations.+Self-Hosted Model \(mistral-7b-ollama-api\)/m + /Code generation.+Self-hosted model \(mistral-7b-ollama-api\)/m ) expect(response.body).to match( - /Code Completions.+GitLab AI Vendor/m + /Code completion.+AI vendor/m ) end @@ -129,7 +129,7 @@ it 'renders edit page' do expect { post admin_ai_feature_settings_path, params: params }.not_to change { ::Ai::FeatureSetting.count } - expect(response.body).to include('Edit Code Completions') + expect(response.body).to include('Code completion') end end @@ -178,7 +178,7 @@ it 'renders edit page' do patch admin_ai_feature_setting_path(feature_setting), params: params - expect(response.body).to include('Edit Code Completions') + expect(response.body).to include('Code completion') end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d5d5df8be6044ad80322aa0a40de4dc5318c4c6e..a45ebff4cc8cb066dbfe61711247948c551101f9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3490,28 +3490,40 @@ msgstr "" msgid "AdminAIPoweredFeatures|AI-powered features" msgstr "" -msgid "AdminAIPoweredFeatures|AI-powered features that can be enabled, disabled or linked to a cloud-based or self-hosted model." +msgid "AdminAIPoweredFeatures|AI-powered features that can be enabled, disabled, or linked to a cloud-based or self-hosted model." +msgstr "" + +msgid "AdminAiPoweredFeatures|%{feature_name}" +msgstr "" + +msgid "AdminAiPoweredFeatures|AI vendor" msgstr "" msgid "AdminAiPoweredFeatures|AI-powered features" msgstr "" -msgid "AdminAiPoweredFeatures|Choose the AI model for %{feature_name} feature" +msgid "AdminAiPoweredFeatures|Choose the AI model to use with %{feature_name}." +msgstr "" + +msgid "AdminAiPoweredFeatures|Disabled" +msgstr "" + +msgid "AdminAiPoweredFeatures|Model provider" msgstr "" -msgid "AdminAiPoweredFeatures|Disables %{feature_name} for the instance." +msgid "AdminAiPoweredFeatures|Self-hosted model" msgstr "" -msgid "AdminAiPoweredFeatures|Edit %{feature_name}" +msgid "AdminAiPoweredFeatures|Turn off" msgstr "" -msgid "AdminAiPoweredFeatures|Enables %{feature_name} empowered by a GitLab AI Vendor. The model must be configured for the instance." +msgid "AdminAiPoweredFeatures|Turn off %{feature_name} for the instance." msgstr "" -msgid "AdminAiPoweredFeatures|Enables %{feature_name} empowered by a Self-Hosted model" +msgid "AdminAiPoweredFeatures|Turn on %{feature_name}, powered by a GitLab-selected AI Vendor. The model must be configured for the instance." msgstr "" -msgid "AdminAiPoweredFeatures|Model Provider" +msgid "AdminAiPoweredFeatures|Turn on %{feature_name}, powered by a self-hosted model." msgstr "" msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"