Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
e8da9d7d
authored
Jun 20, 2025
by
Calcium-Ion
Committed by
GitHub
Jun 20, 2025
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1270 from QuantumNous/refactor_model_mapping
feat: implement new handlers for relay processing
parents
2e242159
13277cf8
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
95 additions
and
38 deletions
+95
-38
controller/channel-test.go
+1
-1
relay/audio_handler.go
+2
-4
relay/channel/gemini/adaptor.go
+3
-3
relay/channel/gemini/relay-gemini.go
+1
-1
relay/claude_handler.go
+1
-3
relay/common/relay_info.go
+38
-7
relay/embedding_handler.go
+2
-4
relay/gemini_handler.go
+2
-2
relay/helper/model_mapped.go
+39
-1
relay/image_handler.go
+2
-4
relay/relay-text.go
+1
-3
relay/rerank_handler.go
+1
-3
relay/responses_handler.go
+2
-2
No files found.
controller/channel-test.go
View file @
e8da9d7d
...
...
@@ -93,7 +93,7 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
info
:=
relaycommon
.
GenRelayInfo
(
c
)
err
=
helper
.
ModelMappedHelper
(
c
,
info
)
err
=
helper
.
ModelMappedHelper
(
c
,
info
,
nil
)
if
err
!=
nil
{
return
err
,
nil
}
...
...
relay/
relay-audio
.go
→
relay/
audio_handler
.go
View file @
e8da9d7d
...
...
@@ -55,7 +55,7 @@ func getAndValidAudioRequest(c *gin.Context, info *relaycommon.RelayInfo) (*dto.
}
func
AudioHelper
(
c
*
gin
.
Context
)
(
openaiErr
*
dto
.
OpenAIErrorWithStatusCode
)
{
relayInfo
:=
relaycommon
.
GenRelayInfo
(
c
)
relayInfo
:=
relaycommon
.
GenRelayInfo
OpenAIAudio
(
c
)
audioRequest
,
err
:=
getAndValidAudioRequest
(
c
,
relayInfo
)
if
err
!=
nil
{
...
...
@@ -89,13 +89,11 @@ func AudioHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode) {
}
}()
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
audioRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
audioRequest
.
Model
=
relayInfo
.
UpstreamModelName
adaptor
:=
GetAdaptor
(
relayInfo
.
ApiType
)
if
adaptor
==
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
fmt
.
Errorf
(
"invalid api type: %d"
,
relayInfo
.
ApiType
),
"invalid_api_type"
,
http
.
StatusBadRequest
)
...
...
relay/channel/gemini/adaptor.go
View file @
e8da9d7d
...
...
@@ -73,12 +73,12 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
// 新增逻辑:处理 -thinking-<budget> 格式
if
strings
.
Contains
(
info
.
Origin
ModelName
,
"-thinking-"
)
{
if
strings
.
Contains
(
info
.
Upstream
ModelName
,
"-thinking-"
)
{
parts
:=
strings
.
Split
(
info
.
UpstreamModelName
,
"-thinking-"
)
info
.
UpstreamModelName
=
parts
[
0
]
}
else
if
strings
.
HasSuffix
(
info
.
Origin
ModelName
,
"-thinking"
)
{
// 旧的适配
}
else
if
strings
.
HasSuffix
(
info
.
Upstream
ModelName
,
"-thinking"
)
{
// 旧的适配
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-thinking"
)
}
else
if
strings
.
HasSuffix
(
info
.
Origin
ModelName
,
"-nothinking"
)
{
}
else
if
strings
.
HasSuffix
(
info
.
Upstream
ModelName
,
"-nothinking"
)
{
info
.
UpstreamModelName
=
strings
.
TrimSuffix
(
info
.
UpstreamModelName
,
"-nothinking"
)
}
}
...
...
relay/channel/gemini/relay-gemini.go
View file @
e8da9d7d
...
...
@@ -99,7 +99,7 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
}
if
model_setting
.
GetGeminiSettings
()
.
ThinkingAdapterEnabled
{
modelName
:=
info
.
Origin
ModelName
modelName
:=
info
.
Upstream
ModelName
isNew25Pro
:=
strings
.
HasPrefix
(
modelName
,
"gemini-2.5-pro"
)
&&
!
strings
.
HasPrefix
(
modelName
,
"gemini-2.5-pro-preview-05-06"
)
&&
!
strings
.
HasPrefix
(
modelName
,
"gemini-2.5-pro-preview-03-25"
)
...
...
relay/claude_handler.go
View file @
e8da9d7d
...
...
@@ -46,13 +46,11 @@ func ClaudeHelper(c *gin.Context) (claudeError *dto.ClaudeErrorWithStatusCode) {
relayInfo
.
IsStream
=
true
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
textRequest
)
if
err
!=
nil
{
return
service
.
ClaudeErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
textRequest
.
Model
=
relayInfo
.
UpstreamModelName
promptTokens
,
err
:=
getClaudePromptTokens
(
textRequest
,
relayInfo
)
// count messages token error 计算promptTokens错误
if
err
!=
nil
{
...
...
relay/common/relay_info.go
View file @
e8da9d7d
...
...
@@ -34,9 +34,14 @@ type ClaudeConvertInfo struct {
}
const
(
RelayFormatOpenAI
=
"openai"
RelayFormatClaude
=
"claude"
RelayFormatGemini
=
"gemini"
RelayFormatOpenAI
=
"openai"
RelayFormatClaude
=
"claude"
RelayFormatGemini
=
"gemini"
RelayFormatOpenAIResponses
=
"openai_responses"
RelayFormatOpenAIAudio
=
"openai_audio"
RelayFormatOpenAIImage
=
"openai_image"
RelayFormatRerank
=
"rerank"
RelayFormatEmbedding
=
"embedding"
)
type
RerankerInfo
struct
{
...
...
@@ -143,6 +148,7 @@ func GenRelayInfoClaude(c *gin.Context) *RelayInfo {
func
GenRelayInfoRerank
(
c
*
gin
.
Context
,
req
*
dto
.
RerankRequest
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayMode
=
relayconstant
.
RelayModeRerank
info
.
RelayFormat
=
RelayFormatRerank
info
.
RerankerInfo
=
&
RerankerInfo
{
Documents
:
req
.
Documents
,
ReturnDocuments
:
req
.
GetReturnDocuments
(),
...
...
@@ -150,9 +156,25 @@ func GenRelayInfoRerank(c *gin.Context, req *dto.RerankRequest) *RelayInfo {
return
info
}
func
GenRelayInfoOpenAIAudio
(
c
*
gin
.
Context
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayFormat
=
RelayFormatOpenAIAudio
return
info
}
func
GenRelayInfoEmbedding
(
c
*
gin
.
Context
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayFormat
=
RelayFormatEmbedding
return
info
}
func
GenRelayInfoResponses
(
c
*
gin
.
Context
,
req
*
dto
.
OpenAIResponsesRequest
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayMode
=
relayconstant
.
RelayModeResponses
info
.
RelayFormat
=
RelayFormatOpenAIResponses
info
.
SupportStreamOptions
=
false
info
.
ResponsesUsageInfo
=
&
ResponsesUsageInfo
{
BuiltInTools
:
make
(
map
[
string
]
*
BuildInToolInfo
),
}
...
...
@@ -175,6 +197,19 @@ func GenRelayInfoResponses(c *gin.Context, req *dto.OpenAIResponsesRequest) *Rel
return
info
}
func
GenRelayInfoGemini
(
c
*
gin
.
Context
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayFormat
=
RelayFormatGemini
info
.
ShouldIncludeUsage
=
false
return
info
}
func
GenRelayInfoImage
(
c
*
gin
.
Context
)
*
RelayInfo
{
info
:=
GenRelayInfo
(
c
)
info
.
RelayFormat
=
RelayFormatOpenAIImage
return
info
}
func
GenRelayInfo
(
c
*
gin
.
Context
)
*
RelayInfo
{
channelType
:=
c
.
GetInt
(
"channel_type"
)
channelId
:=
c
.
GetInt
(
"channel_id"
)
...
...
@@ -243,10 +278,6 @@ func GenRelayInfo(c *gin.Context) *RelayInfo {
if
streamSupportedChannels
[
info
.
ChannelType
]
{
info
.
SupportStreamOptions
=
true
}
// responses 模式不支持 StreamOptions
if
relayconstant
.
RelayModeResponses
==
info
.
RelayMode
{
info
.
SupportStreamOptions
=
false
}
return
info
}
...
...
relay/
relay_embedding
.go
→
relay/
embedding_handler
.go
View file @
e8da9d7d
...
...
@@ -33,7 +33,7 @@ func validateEmbeddingRequest(c *gin.Context, info *relaycommon.RelayInfo, embed
}
func
EmbeddingHelper
(
c
*
gin
.
Context
)
(
openaiErr
*
dto
.
OpenAIErrorWithStatusCode
)
{
relayInfo
:=
relaycommon
.
GenRelayInfo
(
c
)
relayInfo
:=
relaycommon
.
GenRelayInfo
Embedding
(
c
)
var
embeddingRequest
*
dto
.
EmbeddingRequest
err
:=
common
.
UnmarshalBodyReusable
(
c
,
&
embeddingRequest
)
...
...
@@ -47,13 +47,11 @@ func EmbeddingHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode)
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"invalid_embedding_request"
,
http
.
StatusBadRequest
)
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
embeddingRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
embeddingRequest
.
Model
=
relayInfo
.
UpstreamModelName
promptToken
:=
getEmbeddingPromptToken
(
*
embeddingRequest
)
relayInfo
.
PromptTokens
=
promptToken
...
...
relay/
relay-gemini
.go
→
relay/
gemini_handler
.go
View file @
e8da9d7d
...
...
@@ -83,7 +83,7 @@ func GeminiHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode) {
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"invalid_gemini_request"
,
http
.
StatusBadRequest
)
}
relayInfo
:=
relaycommon
.
GenRelayInfo
(
c
)
relayInfo
:=
relaycommon
.
GenRelayInfo
Gemini
(
c
)
// 检查 Gemini 流式模式
checkGeminiStreamMode
(
c
,
relayInfo
)
...
...
@@ -97,7 +97,7 @@ func GeminiHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode) {
}
// model mapped 模型映射
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
req
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusBadRequest
)
}
...
...
relay/helper/model_mapped.go
View file @
e8da9d7d
...
...
@@ -4,12 +4,14 @@ import (
"encoding/json"
"errors"
"fmt"
common2
"one-api/common"
"one-api/dto"
"one-api/relay/common"
"github.com/gin-gonic/gin"
)
func
ModelMappedHelper
(
c
*
gin
.
Context
,
info
*
common
.
RelayInfo
)
error
{
func
ModelMappedHelper
(
c
*
gin
.
Context
,
info
*
common
.
RelayInfo
,
request
any
)
error
{
// map model name
modelMapping
:=
c
.
GetString
(
"model_mapping"
)
if
modelMapping
!=
""
&&
modelMapping
!=
"{}"
{
...
...
@@ -50,5 +52,41 @@ func ModelMappedHelper(c *gin.Context, info *common.RelayInfo) error {
info
.
UpstreamModelName
=
currentModel
}
}
if
request
!=
nil
{
switch
info
.
RelayFormat
{
case
common
.
RelayFormatGemini
:
// Gemini 模型映射
case
common
.
RelayFormatClaude
:
if
claudeRequest
,
ok
:=
request
.
(
*
dto
.
ClaudeRequest
);
ok
{
claudeRequest
.
Model
=
info
.
UpstreamModelName
}
case
common
.
RelayFormatOpenAIResponses
:
if
openAIResponsesRequest
,
ok
:=
request
.
(
*
dto
.
OpenAIResponsesRequest
);
ok
{
openAIResponsesRequest
.
Model
=
info
.
UpstreamModelName
}
case
common
.
RelayFormatOpenAIAudio
:
if
openAIAudioRequest
,
ok
:=
request
.
(
*
dto
.
AudioRequest
);
ok
{
openAIAudioRequest
.
Model
=
info
.
UpstreamModelName
}
case
common
.
RelayFormatOpenAIImage
:
if
imageRequest
,
ok
:=
request
.
(
*
dto
.
ImageRequest
);
ok
{
imageRequest
.
Model
=
info
.
UpstreamModelName
}
case
common
.
RelayFormatRerank
:
if
rerankRequest
,
ok
:=
request
.
(
*
dto
.
RerankRequest
);
ok
{
rerankRequest
.
Model
=
info
.
UpstreamModelName
}
case
common
.
RelayFormatEmbedding
:
if
embeddingRequest
,
ok
:=
request
.
(
*
dto
.
EmbeddingRequest
);
ok
{
embeddingRequest
.
Model
=
info
.
UpstreamModelName
}
default
:
if
openAIRequest
,
ok
:=
request
.
(
*
dto
.
GeneralOpenAIRequest
);
ok
{
openAIRequest
.
Model
=
info
.
UpstreamModelName
}
else
{
common2
.
LogWarn
(
c
,
fmt
.
Sprintf
(
"model mapped but request type %T not supported"
,
request
))
}
}
}
return
nil
}
relay/
relay-image
.go
→
relay/
image_handler
.go
View file @
e8da9d7d
...
...
@@ -102,7 +102,7 @@ func getAndValidImageRequest(c *gin.Context, info *relaycommon.RelayInfo) (*dto.
}
func
ImageHelper
(
c
*
gin
.
Context
)
*
dto
.
OpenAIErrorWithStatusCode
{
relayInfo
:=
relaycommon
.
GenRelayInfo
(
c
)
relayInfo
:=
relaycommon
.
GenRelayInfo
Image
(
c
)
imageRequest
,
err
:=
getAndValidImageRequest
(
c
,
relayInfo
)
if
err
!=
nil
{
...
...
@@ -110,13 +110,11 @@ func ImageHelper(c *gin.Context) *dto.OpenAIErrorWithStatusCode {
return
service
.
OpenAIErrorWrapper
(
err
,
"invalid_image_request"
,
http
.
StatusBadRequest
)
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
imageRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
imageRequest
.
Model
=
relayInfo
.
UpstreamModelName
priceData
,
err
:=
helper
.
ModelPriceHelper
(
c
,
relayInfo
,
len
(
imageRequest
.
Prompt
),
0
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_price_error"
,
http
.
StatusInternalServerError
)
...
...
relay/relay-text.go
View file @
e8da9d7d
...
...
@@ -108,13 +108,11 @@ func TextHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode) {
}
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
textRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
textRequest
.
Model
=
relayInfo
.
UpstreamModelName
// 获取 promptTokens,如果上下文中已经存在,则直接使用
var
promptTokens
int
if
value
,
exists
:=
c
.
Get
(
"prompt_tokens"
);
exists
{
...
...
relay/re
lay_rerank
.go
→
relay/re
rank_handler
.go
View file @
e8da9d7d
...
...
@@ -42,13 +42,11 @@ func RerankHelper(c *gin.Context, relayMode int) (openaiErr *dto.OpenAIErrorWith
return
service
.
OpenAIErrorWrapperLocal
(
fmt
.
Errorf
(
"documents is empty"
),
"invalid_documents"
,
http
.
StatusBadRequest
)
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
rerankRequest
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusInternalServerError
)
}
rerankRequest
.
Model
=
relayInfo
.
UpstreamModelName
promptToken
:=
getRerankPromptToken
(
*
rerankRequest
)
relayInfo
.
PromptTokens
=
promptToken
...
...
relay/re
lay-responses
.go
→
relay/re
sponses_handler
.go
View file @
e8da9d7d
...
...
@@ -63,11 +63,11 @@ func ResponsesHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode)
}
}
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
)
err
=
helper
.
ModelMappedHelper
(
c
,
relayInfo
,
req
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapperLocal
(
err
,
"model_mapped_error"
,
http
.
StatusBadRequest
)
}
req
.
Model
=
relayInfo
.
UpstreamModelName
if
value
,
exists
:=
c
.
Get
(
"prompt_tokens"
);
exists
{
promptTokens
:=
value
.
(
int
)
relayInfo
.
SetPromptTokens
(
promptTokens
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment