diff --git a/dao/model_manage_dao.go b/dao/model_manage_dao.go index c817d86..6480089 100644 --- a/dao/model_manage_dao.go +++ b/dao/model_manage_dao.go @@ -8,6 +8,7 @@ import ( "model-gateway/model/entity" "gitea.redpowerfuture.com/red-future/common/db/gfdb" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" ) @@ -77,6 +78,26 @@ func (d *modelManageDao) GetByCreatorAndName(ctx context.Context, creator, model return } +// CountReferences 统计引用某系统模型的引用行数(Model 链自动过滤软删) +func (d *modelManageDao) CountReferences(ctx context.Context, systemModelId int64) (count int, err error) { + count, err = gfdb.DB(ctx, public.DbNameModelGateway).Model(ctx, public.TableNameModelManage). + Where(entity.ModelManageCol.RefSystemModelId, systemModelId). + Count() + return +} + +// UpdateReferencesName 系统模型改名时同步引用行的 model_name(保列表 DISTINCT ON 去重正确) +func (d *modelManageDao) UpdateReferencesName(ctx context.Context, systemModelId int64, newName string) (rows int64, err error) { + r, err := gfdb.DB(ctx, public.DbNameModelGateway).Model(ctx, public.TableNameModelManage). + Data(gdb.Map{entity.ModelManageCol.ModelName: newName}). + Where(entity.ModelManageCol.RefSystemModelId, systemModelId). + Update() + if err != nil { + return + } + return r.RowsAffected() +} + func (d *modelManageDao) GetNotTenantId(ctx context.Context, req *dto.GetModelManageReq, fields ...string) (res *entity.ModelManage, err error) { // 获取表前缀 prefix := g.Cfg().MustGet(ctx, fmt.Sprintf("database.%s.0.prefix", public.DbNameModelGateway)).String() diff --git a/model/dto/model_manage_dto.go b/model/dto/model_manage_dto.go index 25ec19d..5321bda 100644 --- a/model/dto/model_manage_dto.go +++ b/model/dto/model_manage_dto.go @@ -17,6 +17,7 @@ type CreateModelManageReq struct { ModelType model.ModelType `json:"modelType" v:"required#模型类型不能为空" dc:"模型类型"` BaseURL string `json:"baseUrl" v:"required#模型服务地址不能为空" dc:"模型服务地址"` SystemModel *bool `json:"systemModel" dc:"系统模型"` + RefSystemModelId int64 `json:"refSystemModelId" dc:"引用的系统模型ID(引用创建时填,普通创建留空)"` HttpMethod string `json:"httpMethod" dc:"请求方式:GET/POST" d:"POST"` ChatModel *bool `json:"chatModel" dc:"对话模型"` ResponseType model.ResponseType `json:"responseType" v:"required#调用模式不能为空" dc:"调用模式:0-同步 1-异步 2-流式"` @@ -51,6 +52,7 @@ type UpdateModelManageReq struct { ModelType model.ModelType `json:"modelType" dc:"模型类型"` BaseURL string `json:"baseUrl" dc:"模型服务地址"` SystemModel *bool `json:"systemModel" dc:"系统模型"` + RefSystemModelId int64 `json:"refSystemModelId" dc:"引用的系统模型ID(引用行只改个人字段,本字段无效)"` HttpMethod string `json:"httpMethod" dc:"请求方式:GET/POST"` ChatModel *bool `json:"chatModel" dc:"对话模型"` ResponseType model.ResponseType `json:"responseType" dc:"调用模式:0-同步 1-异步 2-流式"` @@ -152,3 +154,16 @@ type BuildSchemaMappingReq struct { type BuildSchemaMappingRes struct { SchemaMapping map[string]any `json:"schemaMapping" dc:"生成的 Schema 映射 JSON"` } + +// ReferenceSystemModelReq 引用系统模型请求:用户只填 apiKey + 个人开关,配置实时跟随系统模型 +type ReferenceSystemModelReq struct { + g.Meta `path:"/referenceSystemModel" method:"post" tags:"模型管理" summary:"引用系统模型" dc:"用户引用系统模型,只填 apiKey 等个人字段,配置实时跟随系统模型(不再全量拷贝)"` + SystemModelId int64 `json:"systemModelId" v:"required#系统模型ID不能为空" dc:"被引用的系统模型ID"` + ApiKey string `json:"apiKey" v:"required#apiKey不能为空" dc:"调用凭证/密钥"` + ChatModel *bool `json:"chatModel" dc:"设为我的会话模型"` + Enabled *bool `json:"enabled" dc:"启用(默认启用)"` +} + +type ReferenceSystemModelRes struct { + Id int64 `json:"id,string" dc:"引用行ID"` +} diff --git a/model/dto/model_manage_dto_test.go b/model/dto/model_manage_dto_test.go new file mode 100644 index 0000000..1e73601 --- /dev/null +++ b/model/dto/model_manage_dto_test.go @@ -0,0 +1,24 @@ +package dto + +import ( + "testing" + + "model-gateway/model/entity" + + "github.com/gogf/gf/v2/util/gconv" +) + +// 引用行字段落地验证:DTO → entity 映射(CreateModelManageReq.RefSystemModelId → entity.RefSystemModelId) +func TestRefSystemModelIdRoundtrip(t *testing.T) { + req := CreateModelManageReq{ModelName: "gpt-4o", RefSystemModelId: 100} + var e entity.ModelManage + if err := gconv.Struct(&req, &e); err != nil { + t.Fatalf("gconv dto->entity: %v", err) + } + if e.RefSystemModelId != 100 { + t.Fatalf("refSystemModelId mismatch: got %d want 100", e.RefSystemModelId) + } + if e.ModelName != "gpt-4o" { + t.Fatalf("modelName mismatch: got %s", e.ModelName) + } +} diff --git a/model/entity/model_manage.go b/model/entity/model_manage.go index cdaf4ae..d0954af 100644 --- a/model/entity/model_manage.go +++ b/model/entity/model_manage.go @@ -13,6 +13,7 @@ type modelManageCol struct { ModelType string BaseURL string SystemModel string + RefSystemModelId string HttpMethod string ChatModel string ResponseType string @@ -40,6 +41,7 @@ var ModelManageCol = modelManageCol{ ModelType: "model_type", BaseURL: "base_url", SystemModel: "system_model", + RefSystemModelId: "ref_system_model_id", HttpMethod: "http_method", ChatModel: "chat_model", ResponseType: "response_type", @@ -67,6 +69,7 @@ type ModelManage struct { ModelType model.ModelType `orm:"model_type" json:"modelType" description:"模型类型"` BaseURL string `orm:"base_url" json:"baseUrl" description:"模型地址"` SystemModel *bool `orm:"system_model" json:"systemModel" description:"系统模型"` + RefSystemModelId int64 `orm:"ref_system_model_id" json:"refSystemModelId" description:"引用的系统模型ID(NULL=非引用行)"` HttpMethod string `orm:"http_method" json:"httpMethod" description:"http方法"` ChatModel *bool `orm:"chat_model" json:"chatModel" description:"是否聊天模型"` ResponseType model.ResponseType `orm:"response_type" json:"responseType" description:"返回类型:1同步,2异步,3流"` diff --git a/update.sql b/update.sql index ad5c018..898c45b 100644 --- a/update.sql +++ b/update.sql @@ -317,4 +317,15 @@ COMMENT ON COLUMN model_gateway_model_task_start.media_type ALTER TABLE model_gateway_model_task_end ADD COLUMN IF NOT EXISTS total_cost NUMERIC DEFAULT 0; COMMENT ON COLUMN model_gateway_model_task_end.total_cost - IS '本次调用总费用(元),未配置计费规则为0'; \ No newline at end of file + IS '本次调用总费用(元),未配置计费规则为0'; + +-- ========================= +-- 模型引用化:model_manage 新增 ref_system_model_id(引用行指向系统模型) +-- 系统模型 = 配置唯一来源;引用行只存 apiKey/enabled/chatModel,配置列留空 +-- ========================= +ALTER TABLE model_gateway_model_manage + ADD COLUMN IF NOT EXISTS ref_system_model_id BIGINT DEFAULT NULL; +COMMENT ON COLUMN model_gateway_model_manage.ref_system_model_id + IS '引用的系统模型ID(NULL=非引用行;system_model=false 且该列非空=引用行)'; +CREATE INDEX IF NOT EXISTS idx_model_manage_ref_system_model_id + ON model_gateway_model_manage(ref_system_model_id); \ No newline at end of file