Sfoglia il codice sorgente

fix: when get chart query is not full unix index, doesnot provide max rpm (#212)

* fix: when get chart query is not full unix index, doesnot provide max rpm

* fix: ci lint
zijiren 7 mesi fa
parent
commit
f742b214d8
6 ha cambiato i file con 272 aggiunte e 46 eliminazioni
  1. 4 4
      core/controller/dashboard.go
  2. 79 7
      core/docs/docs.go
  3. 79 7
      core/docs/swagger.json
  4. 55 5
      core/docs/swagger.yaml
  5. 19 11
      core/model/log.go
  6. 36 12
      core/model/summary.go

+ 4 - 4
core/controller/dashboard.go

@@ -283,17 +283,15 @@ func GetGroupDashboardModels(c *gin.Context) {
 //	@Tags			dashboard
 //	@Produce		json
 //	@Security		ApiKeyAuth
-//	@Param			group			query		string	false	"Group or *"
 //	@Param			channel			query		int		false	"Channel ID"
 //	@Param			start_timestamp	query		int64	false	"Start timestamp"
 //	@Param			end_timestamp	query		int64	false	"End timestamp"
 //	@Success		200				{object}	middleware.APIResponse{data=[]model.CostRank}
 //	@Router			/api/model_cost_rank/ [get]
 func GetModelCostRank(c *gin.Context) {
-	group := c.Query("group")
 	channelID, _ := strconv.Atoi(c.Query("channel"))
 	startTime, endTime := parseTimeRange(c)
-	models, err := model.GetModelCostRank(group, channelID, startTime, endTime)
+	models, err := model.GetModelCostRank("*", "", channelID, startTime, endTime)
 	if err != nil {
 		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
 		return
@@ -309,6 +307,7 @@ func GetModelCostRank(c *gin.Context) {
 //	@Produce		json
 //	@Security		ApiKeyAuth
 //	@Param			group			path		string	true	"Group"
+//	@Param			token_name		query		string	false	"Token name"
 //	@Param			start_timestamp	query		int64	false	"Start timestamp"
 //	@Param			end_timestamp	query		int64	false	"End timestamp"
 //	@Success		200				{object}	middleware.APIResponse{data=[]model.CostRank}
@@ -319,8 +318,9 @@ func GetGroupModelCostRank(c *gin.Context) {
 		middleware.ErrorResponse(c, http.StatusBadRequest, "invalid group parameter")
 		return
 	}
+	tokenName := c.Query("token_name")
 	startTime, endTime := parseTimeRange(c)
-	models, err := model.GetModelCostRank(group, 0, startTime, endTime)
+	models, err := model.GetModelCostRank(group, tokenName, 0, startTime, endTime)
 	if err != nil {
 		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
 		return

+ 79 - 7
core/docs/docs.go

@@ -4405,12 +4405,6 @@ const docTemplate = `{
                 ],
                 "summary": "Get model cost ranking data",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Channel ID",
@@ -4478,6 +4472,12 @@ const docTemplate = `{
                         "in": "path",
                         "required": true
                     },
+                    {
+                        "type": "string",
+                        "description": "Token name",
+                        "name": "token_name",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "description": "Start timestamp",
@@ -7790,9 +7790,51 @@ const docTemplate = `{
         }
     },
     "definitions": {
+        "adaptor.ConfigTemplate": {
+            "type": "object",
+            "properties": {
+                "description": {
+                    "type": "string"
+                },
+                "example": {},
+                "name": {
+                    "type": "string"
+                },
+                "required": {
+                    "type": "boolean"
+                },
+                "type": {
+                    "$ref": "#/definitions/adaptor.ConfigType"
+                }
+            }
+        },
+        "adaptor.ConfigTemplates": {
+            "type": "object",
+            "additionalProperties": {
+                "$ref": "#/definitions/adaptor.ConfigTemplate"
+            }
+        },
+        "adaptor.ConfigType": {
+            "type": "string",
+            "enum": [
+                "string",
+                "number",
+                "bool",
+                "object"
+            ],
+            "x-enum-varnames": [
+                "ConfigTypeString",
+                "ConfigTypeNumber",
+                "ConfigTypeBool",
+                "ConfigTypeObject"
+            ]
+        },
         "adaptors.AdaptorMeta": {
             "type": "object",
             "properties": {
+                "configTemplates": {
+                    "$ref": "#/definitions/adaptor.ConfigTemplates"
+                },
                 "defaultBaseUrl": {
                     "type": "string"
                 },
@@ -7910,6 +7952,9 @@ const docTemplate = `{
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -7925,6 +7970,9 @@ const docTemplate = `{
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },
@@ -8228,6 +8276,9 @@ const docTemplate = `{
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -8243,6 +8294,9 @@ const docTemplate = `{
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },
@@ -8606,6 +8660,12 @@ const docTemplate = `{
         "model.ChannelConfig": {
             "type": "object",
             "properties": {
+                "spec": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                },
                 "split_think": {
                     "type": "boolean"
                 }
@@ -8873,6 +8933,12 @@ const docTemplate = `{
                 "max_tps": {
                     "type": "integer"
                 },
+                "models": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                },
                 "output_tokens": {
                     "type": "integer"
                 },
@@ -9512,7 +9578,7 @@ const docTemplate = `{
                 },
                 "schema": {
                     "type": "object",
-                    "additionalProperties": true
+                    "additionalProperties": {}
                 },
                 "strict": {
                     "type": "boolean"
@@ -9716,6 +9782,9 @@ const docTemplate = `{
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -9731,6 +9800,9 @@ const docTemplate = `{
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },

+ 79 - 7
core/docs/swagger.json

@@ -4396,12 +4396,6 @@
                 ],
                 "summary": "Get model cost ranking data",
                 "parameters": [
-                    {
-                        "type": "string",
-                        "description": "Group or *",
-                        "name": "group",
-                        "in": "query"
-                    },
                     {
                         "type": "integer",
                         "description": "Channel ID",
@@ -4469,6 +4463,12 @@
                         "in": "path",
                         "required": true
                     },
+                    {
+                        "type": "string",
+                        "description": "Token name",
+                        "name": "token_name",
+                        "in": "query"
+                    },
                     {
                         "type": "integer",
                         "description": "Start timestamp",
@@ -7781,9 +7781,51 @@
         }
     },
     "definitions": {
+        "adaptor.ConfigTemplate": {
+            "type": "object",
+            "properties": {
+                "description": {
+                    "type": "string"
+                },
+                "example": {},
+                "name": {
+                    "type": "string"
+                },
+                "required": {
+                    "type": "boolean"
+                },
+                "type": {
+                    "$ref": "#/definitions/adaptor.ConfigType"
+                }
+            }
+        },
+        "adaptor.ConfigTemplates": {
+            "type": "object",
+            "additionalProperties": {
+                "$ref": "#/definitions/adaptor.ConfigTemplate"
+            }
+        },
+        "adaptor.ConfigType": {
+            "type": "string",
+            "enum": [
+                "string",
+                "number",
+                "bool",
+                "object"
+            ],
+            "x-enum-varnames": [
+                "ConfigTypeString",
+                "ConfigTypeNumber",
+                "ConfigTypeBool",
+                "ConfigTypeObject"
+            ]
+        },
         "adaptors.AdaptorMeta": {
             "type": "object",
             "properties": {
+                "configTemplates": {
+                    "$ref": "#/definitions/adaptor.ConfigTemplates"
+                },
                 "defaultBaseUrl": {
                     "type": "string"
                 },
@@ -7901,6 +7943,9 @@
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -7916,6 +7961,9 @@
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },
@@ -8219,6 +8267,9 @@
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -8234,6 +8285,9 @@
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },
@@ -8597,6 +8651,12 @@
         "model.ChannelConfig": {
             "type": "object",
             "properties": {
+                "spec": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                },
                 "split_think": {
                     "type": "boolean"
                 }
@@ -8864,6 +8924,12 @@
                 "max_tps": {
                     "type": "integer"
                 },
+                "models": {
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                },
                 "output_tokens": {
                     "type": "integer"
                 },
@@ -9503,7 +9569,7 @@
                 },
                 "schema": {
                     "type": "object",
-                    "additionalProperties": true
+                    "additionalProperties": {}
                 },
                 "strict": {
                     "type": "boolean"
@@ -9707,6 +9773,9 @@
                         }
                     }
                 },
+                "max_error_rate": {
+                    "type": "number"
+                },
                 "model": {
                     "type": "string"
                 },
@@ -9722,6 +9791,9 @@
                 "rpm": {
                     "type": "integer"
                 },
+                "timeout": {
+                    "type": "integer"
+                },
                 "tpm": {
                     "type": "integer"
                 },

+ 55 - 5
core/docs/swagger.yaml

@@ -1,6 +1,36 @@
 definitions:
+  adaptor.ConfigTemplate:
+    properties:
+      description:
+        type: string
+      example: {}
+      name:
+        type: string
+      required:
+        type: boolean
+      type:
+        $ref: '#/definitions/adaptor.ConfigType'
+    type: object
+  adaptor.ConfigTemplates:
+    additionalProperties:
+      $ref: '#/definitions/adaptor.ConfigTemplate'
+    type: object
+  adaptor.ConfigType:
+    enum:
+    - string
+    - number
+    - bool
+    - object
+    type: string
+    x-enum-varnames:
+    - ConfigTypeString
+    - ConfigTypeNumber
+    - ConfigTypeBool
+    - ConfigTypeObject
   adaptors.AdaptorMeta:
     properties:
+      configTemplates:
+        $ref: '#/definitions/adaptor.ConfigTemplates'
       defaultBaseUrl:
         type: string
       fetures:
@@ -79,6 +109,8 @@ definitions:
           type: object
         description: map[size]map[quality]price_per_image
         type: object
+      max_error_rate:
+        type: number
       model:
         type: string
       owner:
@@ -89,6 +121,8 @@ definitions:
         type: integer
       rpm:
         type: integer
+      timeout:
+        type: integer
       tpm:
         type: integer
       type:
@@ -288,6 +322,8 @@ definitions:
           type: object
         description: map[size]map[quality]price_per_image
         type: object
+      max_error_rate:
+        type: number
       model:
         type: string
       owner:
@@ -298,6 +334,8 @@ definitions:
         type: integer
       rpm:
         type: integer
+      timeout:
+        type: integer
       tpm:
         type: integer
       type:
@@ -542,6 +580,10 @@ definitions:
     type: object
   model.ChannelConfig:
     properties:
+      spec:
+        items:
+          type: integer
+        type: array
       split_think:
         type: boolean
     type: object
@@ -741,6 +783,10 @@ definitions:
         type: integer
       max_tps:
         type: integer
+      models:
+        items:
+          type: string
+        type: array
       output_tokens:
         type: integer
       rpm:
@@ -1172,7 +1218,7 @@ definitions:
       name:
         type: string
       schema:
-        additionalProperties: true
+        additionalProperties: {}
         type: object
       strict:
         type: boolean
@@ -1308,6 +1354,8 @@ definitions:
           type: object
         description: map[size]map[quality]price_per_image
         type: object
+      max_error_rate:
+        type: number
       model:
         type: string
       owner:
@@ -1318,6 +1366,8 @@ definitions:
         type: integer
       rpm:
         type: integer
+      timeout:
+        type: integer
       tpm:
         type: integer
       type:
@@ -4377,10 +4427,6 @@ paths:
     get:
       description: Returns ranking data for models based on cost
       parameters:
-      - description: Group or *
-        in: query
-        name: group
-        type: string
       - description: Channel ID
         in: query
         name: channel
@@ -4421,6 +4467,10 @@ paths:
         name: group
         required: true
         type: string
+      - description: Token name
+        in: query
+        name: token_name
+        type: string
       - description: Start timestamp
         in: query
         name: start_timestamp

+ 19 - 11
core/model/log.go

@@ -1140,10 +1140,10 @@ type ChartData struct {
 	ExceptionCount      int64   `json:"exception_count"`
 	WebSearchCount      int64   `json:"web_search_count,omitempty"`
 
-	MaxRPM int64 `json:"max_rpm"`
-	MaxTPM int64 `json:"max_tpm"`
-	MaxRPS int64 `json:"max_rps"`
-	MaxTPS int64 `json:"max_tps"`
+	MaxRPM int64 `json:"max_rpm,omitempty"`
+	MaxTPM int64 `json:"max_tpm,omitempty"`
+	MaxRPS int64 `json:"max_rps,omitempty"`
+	MaxTPS int64 `json:"max_tps,omitempty"`
 }
 
 type DashboardResponse struct {
@@ -1154,10 +1154,10 @@ type DashboardResponse struct {
 	RPM int64 `json:"rpm"`
 	TPM int64 `json:"tpm"`
 
-	MaxRPM int64 `json:"max_rpm"`
-	MaxTPM int64 `json:"max_tpm"`
-	MaxRPS int64 `json:"max_rps"`
-	MaxTPS int64 `json:"max_tps"`
+	MaxRPM int64 `json:"max_rpm,omitempty"`
+	MaxTPM int64 `json:"max_tpm,omitempty"`
+	MaxRPS int64 `json:"max_rps,omitempty"`
+	MaxTPS int64 `json:"max_tps,omitempty"`
 
 	UsedAmount          float64 `json:"used_amount"`
 	InputTokens         int64   `json:"input_tokens,omitempty"`
@@ -1167,12 +1167,12 @@ type DashboardResponse struct {
 	CacheCreationTokens int64   `json:"cache_creation_tokens,omitempty"`
 	WebSearchCount      int64   `json:"web_search_count,omitempty"`
 
-	Channels []int `json:"channels,omitempty"`
+	Channels []int    `json:"channels,omitempty"`
+	Models   []string `json:"models,omitempty"`
 }
 
 type GroupDashboardResponse struct {
 	DashboardResponse
-	Models     []string `json:"models"`
 	TokenNames []string `json:"token_names"`
 }
 
@@ -1337,6 +1337,7 @@ func GetDashboardData(
 	var (
 		chartData []*ChartData
 		channels  []int
+		models    []string
 	)
 
 	g := new(errgroup.Group)
@@ -1353,12 +1354,19 @@ func GetDashboardData(
 		return err
 	})
 
+	g.Go(func() error {
+		var err error
+		models, err = GetUsedModels("*", "", start, end)
+		return err
+	})
+
 	if err := g.Wait(); err != nil {
 		return nil, err
 	}
 
 	dashboardResponse := sumDashboardResponse(chartData)
 	dashboardResponse.Channels = channels
+	dashboardResponse.Models = models
 
 	return &dashboardResponse, nil
 }
@@ -1412,10 +1420,10 @@ func GetGroupDashboardData(
 	}
 
 	dashboardResponse := sumDashboardResponse(chartData)
+	dashboardResponse.Models = models
 
 	return &GroupDashboardResponse{
 		DashboardResponse: dashboardResponse,
-		Models:            models,
 		TokenNames:        tokenNames,
 	}, nil
 }

+ 36 - 12
core/model/summary.go

@@ -28,11 +28,11 @@ type SummaryData struct {
 	RequestCount   int64   `json:"request_count"`
 	UsedAmount     float64 `json:"used_amount"`
 	ExceptionCount int64   `json:"exception_count"`
-	MaxRPM         int64   `json:"max_rpm"`
-	MaxRPS         int64   `json:"max_rps"`
-	MaxTPM         int64   `json:"max_tpm"`
-	MaxTPS         int64   `json:"max_tps"`
-	Usage          Usage   `gorm:"embedded"        json:"usage,omitempty"`
+	MaxRPM         int64   `json:"max_rpm,omitempty"`
+	MaxRPS         int64   `json:"max_rps,omitempty"`
+	MaxTPM         int64   `json:"max_tpm,omitempty"`
+	MaxTPS         int64   `json:"max_tps,omitempty"`
+	Usage          Usage   `gorm:"embedded"          json:"usage,omitempty"`
 }
 
 func (d *SummaryData) buildUpdateData(tableName string) map[string]any {
@@ -210,8 +210,22 @@ func getChartData(
 		query = query.Where("hour_timestamp <= ?", end.Unix())
 	}
 
+	// Only include max metrics when we have specific channel and model
+	selectFields := "hour_timestamp as timestamp, sum(request_count) as request_count, sum(used_amount) as used_amount, " +
+		"sum(exception_count) as exception_count, sum(input_tokens) as input_tokens, sum(output_tokens) as output_tokens, " +
+		"sum(cached_tokens) as cached_tokens, sum(cache_creation_tokens) as cache_creation_tokens, " +
+		"sum(total_tokens) as total_tokens, sum(web_search_count) as web_search_count"
+
+	// Only include max metrics when querying for a specific channel and model
+	if (channelID != 0 && modelName != "") || (group != "*" && tokenName != "" && modelName != "") {
+		selectFields += ", max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tpm, max(max_tps) as max_tps"
+	} else {
+		// Set max metrics to 0 when not querying for specific channel and model
+		selectFields += ", 0 as max_rpm, 0 as max_rps, 0 as max_tpm, 0 as max_tps"
+	}
+
 	query = query.
-		Select("hour_timestamp as timestamp, sum(request_count) as request_count, sum(used_amount) as used_amount, sum(exception_count) as exception_count, sum(input_tokens) as input_tokens, sum(output_tokens) as output_tokens, sum(cached_tokens) as cached_tokens, sum(cache_creation_tokens) as cache_creation_tokens, sum(total_tokens) as total_tokens, sum(web_search_count) as web_search_count, max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tpm, max(max_tps) as max_tps").
+		Select(selectFields).
 		Group("timestamp").
 		Order("timestamp ASC")
 
@@ -312,13 +326,13 @@ type CostRank struct {
 	RequestCount        int64   `json:"request_count"`
 	WebSearchCount      int64   `json:"web_search_count"`
 
-	MaxRPM int64 `json:"max_rpm"`
-	MaxRPS int64 `json:"max_rps"`
-	MaxTPM int64 `json:"max_tpm"`
-	MaxTPS int64 `json:"max_tps"`
+	MaxRPM int64 `json:"max_rpm,omitempty"`
+	MaxRPS int64 `json:"max_rps,omitempty"`
+	MaxTPM int64 `json:"max_tpm,omitempty"`
+	MaxTPS int64 `json:"max_tps,omitempty"`
 }
 
-func GetModelCostRank(group string, channelID int, start, end time.Time) ([]*CostRank, error) {
+func GetModelCostRank(group string, tokenName string, channelID int, start, end time.Time) ([]*CostRank, error) {
 	var ranks []*CostRank
 
 	var query *gorm.DB
@@ -330,6 +344,9 @@ func GetModelCostRank(group string, channelID int, start, end time.Time) ([]*Cos
 	} else {
 		query = LogDB.Model(&GroupSummary{}).
 			Where("group_id = ?", group)
+		if tokenName != "" {
+			query = query.Where("token_name = ?", tokenName)
+		}
 	}
 
 	switch {
@@ -341,8 +358,15 @@ func GetModelCostRank(group string, channelID int, start, end time.Time) ([]*Cos
 		query = query.Where("hour_timestamp <= ?", end.Unix())
 	}
 
+	selectFields := "model, SUM(used_amount) as used_amount, SUM(request_count) as request_count, SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens, SUM(cached_tokens) as cached_tokens, SUM(cache_creation_tokens) as cache_creation_tokens, SUM(total_tokens) as total_tokens"
+	if (channelID != 0) || (group != "*" && tokenName != "") {
+		selectFields += ", max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tps, max(max_tps) as max_tps"
+	} else {
+		selectFields += ", 0 as max_rpm, 0 as max_rps, 0 as max_tpm, 0 as max_tps"
+	}
+
 	query = query.
-		Select("model, SUM(used_amount) as used_amount, SUM(request_count) as request_count, SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens, SUM(cached_tokens) as cached_tokens, SUM(cache_creation_tokens) as cache_creation_tokens, SUM(total_tokens) as total_tokens, max(max_rpm) as max_rpm, max(max_rps) as max_rps, max(max_tpm) as max_tps, max(max_tps) as max_tps").
+		Select(selectFields).
 		Group("model")
 
 	err := query.Scan(&ranks).Error