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
e0d9a419
authored
Jul 28, 2025
by
t0ng7u
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/alpha' into alpha
parents
e85bf7b1
10f025ea
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
21 additions
and
1 deletions
+21
-1
relay/relay-text.go
+3
-0
setting/rate_limit.go
+4
-0
web/src/helpers/render.js
+11
-1
web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.js
+3
-0
No files found.
relay/relay-text.go
View file @
e0d9a419
...
@@ -517,6 +517,9 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
...
@@ -517,6 +517,9 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo,
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"total tokens is 0, cannot consume quota, userId %d, channelId %d, "
+
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"total tokens is 0, cannot consume quota, userId %d, channelId %d, "
+
"tokenId %d, model %s, pre-consumed quota %d"
,
relayInfo
.
UserId
,
relayInfo
.
ChannelId
,
relayInfo
.
TokenId
,
modelName
,
preConsumedQuota
))
"tokenId %d, model %s, pre-consumed quota %d"
,
relayInfo
.
UserId
,
relayInfo
.
ChannelId
,
relayInfo
.
TokenId
,
modelName
,
preConsumedQuota
))
}
else
{
}
else
{
if
!
ratio
.
IsZero
()
&&
quota
==
0
{
quota
=
1
}
model
.
UpdateUserUsedQuotaAndRequestCount
(
relayInfo
.
UserId
,
quota
)
model
.
UpdateUserUsedQuotaAndRequestCount
(
relayInfo
.
UserId
,
quota
)
model
.
UpdateChannelUsedQuota
(
relayInfo
.
ChannelId
,
quota
)
model
.
UpdateChannelUsedQuota
(
relayInfo
.
ChannelId
,
quota
)
}
}
...
...
setting/rate_limit.go
View file @
e0d9a419
...
@@ -3,6 +3,7 @@ package setting
...
@@ -3,6 +3,7 @@ package setting
import
(
import
(
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"math"
"one-api/common"
"one-api/common"
"sync"
"sync"
)
)
...
@@ -58,6 +59,9 @@ func CheckModelRequestRateLimitGroup(jsonStr string) error {
...
@@ -58,6 +59,9 @@ func CheckModelRequestRateLimitGroup(jsonStr string) error {
if
limits
[
0
]
<
0
||
limits
[
1
]
<
1
{
if
limits
[
0
]
<
0
||
limits
[
1
]
<
1
{
return
fmt
.
Errorf
(
"group %s has negative rate limit values: [%d, %d]"
,
group
,
limits
[
0
],
limits
[
1
])
return
fmt
.
Errorf
(
"group %s has negative rate limit values: [%d, %d]"
,
group
,
limits
[
0
],
limits
[
1
])
}
}
if
limits
[
0
]
>
math
.
MaxInt32
||
limits
[
1
]
>
math
.
MaxInt32
{
return
fmt
.
Errorf
(
"group %s [%d, %d] has max rate limits value 2147483647"
,
group
,
limits
[
0
],
limits
[
1
])
}
}
}
return
nil
return
nil
...
...
web/src/helpers/render.js
View file @
e0d9a419
...
@@ -883,12 +883,22 @@ export function renderQuotaWithAmount(amount) {
...
@@ -883,12 +883,22 @@ export function renderQuotaWithAmount(amount) {
}
}
export
function
renderQuota
(
quota
,
digits
=
2
)
{
export
function
renderQuota
(
quota
,
digits
=
2
)
{
let
quotaPerUnit
=
localStorage
.
getItem
(
'quota_per_unit'
);
let
quotaPerUnit
=
localStorage
.
getItem
(
'quota_per_unit'
);
let
displayInCurrency
=
localStorage
.
getItem
(
'display_in_currency'
);
let
displayInCurrency
=
localStorage
.
getItem
(
'display_in_currency'
);
quotaPerUnit
=
parseFloat
(
quotaPerUnit
);
quotaPerUnit
=
parseFloat
(
quotaPerUnit
);
displayInCurrency
=
displayInCurrency
===
'true'
;
displayInCurrency
=
displayInCurrency
===
'true'
;
if
(
displayInCurrency
)
{
if
(
displayInCurrency
)
{
return
'$'
+
(
quota
/
quotaPerUnit
).
toFixed
(
digits
);
const
result
=
quota
/
quotaPerUnit
;
const
fixedResult
=
result
.
toFixed
(
digits
);
// 如果 toFixed 后结果为 0 但原始值不为 0,显示最小值
if
(
parseFloat
(
fixedResult
)
===
0
&&
quota
>
0
&&
result
>
0
)
{
const
minValue
=
Math
.
pow
(
10
,
-
digits
);
return
'$'
+
minValue
.
toFixed
(
digits
);
}
return
'$'
+
fixedResult
;
}
}
return
renderNumber
(
quota
);
return
renderNumber
(
quota
);
}
}
...
...
web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.js
View file @
e0d9a419
...
@@ -147,6 +147,7 @@ export default function RequestRateLimit(props) {
...
@@ -147,6 +147,7 @@ export default function RequestRateLimit(props) {
label
=
{
t
(
'用户每周期最多请求次数'
)}
label
=
{
t
(
'用户每周期最多请求次数'
)}
step
=
{
1
}
step
=
{
1
}
min
=
{
0
}
min
=
{
0
}
max
=
{
100000000
}
suffix
=
{
t
(
'次'
)}
suffix
=
{
t
(
'次'
)}
extraText
=
{
t
(
'包括失败请求的次数,0代表不限制'
)}
extraText
=
{
t
(
'包括失败请求的次数,0代表不限制'
)}
field
=
{
'ModelRequestRateLimitCount'
}
field
=
{
'ModelRequestRateLimitCount'
}
...
@@ -163,6 +164,7 @@ export default function RequestRateLimit(props) {
...
@@ -163,6 +164,7 @@ export default function RequestRateLimit(props) {
label
=
{
t
(
'用户每周期最多请求完成次数'
)}
label
=
{
t
(
'用户每周期最多请求完成次数'
)}
step
=
{
1
}
step
=
{
1
}
min
=
{
1
}
min
=
{
1
}
max
=
{
100000000
}
suffix
=
{
t
(
'次'
)}
suffix
=
{
t
(
'次'
)}
extraText
=
{
t
(
'只包括请求成功的次数'
)}
extraText
=
{
t
(
'只包括请求成功的次数'
)}
field
=
{
'ModelRequestRateLimitSuccessCount'
}
field
=
{
'ModelRequestRateLimitSuccessCount'
}
...
@@ -199,6 +201,7 @@ export default function RequestRateLimit(props) {
...
@@ -199,6 +201,7 @@ export default function RequestRateLimit(props) {
<
li
>
{
t
(
'使用 JSON 对象格式,格式为:{"组名": [最多请求次数, 最多请求完成次数]}'
)}
<
/li
>
<
li
>
{
t
(
'使用 JSON 对象格式,格式为:{"组名": [最多请求次数, 最多请求完成次数]}'
)}
<
/li
>
<
li
>
{
t
(
'示例:{"default": [200, 100], "vip": [0, 1000]}。'
)}
<
/li
>
<
li
>
{
t
(
'示例:{"default": [200, 100], "vip": [0, 1000]}。'
)}
<
/li
>
<
li
>
{
t
(
'[最多请求次数]必须大于等于0,[最多请求完成次数]必须大于等于1。'
)}
<
/li
>
<
li
>
{
t
(
'[最多请求次数]必须大于等于0,[最多请求完成次数]必须大于等于1。'
)}
<
/li
>
<
li
>
{
t
(
'[最多请求次数]和[最多请求完成次数]的最大值为2147483647。'
)}
<
/li
>
<
li
>
{
t
(
'分组速率配置优先级高于全局速率限制。'
)}
<
/li
>
<
li
>
{
t
(
'分组速率配置优先级高于全局速率限制。'
)}
<
/li
>
<
li
>
{
t
(
'限制周期统一使用上方配置的“限制周期”值。'
)}
<
/li
>
<
li
>
{
t
(
'限制周期统一使用上方配置的“限制周期”值。'
)}
<
/li
>
<
/ul
>
<
/ul
>
...
...
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