update: 更新配置文件中的服务地址,修改模型管理相关代码,调整数据结构和逻辑,优化模型列表查询和会话模型设置,更新数据库表结构和索引,修改模块名称和依赖版本
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
server:
|
||||
address: ":8001"
|
||||
address: ":3004"
|
||||
name: "model-gateway"
|
||||
workerId: 1 # 雪花算法worker ID(用于 common/db/gfdb)
|
||||
|
||||
@@ -29,14 +29,14 @@ database:
|
||||
|
||||
redis:
|
||||
default:
|
||||
address: 116.204.74.41:6379
|
||||
address: 192.168.3.30:6379
|
||||
db: 0
|
||||
|
||||
consul:
|
||||
address: 116.204.74.41:8500
|
||||
address: 192.168.3.30:8500
|
||||
|
||||
jaeger:
|
||||
addr: 116.204.74.41:4318
|
||||
addr: 192.168.3.30:4318
|
||||
|
||||
# 本地调试用:可选自动执行 worker/cleaner(默认关闭)
|
||||
asynch:
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package public
|
||||
|
||||
const (
|
||||
TableNameModel = "asynch_models" // 模型表
|
||||
TableNameModelType = "asynch_models_type" // 模型类型表
|
||||
TableNameTask = "asynch_task" // 任务表
|
||||
TableNameOpLog = "logs_model_op" // 操作日志表
|
||||
TableNameStat = "logs_model_stat" // 按天统计表(请求次数)
|
||||
TableNameModel = "asynch_models" // 模型表
|
||||
TableNameTask = "asynch_task" // 任务表
|
||||
TableNameOpLog = "logs_model_op" // 操作日志表
|
||||
TableNameStat = "logs_model_stat" // 按天统计表(请求次数)
|
||||
)
|
||||
|
||||
@@ -3,9 +3,9 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/model/entity"
|
||||
"model-asynch/service"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/model/entity"
|
||||
"model-gateway/service"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
@@ -38,21 +38,15 @@ func (c *model) GetModel(ctx context.Context, req *dto.GetModelReq) (res *dto.Ge
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if model == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &dto.GetModelRes{Model: model}, nil
|
||||
}
|
||||
|
||||
// ListModel 配置列表
|
||||
func (c *model) ListModel(ctx context.Context, req *dto.ListModelReq) (res *dto.ListModelRes, err error) {
|
||||
pageNum, pageSize := 1, 10 //默认分页参数
|
||||
if req != nil {
|
||||
if req.PageNum > 0 {
|
||||
pageNum = req.PageNum
|
||||
}
|
||||
if req.PageSize > 0 {
|
||||
pageSize = req.PageSize
|
||||
}
|
||||
}
|
||||
list, total, err := service.Model.List(ctx, pageNum, pageSize, req)
|
||||
list, total, err := service.Model.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/service"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/service"
|
||||
)
|
||||
|
||||
type stat struct{}
|
||||
|
||||
@@ -3,8 +3,8 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/service"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/service"
|
||||
)
|
||||
|
||||
type task struct{}
|
||||
|
||||
103
dao/model_dao.go
103
dao/model_dao.go
@@ -4,11 +4,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
@@ -17,8 +18,13 @@ var Model = &modelDao{}
|
||||
|
||||
type modelDao struct{}
|
||||
|
||||
func (d *modelDao) Insert(ctx context.Context, m *entity.AsynchModel) (id int64, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).Data(m).Insert()
|
||||
func (d *modelDao) Insert(ctx context.Context, req *dto.CreateModelReq) (id int64, err error) {
|
||||
asyncModel := new(entity.AsynchModel)
|
||||
err = gconv.Struct(req, &asyncModel)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).Data(asyncModel).Insert()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -38,20 +44,6 @@ func (d *modelDao) Update(ctx context.Context, m *dto.UpdateModelReq) (rows int6
|
||||
return r.RowsAffected()
|
||||
}
|
||||
|
||||
func (d *modelDao) UpdateByID(ctx context.Context, m *dto.UpdateModelReq) (rows int64, err error) {
|
||||
// 专用于切换会话模型,只更新 is_chat_model 字段
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).
|
||||
Where(entity.AsynchModelCol.Id, m.ID).
|
||||
Data(g.Map{
|
||||
"is_chat_model": m.IsChatModel,
|
||||
}).
|
||||
Update()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r.RowsAffected()
|
||||
}
|
||||
|
||||
func (d *modelDao) DeleteByID(ctx context.Context, id string) (rows int64, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).
|
||||
Where(entity.AsynchModelCol.Id, id).
|
||||
@@ -78,6 +70,7 @@ func (d *modelDao) GetByModelName(ctx context.Context, modelName string) (m *ent
|
||||
|
||||
func (d *modelDao) Get(ctx context.Context, id int64) (m *entity.AsynchModel, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).
|
||||
NoTenantId(ctx).
|
||||
Where(entity.AsynchModelCol.Id, id).
|
||||
One()
|
||||
if err != nil {
|
||||
@@ -90,6 +83,13 @@ func (d *modelDao) Get(ctx context.Context, id int64) (m *entity.AsynchModel, er
|
||||
return
|
||||
}
|
||||
|
||||
func (d *modelDao) Count(ctx context.Context, req *dto.GetModelReq) (count int, err error) {
|
||||
count, err = gfdb.DB(ctx).Model(ctx, public.TableNameModel).OmitEmpty().
|
||||
Where(entity.AsynchModelCol.Creator, req.Creator).
|
||||
Where(entity.AsynchModelCol.Id, req.ID).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *modelDao) List(ctx context.Context, pageNum, pageSize int, modelNameLike string, modelType int, isPrivate int) (list []*entity.AsynchModel, total int64, err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.TableNameModel).
|
||||
OrderDesc(entity.AsynchModelCol.CreatedAt)
|
||||
@@ -97,7 +97,7 @@ func (d *modelDao) List(ctx context.Context, pageNum, pageSize int, modelNameLik
|
||||
model = model.WhereLike(entity.AsynchModelCol.ModelName, "%"+modelNameLike+"%")
|
||||
}
|
||||
if modelType != 0 {
|
||||
model = model.Where(entity.AsynchModelCol.ModelsType, modelType)
|
||||
model = model.Where(entity.AsynchModelCol.ModelType, modelType)
|
||||
}
|
||||
if isPrivate != 0 {
|
||||
model = model.Where(entity.AsynchModelCol.IsPrivate, isPrivate)
|
||||
@@ -150,39 +150,64 @@ func (d *modelDao) ListByCreatorAndPlatform(ctx context.Context, creator string,
|
||||
err = r.Structs(&list)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *modelDao) GetByCreatorAndPlatform(ctx context.Context, creator string, modelNameLike string, modelType int, isPrivate int) (list []*entity.AsynchModel, err error) {
|
||||
whereSQL := "deleted_at IS NULL AND (tenant_id = 1 OR creator = ?)"
|
||||
args := []any{creator}
|
||||
|
||||
if modelNameLike != "" {
|
||||
whereSQL += " AND model_name LIKE ?"
|
||||
args = append(args, "%"+modelNameLike+"%")
|
||||
func (d *modelDao) GetByCreatorAndPlatform(ctx context.Context, req *dto.ListModelReq) (list []*entity.AsynchModel, total int, err error) {
|
||||
// 基础 SQL
|
||||
sql := `
|
||||
SELECT DISTINCT ON (model_name) *
|
||||
FROM asynch_models
|
||||
WHERE deleted_at IS NULL
|
||||
AND (? = '' OR model_name LIKE ?)
|
||||
AND (? = 0 OR model_type = ?)
|
||||
`
|
||||
args := []any{
|
||||
req.ModelName, "%" + req.ModelName + "%",
|
||||
req.ModelType, req.ModelType,
|
||||
}
|
||||
if modelType != 0 {
|
||||
whereSQL += " AND models_type = ?"
|
||||
args = append(args, modelType)
|
||||
if !g.IsEmpty(req.IsPrivate) {
|
||||
sql += ` AND is_private = ? `
|
||||
args = append(args, req.IsPrivate)
|
||||
}
|
||||
if isPrivate != 0 {
|
||||
whereSQL += " AND is_private = ?"
|
||||
args = append(args, isPrivate)
|
||||
if req.IsOwner != nil && *req.IsOwner == 0 {
|
||||
sql += ` AND creator = ? AND is_owner = ? `
|
||||
args = append(args, req.Creator)
|
||||
args = append(args, req.IsOwner)
|
||||
} else if req.IsOwner != nil && *req.IsOwner == 1 {
|
||||
if req.Enabled != nil && *req.Enabled == 1 {
|
||||
sql += ` AND ((creator = ? AND is_owner = ? AND enabled=1) OR (is_owner = 0 AND enabled=1)) `
|
||||
} else if req.Enabled != nil && *req.Enabled == 0 {
|
||||
sql += ` AND ((creator = ? AND is_owner = ? AND enabled=0) OR (is_owner = 0 AND enabled=1)) `
|
||||
} else {
|
||||
sql += ` AND ((creator = ? AND is_owner = ?) OR (is_owner = 0 AND enabled=1)) `
|
||||
}
|
||||
args = append(args, req.Creator)
|
||||
args = append(args, req.IsOwner)
|
||||
}
|
||||
|
||||
querySQL := fmt.Sprintf("SELECT * FROM %s WHERE %s ORDER BY created_at DESC", public.TableNameModel, whereSQL)
|
||||
// 最后拼接排序
|
||||
sql += ` ORDER BY model_name, is_owner DESC, created_at DESC`
|
||||
|
||||
r, err := gfdb.DB(ctx).GetAll(ctx, querySQL, args...)
|
||||
r, err := gfdb.DB(ctx).GetAll(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
err = r.Structs(&list)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
total = len(list)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *modelDao) GetByIsChatModel(ctx context.Context, userName string) (m *entity.AsynchModel, err error) {
|
||||
func (d *modelDao) GetByIsChatModel(ctx context.Context) (m *entity.AsynchModel, err error) {
|
||||
userInfo, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.TableNameModel).
|
||||
Where(entity.AsynchModelCol.IsChatModel, 1).
|
||||
Where(entity.AsynchModelCol.Creator, userName).
|
||||
Where(entity.AsynchModelCol.Creator, userInfo.UserName).
|
||||
One()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -3,8 +3,8 @@ package dao
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ package dao
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
)
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
|
||||
4
go.mod
4
go.mod
@@ -1,9 +1,9 @@
|
||||
module model-asynch
|
||||
module model-gateway
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
gitea.com/red-future/common v0.0.19 // indirect
|
||||
gitea.com/red-future/common v0.0.19
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.10.0
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.10.0
|
||||
github.com/gogf/gf/v2 v2.10.0
|
||||
|
||||
1
go.sum
1
go.sum
@@ -603,6 +603,7 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
|
||||
4
main.go
4
main.go
@@ -7,8 +7,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"model-asynch/controller"
|
||||
"model-asynch/service"
|
||||
"model-gateway/controller"
|
||||
"model-gateway/service"
|
||||
|
||||
"gitea.com/red-future/common/http"
|
||||
"gitea.com/red-future/common/jaeger"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
@@ -8,14 +9,15 @@ import (
|
||||
type CreateModelReq struct {
|
||||
g.Meta `path:"/createModel" method:"post" tags:"模型管理" summary:"创建模型配置" dc:"添加新的模型配置"`
|
||||
ModelName string `p:"modelName" json:"modelName" v:"required#modelName不能为空" dc:"模型名称(唯一标识)"`
|
||||
ModelsType int `p:"modelsType" json:"modelsType" v:"required#modelsType不能为空" dc:"模型类型:1-文本生成 2-图像生成 3-语音 4-视频 5-多模态"`
|
||||
ModelType int `p:"modelType" json:"modelType" v:"required#modelType不能为空" dc:"模型类型:1-文本生成 2-图像生成 3-语音 4-视频 5-多模态"`
|
||||
BaseURL string `p:"baseUrl" json:"baseUrl" v:"required#baseUrl不能为空" dc:"模型服务基础地址(如 http(s)://host:port)"`
|
||||
HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(默认POST)"`
|
||||
HeadMsg string `p:"headMsg" json:"headMsg" dc:"请求头绑定(支持多个,逗号分隔),示例:Authorization:Bearer xxx,Content-Type:application/json"`
|
||||
IsPrivate int `p:"isPrivate" json:"isPrivate" v:"in:0,1#私有化参数只能为0或1" dc:"是否私有化:0-私有(默认) 1-公共"`
|
||||
Enabled int `p:"enabled" json:"enabled" v:"in:0,1#启用参数只能为0或1" dc:"是否启用:0-禁用,1-启用(默认1)"`
|
||||
IsChatModel int `p:"isChatModel" json:"isChatModel" v:"in:0,1#对话模型参数只能为0或1" dc:"是否为对话模型:0-否,1-是(默认0)"`
|
||||
ApiKey string `p:"apiKey" json:"apiKey" v:"required-if:isPrivate,1#公共模型必须填写API密钥" dc:"调用凭证/密钥,用于模型认证"`
|
||||
IsPrivate *int `p:"isPrivate" json:"isPrivate" v:"in:0,1#私有化参数只能为0或1" dc:"是否私有化:0-私有(默认) 1-公共"`
|
||||
Enabled *int `p:"enabled" json:"enabled" v:"in:0,1#启用参数只能为0或1" dc:"是否启用:0-禁用,1-启用(默认1)"`
|
||||
IsChatModel *int `p:"isChatModel" json:"isChatModel" v:"in:0,1#对话模型参数只能为0或1" dc:"是否为对话模型:0-否,1-是(默认0)"`
|
||||
IsOwner *int `p:"isOwner" json:"isOwner" v:"in:0,1#是否为所有者参数只能为0或1" dc:"是否为所有者:0-否,1-是(默认0)"`
|
||||
ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥,用于模型认证"`
|
||||
Form any `p:"form" json:"form" dc:"动态表单配置(JSON),用于前端渲染配置项"`
|
||||
RequestMapping any `p:"requestMapping" json:"requestMapping" dc:"请求映射"`
|
||||
ResponseMapping any `p:"responseMapping" json:"responseMapping" dc:"返回映射"`
|
||||
@@ -38,17 +40,21 @@ type CreateModelRes struct {
|
||||
type UpdateModelReq struct {
|
||||
g.Meta `path:"/updateModel" method:"put" tags:"模型管理" summary:"更新模型配置" dc:"更新指定ID的模型配置"`
|
||||
ID int64 `p:"id" json:"id" v:"required#id不能为空" dc:"配置ID"`
|
||||
ModelsType string `p:"modelsType" json:"modelsType" dc:"模型类型ID列表(逗号分隔)(可选更新)"`
|
||||
ModelName string `p:"modelName" json:"modelName" dc:"模型名称(唯一标识)"`
|
||||
ModelType int `p:"modelType" json:"modelType" dc:"模型类型ID列表(逗号分隔)(可选更新)"`
|
||||
BaseURL string `p:"baseUrl" json:"baseUrl" dc:"模型服务基础地址"`
|
||||
HttpMethod string `p:"httpMethod" json:"httpMethod" dc:"请求方式:GET/POST(可选更新)"`
|
||||
HeadMsg string `p:"headMsg" json:"headMsg" dc:"请求头绑定(可选更新)"`
|
||||
ApiKey string `p:"apiKey" json:"apiKey" dc:"调用凭证/密钥,用于模型认证(可选更新)"`
|
||||
Form any `p:"form" json:"form" dc:"动态表单配置(JSON)(可选更新)"`
|
||||
RequestMapping any `p:"requestMapping" json:"requestMapping" dc:"请求参数映射(可选更新)"`
|
||||
ResponseMapping any `p:"responseMapping" json:"responseMapping" dc:"返回参数映射(可选更新)"`
|
||||
ResponseBody any `p:"responseBody" json:"responseBody" dc:"返回主体(可选更新)"`
|
||||
TokenMapping string `p:"tokenMapping" json:"tokenMapping" dc:"token映射(可选更新)"`
|
||||
Enabled int `p:"enabled" json:"enabled" dc:"是否启用:0-禁用,1-启用(可选更新)"`
|
||||
IsChatModel int `p:"isChatModel" json:"isChatModel" v:"in:0,1#对话模型参数只能为0或1" dc:"是否为对话模型:0-否,1-是(默认0)"`
|
||||
Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-禁用,1-启用(可选更新)"`
|
||||
IsPrivate *int `p:"isPrivate" json:"isPrivate" v:"in:0,1#私有化参数只能为0或1" dc:"是否私有化:0-私有(默认) 1-公共"`
|
||||
IsChatModel *int `p:"isChatModel" json:"isChatModel" v:"in:0,1#对话模型参数只能为0或1" dc:"是否为对话模型:0-否,1-是(默认0)"`
|
||||
IsOwner *int `p:"isOwner" json:"isOwner" v:"in:0,1#是否为所有者参数只能为0或1" dc:"是否为所有者:0-否,1-是(默认0)"`
|
||||
MaxConcurrency int `p:"maxConcurrency" json:"maxConcurrency" dc:"最大并发数(可选更新)"`
|
||||
QueueLimit int `p:"queueLimit" json:"queueLimit" dc:"排队队列上限(可选更新)"`
|
||||
TimeoutSeconds int `p:"timeoutSeconds" json:"timeoutSeconds" dc:"请求超时时间(秒)(可选更新)"`
|
||||
@@ -67,8 +73,9 @@ type DeleteModelReq struct {
|
||||
|
||||
// GetModelReq 获取模型配置详情
|
||||
type GetModelReq struct {
|
||||
g.Meta `path:"/getModel" method:"get" tags:"模型管理" summary:"获取模型配置" dc:"根据模型ID获取配置详情"`
|
||||
ID int64 `p:"id" json:"id,string" v:"required#id不能为空" dc:"配置ID"`
|
||||
g.Meta `path:"/getModel" method:"get" tags:"模型管理" summary:"获取模型配置" dc:"根据模型ID获取配置详情"`
|
||||
ID int64 `p:"id" json:"id,string" v:"required#id不能为空" dc:"配置ID"`
|
||||
Creator string `p:"creator" json:"creator" dc:"创建人"`
|
||||
}
|
||||
|
||||
type GetModelRes struct {
|
||||
@@ -78,16 +85,18 @@ type GetModelRes struct {
|
||||
// ListModelReq 配置列表
|
||||
type ListModelReq struct {
|
||||
g.Meta `path:"/listModel" method:"get" tags:"模型管理" summary:"模型配置列表" dc:"分页获取模型配置列表"`
|
||||
PageNum int `p:"pageNum" json:"pageNum" dc:"页码(默认1)"`
|
||||
PageSize int `p:"pageSize" json:"pageSize" dc:"每页条数(默认10)"`
|
||||
ModelName string `p:"modelName" json:"modelName" dc:"模型名称(模糊查询,可选)"`
|
||||
ModelType int `p:"modelType" json:"modelType" dc:"模型类型"`
|
||||
IsPrivate int `p:"isPrivate" json:"isPrivate" dc:"是否私有化 0-私有 1-公共"`
|
||||
Page *beans.Page `json:"page"`
|
||||
ModelName string `p:"modelName" json:"modelName" dc:"模型名称(模糊查询,可选)"`
|
||||
ModelType int `p:"modelType" json:"modelType" dc:"模型类型"`
|
||||
Enabled *int `p:"enabled" json:"enabled" dc:"是否启用:0-禁用,1-启用"`
|
||||
IsPrivate *int `p:"isPrivate" json:"isPrivate" dc:"是否私有化 0-私有 1-公共"`
|
||||
IsOwner *int `p:"isOwner" json:"isOwner" dc:"是否为所有者 0-否 1-是"`
|
||||
Creator string `p:"creator" json:"creator" dc:"创建人"`
|
||||
}
|
||||
|
||||
type ListModelRes struct {
|
||||
List any `json:"list" dc:"列表数据"`
|
||||
Total int64 `json:"total" dc:"总数"`
|
||||
List any `json:"list" dc:"列表数据"`
|
||||
Total int `json:"total" dc:"总数"`
|
||||
}
|
||||
|
||||
// AutoTuneReq 动态调参(由上层定时任务每小时触发一次)
|
||||
|
||||
@@ -5,7 +5,7 @@ import "gitea.com/red-future/common/beans"
|
||||
type asynchModelCol struct {
|
||||
beans.SQLBaseCol
|
||||
ModelName string
|
||||
ModelsType string
|
||||
ModelType string
|
||||
BaseURL string
|
||||
HttpMethod string
|
||||
HeadMsg string
|
||||
@@ -27,12 +27,13 @@ type asynchModelCol struct {
|
||||
RetryQueueMaxSecs string
|
||||
AutoCleanSeconds string
|
||||
Remark string
|
||||
IsOwner string
|
||||
}
|
||||
|
||||
var AsynchModelCol = asynchModelCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
ModelName: "model_name",
|
||||
ModelsType: "models_type",
|
||||
ModelType: "model_type",
|
||||
BaseURL: "base_url",
|
||||
HttpMethod: "http_method",
|
||||
HeadMsg: "head_msg",
|
||||
@@ -54,13 +55,14 @@ var AsynchModelCol = asynchModelCol{
|
||||
RetryQueueMaxSecs: "retry_queue_max_seconds",
|
||||
AutoCleanSeconds: "auto_clean_seconds",
|
||||
Remark: "remark",
|
||||
IsOwner: "is_owner",
|
||||
}
|
||||
|
||||
// AsynchModel 异步模型配置
|
||||
type AsynchModel struct {
|
||||
beans.SQLBaseDO `orm:",inline"`
|
||||
ModelName string `orm:"model_name" json:"modelName"`
|
||||
ModelsType int `orm:"models_type" json:"modelsType"`
|
||||
ModelType int `orm:"model_type" json:"modelType"`
|
||||
BaseURL string `orm:"base_url" json:"baseUrl"`
|
||||
HttpMethod string `orm:"http_method" json:"httpMethod"`
|
||||
HeadMsg string `orm:"head_msg" json:"headMsg"`
|
||||
@@ -70,10 +72,10 @@ type AsynchModel struct {
|
||||
ResponseBody any `orm:"response_body" json:"responseBody"`
|
||||
TokenMapping string `orm:"token_mapping" json:"tokenMapping"`
|
||||
Prompt string `orm:"prompt" json:"prompt"`
|
||||
IsPrivate int `orm:"is_private" json:"isPrivate"`
|
||||
IsChatModel int `orm:"is_chat_model" json:"isChatModel"`
|
||||
IsPrivate *int `orm:"is_private" json:"isPrivate"`
|
||||
IsChatModel *int `orm:"is_chat_model" json:"isChatModel"`
|
||||
ApiKey string `orm:"api_key" json:"apiKey"`
|
||||
Enabled int `orm:"enabled" json:"enabled"`
|
||||
Enabled *int `orm:"enabled" json:"enabled"`
|
||||
MaxConcurrency int `orm:"max_concurrency" json:"maxConcurrency"`
|
||||
QueueLimit int `orm:"queue_limit" json:"queueLimit"`
|
||||
TimeoutSeconds int `orm:"timeout_seconds" json:"timeoutSeconds"`
|
||||
@@ -82,4 +84,5 @@ type AsynchModel struct {
|
||||
RetryQueueMaxSeconds int `orm:"retry_queue_max_seconds" json:"retryQueueMaxSeconds"`
|
||||
AutoCleanSeconds int `orm:"auto_clean_seconds" json:"autoCleanSeconds"`
|
||||
Remark string `orm:"remark" json:"remark"`
|
||||
IsOwner *int `json:"isOwner" orm:"is_owner"` // 1=当前用户创建的,0=超级管理员的
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"model-asynch/consts/public"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/consts/public"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
// AutoTuneResult 单次调参结果(按 model_name)
|
||||
type AutoTuneResult struct {
|
||||
ModelName string `json:"modelName"` // 模型名称(asynch_models.model_name)
|
||||
Samples int `json:"samples"` // 统计样本数(窗口内 state=2/3 且 started_at/finished_at 非空的任务数量)
|
||||
P90Exec float64 `json:"p90ExecSeconds"` // 执行耗时 P90(秒),口径:finished_at - started_at
|
||||
ModelName string `json:"modelName"` // 模型名称(asynch_models.model_name)
|
||||
Samples int `json:"samples"` // 统计样本数(窗口内 state=2/3 且 started_at/finished_at 非空的任务数量)
|
||||
P90Exec float64 `json:"p90ExecSeconds"` // 执行耗时 P90(秒),口径:finished_at - started_at
|
||||
|
||||
CapMaxConcurrency int `json:"capMaxConcurrency"` // 配置上限:asynch_models.max_concurrency(cap,不会被动态调参覆盖)
|
||||
OldMaxConcurrency int `json:"oldMaxConcurrency"` // 调参前运行时值(Redis),若无则等于 cap
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/http"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -65,23 +65,3 @@ func triggerPromptsCallback(ctx context.Context, t *entity.AsynchTask, epicycleI
|
||||
}
|
||||
g.Log().Infof(ctx, "[提示词回调] 发送成功 epicycleId=%d 回调地址=%s 消息体大小=%d字节", t.EpicycleId, callbackURL, len(jsonData))
|
||||
}
|
||||
|
||||
// IsSuperAdmin 调用admin-go服务检查是否是超级管理员
|
||||
func IsSuperAdmin(ctx context.Context) (res bool, err error) {
|
||||
headers := forwardHeaders(ctx)
|
||||
var r = make(map[string]bool)
|
||||
if err = http.Get(ctx, "admin-go/api/v1/system/user/checkIsSuperAdmin", headers, &r); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return r["isSuperAdmin"], err
|
||||
}
|
||||
|
||||
// IsAdmin 调用admin-go服务检查是否是管理员
|
||||
func IsAdmin(ctx context.Context) (res bool, err error) {
|
||||
headers := forwardHeaders(ctx)
|
||||
var r = make(map[string]bool)
|
||||
if err = http.Get(ctx, "admin-go/api/v1/system/user/checkIsSuperAdmin", headers, &r); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return r["isSuperAdmin"], err
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"model-asynch/dao"
|
||||
"model-gateway/dao"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
@@ -3,13 +3,15 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"model-asynch/dao"
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/dao"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"gitea.com/red-future/common/http"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
@@ -18,32 +20,45 @@ var Model = &modelService{}
|
||||
|
||||
type modelService struct{}
|
||||
|
||||
func (s *modelService) Create(ctx context.Context, req *dto.CreateModelReq) (res *dto.CreateModelRes, err error) {
|
||||
m := &entity.AsynchModel{
|
||||
ModelName: req.ModelName,
|
||||
ModelsType: req.ModelsType,
|
||||
BaseURL: req.BaseURL,
|
||||
HttpMethod: req.HttpMethod,
|
||||
HeadMsg: req.HeadMsg,
|
||||
IsPrivate: req.IsPrivate,
|
||||
Enabled: req.Enabled,
|
||||
IsChatModel: req.IsChatModel,
|
||||
ApiKey: req.ApiKey,
|
||||
Form: req.Form,
|
||||
RequestMapping: req.RequestMapping,
|
||||
ResponseMapping: req.ResponseMapping,
|
||||
ResponseBody: req.ResponseBody,
|
||||
TokenMapping: req.TokenMapping,
|
||||
MaxConcurrency: req.MaxConcurrency,
|
||||
QueueLimit: req.QueueLimit,
|
||||
TimeoutSeconds: req.TimeoutSeconds,
|
||||
ExpectedSeconds: req.ExpectedSeconds,
|
||||
RetryTimes: req.RetryTimes,
|
||||
RetryQueueMaxSeconds: req.RetryQueueMaxSeconds,
|
||||
AutoCleanSeconds: req.AutoCleanSeconds,
|
||||
Remark: req.Remark,
|
||||
// IsSuperAdmin 调用admin-go服务检查是否是超级管理员
|
||||
func (s *modelService) IsSuperAdmin(ctx context.Context) (res bool, err error) {
|
||||
headers := forwardHeaders(ctx)
|
||||
var r = make(map[string]bool)
|
||||
if err = http.Get(ctx, "admin-go/api/v1/system/user/checkIsSuperAdmin", headers, &r); err != nil {
|
||||
return false, err
|
||||
}
|
||||
id, err := dao.Model.Insert(ctx, m)
|
||||
return r["isSuperAdmin"], err
|
||||
}
|
||||
|
||||
func (s *modelService) Create(ctx context.Context, req *dto.CreateModelReq) (res *dto.CreateModelRes, err error) {
|
||||
// 获取当前会话模型
|
||||
if !g.IsEmpty(req.IsChatModel) && *req.IsChatModel == 1 {
|
||||
var model *entity.AsynchModel
|
||||
model, err = dao.Model.GetByIsChatModel(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 如果有会话模型,那就改变为 0
|
||||
if model != nil {
|
||||
_, err = dao.Model.Update(ctx, &dto.UpdateModelReq{
|
||||
ID: model.Id,
|
||||
IsChatModel: gconv.PtrInt(0),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req.IsOwner = gconv.PtrInt(1)
|
||||
admin, err := s.IsSuperAdmin(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if admin {
|
||||
req.IsOwner = gconv.PtrInt(0)
|
||||
}
|
||||
id, err := dao.Model.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -52,23 +67,55 @@ func (s *modelService) Create(ctx context.Context, req *dto.CreateModelReq) (res
|
||||
|
||||
func (s *modelService) Update(ctx context.Context, req *dto.UpdateModelReq) error {
|
||||
//根据当前 isChatModel 来判断是否更新模型
|
||||
if req.IsChatModel == 1 {
|
||||
user, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if req.IsChatModel == gconv.PtrInt(1) {
|
||||
//判断当前用户是否有会话模型
|
||||
model, err := dao.Model.GetByIsChatModel(ctx, user.UserName)
|
||||
model, err := dao.Model.GetByIsChatModel(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if model != nil {
|
||||
return errors.New("用户已存在会话模型,不能创建新的会话模型")
|
||||
return errors.New("用户已存在会话模型,不能创建")
|
||||
}
|
||||
_, err = dao.Model.Update(ctx, req)
|
||||
}
|
||||
|
||||
req.IsOwner = gconv.PtrInt(1)
|
||||
admin, err := s.IsSuperAdmin(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := dao.Model.Update(ctx, req)
|
||||
if admin {
|
||||
req.IsOwner = gconv.PtrInt(0)
|
||||
_, err = dao.Model.Update(ctx, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var user *beans.User
|
||||
user, err = utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断当前传过来的模型id的模型是否是超级管理员的。如果是超管的进行创建,否则更新
|
||||
var count int
|
||||
count, err = dao.Model.Count(ctx, &dto.GetModelReq{
|
||||
ID: req.ID,
|
||||
Creator: user.UserName,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
insertDto := new(dto.CreateModelReq)
|
||||
err = gconv.Struct(req, insertDto)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = dao.Model.Insert(ctx, insertDto)
|
||||
return err
|
||||
}
|
||||
_, err = dao.Model.Update(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -89,27 +136,29 @@ func (s *modelService) Get(ctx context.Context, id int64) (*entity.AsynchModel,
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func (s *modelService) List(ctx context.Context, pageNum, pageSize int, req *dto.ListModelReq) (list []*entity.AsynchModel, total int64, err error) {
|
||||
isSuperAdmin, err := IsSuperAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
user, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
func (s *modelService) List(ctx context.Context, req *dto.ListModelReq) (list []*entity.AsynchModel, total int, err error) {
|
||||
var models []*entity.AsynchModel
|
||||
var count int64
|
||||
|
||||
if isSuperAdmin {
|
||||
models, count, err = dao.Model.List(ctx, pageNum, pageSize, req.ModelName, req.ModelType, req.IsPrivate)
|
||||
} else {
|
||||
models, count, err = s.getModelsWithDedup(ctx, user.UserName, pageNum, pageSize, req.ModelName, req.ModelType, req.IsPrivate)
|
||||
req.IsOwner = gconv.PtrInt(1)
|
||||
admin, err := s.IsSuperAdmin(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if admin {
|
||||
req.IsOwner = gconv.PtrInt(0)
|
||||
}
|
||||
|
||||
var user *beans.User
|
||||
user, err = utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
req.Creator = user.UserName
|
||||
|
||||
models, total, err = dao.Model.GetByCreatorAndPlatform(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 处理列表中每条记录的 JSONB 字段
|
||||
for _, m := range models {
|
||||
@@ -118,61 +167,7 @@ func (s *modelService) List(ctx context.Context, pageNum, pageSize int, req *dto
|
||||
m.ResponseMapping = ParseJSONField(m.ResponseMapping)
|
||||
m.ResponseBody = ParseJSONField(m.ResponseBody)
|
||||
}
|
||||
return models, count, nil
|
||||
}
|
||||
|
||||
// getModelsWithDedup 获取普通用户的模型列表并去重
|
||||
func (s *modelService) getModelsWithDedup(ctx context.Context, creator string, pageNum, pageSize int, modelNameLike string, modelType int, isPrivate int) (list []*entity.AsynchModel, total int64, err error) {
|
||||
// 1. 查全量数据(不分页,便于去重)
|
||||
allModels, err := dao.Model.GetByCreatorAndPlatform(ctx, creator, modelNameLike, modelType, isPrivate)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 2. 按 modelName 去重,保留当前用户的
|
||||
modelMap := make(map[string]*entity.AsynchModel)
|
||||
for _, m := range allModels {
|
||||
if m == nil {
|
||||
continue
|
||||
}
|
||||
name := m.ModelName
|
||||
|
||||
_, ok := modelMap[name]
|
||||
if !ok {
|
||||
// 没有冲突,直接放进去
|
||||
modelMap[name] = m
|
||||
} else {
|
||||
// 有冲突,保留当前用户创建的
|
||||
if m.Creator == creator {
|
||||
modelMap[name] = m
|
||||
}
|
||||
// 如果现有的就是当前用户的,不做任何替换
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 转回切片并排序
|
||||
deduped := make([]*entity.AsynchModel, 0, len(modelMap))
|
||||
for _, m := range modelMap {
|
||||
deduped = append(deduped, m)
|
||||
}
|
||||
sort.Slice(deduped, func(i, j int) bool {
|
||||
return deduped[i].CreatedAt.After(deduped[j].CreatedAt)
|
||||
})
|
||||
|
||||
// 4. 手动分页
|
||||
total = int64(len(deduped))
|
||||
if pageNum > 0 && pageSize > 0 {
|
||||
start := (pageNum - 1) * pageSize
|
||||
if start >= len(deduped) {
|
||||
return []*entity.AsynchModel{}, total, nil
|
||||
}
|
||||
end := start + pageSize
|
||||
if end > len(deduped) {
|
||||
end = len(deduped)
|
||||
}
|
||||
deduped = deduped[start:end]
|
||||
}
|
||||
return deduped, total, nil
|
||||
return models, total, nil
|
||||
}
|
||||
|
||||
// GetModelTypesFromConfig 从配置文件读取模型类型
|
||||
@@ -202,11 +197,6 @@ func GetModelTypesFromConfig(ctx context.Context) map[int]string {
|
||||
}
|
||||
|
||||
func (s *modelService) UpdateChatModel(ctx context.Context, req *dto.UpdateChatModelReq) error {
|
||||
user, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 校验新会话模型是否存在
|
||||
newModel, err := dao.Model.Get(ctx, req.Id)
|
||||
if err != nil {
|
||||
@@ -217,48 +207,40 @@ func (s *modelService) UpdateChatModel(ctx context.Context, req *dto.UpdateChatM
|
||||
}
|
||||
|
||||
// 获取当前用户会话模型
|
||||
currentModel, err := dao.Model.GetByIsChatModel(ctx, user.UserName)
|
||||
currentModel, err := dao.Model.GetByIsChatModel(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if currentModel.ModelsType != 1 {
|
||||
return errors.New("当前模型为非推理模型,不能设置为会话模型")
|
||||
}
|
||||
err = gfdb.DB(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
if !g.IsEmpty(currentModel) {
|
||||
if currentModel.ModelType != 1 {
|
||||
return errors.New("当前模型为非推理模型,不能设置为会话模型")
|
||||
}
|
||||
|
||||
// 如果点击的就是当前会话模型(已经是1),取消它(设为0)
|
||||
if currentModel != nil && currentModel.Id == req.Id {
|
||||
_, err = dao.Model.UpdateByID(ctx, &dto.UpdateModelReq{
|
||||
// 如果点击的就是当前会话模型(已经是1),取消它(设为0)
|
||||
if currentModel.Id != req.Id {
|
||||
_, err = dao.Model.Update(ctx, &dto.UpdateModelReq{
|
||||
ID: currentModel.Id,
|
||||
IsChatModel: gconv.PtrInt(0),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置当前为会话模型(设为1)
|
||||
_, err = dao.Model.Update(ctx, &dto.UpdateModelReq{
|
||||
ID: req.Id,
|
||||
IsChatModel: 0,
|
||||
IsChatModel: gconv.PtrInt(1),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果之前有会话模型,取消它(设为0)
|
||||
if currentModel != nil {
|
||||
_, err = dao.Model.UpdateByID(ctx, &dto.UpdateModelReq{
|
||||
ID: currentModel.Id,
|
||||
IsChatModel: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 设置当前为会话模型(设为1)
|
||||
_, err = dao.Model.UpdateByID(ctx, &dto.UpdateModelReq{
|
||||
ID: req.Id,
|
||||
IsChatModel: 1,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *modelService) GetIsChatModel(ctx context.Context) (*entity.AsynchModel, error) {
|
||||
user, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
model, err := dao.Model.GetByIsChatModel(ctx, user.UserName)
|
||||
model, err := dao.Model.GetByIsChatModel(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package service
|
||||
import (
|
||||
"context"
|
||||
|
||||
"model-asynch/dao"
|
||||
"model-asynch/model/dto"
|
||||
"model-gateway/dao"
|
||||
"model-gateway/model/dto"
|
||||
)
|
||||
|
||||
type statService struct{}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/model/entity"
|
||||
)
|
||||
|
||||
// StorageService 结果存储(OSS/MinIO)抽象
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"mime/multipart"
|
||||
"time"
|
||||
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
commonHttp "gitea.com/red-future/common/http"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
@@ -3,11 +3,12 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"model-asynch/dao"
|
||||
"model-asynch/model/dto"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/dao"
|
||||
"model-gateway/model/dto"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -20,6 +21,7 @@ var Task = &taskService{}
|
||||
type taskService struct{}
|
||||
|
||||
func (s *taskService) Create(ctx context.Context, req *dto.CreateTaskReq) (res *dto.CreateTaskRes, err error) {
|
||||
fmt.Printf("打印请求:%+v", req)
|
||||
startAt := time.Now()
|
||||
// 固化 token/user 等信息
|
||||
ctx = asyncCtx(ctx)
|
||||
@@ -29,7 +31,7 @@ func (s *taskService) Create(ctx context.Context, req *dto.CreateTaskReq) (res *
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m == nil || m.Enabled != 1 {
|
||||
if m == nil || (m.Enabled != nil && *m.Enabled != 1) {
|
||||
return nil, errors.New("模型不存在或未启用")
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"model-asynch/dao"
|
||||
"model-asynch/model/entity"
|
||||
"model-gateway/dao"
|
||||
"model-gateway/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/grpool"
|
||||
@@ -95,7 +95,7 @@ func (w *asyncWorker) handleOne(ctx context.Context, t *entity.AsynchTask, epicy
|
||||
// ================================
|
||||
return
|
||||
}
|
||||
if m == nil || m.Enabled != 1 {
|
||||
if m == nil || (m.Enabled != nil && *m.Enabled != 1) {
|
||||
errMsg := "模型不存在或未启用"
|
||||
_ = dao.Task.UpdateFailedGlobal(ctx, t.Id, errMsg)
|
||||
ReleaseQueueSlot(ctx, t.ModelName, t.TaskID)
|
||||
@@ -172,9 +172,6 @@ func (w *asyncWorker) handleOne(ctx context.Context, t *entity.AsynchTask, epicy
|
||||
contentType, ext = DetectFileType(data)
|
||||
if utf8.Valid(data) && (strings.HasPrefix(contentType, "text/") || contentType == "application/json") {
|
||||
textResult = string(data)
|
||||
if len(textResult) > 20000 {
|
||||
textResult = textResult[:20000]
|
||||
}
|
||||
}
|
||||
tmpPath, err := saveTmpResult(t.TaskID, data, ext)
|
||||
if err == nil && tmpPath != "" {
|
||||
|
||||
10
update.sql
10
update.sql
@@ -18,13 +18,14 @@ CREATE TABLE IF NOT EXISTS asynch_models (
|
||||
deleted_at TIMESTAMP(6), -- 删除时间(软删)
|
||||
-- 业务字段
|
||||
model_name VARCHAR(128) NOT NULL, -- 模型名称
|
||||
models_type SMALLINT NOT NULL DEFAULT 0, -- 模型类型
|
||||
model_type SMALLINT NOT NULL DEFAULT 0, -- 模型类型
|
||||
base_url VARCHAR(256) NOT NULL, -- 模型地址
|
||||
http_method VARCHAR(8) NOT NULL DEFAULT 'POST', -- 请求方式 GET/POST
|
||||
head_msg VARCHAR(1024) DEFAULT '', -- 请求头绑定(支持多个,逗号分隔)示例 X-API:xxx,operation:true
|
||||
is_private SMALLINT NOT NULL DEFAULT 0, -- 是否私有化 0-私有 1-公共
|
||||
enabled SMALLINT NOT NULL DEFAULT 1, -- 是否启用 0停用 1-启用
|
||||
is_chat_model SMALLINT NOT NULL DEFAULT 0, -- 是否为对话模型 0-否 1-是
|
||||
is_owner SMALLINT NOT NULL DEFAULT 99, -- 1=当前用户创建的,0=超级管理员的
|
||||
api_key VARCHAR(256) NOT NULL DEFAULT '', -- 调用凭证,密钥
|
||||
prompt TEXT NOT NULL DEFAULT '', -- 提示词内容(文本)
|
||||
form_json JSONB NOT NULL DEFAULT '{}'::jsonb, -- 表单结构(用于前端渲染)
|
||||
@@ -46,7 +47,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_models_tenant_creator_chat ON asynch
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_asynch_models_tenant_model_name ON asynch_models(tenant_id, creator, model_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_tenant_id ON asynch_models(tenant_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_model_name ON asynch_models(model_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_models_type ON asynch_models(models_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_model_type ON asynch_models(model_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_enabled ON asynch_models(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_asynch_models_deleted_at ON asynch_models(deleted_at);
|
||||
|
||||
@@ -60,13 +61,14 @@ COMMENT ON COLUMN asynch_models.updated_at IS '更新时间';
|
||||
COMMENT ON COLUMN asynch_models.deleted_at IS '删除时间(软删)';
|
||||
|
||||
COMMENT ON COLUMN asynch_models.model_name IS '模型名称';
|
||||
COMMENT ON COLUMN asynch_models.models_type IS '模型类型';
|
||||
COMMENT ON COLUMN asynch_models.model_type IS '模型类型';
|
||||
COMMENT ON COLUMN asynch_models.base_url IS '模型地址';
|
||||
COMMENT ON COLUMN asynch_models.http_method IS '请求方式 GET/POST';
|
||||
COMMENT ON COLUMN asynch_models.head_msg IS '请求头绑定(支持多个,逗号分隔)示例 X-API:xxx,operation:true';
|
||||
COMMENT ON COLUMN asynch_models.is_private IS '是否私有化 0-私有 1-公共';
|
||||
COMMENT ON COLUMN asynch_models.enabled IS '是否启用 0停用 1-启用';
|
||||
COMMENT ON COLUMN asynch_models.is_chat_model IS '是否为对话模型 0-否 1-是';
|
||||
COMMENT ON COLUMN asynch_models.is_owner IS '1=当前用户创建的,0=超级管理员的';
|
||||
COMMENT ON COLUMN asynch_models.api_key IS '调用凭证,密钥';
|
||||
COMMENT ON COLUMN asynch_models.prompt IS '提示词内容(文本)';
|
||||
COMMENT ON COLUMN asynch_models.form_json IS '表单结构(用于前端渲染,也用于后端校验)';
|
||||
@@ -97,7 +99,7 @@ CREATE TABLE IF NOT EXISTS asynch_task (
|
||||
updater VARCHAR(64) NOT NULL, -- 更新人
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 更新时间
|
||||
deleted_at TIMESTAMP(6), -- 删除时间(软删)
|
||||
|
||||
|
||||
-- 业务字段
|
||||
model_name VARCHAR(128) NOT NULL, -- 模型名称
|
||||
task_id VARCHAR(64) NOT NULL, -- 任务ID(对外返回)
|
||||
|
||||
Reference in New Issue
Block a user