diff --git a/ee/app/models/concerns/ai/model_selection/features_configurable.rb b/ee/app/models/concerns/ai/model_selection/features_configurable.rb index 72fab0caaf9e3f3b7595357cb92cb84cf9821ce9..cc64241fe579e1b507123714564a733474ba8e3a 100644 --- a/ee/app/models/concerns/ai/model_selection/features_configurable.rb +++ b/ee/app/models/concerns/ai/model_selection/features_configurable.rb @@ -132,7 +132,7 @@ def model_metadata_params { provider: provider, feature_setting: feature, - identifier: offered_model_ref + identifier: offered_model_ref || claude_4_0_rollout_default_model } end @@ -142,6 +142,13 @@ def model_request_params private + def claude_4_0_rollout_default_model + return unless feature.to_s == 'resolve_vulnerability' + return unless Feature.enabled?(:resolve_vulnerability_claude_4_0_rollout, model_selection_scope) + + 'claude_sonnet_4_20250514' + end + def validate_model_selection_enabled return if model_selection_enabled? diff --git a/ee/config/feature_flags/gitlab_com_derisk/resolve_vulnerability_claude_4_0_rollout.yml b/ee/config/feature_flags/gitlab_com_derisk/resolve_vulnerability_claude_4_0_rollout.yml new file mode 100644 index 0000000000000000000000000000000000000000..c869ac57c640163ad6790a420401ec66f1897e51 --- /dev/null +++ b/ee/config/feature_flags/gitlab_com_derisk/resolve_vulnerability_claude_4_0_rollout.yml @@ -0,0 +1,9 @@ +--- +name: resolve_vulnerability_claude_4_0_rollout +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/545698 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/200813 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/560585 +milestone: '18.4' +group: group::security insights +type: gitlab_com_derisk +default_enabled: false diff --git a/ee/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability.rb b/ee/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability.rb index d5f0a0021439b412eb8e6a09c306f46602194658..0d9dc3aaebb5dc7057c200d8aa48c0dcb0f46ae4 100644 --- a/ee/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability.rb +++ b/ee/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability.rb @@ -14,7 +14,8 @@ class ResolveVulnerability < Base EmptyResponseError = Class.new(StandardError) - DEV_PROMPT = "^1.0.1" + CLAUDE_3_5_PROMPT_VERSION = "1.0.1" + CLAUDE_4_0_PROMPT_VERSION = "1.0.2" override :execute def execute @@ -61,7 +62,11 @@ def root_namespace override :prompt_version def prompt_version - '1.0.1' + if Feature.enabled?(:resolve_vulnerability_claude_4_0_rollout, user) + CLAUDE_4_0_PROMPT_VERSION + else + CLAUDE_3_5_PROMPT_VERSION + end end def request! diff --git a/ee/spec/factories/ai/model_selection/namespace_feature_settings.rb b/ee/spec/factories/ai/model_selection/namespace_feature_settings.rb index cf5ea238f919c7f966f9d6e88589824401e89ebe..5c7fcdd350ba347655bbac6d78dbc97067ba0304 100644 --- a/ee/spec/factories/ai/model_selection/namespace_feature_settings.rb +++ b/ee/spec/factories/ai/model_selection/namespace_feature_settings.rb @@ -72,8 +72,8 @@ }, { "feature_setting" => "resolve_vulnerability", - "default_model" => "claude_sonnet_3_7", - "selectable_models" => %w[claude_sonnet_3_7 claude-3-5-sonnet-20240620], + "default_model" => "claude_sonnet_4_20250514", + "selectable_models" => %w[claude_sonnet_3_7 claude-3-5-sonnet-20240620 claude_sonnet_4_20250514], "beta_models" => [], "unit_primitives" => ["resolve_vulnerability"] }, diff --git a/ee/spec/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability_spec.rb b/ee/spec/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability_spec.rb index 7432e84a50a638111099031bca87b6847727198d..56ec9a677c02f2a021fa3237ff4cd12439f76339 100644 --- a/ee/spec/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability_spec.rb +++ b/ee/spec/lib/gitlab/llm/ai_gateway/completions/resolve_vulnerability_spec.rb @@ -108,6 +108,7 @@ def allow_llm_client_to_return_message(response) describe '#execute' do before do stub_feature_flags(ai_model_switching: false) + stub_feature_flags(resolve_vulnerability_claude_4_0_rollout: false) end it_behaves_like 'a resolve vulnerability completion' do @@ -131,6 +132,7 @@ def allow_llm_client_to_return_message(response) before do stub_feature_flags(ai_model_switching: true) + stub_feature_flags(resolve_vulnerability_claude_4_0_rollout: false) end context 'when the model is pinned to a specific model' do @@ -152,6 +154,56 @@ def allow_llm_client_to_return_message(response) end end end + + context 'when resolve_vulnerability_claude_4_0_rollout is enabled' do + before do + stub_feature_flags(resolve_vulnerability_claude_4_0_rollout: true) + end + + context 'when the model is pinned to a specific model' do + before do + create(:ai_namespace_feature_setting, + namespace: group, + feature: 'resolve_vulnerability', + offered_model_ref: 'claude_sonnet_4_20250514' + ) + end + + it_behaves_like 'a resolve vulnerability completion' do + let(:prompt_version) { "1.0.2" } + let(:expected_description) { vulnerability.description } + let(:model_metadata) do + { + feature_setting: feature_setting_name, + identifier: 'claude_sonnet_4_20250514', + provider: 'gitlab' + } + end + end + end + + context 'when the model is not pinned to a specific model' do + before do + create(:ai_namespace_feature_setting, + namespace: group, + feature: 'resolve_vulnerability', + offered_model_ref: nil + ) + end + + it_behaves_like 'a resolve vulnerability completion' do + let(:prompt_version) { "1.0.2" } + let(:expected_description) { vulnerability.description } + let(:model_metadata) do + { + feature_setting: feature_setting_name, + identifier: 'claude_sonnet_4_20250514', + provider: 'gitlab' + } + end + end + end + end end end end