Skip to content

Commit 184d6ad

Browse files
ganisbackJames
andauthored
Merge code 12 01 (#531)
* support get deploy by date range * Implement restart deploy for failure deploys * add function call field * Support ms-swift dataset tag * fix accouting export fields * support bias dataset for evalscope * support civil_comments for evalscope * support nvidia sglang and vllm for dell --------- Co-authored-by: James <[email protected]>
1 parent 6a51ba9 commit 184d6ad

28 files changed

+1788
-139
lines changed

aigateway/component/openai.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"log/slog"
8+
"strings"
89
"time"
910

1011
"github.com/google/uuid"
@@ -54,16 +55,19 @@ func (m *openaiComponentImpl) GetAvailableModels(c context.Context, userName str
5455
if err != nil {
5556
slog.Error("get deploy hardware ")
5657
}
58+
// Check if engine_args contains tool-call-parser parameter
59+
supportFunctionCall := strings.Contains(deploy.EngineArgs, "tool-call-parser")
5760
m := types.Model{
58-
Object: "model",
59-
Created: deploy.CreatedAt.Unix(),
60-
Task: string(deploy.Task),
61-
CSGHubModelID: deploy.Repository.Path,
62-
SvcName: deploy.SvcName,
63-
SvcType: deploy.Type,
64-
Hardware: hardwareInfo,
65-
RuntimeFramework: deploy.RuntimeFramework,
66-
ImageID: deploy.ImageID,
61+
Object: "model",
62+
Created: deploy.CreatedAt.Unix(),
63+
Task: string(deploy.Task),
64+
CSGHubModelID: deploy.Repository.Path,
65+
SvcName: deploy.SvcName,
66+
SvcType: deploy.Type,
67+
Hardware: hardwareInfo,
68+
RuntimeFramework: deploy.RuntimeFramework,
69+
ImageID: deploy.ImageID,
70+
SupportFunctionCall: supportFunctionCall,
6771
}
6872
modelName := ""
6973
if deploy.Repository.HFPath != "" {

aigateway/types/openai.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ type Model struct {
1616
SvcName string `json:"-"` // the internal service name in CSGHub
1717
SvcType int `json:"-"` // the internal service type like dedicated or serverless in CSGHub
1818

19-
Hardware types.HardWare `json:"-"` // the deployed hardware
20-
RuntimeFramework string `json:"-"` // the deployed framework
21-
ImageID string `json:"-"` // the deployed image
19+
Hardware types.HardWare `json:"-"` // the deployed hardware
20+
RuntimeFramework string `json:"-"` // the deployed framework
21+
ImageID string `json:"-"` // the deployed image
22+
SupportFunctionCall bool `json:"support_function_call,omitempty"` // whether the model supports function calling
2223
}
2324

2425
// ModelList represents the model list response

api/handler/cluster.go

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package handler
22

33
import (
44
"encoding/csv"
5+
"fmt"
56
"log/slog"
67
"net/http"
78
"strconv"
9+
"time"
810

911
"github.com/gin-gonic/gin"
1012
"opencsg.com/csghub-server/api/httpbase"
@@ -29,6 +31,11 @@ type ClusterHandler struct {
2931
c component.ClusterComponent
3032
}
3133

34+
const (
35+
deployTimeLayout = "2006-01-02 15:04:05"
36+
deployDateOnlyLayout = "2006-01-02"
37+
)
38+
3239
// Getclusters godoc
3340
// @Security ApiKey
3441
// @Summary Get cluster list
@@ -146,6 +153,8 @@ func (h *ClusterHandler) GetDeploys(ctx *gin.Context) {
146153
// @Produce text/csv
147154
// @Param status query string false "status" default(all) Enums(all, running, stopped, deployfailed)
148155
// @Param search query string false "search" default("")
156+
// @Param start_time query string false "filter deploys created after or at this time"
157+
// @Param end_time query string false "filter deploys created before or at this time"
149158
// @Success 200 {string} string "CSV file"
150159
// @Failure 400 {object} types.APIBadRequest "Bad request"
151160
// @Failure 500 {object} types.APIInternalServerError "Internal server error"
@@ -165,6 +174,11 @@ func (h *ClusterHandler) GetDeploysReport(ctx *gin.Context) {
165174
req.Status = []int{code.DeployFailed}
166175
}
167176
req.Query = ctx.Query("search")
177+
if err := bindDeployDateRange(ctx, &req); err != nil {
178+
slog.Error("Invalid date range for deploy report", slog.Any("error", err))
179+
httpbase.BadRequest(ctx, err.Error())
180+
return
181+
}
168182

169183
filename := "deploys_report.csv"
170184
ctx.Header("Content-Type", "text/csv; charset=utf-8")
@@ -189,7 +203,6 @@ func (h *ClusterHandler) GetDeploysReport(ctx *gin.Context) {
189203
})
190204
writer.Flush()
191205

192-
const timeLayout = "2006-01-02 15:04:05"
193206
totalProcessed := 0
194207

195208
for {
@@ -207,7 +220,7 @@ func (h *ClusterHandler) GetDeploysReport(ctx *gin.Context) {
207220
d.DeployName,
208221
d.User.Username,
209222
d.Resource,
210-
d.CreateTime.Local().Format(timeLayout),
223+
d.CreateTime.Local().Format(deployTimeLayout),
211224
d.Status,
212225
strconv.Itoa(d.TotalTimeInMin),
213226
strconv.Itoa(d.TotalFeeInCents),
@@ -246,3 +259,43 @@ func (h *ClusterHandler) Update(ctx *gin.Context) {
246259
}
247260
httpbase.OK(ctx, result)
248261
}
262+
263+
func bindDeployDateRange(ctx *gin.Context, req *types.DeployReq) error {
264+
startTime := ctx.Query("start_time")
265+
endTime := ctx.Query("end_time")
266+
if startTime == "" && endTime == "" {
267+
return nil
268+
}
269+
if startTime == "" || endTime == "" {
270+
return fmt.Errorf("start_time and end_time must be provided together")
271+
}
272+
parsedStart, err := parseDeployQueryTime(startTime, false)
273+
if err != nil {
274+
return err
275+
}
276+
parsedEnd, err := parseDeployQueryTime(endTime, true)
277+
if err != nil {
278+
return err
279+
}
280+
req.StartTime = &parsedStart
281+
req.EndTime = &parsedEnd
282+
return nil
283+
}
284+
285+
func parseDeployQueryTime(value string, isEnd bool) (time.Time, error) {
286+
layouts := []string{deployTimeLayout, deployDateOnlyLayout}
287+
for _, layout := range layouts {
288+
parsed, err := time.ParseInLocation(layout, value, time.UTC)
289+
if err != nil {
290+
continue
291+
}
292+
if layout == deployDateOnlyLayout {
293+
if isEnd {
294+
parsed = parsed.Add(24*time.Hour - time.Nanosecond)
295+
}
296+
return parsed, nil
297+
}
298+
return parsed, nil
299+
}
300+
return time.Time{}, fmt.Errorf("invalid datetime format, use '%s' or '%s'", deployTimeLayout, deployDateOnlyLayout)
301+
}

api/handler/cluster_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"net/http"
66
"testing"
7+
"time"
78

89
"github.com/gin-gonic/gin"
910
"github.com/stretchr/testify/mock"
@@ -98,12 +99,25 @@ func Test_GetDeploysReport(t *testing.T) {
9899
},
99100
}
100101

102+
start := "2024-01-01 00:00:00"
103+
end := "2024-01-31"
104+
expectedStart, err := time.ParseInLocation(time.DateTime, start, time.UTC)
105+
require.NoError(t, err)
106+
endDate, err := time.ParseInLocation("2006-01-02", end, time.UTC)
107+
require.NoError(t, err)
108+
expectedEnd := endDate.Add(24*time.Hour - time.Nanosecond)
101109
tester.mocks.clusterComponent.EXPECT().
102110
GetDeploys(context.Background(), mock.Anything).
111+
Run(func(_ context.Context, req types.DeployReq) {
112+
require.NotNil(t, req.StartTime)
113+
require.True(t, req.StartTime.Equal(expectedStart))
114+
require.NotNil(t, req.EndTime)
115+
require.True(t, req.EndTime.Equal(expectedEnd))
116+
}).
103117
Once().
104118
Return(rows, len(rows), nil)
105119

106-
tester.Execute()
120+
tester.WithQuery("start_time", start).WithQuery("end_time", end).Execute()
107121

108122
// assert response headers and body
109123
resp := tester.Response()
@@ -117,3 +131,21 @@ func Test_GetDeploysReport(t *testing.T) {
117131
require.Contains(t, body, "alice")
118132
require.Contains(t, body, "bob")
119133
}
134+
135+
func Test_GetDeploysReport_InvalidDateRange(t *testing.T) {
136+
tester := newClusterTester(t).withHandlerFunc(func(clusterHandler *ClusterHandler) gin.HandlerFunc {
137+
return clusterHandler.GetDeploysReport
138+
})
139+
140+
tester.WithQuery("start_time", "2024-01-01").Execute()
141+
tester.ResponseEqSimple(t, http.StatusBadRequest, httpbase.R{Msg: "start_time and end_time must be provided together"})
142+
}
143+
144+
func Test_GetDeploysReport_InvalidFormat(t *testing.T) {
145+
tester := newClusterTester(t).withHandlerFunc(func(clusterHandler *ClusterHandler) gin.HandlerFunc {
146+
return clusterHandler.GetDeploysReport
147+
})
148+
149+
tester.WithQuery("start_time", "invalid").WithQuery("end_time", "2024-01-01").Execute()
150+
tester.ResponseEqSimple(t, http.StatusBadRequest, httpbase.R{Msg: "invalid datetime format, use '2006-01-02 15:04:05' or '2006-01-02'"})
151+
}

builder/store/database/deploy_task.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,14 @@ func (s *deployTaskStoreImpl) ListDeployByType(ctx context.Context, req types.De
400400
query = query.Where("deploy_name LIKE ? OR \"user\".\"username\" LIKE ? OR cluster_id LIKE ?", "%"+req.Query+"%", "%"+req.Query+"%", "%"+req.Query+"%")
401401
}
402402

403-
query = query.Order("created_at DESC").Limit(req.PageSize).Offset((req.Page - 1) * req.PageSize)
403+
if req.StartTime != nil {
404+
query = query.Where("deploy.created_at >= ?", req.StartTime)
405+
}
406+
if req.EndTime != nil {
407+
query = query.Where("deploy.created_at <= ?", req.EndTime)
408+
}
409+
410+
query = query.Order("deploy.created_at DESC").Limit(req.PageSize).Offset((req.Page - 1) * req.PageSize)
404411
_, err := query.Exec(ctx, &result)
405412
if err != nil {
406413
err = errorx.HandleDBError(err, nil)

builder/store/database/deploy_task_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package database_test
33
import (
44
"context"
55
"testing"
6+
"time"
67

78
"github.com/stretchr/testify/require"
89
"opencsg.com/csghub-server/builder/deploy/common"
@@ -567,6 +568,19 @@ func TestDeployTaskStore_ListDeployBytype(t *testing.T) {
567568
require.Nil(t, err)
568569
}
569570

571+
now := time.Now().UTC().Truncate(time.Second)
572+
older := now.Add(-72 * time.Hour)
573+
middle := now.Add(-12 * time.Hour)
574+
latest := now.Add(-1 * time.Hour)
575+
_, err := db.BunDB.ExecContext(ctx, "UPDATE deploys SET created_at = ?, updated_at = ? WHERE deploy_name = ?", older, older, "running1")
576+
require.NoError(t, err)
577+
_, err = db.BunDB.ExecContext(ctx, "UPDATE deploys SET created_at = ?, updated_at = ? WHERE deploy_name = ?", older.Add(24*time.Hour), older.Add(24*time.Hour), "stopped1")
578+
require.NoError(t, err)
579+
_, err = db.BunDB.ExecContext(ctx, "UPDATE deploys SET created_at = ?, updated_at = ? WHERE deploy_name = ?", middle, middle, "running2")
580+
require.NoError(t, err)
581+
_, err = db.BunDB.ExecContext(ctx, "UPDATE deploys SET created_at = ?, updated_at = ? WHERE deploy_name = ?", latest, latest, "deploy1")
582+
require.NoError(t, err)
583+
570584
// Only test running ones
571585
var req types.DeployReq
572586
req.Page = 1
@@ -578,6 +592,25 @@ func TestDeployTaskStore_ListDeployBytype(t *testing.T) {
578592
result, _, err = store.ListDeployByType(ctx, req)
579593
require.Nil(t, err)
580594
require.Equal(t, 2, len(result))
595+
596+
startWindow := now.Add(-24 * time.Hour)
597+
req.StartTime = &startWindow
598+
endDate, err := time.ParseInLocation("2006-01-02", now.Format("2006-01-02"), time.UTC)
599+
require.NoError(t, err)
600+
endWindow := endDate.Add(24*time.Hour - time.Nanosecond)
601+
req.EndTime = &endWindow
602+
result, _, err = store.ListDeployByType(ctx, req)
603+
require.Nil(t, err)
604+
require.Equal(t, 1, len(result))
605+
require.Equal(t, "running2", result[0].DeployName)
606+
607+
startWindow = now.Add(-5 * time.Hour)
608+
req.StartTime = &startWindow
609+
endWindow = now
610+
req.EndTime = &endWindow
611+
result, _, err = store.ListDeployByType(ctx, req)
612+
require.Nil(t, err)
613+
require.Equal(t, 0, len(result))
581614
}
582615
func TestDeployTaskStore_DeleteDeployByID(t *testing.T) {
583616
db := tests.InitTestDB()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SET statement_timeout = 0;
2+
3+
--bun:split
4+
5+
-- Rollback SQL statements for MS-SWIFT dataset tags
6+
DELETE FROM tag_rules WHERE runtime_framework = 'ms-swift' AND repo_type = 'dataset' AND category = 'task' AND source = 'ms';

0 commit comments

Comments
 (0)