- golem15_golem_models (encrypted write-only api_key) with its cabana list and form under golem15.golem.access_settings, and the Settings lookups (Models, DefaultModel with PHP's position-0 quirk, Vision, Image, File, ByName), every one Trusted - golem:import-settings copies the WinterCMS golem_settings repeater once - AnthropicAdapter; SendStream, SendFile/SendFilePath/SendFileReader, SendWithModel, SendToImageModel, SendToVisionModel, GenerateImage, Ask - PromptFactory; README documents the config keys, the environment variable, the command and the admin screen
120 lines
3.4 KiB
Go
120 lines
3.4 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.golem15.com/golem15/sm-golem-plugin/models"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// The functions below port the WinterCMS plugin's Settings model over the
|
|
// golem15_golem_models rows (in sort_order, then id order). Every config
|
|
// they return is an operator's model: Trusted is set. A nil db means no
|
|
// model is configured.
|
|
|
|
// Models is Settings::getModels: the enabled models, in order. Each keeps
|
|
// its Position among all models, enabled or not, as PHP's array_filter
|
|
// keeps the repeater keys.
|
|
func Models(ctx context.Context, db *gorm.DB) ([]*ModelConfig, error) {
|
|
if db == nil {
|
|
return nil, nil
|
|
}
|
|
var rows []models.AiModel
|
|
if err := db.WithContext(ctx).Order("sort_order, id").Find(&rows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
var out []*ModelConfig
|
|
for i := range rows {
|
|
if !rows[i].IsEnabled {
|
|
continue
|
|
}
|
|
c := modelConfigFrom(&rows[i])
|
|
c.Position = i
|
|
out = append(out, c)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// DefaultModel is Settings::getDefaultModel: the first enabled model
|
|
// marked default, else the model at position 0 when it is enabled. PHP's
|
|
// `$models[0] ?? null` reads the filtered array by key, so a disabled
|
|
// first model means no default even when later models are enabled.
|
|
func DefaultModel(ctx context.Context, db *gorm.DB) (*ModelConfig, error) {
|
|
all, err := Models(ctx, db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, m := range all {
|
|
if m.isDefault {
|
|
return m, nil
|
|
}
|
|
}
|
|
for _, m := range all {
|
|
if m.Position == 0 {
|
|
return m, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
// VisionModel is Settings::getVisionModel: the first enabled model that
|
|
// accepts images.
|
|
func VisionModel(ctx context.Context, db *gorm.DB) (*ModelConfig, error) {
|
|
return firstModel(ctx, db, func(m *ModelConfig) bool { return m.AcceptsImages })
|
|
}
|
|
|
|
// ImageModel is Settings::getImageModel: the first enabled model that
|
|
// generates images.
|
|
func ImageModel(ctx context.Context, db *gorm.DB) (*ModelConfig, error) {
|
|
return firstModel(ctx, db, func(m *ModelConfig) bool { return m.GeneratesImages })
|
|
}
|
|
|
|
// FileModel is Settings::getFileModel: the first enabled model with a
|
|
// files endpoint.
|
|
func FileModel(ctx context.Context, db *gorm.DB) (*ModelConfig, error) {
|
|
return firstModel(ctx, db, func(m *ModelConfig) bool { return m.HasFilesEndpoint })
|
|
}
|
|
|
|
// ModelByName is Settings::getModelByName: the first enabled model named
|
|
// name.
|
|
func ModelByName(ctx context.Context, db *gorm.DB, name string) (*ModelConfig, error) {
|
|
return firstModel(ctx, db, func(m *ModelConfig) bool { return m.Name == name })
|
|
}
|
|
|
|
func firstModel(ctx context.Context, db *gorm.DB, match func(*ModelConfig) bool) (*ModelConfig, error) {
|
|
all, err := Models(ctx, db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, m := range all {
|
|
if match(m) {
|
|
return m, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func modelConfigFrom(row *models.AiModel) *ModelConfig {
|
|
c := &ModelConfig{
|
|
Name: row.Name,
|
|
Adapter: row.Adapter,
|
|
APIKey: row.APIKey.Reveal(),
|
|
Model: row.Model,
|
|
HasFilesEndpoint: row.HasFilesEndpoint,
|
|
AcceptsImages: row.AcceptsImages,
|
|
GeneratesImages: row.GeneratesImages,
|
|
Trusted: true,
|
|
isDefault: row.IsDefault,
|
|
}
|
|
if row.BaseURL != nil {
|
|
c.BaseURL = *row.BaseURL
|
|
}
|
|
if row.SystemPrompt != nil {
|
|
c.SystemPrompt = *row.SystemPrompt
|
|
}
|
|
if row.MaxCompletionTokens != nil {
|
|
c.MaxCompletionTokens = *row.MaxCompletionTokens
|
|
}
|
|
return c
|
|
}
|