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
38791fa4
authored
Jan 20, 2026
by
Seefs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: log shows request conversion
parent
db11bfdb
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
151 additions
and
18 deletions
+151
-18
model/log.go
+2
-1
relay/chat_completions_via_responses.go
+2
-0
relay/claude_handler.go
+1
-0
relay/common/relay_info.go
+63
-14
relay/common/request_conversion.go
+40
-0
relay/compatible_handler.go
+1
-0
relay/embedding_handler.go
+1
-0
relay/gemini_handler.go
+1
-0
relay/image_handler.go
+1
-0
relay/rerank_handler.go
+1
-0
relay/responses_handler.go
+1
-0
service/log_info_generate.go
+21
-0
web/src/hooks/usage-logs/useUsageLogsData.jsx
+10
-3
web/src/i18n/locales/en.json
+3
-0
web/src/i18n/locales/zh.json
+3
-0
No files found.
model/log.go
View file @
38791fa4
...
...
@@ -56,8 +56,9 @@ func formatUserLogs(logs []*Log) {
var
otherMap
map
[
string
]
interface
{}
otherMap
,
_
=
common
.
StrToMap
(
logs
[
i
]
.
Other
)
if
otherMap
!=
nil
{
//
delete admin
//
Remove admin-only debug fields.
delete
(
otherMap
,
"admin_info"
)
delete
(
otherMap
,
"request_conversion"
)
}
logs
[
i
]
.
Other
=
common
.
MapToJsonStr
(
otherMap
)
logs
[
i
]
.
Id
=
logs
[
i
]
.
Id
%
1024
...
...
relay/chat_completions_via_responses.go
View file @
38791fa4
...
...
@@ -97,6 +97,7 @@ func chatCompletionsViaResponses(c *gin.Context, info *relaycommon.RelayInfo, ad
if
err
!=
nil
{
return
nil
,
types
.
NewErrorWithStatusCode
(
err
,
types
.
ErrorCodeInvalidRequest
,
http
.
StatusBadRequest
,
types
.
ErrOptionWithSkipRetry
())
}
info
.
AppendRequestConversion
(
types
.
RelayFormatOpenAIResponses
)
savedRelayMode
:=
info
.
RelayMode
savedRequestURLPath
:=
info
.
RequestURLPath
...
...
@@ -112,6 +113,7 @@ func chatCompletionsViaResponses(c *gin.Context, info *relaycommon.RelayInfo, ad
if
err
!=
nil
{
return
nil
,
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
...
...
relay/claude_handler.go
View file @
38791fa4
...
...
@@ -110,6 +110,7 @@ func ClaudeHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *typ
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
...
...
relay/common/relay_info.go
View file @
38791fa4
...
...
@@ -121,6 +121,10 @@ type RelayInfo struct {
Request
dto
.
Request
// RequestConversionChain records request format conversions in order, e.g.
// ["openai", "openai_responses"] or ["openai", "claude"].
RequestConversionChain
[]
types
.
RelayFormat
ThinkingContentInfo
TokenCountMeta
*
ClaudeConvertInfo
...
...
@@ -448,38 +452,83 @@ func genBaseRelayInfo(c *gin.Context, request dto.Request) *RelayInfo {
}
func
GenRelayInfo
(
c
*
gin
.
Context
,
relayFormat
types
.
RelayFormat
,
request
dto
.
Request
,
ws
*
websocket
.
Conn
)
(
*
RelayInfo
,
error
)
{
var
info
*
RelayInfo
var
err
error
switch
relayFormat
{
case
types
.
RelayFormatOpenAI
:
return
GenRelayInfoOpenAI
(
c
,
request
),
nil
info
=
GenRelayInfoOpenAI
(
c
,
request
)
case
types
.
RelayFormatOpenAIAudio
:
return
GenRelayInfoOpenAIAudio
(
c
,
request
),
nil
info
=
GenRelayInfoOpenAIAudio
(
c
,
request
)
case
types
.
RelayFormatOpenAIImage
:
return
GenRelayInfoImage
(
c
,
request
),
nil
info
=
GenRelayInfoImage
(
c
,
request
)
case
types
.
RelayFormatOpenAIRealtime
:
return
GenRelayInfoWs
(
c
,
ws
),
nil
info
=
GenRelayInfoWs
(
c
,
ws
)
case
types
.
RelayFormatClaude
:
return
GenRelayInfoClaude
(
c
,
request
),
nil
info
=
GenRelayInfoClaude
(
c
,
request
)
case
types
.
RelayFormatRerank
:
if
request
,
ok
:=
request
.
(
*
dto
.
RerankRequest
);
ok
{
return
GenRelayInfoRerank
(
c
,
request
),
nil
info
=
GenRelayInfoRerank
(
c
,
request
)
break
}
return
nil
,
errors
.
New
(
"request is not a RerankRequest"
)
err
=
errors
.
New
(
"request is not a RerankRequest"
)
case
types
.
RelayFormatGemini
:
return
GenRelayInfoGemini
(
c
,
request
),
nil
info
=
GenRelayInfoGemini
(
c
,
request
)
case
types
.
RelayFormatEmbedding
:
return
GenRelayInfoEmbedding
(
c
,
request
),
nil
info
=
GenRelayInfoEmbedding
(
c
,
request
)
case
types
.
RelayFormatOpenAIResponses
:
if
request
,
ok
:=
request
.
(
*
dto
.
OpenAIResponsesRequest
);
ok
{
return
GenRelayInfoResponses
(
c
,
request
),
nil
info
=
GenRelayInfoResponses
(
c
,
request
)
break
}
return
nil
,
errors
.
New
(
"request is not a OpenAIResponsesRequest"
)
err
=
errors
.
New
(
"request is not a OpenAIResponsesRequest"
)
case
types
.
RelayFormatTask
:
return
genBaseRelayInfo
(
c
,
nil
),
nil
info
=
genBaseRelayInfo
(
c
,
nil
)
case
types
.
RelayFormatMjProxy
:
return
genBaseRelayInfo
(
c
,
nil
),
nil
info
=
genBaseRelayInfo
(
c
,
nil
)
default
:
return
nil
,
errors
.
New
(
"invalid relay format"
)
err
=
errors
.
New
(
"invalid relay format"
)
}
if
err
!=
nil
{
return
nil
,
err
}
if
info
==
nil
{
return
nil
,
errors
.
New
(
"failed to build relay info"
)
}
info
.
InitRequestConversionChain
()
return
info
,
nil
}
func
(
info
*
RelayInfo
)
InitRequestConversionChain
()
{
if
info
==
nil
{
return
}
if
len
(
info
.
RequestConversionChain
)
>
0
{
return
}
if
info
.
RelayFormat
==
""
{
return
}
info
.
RequestConversionChain
=
[]
types
.
RelayFormat
{
info
.
RelayFormat
}
}
func
(
info
*
RelayInfo
)
AppendRequestConversion
(
format
types
.
RelayFormat
)
{
if
info
==
nil
{
return
}
if
format
==
""
{
return
}
if
len
(
info
.
RequestConversionChain
)
==
0
{
info
.
RequestConversionChain
=
[]
types
.
RelayFormat
{
format
}
return
}
last
:=
info
.
RequestConversionChain
[
len
(
info
.
RequestConversionChain
)
-
1
]
if
last
==
format
{
return
}
info
.
RequestConversionChain
=
append
(
info
.
RequestConversionChain
,
format
)
}
//func (info *RelayInfo) SetPromptTokens(promptTokens int) {
...
...
relay/common/request_conversion.go
0 → 100644
View file @
38791fa4
package
common
import
(
"github.com/QuantumNous/new-api/dto"
"github.com/QuantumNous/new-api/types"
)
func
GuessRelayFormatFromRequest
(
req
any
)
(
types
.
RelayFormat
,
bool
)
{
switch
req
.
(
type
)
{
case
*
dto
.
GeneralOpenAIRequest
,
dto
.
GeneralOpenAIRequest
:
return
types
.
RelayFormatOpenAI
,
true
case
*
dto
.
OpenAIResponsesRequest
,
dto
.
OpenAIResponsesRequest
:
return
types
.
RelayFormatOpenAIResponses
,
true
case
*
dto
.
ClaudeRequest
,
dto
.
ClaudeRequest
:
return
types
.
RelayFormatClaude
,
true
case
*
dto
.
GeminiChatRequest
,
dto
.
GeminiChatRequest
:
return
types
.
RelayFormatGemini
,
true
case
*
dto
.
EmbeddingRequest
,
dto
.
EmbeddingRequest
:
return
types
.
RelayFormatEmbedding
,
true
case
*
dto
.
RerankRequest
,
dto
.
RerankRequest
:
return
types
.
RelayFormatRerank
,
true
case
*
dto
.
ImageRequest
,
dto
.
ImageRequest
:
return
types
.
RelayFormatOpenAIImage
,
true
case
*
dto
.
AudioRequest
,
dto
.
AudioRequest
:
return
types
.
RelayFormatOpenAIAudio
,
true
default
:
return
""
,
false
}
}
func
AppendRequestConversionFromRequest
(
info
*
RelayInfo
,
req
any
)
{
if
info
==
nil
{
return
}
format
,
ok
:=
GuessRelayFormatFromRequest
(
req
)
if
!
ok
{
return
}
info
.
AppendRequestConversion
(
format
)
}
relay/compatible_handler.go
View file @
38791fa4
...
...
@@ -113,6 +113,7 @@ func TextHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *types
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
if
info
.
ChannelSetting
.
SystemPrompt
!=
""
{
// 如果有系统提示,则将其添加到请求中
...
...
relay/embedding_handler.go
View file @
38791fa4
...
...
@@ -45,6 +45,7 @@ func EmbeddingHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
json
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
...
...
relay/gemini_handler.go
View file @
38791fa4
...
...
@@ -149,6 +149,7 @@ func GeminiHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *typ
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
...
...
relay/image_handler.go
View file @
38791fa4
...
...
@@ -57,6 +57,7 @@ func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *type
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
)
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
switch
convertedRequest
.
(
type
)
{
case
*
bytes
.
Buffer
:
...
...
relay/rerank_handler.go
View file @
38791fa4
...
...
@@ -53,6 +53,7 @@ func RerankHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *typ
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
...
...
relay/responses_handler.go
View file @
38791fa4
...
...
@@ -53,6 +53,7 @@ func ResponsesHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
}
relaycommon
.
AppendRequestConversionFromRequest
(
info
,
convertedRequest
)
jsonData
,
err
:=
common
.
Marshal
(
convertedRequest
)
if
err
!=
nil
{
return
types
.
NewError
(
err
,
types
.
ErrorCodeConvertRequestFailed
,
types
.
ErrOptionWithSkipRetry
())
...
...
service/log_info_generate.go
View file @
38791fa4
...
...
@@ -70,9 +70,30 @@ func GenerateTextOtherInfo(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, m
other
[
"admin_info"
]
=
adminInfo
appendRequestPath
(
ctx
,
relayInfo
,
other
)
appendRequestConversionChain
(
relayInfo
,
other
)
return
other
}
func
appendRequestConversionChain
(
relayInfo
*
relaycommon
.
RelayInfo
,
other
map
[
string
]
interface
{})
{
if
relayInfo
==
nil
||
other
==
nil
{
return
}
if
len
(
relayInfo
.
RequestConversionChain
)
==
0
{
return
}
chain
:=
make
([]
string
,
0
,
len
(
relayInfo
.
RequestConversionChain
))
for
_
,
f
:=
range
relayInfo
.
RequestConversionChain
{
if
f
==
""
{
continue
}
chain
=
append
(
chain
,
string
(
f
))
}
if
len
(
chain
)
==
0
{
return
}
other
[
"request_conversion"
]
=
chain
}
func
GenerateWssOtherInfo
(
ctx
*
gin
.
Context
,
relayInfo
*
relaycommon
.
RelayInfo
,
usage
*
dto
.
RealtimeUsage
,
modelRatio
,
groupRatio
,
completionRatio
,
audioRatio
,
audioCompletionRatio
,
modelPrice
,
userGroupRatio
float64
)
map
[
string
]
interface
{}
{
info
:=
GenerateTextOtherInfo
(
ctx
,
relayInfo
,
modelRatio
,
groupRatio
,
completionRatio
,
0
,
0.0
,
modelPrice
,
userGroupRatio
)
info
[
"ws"
]
=
true
...
...
web/src/hooks/usage-logs/useUsageLogsData.jsx
View file @
38791fa4
...
...
@@ -476,10 +476,17 @@ export const useLogsData = () => {
});
}
}
if
(
other
?.
request_path
)
{
if
(
isAdminUser
)
{
const
requestConversionChain
=
other
?.
request_conversion
;
const
chain
=
Array
.
isArray
(
requestConversionChain
)
?
requestConversionChain
.
filter
(
Boolean
)
:
[];
expandDataLocal
.
push
({
key
:
t
(
'请求路径'
),
value
:
other
.
request_path
,
key
:
t
(
'请求转换'
),
value
:
chain
.
length
>
1
?
`
${
chain
.
join
(
' -> '
)}
`
:
t
(
'原生格式'
),
});
}
if
(
isAdminUser
)
{
...
...
web/src/i18n/locales/en.json
View file @
38791fa4
...
...
@@ -2091,6 +2091,9 @@
"请求结束后多退少补"
:
"Adjust after request completion"
,
"请求超时,请刷新页面后重新发起 GitHub 登录"
:
"Request timed out, please refresh and restart GitHub login"
,
"请求路径"
:
"Request path"
,
"请求转换"
:
"Request conversion"
,
"原生格式"
:
"Native format"
,
"转换"
:
"Convert"
,
"请求预扣费额度"
:
"Pre-deduction quota for requests"
,
"请点击我"
:
"Please click me"
,
"请确认以下设置信息,点击
\"
初始化系统
\"
开始配置"
:
"Please confirm the following settings information, click
\"
Initialize system
\"
to start configuration"
,
...
...
web/src/i18n/locales/zh.json
View file @
38791fa4
...
...
@@ -2077,6 +2077,9 @@
"请求结束后多退少补"
:
"请求结束后多退少补"
,
"请求超时,请刷新页面后重新发起 GitHub 登录"
:
"请求超时,请刷新页面后重新发起 GitHub 登录"
,
"请求路径"
:
"请求路径"
,
"请求转换"
:
"请求转换"
,
"原生格式"
:
"原生格式"
,
"转换"
:
"转换"
,
"请求预扣费额度"
:
"请求预扣费额度"
,
"请点击我"
:
"请点击我"
,
"请确认以下设置信息,点击
\"
初始化系统
\"
开始配置"
:
"请确认以下设置信息,点击
\"
初始化系统
\"
开始配置"
,
...
...
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