Merge pull request #1611 from nekohy/feats-zhipu_4v-anthropic

Feats:Standardize ClaudeHandler, add Zhipu_4v Anthropic native channel support
This commit is contained in:
Calcium-Ion
2025-08-23 13:48:18 +08:00
committed by GitHub
6 changed files with 46 additions and 40 deletions

View File

@@ -120,15 +120,14 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
switch info.RelayFormat { switch info.RelayFormat {
case types.RelayFormatClaude: case types.RelayFormatClaude:
if info.IsStream { if info.IsStream {
err, usage = claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage)
} else { } else {
err, usage = claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage)
} }
default: default:
adaptor := openai.Adaptor{} adaptor := openai.Adaptor{}
return adaptor.DoResponse(c, resp, info) return adaptor.DoResponse(c, resp, info)
} }
return
} }
func (a *Adaptor) GetModelList() []string { func (a *Adaptor) GetModelList() []string {

View File

@@ -102,9 +102,9 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) { func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) {
if info.IsStream { if info.IsStream {
err, usage = ClaudeStreamHandler(c, resp, info, a.RequestMode) return ClaudeStreamHandler(c, resp, info, a.RequestMode)
} else { } else {
err, usage = ClaudeHandler(c, resp, info, a.RequestMode) return ClaudeHandler(c, resp, info, a.RequestMode)
} }
return return
} }

View File

@@ -674,7 +674,7 @@ func HandleStreamFinalResponse(c *gin.Context, info *relaycommon.RelayInfo, clau
} }
} }
func ClaudeStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo, requestMode int) (*types.NewAPIError, *dto.Usage) { func ClaudeStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo, requestMode int) (*dto.Usage, *types.NewAPIError) {
claudeInfo := &ClaudeResponseInfo{ claudeInfo := &ClaudeResponseInfo{
ResponseId: helper.GetResponseID(c), ResponseId: helper.GetResponseID(c),
Created: common.GetTimestamp(), Created: common.GetTimestamp(),
@@ -691,11 +691,11 @@ func ClaudeStreamHandler(c *gin.Context, resp *http.Response, info *relaycommon.
return true return true
}) })
if err != nil { if err != nil {
return err, nil return nil, err
} }
HandleStreamFinalResponse(c, info, claudeInfo, requestMode) HandleStreamFinalResponse(c, info, claudeInfo, requestMode)
return nil, claudeInfo.Usage return claudeInfo.Usage, nil
} }
func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claudeInfo *ClaudeResponseInfo, data []byte, requestMode int) *types.NewAPIError { func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claudeInfo *ClaudeResponseInfo, data []byte, requestMode int) *types.NewAPIError {
@@ -740,7 +740,7 @@ func HandleClaudeResponseData(c *gin.Context, info *relaycommon.RelayInfo, claud
return nil return nil
} }
func ClaudeHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo, requestMode int) (*types.NewAPIError, *dto.Usage) { func ClaudeHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo, requestMode int) (*dto.Usage, *types.NewAPIError) {
defer service.CloseResponseBodyGracefully(resp) defer service.CloseResponseBodyGracefully(resp)
claudeInfo := &ClaudeResponseInfo{ claudeInfo := &ClaudeResponseInfo{
@@ -752,16 +752,16 @@ func ClaudeHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayI
} }
responseBody, err := io.ReadAll(resp.Body) responseBody, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return types.NewError(err, types.ErrorCodeBadResponseBody), nil return nil, types.NewError(err, types.ErrorCodeBadResponseBody)
} }
if common.DebugEnabled { if common.DebugEnabled {
println("responseBody: ", string(responseBody)) println("responseBody: ", string(responseBody))
} }
handleErr := HandleClaudeResponseData(c, info, claudeInfo, responseBody, requestMode) handleErr := HandleClaudeResponseData(c, info, claudeInfo, responseBody, requestMode)
if handleErr != nil { if handleErr != nil {
return handleErr, nil return nil, handleErr
} }
return nil, claudeInfo.Usage return claudeInfo.Usage, nil
} }
func mapToolChoice(toolChoice any, parallelToolCalls *bool) *dto.ClaudeToolChoice { func mapToolChoice(toolChoice any, parallelToolCalls *bool) *dto.ClaudeToolChoice {

View File

@@ -89,17 +89,16 @@ func (a *Adaptor) ConvertEmbeddingRequest(c *gin.Context, info *relaycommon.Rela
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) { func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) {
switch info.RelayFormat { switch info.RelayFormat {
case types.RelayFormatOpenAI:
adaptor := openai.Adaptor{}
return adaptor.DoResponse(c, resp, info)
case types.RelayFormatClaude: case types.RelayFormatClaude:
if info.IsStream { if info.IsStream {
err, usage = claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage)
} else { } else {
err, usage = claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage)
} }
default:
adaptor := openai.Adaptor{}
return adaptor.DoResponse(c, resp, info)
} }
return
} }
func (a *Adaptor) GetModelList() []string { func (a *Adaptor) GetModelList() []string {

View File

@@ -279,31 +279,31 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
if info.IsStream { if info.IsStream {
switch a.RequestMode { switch a.RequestMode {
case RequestModeClaude: case RequestModeClaude:
err, usage = claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage)
case RequestModeGemini: case RequestModeGemini:
if info.RelayMode == constant.RelayModeGemini { if info.RelayMode == constant.RelayModeGemini {
usage, err = gemini.GeminiTextGenerationStreamHandler(c, info, resp) return gemini.GeminiTextGenerationStreamHandler(c, info, resp)
} else { } else {
usage, err = gemini.GeminiChatStreamHandler(c, info, resp) return gemini.GeminiChatStreamHandler(c, info, resp)
} }
case RequestModeLlama: case RequestModeLlama:
usage, err = openai.OaiStreamHandler(c, info, resp) return openai.OaiStreamHandler(c, info, resp)
} }
} else { } else {
switch a.RequestMode { switch a.RequestMode {
case RequestModeClaude: case RequestModeClaude:
err, usage = claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage) return claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage)
case RequestModeGemini: case RequestModeGemini:
if info.RelayMode == constant.RelayModeGemini { if info.RelayMode == constant.RelayModeGemini {
usage, err = gemini.GeminiTextGenerationHandler(c, info, resp) return gemini.GeminiTextGenerationHandler(c, info, resp)
} else { } else {
if strings.HasPrefix(info.UpstreamModelName, "imagen") { if strings.HasPrefix(info.UpstreamModelName, "imagen") {
return gemini.GeminiImageHandler(c, info, resp) return gemini.GeminiImageHandler(c, info, resp)
} }
usage, err = gemini.GeminiChatHandler(c, info, resp) return gemini.GeminiChatHandler(c, info, resp)
} }
case RequestModeLlama: case RequestModeLlama:
usage, err = openai.OpenaiHandler(c, info, resp) return openai.OpenaiHandler(c, info, resp)
} }
} }
return return

