Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/common/consume/consume.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,15 @@ func checkNeedRecordConsume(code int, meta *meta.Meta) bool {
mode.VideosDelete,
mode.GeminiFiles,
mode.GeminiVideoOperations,
mode.AliVideoTasks,
mode.DoubaoVideoTasks,
mode.ResponsesGet,
mode.ResponsesDelete,
mode.ResponsesCancel,
mode.ResponsesInputItems:
return code != http.StatusOK
case mode.DoubaoVideoTasksDelete:
return code != http.StatusOK && code != http.StatusNoContent
default:
return true
}
Expand Down
14 changes: 14 additions & 0 deletions core/common/consume/consume_record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ import (

func TestNeedRecordConsumeSkipsSuccessfulStoredVideoReads(t *testing.T) {
tests := []mode.Mode{
mode.VideoGenerationsGetJobs,
mode.VideoGenerationsContent,
mode.VideosGet,
mode.VideosContent,
mode.VideosDelete,
mode.GeminiFiles,
mode.GeminiVideoOperations,
mode.AliVideoTasks,
mode.DoubaoVideoTasks,
mode.DoubaoVideoTasksDelete,
}

for _, relayMode := range tests {
Expand All @@ -37,6 +42,15 @@ func TestNeedRecordConsumeSkipsSuccessfulStoredVideoReads(t *testing.T) {
}
}

func TestNeedRecordConsumeSkipsSuccessfulDoubaoNativeDeleteNoContent(t *testing.T) {
if consume.NeedRecordConsumeForTest(
http.StatusNoContent,
&meta.Meta{Mode: mode.DoubaoVideoTasksDelete},
) {
t.Fatal("expected successful doubao native delete 204 request not to record consume")
}
}

func TestNeedRecordConsumeRecordsVideoCreateAndRemix(t *testing.T) {
tests := []mode.Mode{
mode.Videos,
Expand Down
12 changes: 12 additions & 0 deletions core/controller/log_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ func buildLogExportHeader(includeChannel, includeRetryAt bool) []string {
"native_resolution",
"quality",
"service_tier",
"input_video",
"output_audio",
"ttfb_milliseconds",
"retry_times",
"input_tokens",
Expand Down Expand Up @@ -537,6 +539,8 @@ func buildLogExportRow(
sanitizeCSVCell(logItem.UsageContext.NativeResolution),
sanitizeCSVCell(logItem.UsageContext.Quality),
sanitizeCSVCell(logItem.UsageContext.ServiceTier),
formatOptionalBool(logItem.UsageContext.InputVideo),
formatOptionalBool(logItem.UsageContext.OutputAudio),
strconv.FormatInt(int64(logItem.TTFBMilliseconds), 10),
strconv.FormatInt(int64(logItem.RetryTimes), 10),
strconv.FormatInt(int64(logItem.Usage.InputTokens), 10),
Expand Down Expand Up @@ -570,6 +574,14 @@ func buildLogExportRow(
)
}

func formatOptionalBool(value *bool) string {
if value == nil {
return ""
}

return strconv.FormatBool(*value)
}

func formatTimeForExport(t time.Time, location *time.Location) string {
if t.IsZero() {
return ""
Expand Down
10 changes: 10 additions & 0 deletions core/controller/log_export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ func TestBuildLogExportCSVIncludesFullUsageContext(t *testing.T) {
NativeResolution: "1080p",
Quality: "high",
ServiceTier: "priority",
InputVideo: new(true),
OutputAudio: new(false),
},
},
}, time.UTC, false, false)
Expand All @@ -209,6 +211,14 @@ func TestBuildLogExportCSVIncludesFullUsageContext(t *testing.T) {
if values["service_tier"] != "priority" {
t.Fatalf("expected service_tier to be exported, got %q", values["service_tier"])
}

if values["input_video"] != "true" {
t.Fatalf("expected input_video to be exported, got %q", values["input_video"])
}

if values["output_audio"] != "false" {
t.Fatalf("expected output_audio to be exported, got %q", values["output_audio"])
}
}

func TestSanitizeFilename(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions core/controller/relay-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ func relayController(m mode.Mode) RelayController {
c.ValidateRequest = controller.ValidateGeminiVideoRequest
c.GetRequestPrice = controller.GetGeminiVideoRequestPrice
c.GetRequestUsage = controller.GetGeminiVideoRequestUsage
case mode.AliVideo:
c.ValidateRequest = controller.ValidateAliVideoRequest
c.GetRequestPrice = controller.GetAliVideoRequestPrice
c.GetRequestUsage = controller.GetAliVideoRequestUsage
case mode.DoubaoVideo:
c.ValidateRequest = controller.ValidateDoubaoVideoRequest
c.GetRequestPrice = controller.GetDoubaoVideoRequestPrice
c.GetRequestUsage = controller.GetDoubaoVideoRequestUsage
case mode.Responses:
c.GetRequestUsage = controller.GetResponsesRequestUsage
}
Expand Down
10 changes: 10 additions & 0 deletions core/controller/relay-controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@ func TestRelayControllerVideoModesValidateRequests(t *testing.T) {
mode: mode.GeminiVideo,
want: relaycontroller.ValidateGeminiVideoRequest,
},
{
name: "ali native video",
mode: mode.AliVideo,
want: relaycontroller.ValidateAliVideoRequest,
},
{
name: "doubao native video",
mode: mode.DoubaoVideo,
want: relaycontroller.ValidateDoubaoVideoRequest,
},
}

for _, tt := range tests {
Expand Down
9 changes: 9 additions & 0 deletions core/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15006,8 +15006,17 @@ const docTemplate = `{
"resolution": {
"type": "string"
},
"native_resolution": {
"type": "string"
},
"service_tier": {
"type": "string"
},
"input_video": {
"type": "boolean"
},
"output_audio": {
"type": "boolean"
}
}
},
Expand Down
11 changes: 10 additions & 1 deletion core/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -14997,8 +14997,17 @@
"resolution": {
"type": "string"
},
"native_resolution": {
"type": "string"
},
"service_tier": {
"type": "string"
},
"input_video": {
"type": "boolean"
},
"output_audio": {
"type": "boolean"
}
}
},
Expand Down Expand Up @@ -15259,4 +15268,4 @@
"in": "header"
}
}
}
}
6 changes: 6 additions & 0 deletions core/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3508,8 +3508,14 @@ definitions:
type: string
resolution:
type: string
native_resolution:
type: string
service_tier:
type: string
input_video:
type: boolean
output_audio:
type: boolean
type: object
model.Video:
properties:
Expand Down
45 changes: 45 additions & 0 deletions core/model/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type PriceCondition struct {
Resolution []string `json:"resolution,omitempty"`
Quality []string `json:"quality,omitempty"`
ServiceTier string `json:"service_tier,omitempty"`
InputVideo *bool `json:"input_video,omitempty"`
OutputAudio *bool `json:"output_audio,omitempty"`
}

type ConditionalPrice struct {
Expand Down Expand Up @@ -128,6 +130,14 @@ func qualityConditionValuesOverlap(values1, values2 []string) bool {
return false
}

func boolConditionOverlap(value1, value2 *bool) bool {
if value1 == nil || value2 == nil {
return true
}

return *value1 == *value2
}

func priceConditionSpecificity(condition PriceCondition) int {
specificity := 0

Expand All @@ -143,6 +153,14 @@ func priceConditionSpecificity(condition PriceCondition) int {
specificity++
}

if condition.InputVideo != nil {
specificity++
}

if condition.OutputAudio != nil {
specificity++
}

if condition.InputTokenMin > 0 {
specificity++
}
Expand Down Expand Up @@ -380,6 +398,11 @@ func (p *Price) ValidateConditionalPrices() error {
continue
}

if !boolConditionOverlap(condition.InputVideo, otherCondition.InputVideo) ||
!boolConditionOverlap(condition.OutputAudio, otherCondition.OutputAudio) {
continue
}

// Check input token range overlap
if hasRangeOverlap(
condition.InputTokenMin, condition.InputTokenMax,
Expand Down Expand Up @@ -673,6 +696,8 @@ type UsageContext struct {
NativeResolution string `gorm:"size:32" json:"native_resolution,omitempty"`
Quality string `gorm:"size:32" json:"quality,omitempty"`
ServiceTier string `gorm:"size:32" json:"service_tier,omitempty"`
InputVideo *bool ` json:"input_video,omitempty"`
OutputAudio *bool ` json:"output_audio,omitempty"`
}

func (c UsageContext) PriceConditionMatches(condition PriceCondition) bool {
Expand Down Expand Up @@ -708,6 +733,18 @@ func (c UsageContext) priceConditionMatches(
return false
}

if condition.InputVideo != nil {
if c.InputVideo == nil || *c.InputVideo != *condition.InputVideo {
return false
}
}

if condition.OutputAudio != nil {
if c.OutputAudio == nil || *c.OutputAudio != *condition.OutputAudio {
return false
}
}

return true
}

Expand All @@ -728,6 +765,14 @@ func (c UsageContext) WithFallback(fallback UsageContext) UsageContext {
c.Quality = fallback.Quality
}

if c.InputVideo == nil {
c.InputVideo = fallback.InputVideo
}

if c.OutputAudio == nil {
c.OutputAudio = fallback.OutputAudio
}

return c
}

Expand Down
Loading
Loading