Top namespace level model selection DB
What does this MR do and why?
For our AI-features, this MR is part of the epic gives &17570 (closed). The goal of the epic is to give the possibility to top-level namespace admins to change the default model routing for specific features when calling the AIGW.
This MR takes care of the selection of model business logic. To do so, it fetches the available model for each feature first from the AIGW, then create an ::Ai::ModelSelection::NamespaceFeatureSetting entry (new table).
How to set up and validate locally
Prequisites
- Make sure you AIGW is working and up to date
- You will need an active Duo online cloud license.
- You will need a Duo license. You can make a Duo Enterprise subscription pretty quickly by running the following command in the terminal:
GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup_instance[duo_enterprise]'
- Start GDK in SASS mode
GITLAB_SIMULATE_SAAS=1 gdk start(don't worries you won't lose your license) - Migrate the db changes
gdk rails db:migrate
Validation steps
- Go to your rails console
gdk rails c - Enable the FF
Feature.enable(:ai_model_switching) - Select a user
user = User.first - Select a root namespace
group = Group.first - Fetch the model definitions
Ai::ModelSelection::FetchModelDefinitionsService.new(user, model_selection_scope: group).execute
- Result should look like this:
=> #<ServiceResponse:0x0000000338418df0
@http_status=:ok,
@message=nil,
@payload=
{"models"=>
[{"name"=>"Claude Sonnet 3.7 - Anthropic", "identifier"=>"claude_sonnet_3_7_20250219"},
{"name"=>"Claude Sonnet 3.7 - Vertex", "identifier"=>"claude_sonnet_3_7_20250219_vertex"},
{"name"=>"Claude Sonnet 3.5 - Anthropic", "identifier"=>"claude_3_5_sonnet_20240620"},
{"name"=>"Codestral 25.01 - Fireworks", "identifier"=>"codestral_2501_fireworks"},
{"name"=>"Codestral 25.01 - Vertex", "identifier"=>"codestral_2501_vertex"}],
"unit_primitives"=>
[{"feature_setting"=>"duo_chat",
"default_model"=>"claude_sonnet_3_7_20250219",
"selectable_models"=>["claude_sonnet_3_7_20250219", "claude_3_5_sonnet_20240620"],
"beta_models"=>[],
"unit_primitives"=>["ask_build", "ask_commit"]},
{"feature_setting"=>"ETC..."}
]
},
@reason=nil,
@status=:success>
- Choose the the feature and the model identifier you would to route. For this example
duo_chatshould useclaude_3_5_sonnet_20240620 - Initialize a feature setting
feature_setting = Ai::ModelSelection::NamespaceFeatureSetting.find_or_initialize_by_feature(group, :duo_chat) - Set the parameters for the update service
params = {offered_model_ref: 'claude_sonnet_3_7_20250219'} - execute the service
Ai::ModelSelection::UpdateService.new(feature_setting, user, params).execute
- Result should look like this:
=> #<ServiceResponse:0x0000000338418df0
=> #<ServiceResponse:0x000000033a2ffbb0
@http_status=:ok,
@message=nil,
@payload=
#<Ai::ModelSelection::NamespaceFeatureSetting:0x000000033329b900
id: 1,
created_at: Wed, 07 May 2025 09:54:13.107582000 UTC +00:00,
updated_at: Wed, 07 May 2025 09:54:13.107582000 UTC +00:00,
namespace_id: 95,
feature: "duo_chat",
offered_model_ref: "claude_sonnet_3_7_20250219",
offered_model_name: "Claude Sonnet 3.7 - Anthropic",
model_definitions: {...}
- That means it was successful
👌🏿
Caviates
- The
Ai::ModelSelection::NamespaceFeatureSettingis designed to validate the inputedoffered_model_refagainst the model definition fetch by the AIGW. If, according to the model definition, the feature is not compactible with the selected model it will fail (see diffs). - The model definition is cached. the cache expires after one hour. But you can for the fetch service to make the API call to the AIGW and refresh the cache with the
:force_api_callparam.Ai::ModelSelection::FetchModelDefinitionsService.new(user, model_selection_scope: group).execute(force_api_call: true) - Most of the model selection logic is abstracted away in the
Ai::ModelSelection::FeaturesConfigurableconcernee/app/models/concerns/ai/model_selection/features_configurable.rb - The enum values for the
featureattributes takes after the values in the SHM feature setting values to be able to use the shared ressources and interoperability in the future.
Related to #526009 (closed)
Edited by Patrick Cyiza