feat(gallery): Add 'Get Config' button for models (#6154)

* feat(gallery): Add 'Get Config' button for models

This commit introduces a 'Get Config' button to the model gallery UI. This allows users to download and save the configuration file for a model without installing the model's weights.

Key changes:
- Added a getConfigButton element and integrated it into the gallery card.
- Created a new API endpoint /browse/config/model/:id to handle fetching and saving the model configuration.
- Refactored the InstallModel function to allow saving only the configuration file without downloading model weights.
- Added a ToYAML method on ModelConfig for serialization.
- Fixed button spacing in the gallery UI.

Signed-off-by: Matt Cowger <matt.cowger@sigmacomputing.com>

* Update for reviewer comments

Signed-off-by: Matt Cowger <matt.cowger@sigmacomputing.com>

---------

Signed-off-by: Matt Cowger <matt.cowger@sigmacomputing.com>
This commit is contained in:
Matt Cowger
2025-08-28 09:32:49 -07:00
committed by GitHub
parent ad99399c6e
commit d0b6aa3f7d
3 changed files with 52 additions and 1 deletions

View File

@@ -70,6 +70,24 @@ func infoButton(m *gallery.GalleryModel) elem.Node {
)
}
func getConfigButton(galleryName string) elem.Node {
return elem.Button(
attrs.Props{
"data-twe-ripple-init": "",
"data-twe-ripple-color": "light",
"class": "float-right ml-2 inline-flex items-center rounded-lg bg-gray-700 hover:bg-gray-600 px-4 py-2 text-sm font-medium text-white transition duration-300 ease-in-out",
"hx-swap": "outerHTML",
"hx-post": "browse/config/model/" + galleryName,
},
elem.I(
attrs.Props{
"class": "fa-solid fa-download pr-2",
},
),
elem.Text("Get Config"),
)
}
func deleteButton(galleryID string) elem.Node {
return elem.Button(
attrs.Props{

View File

@@ -339,7 +339,12 @@ func modelActionItems(m *gallery.GalleryModel, processTracker ProcessTracker, ga
reInstallButton(m.ID()),
deleteButton(m.ID()),
)),
installButton(m.ID()),
// otherwise, show the install button, and the get config button
elem.Node(elem.Div(
attrs.Props{},
getConfigButton(m.ID()),
installButton(m.ID()),
)),
),
),
),

View File

@@ -189,6 +189,34 @@ func registerGalleryRoutes(app *fiber.App, cl *config.ModelConfigLoader, appConf
return c.SendString(elements.StartModelProgressBar(uid, "0", "Installation"))
})
app.Post("/browse/config/model/:id", func(c *fiber.Ctx) error {
galleryID := strings.Clone(c.Params("id")) // note: strings.Clone is required for multiple requests!
log.Debug().Msgf("UI job submitted to get config for : %+v\n", galleryID)
models, err := gallery.AvailableGalleryModels(appConfig.Galleries, appConfig.SystemState)
if err != nil {
return err
}
model := gallery.FindGalleryElement(models, galleryID)
if model == nil {
return fmt.Errorf("model not found")
}
config, err := gallery.GetGalleryConfigFromURL[gallery.ModelConfig](model.URL, appConfig.SystemState.Model.ModelsPath)
if err != nil {
return err
}
// Save the config file
_, err = gallery.InstallModel(appConfig.SystemState, model.Name, &config, model.Overrides, nil, false)
if err != nil {
return err
}
return c.SendString("Configuration file saved.")
})
// This route is used when the "Install" button is pressed, we submit here a new job to the gallery service
// https://htmx.org/examples/progress-bar/
app.Post("/browse/delete/model/:id", func(c *fiber.Ctx) error {