mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-09 02:33:42 +08:00
merge code for v4.1.8
This commit is contained in:
@@ -60,6 +60,8 @@ func (s *AppServer) Init(debug bool, client *redis.Client) {
|
||||
s.Engine.Use(errorHandler)
|
||||
// 添加静态资源访问
|
||||
s.Engine.Static("/static", s.Config.StaticDir)
|
||||
//启动服务
|
||||
|
||||
}
|
||||
|
||||
func (s *AppServer) Run(db *gorm.DB) error {
|
||||
@@ -247,6 +249,7 @@ func needLogin(c *gin.Context) bool {
|
||||
c.Request.URL.Path == "/api/suno/detail" ||
|
||||
c.Request.URL.Path == "/api/suno/play" ||
|
||||
c.Request.URL.Path == "/api/download" ||
|
||||
c.Request.URL.Path == "/api/dall/models" ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/payment/notify/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/user/clogin") ||
|
||||
|
||||
@@ -107,7 +107,10 @@ func (t PowerType) String() string {
|
||||
return "退款"
|
||||
case PowerRedeem:
|
||||
return "兑换"
|
||||
|
||||
case PowerGift:
|
||||
return "赠送"
|
||||
case PowerInvite:
|
||||
return "邀请"
|
||||
}
|
||||
return "其他"
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ type SystemConfig struct {
|
||||
AdminTitle string `json:"admin_title,omitempty"` // 管理后台标题
|
||||
Logo string `json:"logo,omitempty"` // 方形 Logo
|
||||
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
||||
DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力
|
||||
DailyPower int `json:"daily_power,omitempty"` // 每日签到赠送算力
|
||||
InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
|
||||
VipMonthPower int `json:"vip_month_power,omitempty"` // VIP 会员每月赠送的算力值
|
||||
|
||||
@@ -143,12 +143,14 @@ type SystemConfig struct {
|
||||
OrderPayTimeout int `json:"order_pay_timeout,omitempty"` //订单支付超时时间
|
||||
VipInfoText string `json:"vip_info_text,omitempty"` // 会员页面充值说明
|
||||
|
||||
MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力
|
||||
MjActionPower int `json:"mj_action_power,omitempty"` // MJ 操作(放大,变换)消耗算力
|
||||
SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力
|
||||
DallPower int `json:"dall_power,omitempty"` // DALL-E-3 绘图消耗算力
|
||||
SunoPower int `json:"suno_power,omitempty"` // Suno 生成歌曲消耗算力
|
||||
LumaPower int `json:"luma_power,omitempty"` // Luma 生成视频消耗算力
|
||||
MjPower int `json:"mj_power,omitempty"` // MJ 绘画消耗算力
|
||||
MjActionPower int `json:"mj_action_power,omitempty"` // MJ 操作(放大,变换)消耗算力
|
||||
SdPower int `json:"sd_power,omitempty"` // SD 绘画消耗算力
|
||||
DallPower int `json:"dall_power,omitempty"` // DALL-E-3 绘图消耗算力
|
||||
SunoPower int `json:"suno_power,omitempty"` // Suno 生成歌曲消耗算力
|
||||
LumaPower int `json:"luma_power,omitempty"` // Luma 生成视频消耗算力
|
||||
AdvanceVoicePower int `json:"advance_voice_power,omitempty"` // 高级语音对话消耗算力
|
||||
PromptPower int `json:"prompt_power,omitempty"` // 生成提示词消耗算力
|
||||
|
||||
WechatCardURL string `json:"wechat_card_url,omitempty"` // 微信客服地址
|
||||
|
||||
@@ -166,4 +168,5 @@ type SystemConfig struct {
|
||||
EnabledVerify bool `json:"enabled_verify"` // 是否启用验证码
|
||||
EmailWhiteList []string `json:"email_white_list"` // 邮箱白名单列表
|
||||
TranslateModelId int `json:"translate_model_id"` // 用来做提示词翻译的大模型 id
|
||||
|
||||
}
|
||||
|
||||
@@ -74,6 +74,8 @@ type SdTaskParams struct {
|
||||
// DallTask DALL-E task
|
||||
type DallTask struct {
|
||||
ClientId string `json:"client_id"`
|
||||
ModelId uint `json:"model_id"`
|
||||
ModelName string `json:"model_name"`
|
||||
Id uint `json:"id"`
|
||||
UserId uint `json:"user_id"`
|
||||
Prompt string `json:"prompt"`
|
||||
@@ -81,8 +83,7 @@ type DallTask struct {
|
||||
Quality string `json:"quality"`
|
||||
Size string `json:"size"`
|
||||
Style string `json:"style"`
|
||||
|
||||
Power int `json:"power"`
|
||||
Power int `json:"power"`
|
||||
TranslateModelId int `json:"translate_model_id"` // 提示词翻译模型ID
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ require (
|
||||
github.com/go-pay/gopay v1.5.101
|
||||
github.com/google/go-tika v0.3.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/shopspring/decimal v1.3.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
golang.org/x/image v0.15.0
|
||||
@@ -44,7 +45,11 @@ require (
|
||||
github.com/go-pay/xtime v0.0.2 // indirect
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||
github.com/gravityblast/fresh v0.0.0-20240621171608-8d1fef547a99 // indirect
|
||||
github.com/howeyc/fsnotify v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a // indirect
|
||||
github.com/pilu/fresh v0.0.0-20240621171608-8d1fef547a99 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
|
||||
12
api/go.sum
12
api/go.sum
@@ -100,11 +100,15 @@ github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gravityblast/fresh v0.0.0-20240621171608-8d1fef547a99 h1:A6qlLfihaWef15viqtecCz4XknZcgjgD7mEuhu7bHEc=
|
||||
github.com/gravityblast/fresh v0.0.0-20240621171608-8d1fef547a99/go.mod h1:ukFDwXV66bGV7JnfyxFKuKiVp4zH4orBKXML+VCSrhI=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/howeyc/fsnotify v0.9.0 h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY=
|
||||
github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imroc/req/v3 v3.37.2 h1:vEemuA0cq9zJ6lhe+mSRhsZm951bT0CdiSH47+KTn6I=
|
||||
github.com/imroc/req/v3 v3.37.2/go.mod h1:DECzjVIrj6jcUr5n6e+z0ygmCO93rx4Jy0RjOEe1YCI=
|
||||
@@ -137,6 +141,9 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259ae0 h1:LgmjED/yQILqmUED4GaXjrINWe7YJh4HM6z2EvEINPs=
|
||||
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259ae0/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||
@@ -170,6 +177,10 @@ github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:Ff
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a h1:Tg4E4cXPZSZyd3H1tJlYo6ZreXV0ZJvE/lorNqyw1AU=
|
||||
github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a/go.mod h1:9Or9aIl95Kp43zONcHd5tLZGKXb9iLx0pZjau0uJ5zg=
|
||||
github.com/pilu/fresh v0.0.0-20240621171608-8d1fef547a99 h1:+X7Gb40b5Bl3v5+3MiGK8Jhemjp65MHc+nkVCfq1Yfc=
|
||||
github.com/pilu/fresh v0.0.0-20240621171608-8d1fef547a99/go.mod h1:2LLTtftTZSdAPR/iVyennXZDLZOYzyDn+T0qEKJ8eSw=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -291,6 +302,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -43,6 +43,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) {
|
||||
Temperature float32 `json:"temperature"` // 模型温度
|
||||
KeyId int `json:"key_id,omitempty"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
@@ -65,7 +66,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) {
|
||||
item.MaxContext = data.MaxContext
|
||||
item.Temperature = data.Temperature
|
||||
item.KeyId = data.KeyId
|
||||
|
||||
item.Type = data.Type
|
||||
var res *gorm.DB
|
||||
if data.Id > 0 {
|
||||
res = h.DB.Save(&item)
|
||||
|
||||
@@ -30,7 +30,7 @@ func NewChatModelHandler(app *core.AppServer, db *gorm.DB) *ChatModelHandler {
|
||||
func (h *ChatModelHandler) List(c *gin.Context) {
|
||||
var items []model.ChatModel
|
||||
var chatModels = make([]vo.ChatModel, 0)
|
||||
session := h.DB.Session(&gorm.Session{}).Where("enabled", true)
|
||||
session := h.DB.Session(&gorm.Session{}).Where("type", "chat").Where("enabled", true)
|
||||
t := c.Query("type")
|
||||
if t != "" {
|
||||
session = session.Where("type", t)
|
||||
|
||||
@@ -17,10 +17,11 @@ import (
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
req2 "github.com/imroc/req/v3"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
req2 "github.com/imroc/req/v3"
|
||||
)
|
||||
|
||||
type Usage struct {
|
||||
@@ -172,16 +173,22 @@ func (h *ChatHandler) sendOpenAiMessage(
|
||||
var apiRes types.BizVo
|
||||
r, err := req2.C().R().SetHeader("Body-Type", "application/json").
|
||||
SetHeader("Authorization", function.Token).
|
||||
SetBody(params).
|
||||
SetSuccessResult(&apiRes).Post(function.Action)
|
||||
SetBody(params).Post(function.Action)
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
} else if r.IsErrorState() {
|
||||
errMsg = r.Status
|
||||
} else {
|
||||
all, _ := io.ReadAll(r.Body)
|
||||
err = json.Unmarshal(all, &apiRes)
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
} else if apiRes.Code != types.Success {
|
||||
errMsg = apiRes.Message
|
||||
}
|
||||
}
|
||||
if errMsg != "" || apiRes.Code != types.Success {
|
||||
errMsg = "调用函数工具出错:" + apiRes.Message + errMsg
|
||||
|
||||
if errMsg != "" {
|
||||
errMsg = "调用函数工具出错:" + errMsg
|
||||
contents = append(contents, errMsg)
|
||||
} else {
|
||||
errMsg = utils.InterfaceToString(apiRes.Data)
|
||||
@@ -8,6 +8,7 @@ package handler
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
@@ -17,14 +18,13 @@ import (
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DallJobHandler struct {
|
||||
BaseHandler
|
||||
redis *redis.Client
|
||||
dallService *dalle.Service
|
||||
uploader *oss.UploaderManager
|
||||
userService *service.UserService
|
||||
@@ -42,49 +42,49 @@ func NewDallJobHandler(app *core.AppServer, db *gorm.DB, service *dalle.Service,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DallJobHandler) preCheck(c *gin.Context) bool {
|
||||
user, err := h.GetLoginUser(c)
|
||||
if err != nil {
|
||||
resp.NotAuth(c)
|
||||
return false
|
||||
}
|
||||
if user.Power < h.App.SysConfig.DallPower {
|
||||
resp.ERROR(c, "当前用户剩余算力不足以完成本次绘画!")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// Image 创建一个绘画任务
|
||||
func (h *DallJobHandler) Image(c *gin.Context) {
|
||||
if !h.preCheck(c) {
|
||||
return
|
||||
}
|
||||
|
||||
var data types.DallTask
|
||||
if err := c.ShouldBindJSON(&data); err != nil || data.Prompt == "" {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
var chatModel model.ChatModel
|
||||
if res := h.DB.Where("id = ?", data.ModelId).First(&chatModel); res.Error != nil {
|
||||
resp.ERROR(c, "模型不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户剩余算力
|
||||
user, err := h.GetLoginUser(c)
|
||||
if err != nil {
|
||||
resp.NotAuth(c)
|
||||
return
|
||||
}
|
||||
if user.Power < chatModel.Power {
|
||||
resp.ERROR(c, "当前用户剩余算力不足以完成本次绘画!")
|
||||
return
|
||||
}
|
||||
|
||||
idValue, _ := c.Get(types.LoginUserID)
|
||||
userId := utils.IntValue(utils.InterfaceToString(idValue), 0)
|
||||
task := types.DallTask{
|
||||
ClientId: data.ClientId,
|
||||
UserId: uint(userId),
|
||||
ModelId: chatModel.Id,
|
||||
ModelName: chatModel.Value,
|
||||
Prompt: data.Prompt,
|
||||
Quality: data.Quality,
|
||||
Size: data.Size,
|
||||
Style: data.Style,
|
||||
Power: h.App.SysConfig.DallPower,
|
||||
TranslateModelId: h.App.SysConfig.TranslateModelId,
|
||||
Power: chatModel.Power,
|
||||
}
|
||||
job := model.DallJob{
|
||||
UserId: uint(userId),
|
||||
Prompt: data.Prompt,
|
||||
Power: task.Power,
|
||||
Power: chatModel.Power,
|
||||
TaskInfo: utils.JsonEncode(task),
|
||||
}
|
||||
res := h.DB.Create(&job)
|
||||
@@ -95,6 +95,17 @@ func (h *DallJobHandler) Image(c *gin.Context) {
|
||||
|
||||
task.Id = job.Id
|
||||
h.dallService.PushTask(task)
|
||||
|
||||
// 扣减算力
|
||||
err = h.userService.DecreasePower(int(user.Id), chatModel.Power, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: chatModel.Value,
|
||||
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)),
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, "error with decrease power: "+err.Error())
|
||||
return
|
||||
}
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
|
||||
@@ -210,3 +221,25 @@ func (h *DallJobHandler) Publish(c *gin.Context) {
|
||||
|
||||
resp.SUCCESS(c)
|
||||
}
|
||||
|
||||
func (h *DallJobHandler) GetModels(c *gin.Context) {
|
||||
var models []model.ChatModel
|
||||
err := h.DB.Where("type", "img").Where("enabled", true).Find(&models).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var modelVos []vo.ChatModel
|
||||
for _, v := range models {
|
||||
var modelVo vo.ChatModel
|
||||
err := utils.CopyObject(v, &modelVo)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
modelVo.Id = v.Id
|
||||
modelVos = append(modelVos, modelVo)
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, modelVos)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/service/dalle"
|
||||
"geekai/service/oss"
|
||||
"geekai/store/model"
|
||||
@@ -32,6 +33,7 @@ type FunctionHandler struct {
|
||||
config types.ApiConfig
|
||||
uploadManager *oss.UploaderManager
|
||||
dallService *dalle.Service
|
||||
userService *service.UserService
|
||||
}
|
||||
|
||||
func NewFunctionHandler(
|
||||
@@ -39,7 +41,8 @@ func NewFunctionHandler(
|
||||
db *gorm.DB,
|
||||
config *types.AppConfig,
|
||||
manager *oss.UploaderManager,
|
||||
dallService *dalle.Service) *FunctionHandler {
|
||||
dallService *dalle.Service,
|
||||
userService *service.UserService) *FunctionHandler {
|
||||
return &FunctionHandler{
|
||||
BaseHandler: BaseHandler{
|
||||
App: server,
|
||||
@@ -48,6 +51,7 @@ func NewFunctionHandler(
|
||||
config: config.ApiConfig,
|
||||
uploadManager: manager,
|
||||
dallService: dallService,
|
||||
userService: userService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +156,12 @@ func (h *FunctionHandler) ZaoBao(c *gin.Context) {
|
||||
SetHeader("AppId", h.config.AppId).
|
||||
SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.config.Token)).
|
||||
SetSuccessResult(&res).Get(url)
|
||||
if err != nil || r.IsErrorState() {
|
||||
resp.ERROR(c, fmt.Sprintf("%v%v", err, r.Err))
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("%v", err))
|
||||
return
|
||||
}
|
||||
if r.IsErrorState() {
|
||||
resp.ERROR(c, fmt.Sprintf("%v", r.Err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -167,7 +175,7 @@ func (h *FunctionHandler) ZaoBao(c *gin.Context) {
|
||||
for _, v := range res.Data.Items {
|
||||
builder = append(builder, v.Title)
|
||||
}
|
||||
builder = append(builder, fmt.Sprintf("%s", res.Data.Title))
|
||||
builder = append(builder, res.Data.Title)
|
||||
resp.SUCCESS(c, strings.Join(builder, "\n\n"))
|
||||
}
|
||||
|
||||
@@ -199,33 +207,48 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
|
||||
|
||||
// create dall task
|
||||
prompt := utils.InterfaceToString(params["prompt"])
|
||||
job := model.DallJob{
|
||||
UserId: user.Id,
|
||||
Prompt: prompt,
|
||||
Power: h.App.SysConfig.DallPower,
|
||||
task := types.DallTask{
|
||||
UserId: user.Id,
|
||||
Prompt: prompt,
|
||||
ModelId: 0,
|
||||
ModelName: "dall-e-3",
|
||||
TranslateModelId: h.App.SysConfig.TranslateModelId,
|
||||
N: 1,
|
||||
Quality: "standard",
|
||||
Size: "1024x1024",
|
||||
Style: "vivid",
|
||||
Power: h.App.SysConfig.DallPower,
|
||||
}
|
||||
res = h.DB.Create(&job)
|
||||
|
||||
if res.Error != nil {
|
||||
resp.ERROR(c, "创建 DALL-E 绘图任务失败:"+res.Error.Error())
|
||||
job := model.DallJob{
|
||||
UserId: user.Id,
|
||||
Prompt: prompt,
|
||||
Power: h.App.SysConfig.DallPower,
|
||||
TaskInfo: utils.JsonEncode(task),
|
||||
}
|
||||
err := h.DB.Create(&job).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, "创建 DALL-E 绘图任务失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
content, err := h.dallService.Image(types.DallTask{
|
||||
Id: job.Id,
|
||||
UserId: user.Id,
|
||||
Prompt: job.Prompt,
|
||||
N: 1,
|
||||
Quality: "standard",
|
||||
Size: "1024x1024",
|
||||
Style: "vivid",
|
||||
Power: job.Power,
|
||||
}, true)
|
||||
task.Id = job.Id
|
||||
content, err := h.dallService.Image(task, true)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "任务执行失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 扣减算力
|
||||
err = h.userService.DecreasePower(int(user.Id), job.Power, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: task.ModelName,
|
||||
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(job.Prompt, 10)),
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, "扣减算力失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, content)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/service/oss"
|
||||
"geekai/service/suno"
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 提示词生成 handler
|
||||
@@ -26,8 +26,6 @@ import (
|
||||
|
||||
type PromptHandler struct {
|
||||
BaseHandler
|
||||
sunoService *suno.Service
|
||||
uploader *oss.UploaderManager
|
||||
userService *service.UserService
|
||||
}
|
||||
|
||||
@@ -56,6 +54,15 @@ func (h *PromptHandler) Lyric(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.App.SysConfig.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成歌词",
|
||||
})
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, content)
|
||||
}
|
||||
|
||||
@@ -73,7 +80,14 @@ func (h *PromptHandler) Image(c *gin.Context) {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if h.App.SysConfig.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成绘画提示词",
|
||||
})
|
||||
}
|
||||
resp.SUCCESS(c, strings.Trim(content, `"`))
|
||||
}
|
||||
|
||||
@@ -92,6 +106,15 @@ func (h *PromptHandler) Video(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.App.SysConfig.PromptPower > 0 {
|
||||
userId := h.GetLoginUserId(c)
|
||||
h.userService.DecreasePower(int(userId), h.App.SysConfig.PromptPower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: h.getPromptModel(),
|
||||
Remark: "生成视频脚本",
|
||||
})
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, strings.Trim(content, `"`))
|
||||
}
|
||||
|
||||
@@ -121,3 +144,12 @@ func (h *PromptHandler) MetaPrompt(c *gin.Context) {
|
||||
|
||||
resp.SUCCESS(c, strings.Trim(content, `"`))
|
||||
}
|
||||
|
||||
func (h *PromptHandler) getPromptModel() string {
|
||||
if h.App.SysConfig.TranslateModelId > 0 {
|
||||
var chatModel model.ChatModel
|
||||
h.DB.Where("id", h.App.SysConfig.TranslateModelId).First(&chatModel)
|
||||
return chatModel.Value
|
||||
}
|
||||
return "gpt-4o"
|
||||
}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/store/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"gorm.io/gorm"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/imroc/req/v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
@@ -23,10 +32,11 @@ import (
|
||||
|
||||
type RealtimeHandler struct {
|
||||
BaseHandler
|
||||
userService *service.UserService
|
||||
}
|
||||
|
||||
func NewRealtimeHandler(server *core.AppServer, db *gorm.DB) *RealtimeHandler {
|
||||
return &RealtimeHandler{BaseHandler{App: server, DB: db}}
|
||||
func NewRealtimeHandler(server *core.AppServer, db *gorm.DB, userService *service.UserService) *RealtimeHandler {
|
||||
return &RealtimeHandler{BaseHandler: BaseHandler{App: server, DB: db}, userService: userService}
|
||||
}
|
||||
|
||||
func (h *RealtimeHandler) Connection(c *gin.Context) {
|
||||
@@ -126,3 +136,74 @@ func sendError(ws *websocket.Conn, message string) {
|
||||
logger.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAI 实时语音对话,一次性对话
|
||||
func (h *RealtimeHandler) VoiceChat(c *gin.Context) {
|
||||
var apiKey model.ApiKey
|
||||
err := h.DB.Session(&gorm.Session{}).Where("type", "realtime").Where("enabled", true).First(&apiKey).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("error with fetch OpenAI API KEY:%v", err))
|
||||
return
|
||||
}
|
||||
|
||||
var response utils.OpenAIResponse
|
||||
client := req.C()
|
||||
if len(apiKey.ProxyURL) > 5 {
|
||||
client.SetProxyURL(apiKey.ApiURL)
|
||||
}
|
||||
apiURL := fmt.Sprintf("%s/v1/chat/completions", apiKey.ApiURL)
|
||||
logger.Infof("Sending %s request, API KEY:%s, PROXY: %s, Model: %s", apiKey.ApiURL, apiURL, apiKey.ProxyURL, "advanced-voice")
|
||||
r, err := client.R().SetHeader("Body-Type", "application/json").
|
||||
SetHeader("Authorization", "Bearer "+apiKey.Value).
|
||||
SetBody(types.ApiRequest{
|
||||
Model: "advanced-voice",
|
||||
Temperature: 0.9,
|
||||
MaxTokens: 1024,
|
||||
Stream: false,
|
||||
Messages: []interface{}{types.Message{
|
||||
Role: "user",
|
||||
Content: "实时语音通话",
|
||||
}},
|
||||
}).Post(apiURL)
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("请求 OpenAI API失败:%v", err))
|
||||
return
|
||||
}
|
||||
|
||||
if r.IsErrorState() {
|
||||
resp.ERROR(c, fmt.Sprintf("请求 OpenAI API失败:%v", r.Status))
|
||||
return
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
err = json.Unmarshal(body, &response)
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("解析API数据失败:%v, %s", err, string(body)))
|
||||
}
|
||||
|
||||
// 更新 API KEY 的最后使用时间
|
||||
h.DB.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
|
||||
|
||||
// 扣减算力
|
||||
userId := h.GetLoginUserId(c)
|
||||
err = h.userService.DecreasePower(int(userId), h.App.SysConfig.AdvanceVoicePower, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: "advanced-voice",
|
||||
Remark: "实时语音通话",
|
||||
})
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
logger.Infof("Response: %v", response.Choices[0].Message.Content)
|
||||
|
||||
// 提取链接
|
||||
re := regexp.MustCompile(`\[(.*?)\]\((.*?)\)`)
|
||||
links := re.FindAllStringSubmatch(response.Choices[0].Message.Content, -1)
|
||||
var url = ""
|
||||
if len(links) > 0 {
|
||||
url = links[0][2]
|
||||
}
|
||||
resp.SUCCESS(c, url)
|
||||
}
|
||||
|
||||
@@ -215,8 +215,8 @@ func (h *SunoHandler) Remove(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 只有失败,或者超时的任务才能删除
|
||||
if job.Progress != service.FailTaskProgress || time.Now().Before(job.CreatedAt.Add(time.Minute*10)) {
|
||||
// 只有失败或者已完成的任务可以删除
|
||||
if !(job.Progress == service.FailTaskProgress || job.Progress == 100) {
|
||||
resp.ERROR(c, "只有失败和超时(10分钟)的任务才能删除!")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func (h *UserHandler) Register(c *gin.Context) {
|
||||
if h.App.SysConfig.InvitePower > 0 {
|
||||
err := h.userService.IncreasePower(int(inviteCode.UserId), h.App.SysConfig.InvitePower, model.PowerLog{
|
||||
Type: types.PowerInvite,
|
||||
Model: "",
|
||||
Model: "Invite",
|
||||
Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d,邀请码:%s,新用户:%s", h.App.SysConfig.InvitePower, inviteCode.Code, user.Username),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -474,6 +474,7 @@ func main() {
|
||||
group.GET("imgWall", h.ImgWall)
|
||||
group.GET("remove", h.Remove)
|
||||
group.GET("publish", h.Publish)
|
||||
group.GET("models", h.GetModels)
|
||||
}),
|
||||
fx.Provide(handler.NewSunoHandler),
|
||||
fx.Invoke(func(s *core.AppServer, h *handler.SunoHandler) {
|
||||
@@ -565,6 +566,7 @@ func main() {
|
||||
fx.Provide(handler.NewRealtimeHandler),
|
||||
fx.Invoke(func(s *core.AppServer, h *handler.RealtimeHandler) {
|
||||
s.Engine.Any("/api/realtime", h.Connection)
|
||||
s.Engine.POST("/api/realtime/voice", h.VoiceChat)
|
||||
}),
|
||||
)
|
||||
// 启动应用程序
|
||||
|
||||
@@ -8,7 +8,6 @@ package dalle
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
logger2 "geekai/logger"
|
||||
@@ -17,9 +16,11 @@ import (
|
||||
"geekai/store"
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
|
||||
"github.com/imroc/req/v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -100,17 +101,18 @@ func (s *Service) Run() {
|
||||
type imgReq struct {
|
||||
Model string `json:"model"`
|
||||
Prompt string `json:"prompt"`
|
||||
N int `json:"n"`
|
||||
Size string `json:"size"`
|
||||
Quality string `json:"quality"`
|
||||
Style string `json:"style"`
|
||||
N int `json:"n,omitempty"`
|
||||
Size string `json:"size,omitempty"`
|
||||
Quality string `json:"quality,omitempty"`
|
||||
Style string `json:"style,omitempty"`
|
||||
}
|
||||
|
||||
type imgRes struct {
|
||||
Created int64 `json:"created"`
|
||||
Data []struct {
|
||||
RevisedPrompt string `json:"revised_prompt"`
|
||||
Url string `json:"url"`
|
||||
RevisedPrompt string `json:"revised_prompt,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
B64Json string `json:"b64_json,omitempty"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
@@ -135,29 +137,20 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var user model.User
|
||||
s.db.Where("id", task.UserId).First(&user)
|
||||
if user.Power < task.Power {
|
||||
return "", errors.New("insufficient of power")
|
||||
}
|
||||
|
||||
// 扣减算力
|
||||
err := s.userService.DecreasePower(int(user.Id), task.Power, model.PowerLog{
|
||||
Type: types.PowerConsume,
|
||||
Model: "dall-e-3",
|
||||
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)),
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error with decrease power: %v", err)
|
||||
}
|
||||
var chatModel model.ChatModel
|
||||
s.db.Where("id = ?", task.ModelId).First(&chatModel)
|
||||
|
||||
// get image generation API KEY
|
||||
var apiKey model.ApiKey
|
||||
err = s.db.Where("type", "dalle").
|
||||
Where("enabled", true).
|
||||
Order("last_used_at ASC").First(&apiKey).Error
|
||||
session := s.db.Where("enabled", true)
|
||||
if chatModel.KeyId > 0 {
|
||||
session = session.Where("id = ?", chatModel.KeyId)
|
||||
} else {
|
||||
session = session.Where("type = ?", "dalle")
|
||||
}
|
||||
err := session.Order("last_used_at ASC").First(&apiKey).Error
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("no available DALL-E api key: %v", err)
|
||||
return "", fmt.Errorf("no available Image Generation api key: %v", err)
|
||||
}
|
||||
|
||||
var res imgRes
|
||||
@@ -167,7 +160,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
}
|
||||
apiURL := fmt.Sprintf("%s/v1/images/generations", apiKey.ApiURL)
|
||||
reqBody := imgReq{
|
||||
Model: "dall-e-3",
|
||||
Model: chatModel.Value,
|
||||
Prompt: prompt,
|
||||
N: 1,
|
||||
Size: task.Size,
|
||||
@@ -182,20 +175,39 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
SetSuccessResult(&res).
|
||||
Post(apiURL)
|
||||
if err != nil {
|
||||
logger.Errorf("error with send request: %v", err)
|
||||
return "", fmt.Errorf("error with send request: %v", err)
|
||||
}
|
||||
|
||||
if r.IsErrorState() {
|
||||
logger.Errorf("error with send request, status: %s, %+v", r.Status, errRes.Error)
|
||||
return "", fmt.Errorf("error with send request, status: %s, %+v", r.Status, errRes.Error)
|
||||
}
|
||||
|
||||
all, _ := io.ReadAll(r.Body)
|
||||
logger.Debugf("response: %+v", string(all))
|
||||
|
||||
// update the api key last use time
|
||||
s.db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
|
||||
// update task progress
|
||||
err = s.db.Model(&model.DallJob{Id: task.Id}).UpdateColumns(map[string]interface{}{
|
||||
var imgURL string
|
||||
var data = map[string]interface{}{
|
||||
"progress": 100,
|
||||
"org_url": res.Data[0].Url,
|
||||
"prompt": prompt,
|
||||
}).Error
|
||||
}
|
||||
// 如果返回的是base64,则需要上传到oss
|
||||
if res.Data[0].B64Json != "" {
|
||||
imgURL, err = s.uploadManager.GetUploadHandler().PutBase64(res.Data[0].B64Json)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error with upload image: %v", err)
|
||||
}
|
||||
logger.Infof("upload image to oss: %s", imgURL)
|
||||
data["img_url"] = imgURL
|
||||
} else {
|
||||
imgURL = res.Data[0].Url
|
||||
}
|
||||
data["org_url"] = imgURL
|
||||
// update task progress
|
||||
err = s.db.Model(&model.DallJob{Id: task.Id}).UpdateColumns(data).Error
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("err with update database: %v", err)
|
||||
}
|
||||
@@ -252,9 +264,14 @@ func (s *Service) CheckTaskStatus() {
|
||||
// 找出失败的任务,并恢复其扣减算力
|
||||
s.db.Where("progress", service.FailTaskProgress).Where("power > ?", 0).Find(&jobs)
|
||||
for _, job := range jobs {
|
||||
err := s.userService.IncreasePower(int(job.UserId), job.Power, model.PowerLog{
|
||||
var task types.DallTask
|
||||
err := utils.JsonDecode(job.TaskInfo, &task)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
err = s.userService.IncreasePower(int(job.UserId), job.Power, model.PowerLog{
|
||||
Type: types.PowerRefund,
|
||||
Model: "dall-e-3",
|
||||
Model: task.ModelName,
|
||||
Remark: fmt.Sprintf("任务失败,退回算力。任务ID:%d,Err: %s", job.Id, job.ErrMsg),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -130,10 +130,13 @@ type LumaRespVo struct {
|
||||
Id string `json:"id"`
|
||||
Prompt string `json:"prompt"`
|
||||
State string `json:"state"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
QueueState interface{} `json:"queue_state"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Video interface{} `json:"video"`
|
||||
VideoRaw interface{} `json:"video_raw"`
|
||||
Liked interface{} `json:"liked"`
|
||||
EstimateWaitSeconds interface{} `json:"estimate_wait_seconds"`
|
||||
Thumbnail interface{} `json:"thumbnail"`
|
||||
Channel string `json:"channel,omitempty"`
|
||||
}
|
||||
|
||||
@@ -234,7 +237,7 @@ func (s *Service) DownloadFiles() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Info("download no water video success: %s", videoURL)
|
||||
logger.Infof("download no water video success: %s", videoURL)
|
||||
v.VideoURL = videoURL
|
||||
v.Progress = 100
|
||||
s.db.Updates(&v)
|
||||
@@ -275,6 +278,7 @@ func (s *Service) SyncTaskProgress() {
|
||||
"water_url": task.Video.Url,
|
||||
"raw_data": utils.JsonEncode(task),
|
||||
"prompt_ext": task.Prompt,
|
||||
"cover_url": task.Thumbnail.Url,
|
||||
}
|
||||
if task.Video.DownloadUrl != "" {
|
||||
data["video_url"] = task.Video.DownloadUrl
|
||||
@@ -315,11 +319,28 @@ type LumaTaskVo struct {
|
||||
Url string `json:"url"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Thumbnail string `json:"thumbnail"`
|
||||
DownloadUrl string `json:"download_url"`
|
||||
} `json:"video"`
|
||||
Prompt string `json:"prompt"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
EstimateWaitSeconds interface{} `json:"estimate_wait_seconds"`
|
||||
Prompt string `json:"prompt"`
|
||||
UserId string `json:"user_id"`
|
||||
BatchId string `json:"batch_id"`
|
||||
Thumbnail struct {
|
||||
Url string `json:"url"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
} `json:"thumbnail"`
|
||||
VideoRaw struct {
|
||||
Url string `json:"url"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
} `json:"video_raw"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
LastFrame struct {
|
||||
Url string `json:"url"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
} `json:"last_frame"`
|
||||
}
|
||||
|
||||
func (s *Service) QueryLumaTask(taskId string, channel string) (LumaTaskVo, error) {
|
||||
|
||||
@@ -12,4 +12,5 @@ type ChatModel struct {
|
||||
MaxContext int // 最大上下文长度
|
||||
Temperature float32 // 模型温度
|
||||
KeyId int // 绑定 API KEY ID
|
||||
Type string // 模型类型
|
||||
}
|
||||
|
||||
@@ -13,4 +13,5 @@ type ChatModel struct {
|
||||
Temperature float32 `json:"temperature"` // 模型温度
|
||||
KeyId int `json:"key_id,omitempty"`
|
||||
KeyName string `json:"key_name"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
@@ -12,11 +12,12 @@ import (
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/imroc/req/v3"
|
||||
"github.com/pkoukk/tiktoken-go"
|
||||
"gorm.io/gorm"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CalcTokens(text string, model string) (int, error) {
|
||||
@@ -33,7 +34,7 @@ func CalcTokens(text string, model string) (int, error) {
|
||||
return len(token), nil
|
||||
}
|
||||
|
||||
type apiRes struct {
|
||||
type OpenAIResponse struct {
|
||||
Model string `json:"model"`
|
||||
Choices []struct {
|
||||
Index int `json:"index"`
|
||||
@@ -70,7 +71,7 @@ func SendOpenAIMessage(db *gorm.DB, messages []interface{}, modelId int) (string
|
||||
return "", fmt.Errorf("error with fetch OpenAI API KEY:%v", err)
|
||||
}
|
||||
|
||||
var response apiRes
|
||||
var response OpenAIResponse
|
||||
client := req.C()
|
||||
if len(apiKey.ProxyURL) > 5 {
|
||||
client.SetProxyURL(apiKey.ApiURL)
|
||||
|
||||
Reference in New Issue
Block a user