Files
cloudpods/pkg/llm/models/llm_instant_model.go
2026-05-20 11:06:23 +08:00

272 lines
6.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package models
import (
"context"
"database/sql"
"fmt"
"time"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/llm"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
)
var llmInstantModelManager *SLLMInstantModelManager
func init() {
GetLLMInstantModelManager()
}
func GetLLMInstantModelManager() *SLLMInstantModelManager {
if llmInstantModelManager == nil {
llmInstantModelManager = &SLLMInstantModelManager{
SResourceBaseManager: db.NewResourceBaseManager(
SLLMInstantModel{},
"llm_instant_models_tbl",
"llm_with_instant_model",
"llm_with_instant_models",
),
}
llmInstantModelManager.SetVirtualObject(llmInstantModelManager)
}
return llmInstantModelManager
}
type SLLMInstantModelManager struct {
db.SResourceBaseManager
db.SStatusResourceBaseManager
}
type SLLMInstantModel struct {
db.SResourceBase
db.SStatusResourceBase
LlmId string `width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
// InstantModelId instant model 主键 idSInstantModel.Id
InstantModelId string `name:"model_id" width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
// Model Tag
Tag string `width:"64" charset:"utf8" nullable:"true" list:"user"`
// Model Name
ModelName string `width:"128" charset:"utf8" nullable:"false" list:"user"`
IsProbed bool `list:"user"`
IsMounted bool `list:"user"`
// IsSystem tristate.TriState `list:"user"`
}
func (man *SLLMInstantModelManager) fetchLLMInstantModel(llmId string, instantModelId string) (*SLLMInstantModel, error) {
q := man.Query().Equals("llm_id", llmId).Equals("model_id", instantModelId)
llmInstantModel := SLLMInstantModel{}
err := q.First(&llmInstantModel)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return nil, errors.ErrNotFound
}
return nil, errors.Wrap(err, "Query")
}
llmInstantModel.SetModelManager(man, &llmInstantModel)
return &llmInstantModel, nil
}
func (man *SLLMInstantModelManager) getDeletedModelIds(llmId string) ([]string, error) {
q := man.RawQuery("model_id").Equals("llm_id", llmId).IsTrue("deleted").Distinct()
llmInstantModel := make([]SLLMInstantModel, 0)
err := db.FetchModelObjects(man, q, &llmInstantModel)
if err != nil {
return nil, errors.Wrap(err, "Query")
}
instantModelIds := make([]string, len(llmInstantModel))
for i := range llmInstantModel {
instantModelIds[i] = llmInstantModel[i].InstantModelId
}
return instantModelIds, nil
}
func (man *SLLMInstantModelManager) updateInstantModel(ctx context.Context, llmId string, instantModelId string, mdlName string, tag string, probed, mounted *bool) (*SLLMInstantModel, error) {
mdl, err := man.fetchLLMInstantModel(llmId, instantModelId)
if err != nil && errors.Cause(err) != errors.ErrNotFound {
return nil, errors.Wrap(err, "updateInstantModel")
}
mountStr := "nil"
probedStr := "nil"
if mounted != nil {
mountStr = fmt.Sprintf("%v", *mounted)
}
if probed != nil {
probedStr = fmt.Sprintf("%v", *probed)
}
log.Debugf("=======updateInstantModel %#v to mounted %s, probed %s", mdl, mountStr, probedStr)
if mdl == nil {
// if no such app
mdl = &SLLMInstantModel{
LlmId: llmId,
InstantModelId: instantModelId,
ModelName: mdlName,
// IsSystem: tristate.None,
// Entry: entry,
}
// if isSys != nil {
// if *isSys {
// mdl.IsSystem = tristate.True
// } else {
// mdl.IsSystem = tristate.False
// }
// }
mdl.Tag = tag
if probed != nil {
mdl.IsProbed = *probed
}
if mounted != nil {
mdl.IsMounted = *mounted
}
mdl.syncStatus()
err := man.TableSpec().Insert(ctx, mdl)
if err != nil {
return nil, errors.Wrap(err, "Insert")
}
return mdl, nil
} else {
_, err := db.Update(mdl, func() error {
if len(tag) > 0 {
mdl.Tag = tag
}
if len(mdlName) > 0 {
mdl.ModelName = mdlName
}
// if isSys != nil {
// if *isSys {
// mdl.IsSystem = tristate.True
// } else {
// mdl.IsSystem = tristate.False
// }
// }
// if len(entry) > 0 {
// app.Entry = entry
// }
if probed != nil {
mdl.IsProbed = *probed
if mdl.IsProbed {
mdl.Status = api.LLM_STATUS_READY
} else {
mdl.Status = api.LLM_STATUS_DELETED
}
}
if mounted != nil {
mdl.IsMounted = *mounted
}
mdl.syncStatus()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "Update")
}
}
return mdl, nil
}
func (man *SLLMInstantModelManager) filterModels(q *sqlchemy.SQuery, isProbed, isMounted, isSystem *bool) *sqlchemy.SQuery {
if isProbed != nil {
if *isProbed {
q = q.IsTrue("is_probed")
} else {
q = q.IsFalse("is_probed")
}
}
if isMounted != nil {
if *isMounted {
q = q.IsTrue("is_mounted")
} else {
q = q.IsFalse("is_mounted")
}
}
if isSystem != nil {
if *isSystem {
q = q.IsTrue("is_system")
} else {
q = q.Filter(sqlchemy.OR(
sqlchemy.IsNull(q.Field("is_system")),
sqlchemy.IsFalse(q.Field("is_system")),
))
}
}
return q
}
func (mdl *SLLMInstantModel) FindInstantModel(isInstall bool) (*SInstantModel, error) {
instMdl, err := GetInstantModelManager().GetInstantModelById(mdl.InstantModelId)
if err != nil {
return nil, errors.Wrap(err, "FindInstantModel")
}
return instMdl, nil
}
func (mdl *SLLMInstantModel) syncStatus() {
if !mdl.IsProbed && !mdl.IsMounted {
mdl.MarkDelete()
} else {
mdl.Deleted = false
mdl.DeletedAt = time.Time{}
}
}
func (mdl *SLLMInstantModel) getMountPaths(isInstall bool) ([]api.LLMMountDirInfo, error) {
info, err := mdl.getMountPathsFromImage(isInstall)
if err != nil {
return nil, errors.Wrap(err, "getMountPathsFromImage")
}
return info, nil
}
func (mdl *SLLMInstantModel) getMountPathsFromImage(isInstall bool) ([]api.LLMMountDirInfo, error) {
instMdl, err := mdl.FindInstantModel(isInstall)
if err != nil {
return nil, errors.Wrap(err, "findInstantApp")
}
if instMdl == nil {
return nil, nil
}
info := make([]api.LLMMountDirInfo, 0)
info = append(info, api.LLMMountDirInfo{
ImageId: instMdl.ImageId,
})
return info, nil
}
func (man *SLLMInstantModelManager) DeleteByLlmId(ctx context.Context, llmId string) error {
q := man.Query().Equals("llm_id", llmId)
models := make([]SLLMInstantModel, 0)
err := db.FetchModelObjects(man, q, &models)
if err != nil {
return errors.Wrap(err, "FetchModelObjects")
}
for i := range models {
_, err := db.Update(&models[i], func() error {
return models[i].MarkDelete()
})
if err != nil {
return errors.Wrapf(err, "delete llm model %s", models[i].ModelName)
}
}
return nil
}
func (man *SLLMInstantModelManager) purgeModelList(llmId string) error {
err := man.TableSpec().GetTableSpec().DeleteFrom(map[string]interface{}{
"llm_id": llmId,
})
if err != nil {
return errors.Wrap(err, "purgeModelList.DeleteFrom")
}
return nil
}
func (mdl *SLLMInstantModel) purgeModelList() error {
return GetLLMInstantModelManager().purgeModelList(mdl.InstantModelId)
}