|
- package doubao
-
- import (
- "testing"
-
- "github.com/QuantumNous/new-api/dto"
- "github.com/QuantumNous/new-api/model"
- relaycommon "github.com/QuantumNous/new-api/relay/common"
- "github.com/stretchr/testify/require"
- )
-
- func TestParseTaskResult_SuccessWithUsage(t *testing.T) {
- adaptor := &TaskAdaptor{}
- taskInfo, err := adaptor.ParseTaskResult([]byte(`{
- "status":"succeeded",
- "content":{"video_url":"https://example.test/video.mp4"},
- "usage":{"completion_tokens":12,"total_tokens":3456}
- }`))
-
- require.NoError(t, err)
- require.Equal(t, string(model.TaskStatusSuccess), taskInfo.Status)
- require.Equal(t, "https://example.test/video.mp4", taskInfo.Url)
- require.Equal(t, 12, taskInfo.CompletionTokens)
- require.Equal(t, 3456, taskInfo.TotalTokens)
- }
-
- func TestParseTaskResult_SuccessWithoutUsage(t *testing.T) {
- adaptor := &TaskAdaptor{}
- taskInfo, err := adaptor.ParseTaskResult([]byte(`{
- "status":"succeeded",
- "content":{"video_url":"https://example.test/video.mp4"}
- }`))
-
- require.NoError(t, err)
- require.Equal(t, string(model.TaskStatusSuccess), taskInfo.Status)
- require.Zero(t, taskInfo.TotalTokens)
- }
-
- func TestParseTaskResult_NonSuccessStatusesDoNotRequireUsage(t *testing.T) {
- adaptor := &TaskAdaptor{}
- cases := map[string]model.TaskStatus{
- "queued": model.TaskStatusQueued,
- "processing": model.TaskStatusInProgress,
- "failed": model.TaskStatusFailure,
- }
- for status, want := range cases {
- taskInfo, err := adaptor.ParseTaskResult([]byte(`{"status":"` + status + `"}`))
- require.NoError(t, err)
- require.Equal(t, string(want), taskInfo.Status)
- require.Zero(t, taskInfo.TotalTokens)
- }
- }
-
- func TestConvertToRequestPayload_MetadataSupportsVideoAudioAndTools(t *testing.T) {
- adaptor := &TaskAdaptor{}
- req := &relaycommon.TaskSubmitReq{
- Model: "doubao-seedance-2-0-260128",
- Prompt: "make a reference video",
- Metadata: map[string]interface{}{
- "content": []interface{}{
- map[string]interface{}{
- "type": "video_url",
- "video_url": map[string]interface{}{
- "url": "https://example.test/input.mp4",
- },
- "role": "reference_video",
- },
- map[string]interface{}{
- "type": "audio_url",
- "audio_url": map[string]interface{}{
- "url": "https://example.test/input.wav",
- },
- "role": "reference_audio",
- },
- },
- "tools": []interface{}{
- map[string]interface{}{"type": "web_search"},
- },
- },
- }
-
- payload, err := adaptor.convertToRequestPayload(req)
-
- require.NoError(t, err)
- require.Len(t, payload.Content, 3)
- require.Equal(t, "video_url", payload.Content[0].Type)
- require.Equal(t, "https://example.test/input.mp4", payload.Content[0].VideoURL.URL)
- require.Equal(t, "reference_video", payload.Content[0].Role)
- require.Equal(t, "audio_url", payload.Content[1].Type)
- require.Equal(t, "https://example.test/input.wav", payload.Content[1].AudioURL.URL)
- require.Equal(t, "reference_audio", payload.Content[1].Role)
- require.Len(t, payload.Tools, 1)
- require.Equal(t, "web_search", payload.Tools[0].Type)
- }
-
- func TestConvertToRequestPayload_SecondsOverridesDuration(t *testing.T) {
- adaptor := &TaskAdaptor{}
- req := &relaycommon.TaskSubmitReq{
- Model: "doubao-seedance-1-5-pro-251215",
- Prompt: "cat yawning",
- Seconds: "8",
- Metadata: map[string]interface{}{
- "duration": 5,
- },
- }
-
- payload, err := adaptor.convertToRequestPayload(req)
-
- require.NoError(t, err)
- require.NotNil(t, payload.Duration)
- require.Equal(t, dto.IntValue(8), *payload.Duration)
- }
-
- func TestConvertToRequestPayload_PromptAppendedAfterMetadataAndReplacesMetadataText(t *testing.T) {
- adaptor := &TaskAdaptor{}
- req := &relaycommon.TaskSubmitReq{
- Model: "doubao-seedance-1-5-pro-251215",
- Prompt: "current prompt",
- Images: []string{"https://example.test/first.png"},
- Metadata: map[string]interface{}{
- "content": []interface{}{
- map[string]interface{}{
- "type": "text",
- "text": "metadata prompt",
- },
- map[string]interface{}{
- "type": "image_url",
- "image_url": map[string]interface{}{
- "url": "https://example.test/second.png",
- },
- "role": "last_frame",
- },
- },
- },
- }
-
- payload, err := adaptor.convertToRequestPayload(req)
-
- require.NoError(t, err)
- require.Len(t, payload.Content, 2)
- require.Equal(t, "image_url", payload.Content[0].Type)
- require.Equal(t, "https://example.test/second.png", payload.Content[0].ImageURL.URL)
- require.Equal(t, "last_frame", payload.Content[0].Role)
- require.Equal(t, "text", payload.Content[1].Type)
- require.Equal(t, "current prompt", payload.Content[1].Text)
- }
-
- func TestParseTaskResult_FailedUsesUpstreamErrorMessage(t *testing.T) {
- adaptor := &TaskAdaptor{}
- taskInfo, err := adaptor.ParseTaskResult([]byte(`{
- "status":"failed",
- "error":{"code":"InvalidParameter","message":"duration is invalid"}
- }`))
-
- require.NoError(t, err)
- require.Equal(t, string(model.TaskStatusFailure), taskInfo.Status)
- require.Equal(t, "duration is invalid", taskInfo.Reason)
- }
-
- func TestConvertToOpenAIVideo_FailedUsesUpstreamError(t *testing.T) {
- adaptor := &TaskAdaptor{}
- task := &model.Task{
- TaskID: "task_public",
- Status: model.TaskStatusFailure,
- Progress: "100%",
- CreatedAt: 100,
- UpdatedAt: 200,
- Properties: model.Properties{
- OriginModelName: "doubao-seedance-1-5-pro-251215",
- },
- Data: []byte(`{
- "status":"failed",
- "error":{"code":"InvalidParameter","message":"duration is invalid"}
- }`),
- }
-
- data, err := adaptor.ConvertToOpenAIVideo(task)
-
- require.NoError(t, err)
- require.Contains(t, string(data), `"message":"duration is invalid"`)
- require.Contains(t, string(data), `"code":"InvalidParameter"`)
- }
-
- func TestGetModelList_IncludesSeedance20Models(t *testing.T) {
- adaptor := &TaskAdaptor{}
- models := adaptor.GetModelList()
-
- require.Contains(t, models, "doubao-seedance-2-0-260128")
- require.Contains(t, models, "doubao-seedance-2-0-fast-260128")
- }
|