feat: model cost rank and ali tts (#5428)

* feat: model cost rank api

* fix: ali stt
This commit is contained in:
zijiren
2025-02-28 17:30:37 +08:00
committed by GitHub
parent 11ccb1d779
commit 9b6b3e40f5
4 changed files with 91 additions and 26 deletions
+25
View File
@@ -205,3 +205,28 @@ func GetGroupDashboardModels(c *gin.Context) {
}
middleware.SuccessResponse(c, newEnabledModelConfigs)
}
func GetModelCostRank(c *gin.Context) {
startTime, endTime := parseTimeRange(c)
models, err := model.GetModelCostRank("", startTime, endTime)
if err != nil {
middleware.ErrorResponse(c, http.StatusOK, err.Error())
return
}
middleware.SuccessResponse(c, models)
}
func GetGroupModelCostRank(c *gin.Context) {
group := c.Param("group")
if group == "" {
middleware.ErrorResponse(c, http.StatusOK, "group is required")
return
}
startTime, endTime := parseTimeRange(c)
models, err := model.GetModelCostRank(group, startTime, endTime)
if err != nil {
middleware.ErrorResponse(c, http.StatusOK, err.Error())
return
}
middleware.SuccessResponse(c, models)
}
+44 -14
View File
@@ -81,18 +81,16 @@ func CreateLogIndexes(db *gorm.DB) error {
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat ON logs (group_id, token_name, request_at)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat ON logs (group_id, model, request_at)",
// used by group used tokens
"CREATE INDEX IF NOT EXISTS idx_group_reqat_token ON logs (group_id, request_at, token_name)",
// used by group used models
"CREATE INDEX IF NOT EXISTS idx_group_reqat_model ON logs (group_id, request_at, model)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_token_model_reqat ON logs (group_id, token_name, model, request_at)",
// day indexes, used by dashboard
"CREATE INDEX IF NOT EXISTS idx_group_reqat_truncday ON logs (group_id, request_at, timestamp_trunc_by_day)",
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_truncday ON logs (group_id, model, request_at, timestamp_trunc_by_day)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat_truncday ON logs (group_id, token_name, request_at, timestamp_trunc_by_day)",
"CREATE INDEX IF NOT EXISTS idx_group_model_token_reqat_truncday ON logs (group_id, model, token_name, request_at, timestamp_trunc_by_day)",
// hour indexes, used by dashboard
"CREATE INDEX IF NOT EXISTS idx_group_reqat_trunchour ON logs (group_id, request_at, timestamp_trunc_by_hour)",
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_trunchour ON logs (group_id, model, request_at, timestamp_trunc_by_hour)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat_trunchour ON logs (group_id, token_name, request_at, timestamp_trunc_by_hour)",
"CREATE INDEX IF NOT EXISTS idx_group_model_token_reqat_trunchour ON logs (group_id, model, token_name, request_at, timestamp_trunc_by_hour)",
@@ -100,30 +98,28 @@ func CreateLogIndexes(db *gorm.DB) error {
} else {
indexes = []string{
// used by global search logs
"CREATE INDEX IF NOT EXISTS idx_model_reqat ON logs (model, request_at) INCLUDE (code)",
"CREATE INDEX IF NOT EXISTS idx_model_reqat ON logs (model, request_at) INCLUDE (code, used_amount, total_tokens)",
// global day indexes, used by global dashboard
"CREATE INDEX IF NOT EXISTS idx_model_reqat_truncday ON logs (model, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
// global hour indexes, used by global dashboard
"CREATE INDEX IF NOT EXISTS idx_model_reqat_trunchour ON logs (model, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat ON logs (group_id, token_name, request_at) INCLUDE (code)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat ON logs (group_id, token_name, request_at) INCLUDE (code, used_amount, total_tokens)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat ON logs (group_id, model, request_at) INCLUDE (code)",
// used by group used tokens
"CREATE INDEX IF NOT EXISTS idx_group_reqat_token ON logs (group_id, request_at, token_name)",
// used by group used models
"CREATE INDEX IF NOT EXISTS idx_group_reqat_model ON logs (group_id, request_at, model)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat ON logs (group_id, token_name, request_at) INCLUDE (code, used_amount, total_tokens)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_token_model_reqat ON logs (group_id, token_name, model, request_at) INCLUDE (code)",
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat ON logs (group_id, model, request_at) INCLUDE (code, used_amount, total_tokens)",
// used by search group logs
"CREATE INDEX IF NOT EXISTS idx_group_token_model_reqat ON logs (group_id, token_name, model, request_at) INCLUDE (code, used_amount, total_tokens)",
// day indexes, used by dashboard
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_truncday ON logs (group_id, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_reqat_truncday ON logs (group_id, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_truncday ON logs (group_id, model, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat_truncday ON logs (group_id, token_name, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_model_token_reqat_truncday ON logs (group_id, model, token_name, request_at, timestamp_trunc_by_day) INCLUDE (code, used_amount, total_tokens)",
// hour indexes, used by dashboard
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_trunchour ON logs (group_id, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_reqat_trunchour ON logs (group_id, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_model_reqat_trunchour ON logs (group_id, model, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_token_reqat_trunchour ON logs (group_id, token_name, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
"CREATE INDEX IF NOT EXISTS idx_group_model_token_reqat_trunchour ON logs (group_id, model, token_name, request_at, timestamp_trunc_by_hour) INCLUDE (code, used_amount, total_tokens)",
@@ -1238,3 +1234,37 @@ func GetGroupModelTPM(group string, model string) (int64, error) {
Scan(&tpm).Error
return tpm, err
}
type ModelCostRank struct {
Model string `json:"model"`
UsedAmount float64 `json:"used_amount"`
Total int64 `json:"total"`
}
func GetModelCostRank(group string, start, end time.Time) ([]*ModelCostRank, error) {
var ranks []*ModelCostRank
query := LogDB.Model(&Log{}).
Select("model, SUM(used_amount) as used_amount, COUNT(*) as total").
Group("model").
Order("used_amount DESC")
if group != "" {
query = query.Where("group_id = ?", group)
}
if !start.IsZero() && !end.IsZero() {
query = query.Where("request_at BETWEEN ? AND ?", start, end)
} else if !start.IsZero() {
query = query.Where("request_at >= ?", start)
} else if !end.IsZero() {
query = query.Where("request_at <= ?", end)
}
err := query.Scan(&ranks).Error
if err != nil {
return nil, err
}
return ranks, nil
}
@@ -4,12 +4,12 @@ import (
"bytes"
"io"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/gorilla/websocket"
json "github.com/json-iterator/go"
"github.com/labring/sealos/service/aiproxy/middleware"
"github.com/labring/sealos/service/aiproxy/relay/adaptor/openai"
"github.com/labring/sealos/service/aiproxy/relay/meta"
relaymodel "github.com/labring/sealos/service/aiproxy/relay/model"
@@ -46,12 +46,17 @@ type STTInput struct {
}
type STTParameters struct {
Format string `json:"format"`
SampleRate int `json:"sample_rate"`
Format string `json:"format,omitempty"`
SampleRate int `json:"sample_rate,omitempty"`
}
type STTOutput struct {
Text string `json:"text"`
STTSentence STTSentence `json:"sentence"`
}
type STTSentence struct {
Text string `json:"text"`
EndTime *int `json:"end_time"`
}
type STTUsage struct {
@@ -83,10 +88,6 @@ func ConvertSTTRequest(meta *meta.Meta, request *http.Request) (string, http.Hea
TaskGroup: "audio",
Function: "recognition",
Input: STTInput{},
Parameters: STTParameters{
Format: "mp3",
SampleRate: 16000,
},
},
}
@@ -128,14 +129,14 @@ func STTDoRequest(meta *meta.Meta, req *http.Request) (*http.Response, error) {
}
func STTDoResponse(meta *meta.Meta, c *gin.Context, _ *http.Response) (usage *relaymodel.Usage, err *relaymodel.ErrorWithStatusCode) {
log := middleware.GetLogger(c)
audioData := meta.MustGet("audio_data").([]byte)
taskID := meta.MustGet("task_id").(string)
conn := meta.MustGet("ws_conn").(*websocket.Conn)
defer conn.Close()
output := strings.Builder{}
usage = &relaymodel.Usage{}
for {
@@ -178,13 +179,16 @@ func STTDoResponse(meta *meta.Meta, c *gin.Context, _ *http.Response) (usage *re
return usage, openai.ErrorWrapperWithMessage("ali_wss_write_msg_failed", "ali_wss_write_msg_failed", http.StatusInternalServerError)
}
case "result-generated":
if msg.Payload.Output.Text != "" {
log.Info("STT result: " + msg.Payload.Output.Text)
if msg.Payload.Output.STTSentence.Text != "" {
output.WriteString(msg.Payload.Output.STTSentence.Text)
}
continue
case "task-finished":
usage.PromptTokens = msg.Payload.Usage.Characters
usage.TotalTokens = msg.Payload.Usage.Characters
c.JSON(http.StatusOK, gin.H{
"text": output.String(),
})
return usage, nil
case "task-failed":
return usage, openai.ErrorWrapperWithMessage(msg.Header.ErrorMessage, msg.Header.ErrorCode, http.StatusInternalServerError)
+6
View File
@@ -40,6 +40,12 @@ func SetAPIRouter(router *gin.Engine) {
dashboardRoute.GET("/:group/models", controller.GetGroupDashboardModels)
}
modelCostRankRoute := apiRouter.Group("/model_cost_rank")
{
modelCostRankRoute.GET("/", controller.GetModelCostRank)
modelCostRankRoute.GET("/:group", controller.GetGroupModelCostRank)
}
groupsRoute := apiRouter.Group("/groups")
{
groupsRoute.GET("/", controller.GetGroups)