From 8a3c0bb342a6650e32e04329e061bc56d8b9c07a Mon Sep 17 00:00:00 2001 From: woody Date: Tue, 11 Nov 2025 19:39:49 +0800 Subject: [PATCH] feat(ai-proxy): add video-related API paths and capabilities (#3108) --- plugins/wasm-go/extensions/ai-proxy/main.go | 4 ++++ .../extensions/ai-proxy/provider/openai.go | 9 +++++++-- .../extensions/ai-proxy/provider/provider.go | 20 +++++++++++++++++-- .../wasm-go/extensions/ai-proxy/util/http.go | 6 ++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/plugins/wasm-go/extensions/ai-proxy/main.go b/plugins/wasm-go/extensions/ai-proxy/main.go index 32688d27e..051284699 100644 --- a/plugins/wasm-go/extensions/ai-proxy/main.go +++ b/plugins/wasm-go/extensions/ai-proxy/main.go @@ -60,6 +60,7 @@ var ( {provider.PathOpenAIModels, provider.ApiNameModels}, {provider.PathOpenAIFineTuningJobs, provider.ApiNameFineTuningJobs}, {provider.PathOpenAIResponses, provider.ApiNameResponses}, + {provider.PathOpenAIVideos, provider.ApiNameVideos}, // Anthropic style {provider.PathAnthropicMessages, provider.ApiNameAnthropicMessages}, {provider.PathAnthropicComplete, provider.ApiNameAnthropicComplete}, @@ -72,6 +73,9 @@ var ( {util.RegCancelBatchPath, provider.ApiNameCancelBatch}, {util.RegRetrieveFilePath, provider.ApiNameRetrieveFile}, {util.RegRetrieveFileContentPath, provider.ApiNameRetrieveFileContent}, + {util.RegRetrieveVideoPath, provider.ApiNameRetrieveVideo}, + {util.RegRetrieveVideoContentPath, provider.ApiNameRetrieveVideoContent}, + {util.RegVideoRemixPath, provider.ApiNameVideoRemix}, {util.RegRetrieveFineTuningJobPath, provider.ApiNameRetrieveFineTuningJob}, {util.RegRetrieveFineTuningJobEventsPath, provider.ApiNameFineTuningJobEvents}, {util.RegRetrieveFineTuningJobCheckpointsPath, provider.ApiNameFineTuningJobCheckpoints}, diff --git a/plugins/wasm-go/extensions/ai-proxy/provider/openai.go b/plugins/wasm-go/extensions/ai-proxy/provider/openai.go index e952ae6f0..746015267 100644 --- a/plugins/wasm-go/extensions/ai-proxy/provider/openai.go +++ b/plugins/wasm-go/extensions/ai-proxy/provider/openai.go @@ -7,9 +7,9 @@ import ( "strings" "github.com/alibaba/higress/plugins/wasm-go/extensions/ai-proxy/util" + "github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types" "github.com/higress-group/wasm-go/pkg/log" "github.com/higress-group/wasm-go/pkg/wrapper" - "github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types" ) // openaiProvider is the provider for OpenAI service. @@ -50,6 +50,10 @@ func (m *openaiProviderInitializer) DefaultCapabilities() map[string]string { string(ApiNamePauseFineTuningJob): PathOpenAIPauseFineTuningJob, string(ApiNameFineTuningCheckpointPermissions): PathOpenAIFineTuningCheckpointPermissions, string(ApiNameDeleteFineTuningCheckpointPermission): PathOpenAIFineDeleteTuningCheckpointPermission, + string(ApiNameVideos): PathOpenAIVideos, + string(ApiNameRetrieveVideo): PathOpenAIRetrieveVideo, + string(ApiNameVideoRemix): PathOpenAIVideoRemix, + string(ApiNameRetrieveVideoContent): PathOpenAIRetrieveVideoContent, } } @@ -64,7 +68,8 @@ func isDirectPath(path string) bool { strings.HasSuffix(path, "/models") || strings.HasSuffix(path, "/responses") || strings.HasSuffix(path, "/fine_tuning/jobs") || - strings.HasSuffix(path, "/fine_tuning/checkpoints") + strings.HasSuffix(path, "/fine_tuning/checkpoints") || + strings.HasSuffix(path, "/videos") } func (m *openaiProviderInitializer) CreateProvider(config ProviderConfig) (Provider, error) { diff --git a/plugins/wasm-go/extensions/ai-proxy/provider/provider.go b/plugins/wasm-go/extensions/ai-proxy/provider/provider.go index 975d64e5c..c35597a9e 100644 --- a/plugins/wasm-go/extensions/ai-proxy/provider/provider.go +++ b/plugins/wasm-go/extensions/ai-proxy/provider/provider.go @@ -56,6 +56,10 @@ const ( ApiNamePauseFineTuningJob ApiName = "openai/v1/pausefine-tuningjob" ApiNameFineTuningCheckpointPermissions ApiName = "openai/v1/fine-tuningjobcheckpointpermissions" ApiNameDeleteFineTuningCheckpointPermission ApiName = "openai/v1/deletefine-tuningjobcheckpointpermission" + ApiNameVideos ApiName = "openai/v1/videos" + ApiNameRetrieveVideo ApiName = "openai/v1/retrievevideo" + ApiNameVideoRemix ApiName = "openai/v1/videoremix" + ApiNameRetrieveVideoContent ApiName = "openai/v1/retrievevideocontent" // TODO: 以下是一些非标准的API名称,需要进一步确认是否支持 ApiNameCohereV1Rerank ApiName = "cohere/v1/rerank" @@ -93,6 +97,10 @@ const ( PathOpenAIPauseFineTuningJob = "/v1/fine_tuning/jobs/{fine_tuning_job_id}/pause" PathOpenAIFineTuningCheckpointPermissions = "/v1/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions" PathOpenAIFineDeleteTuningCheckpointPermission = "/v1/fine_tuning/checkpoints/{fine_tuned_model_checkpoint}/permissions/{permission_id}" + PathOpenAIVideos = "/v1/videos" + PathOpenAIRetrieveVideo = "/v1/videos/{video_id}" + PathOpenAIVideoRemix = "/v1/videos/{video_id}/remix" + PathOpenAIRetrieveVideoContent = "/v1/videos/{video_id}/content" // Anthropic PathAnthropicMessages = "/v1/messages" @@ -598,7 +606,11 @@ func (c *ProviderConfig) FromJson(json gjson.Result) { string(ApiNameImageVariation), string(ApiNameImageEdit), string(ApiNameAudioSpeech), - string(ApiNameCohereV1Rerank): + string(ApiNameCohereV1Rerank), + string(ApiNameVideos), + string(ApiNameRetrieveVideo), + string(ApiNameRetrieveVideoContent), + string(ApiNameVideoRemix): c.capabilities[capability] = pathJson.String() } } @@ -966,7 +978,9 @@ func (c *ProviderConfig) handleRequestHeaders(provider Provider, ctx wrapper.Htt // defaultTransformRequestBody 默认的请求体转换方法,只做模型映射,用slog替换模型名称,不用序列化和反序列化,提高性能 func (c *ProviderConfig) defaultTransformRequestBody(ctx wrapper.HttpContext, apiName ApiName, body []byte) ([]byte, error) { switch apiName { - case ApiNameChatCompletion: + case ApiNameChatCompletion, + ApiNameVideos, + ApiNameVideoRemix: stream := gjson.GetBytes(body, "stream").Bool() if stream { _ = proxywasm.ReplaceHttpRequestHeader("Accept", "text/event-stream") @@ -1011,6 +1025,8 @@ func (c *ProviderConfig) isStreamingAPI(apiName ApiName, body []byte) bool { func (c *ProviderConfig) needToProcessRequestBody(apiName ApiName) bool { switch apiName { case ApiNameChatCompletion, + ApiNameVideos, + ApiNameVideoRemix, ApiNameCompletion, ApiNameEmbeddings, ApiNameImageGeneration, diff --git a/plugins/wasm-go/extensions/ai-proxy/util/http.go b/plugins/wasm-go/extensions/ai-proxy/util/http.go index 0266f245d..8fada21dd 100644 --- a/plugins/wasm-go/extensions/ai-proxy/util/http.go +++ b/plugins/wasm-go/extensions/ai-proxy/util/http.go @@ -28,6 +28,9 @@ var ( RegCancelBatchPath = regexp.MustCompile(`^.*/v1/batches/(?P[^/]+)/cancel$`) RegRetrieveFilePath = regexp.MustCompile(`^.*/v1/files/(?P[^/]+)$`) RegRetrieveFileContentPath = regexp.MustCompile(`^.*/v1/files/(?P[^/]+)/content$`) + RegRetrieveVideoPath = regexp.MustCompile(`^.*/v1/videos/(?P[^/]+)$`) + RegRetrieveVideoContentPath = regexp.MustCompile(`^.*/v1/videos/(?P[^/]+)/content$`) + RegVideoRemixPath = regexp.MustCompile(`^.*/v1/videos/(?P[^/]+)/remix$`) RegRetrieveFineTuningJobPath = regexp.MustCompile(`^.*/v1/fine_tuning/jobs/(?P[^/]+)$`) RegRetrieveFineTuningJobEventsPath = regexp.MustCompile(`^.*/v1/fine_tuning/jobs/(?P[^/]+)/events$`) RegRetrieveFineTuningJobCheckpointsPath = regexp.MustCompile(`^.*/v1/fine_tuning/jobs/(?P[^/]+)/checkpoints$`) @@ -99,6 +102,9 @@ func MapRequestPathByCapability(apiName string, originPath string, mapping map[s {RegRetrieveFileContentPath, "file_id"}, {RegRetrieveBatchPath, "batch_id"}, {RegCancelBatchPath, "batch_id"}, + {RegRetrieveVideoPath, "video_id"}, + {RegRetrieveVideoContentPath, "video_id"}, + {RegVideoRemixPath, "video_id"}, } for _, r := range replacements {