1212from llama_stack .core .datatypes import (
1313 ModelWithOwner ,
1414 RegistryEntrySource ,
15+ StackRunConfig ,
1516)
1617from llama_stack .log import get_logger
1718
2223
2324class ModelsRoutingTable (CommonRoutingTableImpl , Models ):
2425 listed_providers : set [str ] = set ()
26+ current_run_config : "StackRunConfig | None" = None
2527
2628 async def refresh (self ) -> None :
2729 for provider_id , provider in self .impls_by_provider_id .items ():
@@ -43,10 +45,26 @@ async def refresh(self) -> None:
4345 await self .update_registered_models (provider_id , models )
4446
4547 async def list_models (self ) -> ListModelsResponse :
46- return ListModelsResponse (data = await self .get_all_with_type ("model" ))
48+ # Get persistent models from registry
49+ persistent_models = await self .get_all_with_type ("model" )
50+
51+ # Generate from_config models dynamically
52+ from_config_models = self ._generate_from_config_models ()
53+
54+ # Combine both lists
55+ all_models = persistent_models + from_config_models
56+
57+ return ListModelsResponse (data = all_models )
4758
4859 async def openai_list_models (self ) -> OpenAIListModelsResponse :
49- models = await self .get_all_with_type ("model" )
60+ # Get persistent models from registry
61+ persistent_models = await self .get_all_with_type ("model" )
62+
63+ # Generate from_config models dynamically
64+ from_config_models = self ._generate_from_config_models ()
65+
66+ # Combine both lists
67+ models = persistent_models + from_config_models
5068 openai_models = [
5169 OpenAIModel (
5270 id = model .identifier ,
@@ -74,6 +92,7 @@ async def register_model(
7492 provider_id : str | None = None ,
7593 metadata : dict [str , Any ] | None = None ,
7694 model_type : ModelType | None = None ,
95+ source : RegistryEntrySource = RegistryEntrySource .via_register_api ,
7796 ) -> Model :
7897 if provider_id is None :
7998 # If provider_id not specified, use the only provider if it supports this model
@@ -106,7 +125,7 @@ async def register_model(
106125 provider_id = provider_id ,
107126 metadata = metadata ,
108127 model_type = model_type ,
109- source = RegistryEntrySource . via_register_api ,
128+ source = source ,
110129 )
111130 registered_model = await self .register_object (model )
112131 return registered_model
@@ -117,6 +136,39 @@ async def unregister_model(self, model_id: str) -> None:
117136 raise ModelNotFoundError (model_id )
118137 await self .unregister_object (existing_model )
119138
139+ def set_run_config (self , run_config : "StackRunConfig" ) -> None :
140+ """Set the current run configuration for generating from_config models."""
141+ self .current_run_config = run_config
142+
143+ def _generate_from_config_models (self ) -> list [ModelWithOwner ]:
144+ """Generate from_config models from the current run configuration."""
145+ if not self .current_run_config :
146+ return []
147+
148+ from_config_models = []
149+ for model_input in self .current_run_config .models :
150+ # Skip models with disabled providers
151+ if not model_input .provider_id or model_input .provider_id == "__disabled__" :
152+ continue
153+
154+ # Generate identifier
155+ if model_input .model_id != (model_input .provider_model_id or model_input .model_id ):
156+ identifier = model_input .model_id
157+ else :
158+ identifier = f"{ model_input .provider_id } /{ model_input .provider_model_id or model_input .model_id } "
159+
160+ model = ModelWithOwner (
161+ identifier = identifier ,
162+ provider_resource_id = model_input .provider_model_id or model_input .model_id ,
163+ provider_id = model_input .provider_id ,
164+ metadata = model_input .metadata ,
165+ model_type = model_input .model_type or ModelType .llm ,
166+ source = RegistryEntrySource .from_config ,
167+ )
168+ from_config_models .append (model )
169+
170+ return from_config_models
171+
120172 async def update_registered_models (
121173 self ,
122174 provider_id : str ,
@@ -133,6 +185,10 @@ async def update_registered_models(
133185 if model .source == RegistryEntrySource .via_register_api :
134186 model_ids [model .provider_resource_id ] = model .identifier
135187 continue
188+ # Also preserve from_config models - they should not be unregistered during refresh
189+ if model .source == RegistryEntrySource .from_config :
190+ model_ids [model .provider_resource_id ] = model .identifier
191+ continue
136192
137193 logger .debug (f"unregistering model { model .identifier } " )
138194 await self .unregister_object (model )
0 commit comments