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
8b55c9b9
authored
Jun 08, 2025
by
CaIon
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/alpha' into alpha
parents
e0993155
09c6c2c5
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
175 additions
and
23 deletions
+175
-23
relay/channel/ali/adaptor.go
+5
-1
relay/channel/ali/constants.go
+1
-0
relay/channel/ali/dto.go
+27
-0
relay/channel/ali/rerank.go
+83
-0
web/src/components/auth/PasswordResetConfirm.js
+48
-19
web/src/components/auth/PasswordResetForm.js
+4
-1
web/src/components/common/Loading.js
+1
-1
web/src/i18n/locales/en.json
+6
-1
No files found.
relay/channel/ali/adaptor.go
View file @
8b55c9b9
...
@@ -31,6 +31,8 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
...
@@ -31,6 +31,8 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
switch
info
.
RelayMode
{
switch
info
.
RelayMode
{
case
constant
.
RelayModeEmbeddings
:
case
constant
.
RelayModeEmbeddings
:
fullRequestURL
=
fmt
.
Sprintf
(
"%s/api/v1/services/embeddings/text-embedding/text-embedding"
,
info
.
BaseUrl
)
fullRequestURL
=
fmt
.
Sprintf
(
"%s/api/v1/services/embeddings/text-embedding/text-embedding"
,
info
.
BaseUrl
)
case
constant
.
RelayModeRerank
:
fullRequestURL
=
fmt
.
Sprintf
(
"%s/api/v1/services/rerank/text-rerank/text-rerank"
,
info
.
BaseUrl
)
case
constant
.
RelayModeImagesGenerations
:
case
constant
.
RelayModeImagesGenerations
:
fullRequestURL
=
fmt
.
Sprintf
(
"%s/api/v1/services/aigc/text2image/image-synthesis"
,
info
.
BaseUrl
)
fullRequestURL
=
fmt
.
Sprintf
(
"%s/api/v1/services/aigc/text2image/image-synthesis"
,
info
.
BaseUrl
)
case
constant
.
RelayModeCompletions
:
case
constant
.
RelayModeCompletions
:
...
@@ -76,7 +78,7 @@ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInf
...
@@ -76,7 +78,7 @@ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInf
}
}
func
(
a
*
Adaptor
)
ConvertRerankRequest
(
c
*
gin
.
Context
,
relayMode
int
,
request
dto
.
RerankRequest
)
(
any
,
error
)
{
func
(
a
*
Adaptor
)
ConvertRerankRequest
(
c
*
gin
.
Context
,
relayMode
int
,
request
dto
.
RerankRequest
)
(
any
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
return
ConvertRerankRequest
(
request
),
nil
}
}
func
(
a
*
Adaptor
)
ConvertEmbeddingRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
EmbeddingRequest
)
(
any
,
error
)
{
func
(
a
*
Adaptor
)
ConvertEmbeddingRequest
(
c
*
gin
.
Context
,
info
*
relaycommon
.
RelayInfo
,
request
dto
.
EmbeddingRequest
)
(
any
,
error
)
{
...
@@ -103,6 +105,8 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
...
@@ -103,6 +105,8 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
err
,
usage
=
aliImageHandler
(
c
,
resp
,
info
)
err
,
usage
=
aliImageHandler
(
c
,
resp
,
info
)
case
constant
.
RelayModeEmbeddings
:
case
constant
.
RelayModeEmbeddings
:
err
,
usage
=
aliEmbeddingHandler
(
c
,
resp
)
err
,
usage
=
aliEmbeddingHandler
(
c
,
resp
)
case
constant
.
RelayModeRerank
:
err
,
usage
=
RerankHandler
(
c
,
resp
,
info
)
default
:
default
:
if
info
.
IsStream
{
if
info
.
IsStream
{
err
,
usage
=
openai
.
OaiStreamHandler
(
c
,
resp
,
info
)
err
,
usage
=
openai
.
OaiStreamHandler
(
c
,
resp
,
info
)
...
...
relay/channel/ali/constants.go
View file @
8b55c9b9
...
@@ -8,6 +8,7 @@ var ModelList = []string{
...
@@ -8,6 +8,7 @@ var ModelList = []string{
"qwq-32b"
,
"qwq-32b"
,
"qwen3-235b-a22b"
,
"qwen3-235b-a22b"
,
"text-embedding-v1"
,
"text-embedding-v1"
,
"gte-rerank-v2"
,
}
}
var
ChannelName
=
"ali"
var
ChannelName
=
"ali"
relay/channel/ali/dto.go
View file @
8b55c9b9
package
ali
package
ali
import
"one-api/dto"
type
AliMessage
struct
{
type
AliMessage
struct
{
Content
string
`json:"content"`
Content
string
`json:"content"`
Role
string
`json:"role"`
Role
string
`json:"role"`
...
@@ -97,3 +99,28 @@ type AliImageRequest struct {
...
@@ -97,3 +99,28 @@ type AliImageRequest struct {
}
`json:"parameters,omitempty"`
}
`json:"parameters,omitempty"`
ResponseFormat
string
`json:"response_format,omitempty"`
ResponseFormat
string
`json:"response_format,omitempty"`
}
}
type
AliRerankParameters
struct
{
TopN
*
int
`json:"top_n,omitempty"`
ReturnDocuments
*
bool
`json:"return_documents,omitempty"`
}
type
AliRerankInput
struct
{
Query
string
`json:"query"`
Documents
[]
any
`json:"documents"`
}
type
AliRerankRequest
struct
{
Model
string
`json:"model"`
Input
AliRerankInput
`json:"input"`
Parameters
AliRerankParameters
`json:"parameters,omitempty"`
}
type
AliRerankResponse
struct
{
Output
struct
{
Results
[]
dto
.
RerankResponseResult
`json:"results"`
}
`json:"output"`
Usage
AliUsage
`json:"usage"`
RequestId
string
`json:"request_id"`
AliError
}
relay/channel/ali/rerank.go
0 → 100644
View file @
8b55c9b9
package
ali
import
(
"encoding/json"
"io"
"net/http"
"one-api/dto"
relaycommon
"one-api/relay/common"
"one-api/service"
"github.com/gin-gonic/gin"
)
func
ConvertRerankRequest
(
request
dto
.
RerankRequest
)
*
AliRerankRequest
{
returnDocuments
:=
request
.
ReturnDocuments
if
returnDocuments
==
nil
{
t
:=
true
returnDocuments
=
&
t
}
return
&
AliRerankRequest
{
Model
:
request
.
Model
,
Input
:
AliRerankInput
{
Query
:
request
.
Query
,
Documents
:
request
.
Documents
,
},
Parameters
:
AliRerankParameters
{
TopN
:
&
request
.
TopN
,
ReturnDocuments
:
returnDocuments
,
},
}
}
func
RerankHandler
(
c
*
gin
.
Context
,
resp
*
http
.
Response
,
info
*
relaycommon
.
RelayInfo
)
(
*
dto
.
OpenAIErrorWithStatusCode
,
*
dto
.
Usage
)
{
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"read_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
err
=
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
var
aliResponse
AliRerankResponse
err
=
json
.
Unmarshal
(
responseBody
,
&
aliResponse
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"unmarshal_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
if
aliResponse
.
Code
!=
""
{
return
&
dto
.
OpenAIErrorWithStatusCode
{
Error
:
dto
.
OpenAIError
{
Message
:
aliResponse
.
Message
,
Type
:
aliResponse
.
Code
,
Param
:
aliResponse
.
RequestId
,
Code
:
aliResponse
.
Code
,
},
StatusCode
:
resp
.
StatusCode
,
},
nil
}
usage
:=
dto
.
Usage
{
PromptTokens
:
aliResponse
.
Usage
.
TotalTokens
,
CompletionTokens
:
0
,
TotalTokens
:
aliResponse
.
Usage
.
TotalTokens
,
}
rerankResponse
:=
dto
.
RerankResponse
{
Results
:
aliResponse
.
Output
.
Results
,
Usage
:
usage
,
}
jsonResponse
,
err
:=
json
.
Marshal
(
rerankResponse
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"marshal_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
c
.
Writer
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
c
.
Writer
.
WriteHeader
(
resp
.
StatusCode
)
_
,
err
=
c
.
Writer
.
Write
(
jsonResponse
)
if
err
!=
nil
{
return
service
.
OpenAIErrorWrapper
(
err
,
"write_response_body_failed"
,
http
.
StatusInternalServerError
),
nil
}
return
nil
,
&
usage
}
web/src/components/auth/PasswordResetConfirm.js
View file @
8b55c9b9
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
API
,
copy
,
showError
,
showNotice
,
getLogo
,
getSystemName
}
from
'../../helpers'
;
import
{
API
,
copy
,
showError
,
showNotice
,
getLogo
,
getSystemName
}
from
'../../helpers'
;
import
{
useSearchParams
,
Link
}
from
'react-router-dom'
;
import
{
useSearchParams
,
Link
}
from
'react-router-dom'
;
import
{
Button
,
Card
,
Form
,
Typography
}
from
'@douyinfe/semi-ui'
;
import
{
Button
,
Card
,
Form
,
Typography
,
Banner
}
from
'@douyinfe/semi-ui'
;
import
{
IconMail
,
IconLock
}
from
'@douyinfe/semi-icons'
;
import
{
IconMail
,
IconLock
,
IconCopy
}
from
'@douyinfe/semi-icons'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
{
useTranslation
}
from
'react-i18next'
;
import
Background
from
'/example.png'
;
import
Background
from
'/example.png'
;
...
@@ -15,13 +15,14 @@ const PasswordResetConfirm = () => {
...
@@ -15,13 +15,14 @@ const PasswordResetConfirm = () => {
token
:
''
,
token
:
''
,
});
});
const
{
email
,
token
}
=
inputs
;
const
{
email
,
token
}
=
inputs
;
const
isValidResetLink
=
email
&&
token
;
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
disableButton
,
setDisableButton
]
=
useState
(
false
);
const
[
disableButton
,
setDisableButton
]
=
useState
(
false
);
const
[
countdown
,
setCountdown
]
=
useState
(
30
);
const
[
countdown
,
setCountdown
]
=
useState
(
30
);
const
[
newPassword
,
setNewPassword
]
=
useState
(
''
);
const
[
newPassword
,
setNewPassword
]
=
useState
(
''
);
const
[
searchParams
,
setSearchParams
]
=
useSearchParams
();
const
[
searchParams
,
setSearchParams
]
=
useSearchParams
();
const
[
formApi
,
setFormApi
]
=
useState
(
null
);
const
logo
=
getLogo
();
const
logo
=
getLogo
();
const
systemName
=
getSystemName
();
const
systemName
=
getSystemName
();
...
@@ -30,10 +31,16 @@ const PasswordResetConfirm = () => {
...
@@ -30,10 +31,16 @@ const PasswordResetConfirm = () => {
let
token
=
searchParams
.
get
(
'token'
);
let
token
=
searchParams
.
get
(
'token'
);
let
email
=
searchParams
.
get
(
'email'
);
let
email
=
searchParams
.
get
(
'email'
);
setInputs
({
setInputs
({
token
,
token
:
token
||
''
,
email
,
email
:
email
||
''
,
});
if
(
formApi
)
{
formApi
.
setValues
({
email
:
email
||
''
,
newPassword
:
newPassword
||
''
});
});
},
[]);
}
},
[
searchParams
,
newPassword
,
formApi
]);
useEffect
(()
=>
{
useEffect
(()
=>
{
let
countdownInterval
=
null
;
let
countdownInterval
=
null
;
...
@@ -49,7 +56,10 @@ const PasswordResetConfirm = () => {
...
@@ -49,7 +56,10 @@ const PasswordResetConfirm = () => {
},
[
disableButton
,
countdown
]);
},
[
disableButton
,
countdown
]);
async
function
handleSubmit
(
e
)
{
async
function
handleSubmit
(
e
)
{
if
(
!
email
||
!
token
)
return
;
if
(
!
email
||
!
token
)
{
showError
(
t
(
'无效的重置链接,请重新发起密码重置请求'
));
return
;
}
setDisableButton
(
true
);
setDisableButton
(
true
);
setLoading
(
true
);
setLoading
(
true
);
const
res
=
await
API
.
post
(
`/api/user/reset`
,
{
const
res
=
await
API
.
post
(
`/api/user/reset`
,
{
...
@@ -61,7 +71,7 @@ const PasswordResetConfirm = () => {
...
@@ -61,7 +71,7 @@ const PasswordResetConfirm = () => {
let
password
=
res
.
data
.
data
;
let
password
=
res
.
data
.
data
;
setNewPassword
(
password
);
setNewPassword
(
password
);
await
copy
(
password
);
await
copy
(
password
);
showNotice
(
`
${
t
(
'密码已重置并已复制到剪贴板
'
)}
:
${
password
}
`
);
showNotice
(
`
${
t
(
'密码已重置并已复制到剪贴板
:'
)}
${
password
}
`
);
}
else
{
}
else
{
showError
(
message
);
showError
(
message
);
}
}
...
@@ -94,16 +104,28 @@ const PasswordResetConfirm = () => {
...
@@ -94,16 +104,28 @@ const PasswordResetConfirm = () => {
<
Title
heading
=
{
3
}
className
=
"text-gray-800 dark:text-gray-200"
>
{
t
(
'密码重置确认'
)}
<
/Title
>
<
Title
heading
=
{
3
}
className
=
"text-gray-800 dark:text-gray-200"
>
{
t
(
'密码重置确认'
)}
<
/Title
>
<
/div
>
<
/div
>
<
div
className
=
"px-2 py-8"
>
<
div
className
=
"px-2 py-8"
>
<
Form
className
=
"space-y-3"
>
{
!
isValidResetLink
&&
(
<
Banner
type
=
"danger"
description
=
{
t
(
'无效的重置链接,请重新发起密码重置请求'
)}
className
=
"mb-4 !rounded-lg"
closeIcon
=
{
null
}
/
>
)}
<
Form
getFormApi
=
{(
api
)
=>
setFormApi
(
api
)}
initValues
=
{{
email
:
email
||
''
,
newPassword
:
newPassword
||
''
}}
className
=
"space-y-4"
>
<
Form
.
Input
<
Form
.
Input
field
=
"email"
field
=
"email"
label
=
{
t
(
'邮箱'
)}
label
=
{
t
(
'邮箱'
)}
name
=
"email"
name
=
"email"
size
=
"large"
size
=
"large"
className
=
"!rounded-md"
className
=
"!rounded-md"
value
=
{
email
}
disabled
=
{
true
}
readOnly
prefix
=
{
<
IconMail
/>
}
prefix
=
{
<
IconMail
/>
}
placeholder
=
{
email
?
''
:
t
(
'等待获取邮箱信息...'
)}
/
>
/
>
{
newPassword
&&
(
{
newPassword
&&
(
...
@@ -113,14 +135,21 @@ const PasswordResetConfirm = () => {
...
@@ -113,14 +135,21 @@ const PasswordResetConfirm = () => {
name
=
"newPassword"
name
=
"newPassword"
size
=
"large"
size
=
"large"
className
=
"!rounded-md"
className
=
"!rounded-md"
value
=
{
newPassword
}
disabled
=
{
true
}
readOnly
prefix
=
{
<
IconLock
/>
}
prefix
=
{
<
IconLock
/>
}
onClick
=
{(
e
)
=>
{
suffix
=
{
e
.
target
.
select
();
<
Button
navigator
.
clipboard
.
writeText
(
newPassword
);
icon
=
{
<
IconCopy
/>
}
showNotice
(
`
${
t
(
'密码已复制到剪贴板'
)}
:
${
newPassword
}
`
);
type
=
"tertiary"
theme
=
"borderless"
onClick
=
{
async
()
=>
{
await
copy
(
newPassword
);
showNotice
(
`
${
t
(
'密码已复制到剪贴板:'
)}
${
newPassword
}
`
);
}}
}}
>
{
t
(
'复制'
)}
<
/Button
>
}
/
>
/
>
)}
)}
...
@@ -133,9 +162,9 @@ const PasswordResetConfirm = () => {
...
@@ -133,9 +162,9 @@ const PasswordResetConfirm = () => {
size
=
"large"
size
=
"large"
onClick
=
{
handleSubmit
}
onClick
=
{
handleSubmit
}
loading
=
{
loading
}
loading
=
{
loading
}
disabled
=
{
disableButton
||
newPassword
}
disabled
=
{
disableButton
||
newPassword
||
!
isValidResetLink
}
>
>
{
newPassword
?
t
(
'密码重置完成'
)
:
t
(
'
提交
'
)}
{
newPassword
?
t
(
'密码重置完成'
)
:
t
(
'
确认重置密码
'
)}
<
/Button
>
<
/Button
>
<
/div
>
<
/div
>
<
/Form
>
<
/Form
>
...
...
web/src/components/auth/PasswordResetForm.js
View file @
8b55c9b9
...
@@ -55,7 +55,10 @@ const PasswordResetForm = () => {
...
@@ -55,7 +55,10 @@ const PasswordResetForm = () => {
}
}
async
function
handleSubmit
(
e
)
{
async
function
handleSubmit
(
e
)
{
if
(
!
email
)
return
;
if
(
!
email
)
{
showError
(
t
(
'请输入邮箱地址'
));
return
;
}
if
(
turnstileEnabled
&&
turnstileToken
===
''
)
{
if
(
turnstileEnabled
&&
turnstileToken
===
''
)
{
showInfo
(
t
(
'请稍后几秒重试,Turnstile 正在检查用户环境!'
));
showInfo
(
t
(
'请稍后几秒重试,Turnstile 正在检查用户环境!'
));
return
;
return
;
...
...
web/src/components/common/Loading.js
View file @
8b55c9b9
...
@@ -14,7 +14,7 @@ const Loading = ({ prompt: name = '', size = 'large' }) => {
...
@@ -14,7 +14,7 @@ const Loading = ({ prompt: name = '', size = 'large' }) => {
tip
=
{
null
}
tip
=
{
null
}
/
>
/
>
<
span
className
=
"whitespace-nowrap mt-2 text-center"
style
=
{{
color
:
'var(--semi-color-primary)'
}}
>
<
span
className
=
"whitespace-nowrap mt-2 text-center"
style
=
{{
color
:
'var(--semi-color-primary)'
}}
>
{
name
?
t
(
'
加载{{name}}中...
'
,
{
name
})
:
t
(
'加载中...'
)}
{
name
?
t
(
'
{{name}}
'
,
{
name
})
:
t
(
'加载中...'
)}
<
/span
>
<
/span
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
...
web/src/i18n/locales/en.json
View file @
8b55c9b9
...
@@ -265,10 +265,15 @@
...
@@ -265,10 +265,15 @@
"设置页脚"
:
"Set Footer"
,
"设置页脚"
:
"Set Footer"
,
"新版本"
:
"New Version"
,
"新版本"
:
"New Version"
,
"关闭"
:
"Close"
,
"关闭"
:
"Close"
,
"密码已重置并已复制到剪贴板"
:
"Password has been reset and copied to clipboard"
,
"密码已重置并已复制到剪贴板:"
:
"Password has been reset and copied to clipboard: "
,
"密码已复制到剪贴板:"
:
"Password has been copied to clipboard: "
,
"密码重置确认"
:
"Password Reset Confirmation"
,
"密码重置确认"
:
"Password Reset Confirmation"
,
"邮箱地址"
:
"Email address"
,
"邮箱地址"
:
"Email address"
,
"提交"
:
"Submit"
,
"提交"
:
"Submit"
,
"等待获取邮箱信息..."
:
"Waiting to get email information..."
,
"确认重置密码"
:
"Confirm Password Reset"
,
"无效的重置链接,请重新发起密码重置请求"
:
"Invalid reset link, please initiate a new password reset request"
,
"请输入邮箱地址"
:
"Please enter the email address"
,
"请稍后几秒重试"
:
"Please retry in a few seconds"
,
"请稍后几秒重试"
:
"Please retry in a few seconds"
,
"正在检查用户环境"
:
"Checking user environment"
,
"正在检查用户环境"
:
"Checking user environment"
,
"重置邮件发送成功"
:
"Reset mail sent successfully"
,
"重置邮件发送成功"
:
"Reset mail sent successfully"
,
...
...
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