View File

@@ -7,6 +7,7 @@ import (
"net/http" "net/http"
"one-api/dto" "one-api/dto"
"one-api/relay/channel" "one-api/relay/channel"
"one-api/relay/channel/claude"
"one-api/relay/channel/openai" "one-api/relay/channel/openai"
relaycommon "one-api/relay/common" relaycommon "one-api/relay/common"
relayconstant "one-api/relay/constant" relayconstant "one-api/relay/constant"
@@ -23,10 +24,8 @@ func (a *Adaptor) ConvertGeminiRequest(*gin.Context, *relaycommon.RelayInfo, *dt
return nil, errors.New("not implemented") return nil, errors.New("not implemented")
} }
func (a *Adaptor) ConvertClaudeRequest(*gin.Context, *relaycommon.RelayInfo, *dto.ClaudeRequest) (any, error) { func (a *Adaptor) ConvertClaudeRequest(c *gin.Context, info *relaycommon.RelayInfo, req *dto.ClaudeRequest) (any, error) {
//TODO implement me return req, nil
panic("implement me")
return nil, nil
} }
func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) { func (a *Adaptor) ConvertAudioRequest(c *gin.Context, info *relaycommon.RelayInfo, request dto.AudioRequest) (io.Reader, error) {
@@ -43,12 +42,16 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
} }
func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) { func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
baseUrl := fmt.Sprintf("%s/api/paas/v4", info.ChannelBaseUrl) switch info.RelayFormat {
case types.RelayFormatClaude:
return fmt.Sprintf("%s/api/anthropic/v1/messages", info.ChannelBaseUrl), nil
default:
switch info.RelayMode { switch info.RelayMode {
case relayconstant.RelayModeEmbeddings: case relayconstant.RelayModeEmbeddings:
return fmt.Sprintf("%s/embeddings", baseUrl), nil return fmt.Sprintf("%s/api/paas/v4/embeddings", info.ChannelBaseUrl), nil
default: default:
return fmt.Sprintf("%s/chat/completions", baseUrl), nil return fmt.Sprintf("%s/api/paas/v4/chat/completions", info.ChannelBaseUrl), nil
}
} }
} }
@@ -86,12 +89,17 @@ func (a *Adaptor) DoRequest(c *gin.Context, info *relaycommon.RelayInfo, request
} }
func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) { func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (usage any, err *types.NewAPIError) {
switch info.RelayFormat {
case types.RelayFormatClaude:
if info.IsStream { if info.IsStream {
usage, err = openai.OaiStreamHandler(c, info, resp) return claude.ClaudeStreamHandler(c, resp, info, claude.RequestModeMessage)
} else { } else {
usage, err = openai.OpenaiHandler(c, info, resp) return claude.ClaudeHandler(c, resp, info, claude.RequestModeMessage)
}
default:
adaptor := openai.Adaptor{}
return adaptor.DoResponse(c, resp, info)
} }
return
} }
func (a *Adaptor) GetModelList() []string { func (a *Adaptor) GetModelList() []string {