Files
MonkeyCode/backend/internal/model/handler/http/v1/model.go

252 lines
6.7 KiB
Go

package v1
import (
"context"
"log/slog"
"strings"
"github.com/GoYoko/web"
modelkitDomain "github.com/chaitin/ModelKit/domain"
modelkit "github.com/chaitin/ModelKit/usecase"
"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/internal/middleware"
)
type ModelHandler struct {
usecase domain.ModelUsecase
logger *slog.Logger
}
func NewModelHandler(
w *web.Web,
usecase domain.ModelUsecase,
auth *middleware.AuthMiddleware,
active *middleware.ActiveMiddleware,
readonly *middleware.ReadOnlyMiddleware,
logger *slog.Logger,
) *ModelHandler {
m := &ModelHandler{usecase: usecase, logger: logger.With("handler", "model")}
g := w.Group("/api/v1/model")
g.Use(auth.Auth(), active.Active("admin"), readonly.Guard())
g.GET("", web.BaseHandler(m.List))
g.GET("/provider/supported", web.BindHandler(m.GetProviderModelList))
g.GET("/token-usage", web.BindHandler(m.GetTokenUsage))
g.GET("/my", web.BindHandler(m.MyModelList))
g.POST("", web.BindHandler(m.Create))
g.POST("/check", web.BindHandler(m.Check))
g.PUT("", web.BindHandler(m.Update))
g.DELETE("", web.BaseHandler(m.Delete))
return m
}
// Check 检查模型
//
// @Tags Model
// @Summary 检查模型
// @Description 检查模型
// @ID check-model
// @Accept json
// @Produce json
// @Param model body domain.CheckModelReq true "模型"
// @Success 200 {object} web.Resp{data=domain.CheckModelResp}
// @Router /api/v1/model/check [post]
func (h *ModelHandler) Check(c *web.Context, req domain.CheckModelReq) error {
modelkitRes, err := modelkit.CheckModel(c.Request().Context(), &modelkitDomain.CheckModelReq{
Provider: string(req.Provider),
Model: req.ModelName,
BaseURL: req.APIBase,
APIKey: req.APIKey,
APIHeader: req.APIHeader,
APIVersion: req.APIVersion,
Type: string(req.Type),
})
if err != nil {
return c.Success(domain.CheckModelResp{
Error: err.Error(),
})
}
if modelkitRes.Error != "" {
return c.Success(domain.CheckModelResp{
Error: modelkitRes.Error,
})
}
// 将输出转化为monkeycode格式
m := &domain.Model{
ModelType: req.Type,
Provider: req.Provider,
ModelName: req.ModelName,
APIBase: req.APIBase,
}
// end
return c.Success(domain.CheckModelResp{
Model: m,
Error: "",
})
}
// List 获取模型列表
//
// @Tags Model
// @Summary 获取模型列表
// @Description 获取模型列表
// @ID list-model
// @Accept json
// @Produce json
// @Success 200 {object} web.Resp{data=domain.AllModelResp}
// @Router /api/v1/model [get]
func (h *ModelHandler) List(c *web.Context) error {
models, err := h.usecase.List(c.Request().Context())
if err != nil {
return err
}
return c.Success(models)
}
// MyModelList 获取我的模型列表
//
// @Tags Model
// @Summary 获取我的模型列表
// @Description 获取我的模型列表
// @ID my-model-list
// @Accept json
// @Produce json
// @Param model_type query domain.MyModelListReq true "模型类型"
// @Success 200 {object} web.Resp{data=[]domain.Model}
// @Router /api/v1/model/my [get]
func (h *ModelHandler) MyModelList(c *web.Context, req domain.MyModelListReq) error {
models, err := h.usecase.MyModelList(c.Request().Context(), &req)
if err != nil {
return err
}
return c.Success(models)
}
// Create 创建模型
//
// @Tags Model
// @Summary 创建模型
// @Description 创建模型
// @ID create-model
// @Accept json
// @Produce json
// @Param model body domain.CreateModelReq true "模型"
// @Success 200 {object} web.Resp{data=domain.Model}
// @Router /api/v1/model [post]
func (h *ModelHandler) Create(c *web.Context, req domain.CreateModelReq) error {
admin := middleware.GetAdmin(c)
req.AdminID = admin.ID
req.APIBase = strings.TrimSuffix(req.APIBase, "/")
m, err := h.usecase.Create(c.Request().Context(), &req)
if err != nil {
return err
}
return c.Success(m)
}
// Update 更新模型
//
// @Tags Model
// @Summary 更新模型
// @Description 更新模型
// @ID update-model
// @Accept json
// @Produce json
// @Param model body domain.UpdateModelReq true "模型"
// @Success 200 {object} web.Resp{data=domain.Model}
// @Router /api/v1/model [put]
func (h *ModelHandler) Update(c *web.Context, req domain.UpdateModelReq) error {
m, err := h.usecase.Update(c.Request().Context(), &req)
if err != nil {
return err
}
return c.Success(m)
}
// GetTokenUsage 获取模型token使用情况
//
// @Tags Model
// @Summary 获取模型token使用情况
// @Description 获取模型token使用情况
// @ID get-token-usage
// @Accept json
// @Produce json
// @Param param query domain.GetTokenUsageReq true "模型类型"
// @Success 200 {object} web.Resp{data=domain.ModelTokenUsageResp}
// @Router /api/v1/model/token-usage [get]
func (h *ModelHandler) GetTokenUsage(c *web.Context, req domain.GetTokenUsageReq) error {
resp, err := h.usecase.GetTokenUsage(c.Request().Context(), req.ModelType)
if err != nil {
return err
}
return c.Success(resp)
}
// GetProviderModelList 获取供应商支持的模型列表
//
// @Tags Model
// @Summary 获取供应商支持的模型列表
// @Description 获取供应商支持的模型列表
// @ID get-provider-model-list
// @Accept json
// @Produce json
// @Param param query domain.GetProviderModelListReq true "模型类型"
// @Success 200 {object} web.Resp{data=domain.GetProviderModelListResp}
// @Router /api/v1/model/provider/supported [get]
func (h *ModelHandler) GetProviderModelList(c *web.Context, req domain.GetProviderModelListReq) error {
modelkitRes, err := modelkit.ModelList(c.Request().Context(), &modelkitDomain.ModelListReq{
Provider: string(req.Provider),
Type: string(req.Type),
BaseURL: req.BaseURL,
APIKey: req.APIKey,
APIHeader: req.APIHeader,
})
if err != nil {
res := &domain.GetProviderModelListResp{
Error: err.Error(),
}
return c.Success(res)
}
// 将输出转化为monkeycode格式
res := &domain.GetProviderModelListResp{
Models: make([]domain.ProviderModelListItem, len(modelkitRes.Models)),
Error: modelkitRes.Error,
}
for i, model := range modelkitRes.Models {
res.Models[i] = domain.ProviderModelListItem{
Model: model.Model,
}
}
// end
return c.Success(res)
}
// Delete 删除模型
//
// @Tags Model
// @Summary 删除模型
// @Description 删除模型
// @ID delete-model
// @Accept json
// @Produce json
// @Param id query string true "模型ID"
// @Success 200 {object} web.Resp{}
// @Router /api/v1/model [delete]
func (h *ModelHandler) Delete(c *web.Context) error {
if err := h.usecase.Delete(c.Request().Context(), c.QueryParam("id")); err != nil {
return err
}
return c.Success(nil)
}
func (h *ModelHandler) InitModel() error {
return h.usecase.InitModel(context.Background())
}