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
7b447708
authored
May 21, 2024
by
bubu
Browse files
Options
Browse Files
Download
Plain Diff
合并上游、支持已有渠道获取模型
parents
35349a8f
5bf8cb74
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
32 additions
and
74 deletions
+32
-74
common/model-ratio.go
+0
-0
relay/channel/openai/adaptor.go
+4
-4
web/src/components/ChannelsTable.js
+6
-6
web/src/components/LogsTable.js
+5
-2
web/src/components/ModelPricing.js
+3
-3
web/src/helpers/render.js
+2
-1
web/src/pages/Channel/EditChannel.js
+12
-58
No files found.
common/model-ratio.go
View file @
7b447708
This diff is collapsed.
Click to expand it.
relay/channel/openai/adaptor.go
View file @
7b447708
...
@@ -41,10 +41,10 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
...
@@ -41,10 +41,10 @@ func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
return
relaycommon
.
GetFullRequestURL
(
info
.
BaseUrl
,
requestURL
,
info
.
ChannelType
),
nil
return
relaycommon
.
GetFullRequestURL
(
info
.
BaseUrl
,
requestURL
,
info
.
ChannelType
),
nil
case
common
.
ChannelTypeMiniMax
:
case
common
.
ChannelTypeMiniMax
:
return
minimax
.
GetRequestURL
(
info
)
return
minimax
.
GetRequestURL
(
info
)
//
case common.ChannelTypeCustom:
case
common
.
ChannelTypeCustom
:
//
url := info.BaseUrl
url
:=
info
.
BaseUrl
//
url = strings.Replace(url, "{model}", info.UpstreamModelName, -1)
url
=
strings
.
Replace
(
url
,
"{model}"
,
info
.
UpstreamModelName
,
-
1
)
//
return url, nil
return
url
,
nil
default
:
default
:
return
relaycommon
.
GetFullRequestURL
(
info
.
BaseUrl
,
info
.
RequestURLPath
,
info
.
ChannelType
),
nil
return
relaycommon
.
GetFullRequestURL
(
info
.
BaseUrl
,
info
.
RequestURLPath
,
info
.
ChannelType
),
nil
}
}
...
...
web/src/components/ChannelsTable.js
View file @
7b447708
...
@@ -310,12 +310,12 @@ const ChannelsTable = () => {
...
@@ -310,12 +310,12 @@ const ChannelsTable = () => {
const
setChannelFormat
=
(
channels
)
=>
{
const
setChannelFormat
=
(
channels
)
=>
{
for
(
let
i
=
0
;
i
<
channels
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
channels
.
length
;
i
++
)
{
if
(
channels
[
i
].
type
===
8
)
{
//
if (channels[i].type === 8) {
showWarning
(
//
showWarning(
'检测到您使用了“自定义渠道”类型,请更换为“OpenAI”渠道类型!'
,
//
'检测到您使用了“自定义渠道”类型,请更换为“OpenAI”渠道类型!',
);
//
);
showWarning
(
'下个版本将不再支持“自定义渠道”类型!'
);
//
showWarning('下个版本将不再支持“自定义渠道”类型!');
}
//
}
channels
[
i
].
key
=
''
+
channels
[
i
].
id
;
channels
[
i
].
key
=
''
+
channels
[
i
].
id
;
let
test_models
=
[];
let
test_models
=
[];
channels
[
i
].
models
.
split
(
','
).
forEach
((
item
,
index
)
=>
{
channels
[
i
].
models
.
split
(
','
).
forEach
((
item
,
index
)
=>
{
...
...
web/src/components/LogsTable.js
View file @
7b447708
...
@@ -302,6 +302,9 @@ const LogsTable = () => {
...
@@ -302,6 +302,9 @@ const LogsTable = () => {
let
content
=
'渠道:'
+
record
.
channel
;
let
content
=
'渠道:'
+
record
.
channel
;
if
(
record
.
other
!==
''
)
{
if
(
record
.
other
!==
''
)
{
let
other
=
JSON
.
parse
(
record
.
other
);
let
other
=
JSON
.
parse
(
record
.
other
);
if
(
other
===
null
)
{
return
<><
/
>
}
if
(
other
.
admin_info
!==
undefined
)
{
if
(
other
.
admin_info
!==
undefined
)
{
if
(
if
(
other
.
admin_info
.
use_channel
!==
null
&&
other
.
admin_info
.
use_channel
!==
null
&&
...
@@ -322,7 +325,8 @@ const LogsTable = () => {
...
@@ -322,7 +325,8 @@ const LogsTable = () => {
title
:
'详情'
,
title
:
'详情'
,
dataIndex
:
'content'
,
dataIndex
:
'content'
,
render
:
(
text
,
record
,
index
)
=>
{
render
:
(
text
,
record
,
index
)
=>
{
if
(
record
.
other
===
''
)
{
let
other
=
JSON
.
parse
(
record
.
other
);
if
(
other
==
null
)
{
return
(
return
(
<
Paragraph
<
Paragraph
ellipsis
=
{{
ellipsis
=
{{
...
@@ -338,7 +342,6 @@ const LogsTable = () => {
...
@@ -338,7 +342,6 @@ const LogsTable = () => {
<
/Paragraph
>
<
/Paragraph
>
);
);
}
}
let
other
=
JSON
.
parse
(
record
.
other
);
let
content
=
renderModelPrice
(
let
content
=
renderModelPrice
(
record
.
prompt_tokens
,
record
.
prompt_tokens
,
record
.
completion_tokens
,
record
.
completion_tokens
,
...
...
web/src/components/ModelPricing.js
View file @
7b447708
...
@@ -146,11 +146,11 @@ const ModelPricing = () => {
...
@@ -146,11 +146,11 @@ const ModelPricing = () => {
render
:
(
text
,
record
,
index
)
=>
{
render
:
(
text
,
record
,
index
)
=>
{
let
content
=
text
;
let
content
=
text
;
if
(
record
.
quota_type
===
0
)
{
if
(
record
.
quota_type
===
0
)
{
let
inputRatioPrice
=
record
.
model_ratio
*
2.0
*
record
.
group_ratio
;
// 这里的 *2 是因为 1倍率=0.002刀,请勿删除
let
inputRatioPrice
=
record
.
model_ratio
*
2
*
record
.
group_ratio
;
let
completionRatioPrice
=
let
completionRatioPrice
=
record
.
model_ratio
*
record
.
model_ratio
*
record
.
completion_ratio
*
record
.
completion_ratio
*
2
*
2.0
*
record
.
group_ratio
;
record
.
group_ratio
;
content
=
(
content
=
(
<>
<>
...
...
web/src/helpers/render.js
View file @
7b447708
...
@@ -149,8 +149,9 @@ export function renderModelPrice(
...
@@ -149,8 +149,9 @@ export function renderModelPrice(
if
(
completionRatio
===
undefined
)
{
if
(
completionRatio
===
undefined
)
{
completionRatio
=
0
;
completionRatio
=
0
;
}
}
// 这里的 *2 是因为 1倍率=0.002刀,请勿删除
let
inputRatioPrice
=
modelRatio
*
2.0
*
groupRatio
;
let
inputRatioPrice
=
modelRatio
*
2.0
*
groupRatio
;
let
completionRatioPrice
=
modelRatio
*
completionRatio
*
2.0
*
groupRatio
;
let
completionRatioPrice
=
modelRatio
*
2.0
*
completionRatio
*
groupRatio
;
let
price
=
let
price
=
(
inputTokens
/
1000000
)
*
inputRatioPrice
+
(
inputTokens
/
1000000
)
*
inputRatioPrice
+
(
completionTokens
/
1000000
)
*
completionRatioPrice
;
(
completionTokens
/
1000000
)
*
completionRatioPrice
;
...
...
web/src/pages/Channel/EditChannel.js
View file @
7b447708
...
@@ -37,8 +37,6 @@ const STATUS_CODE_MAPPING_EXAMPLE = {
...
@@ -37,8 +37,6 @@ const STATUS_CODE_MAPPING_EXAMPLE = {
400
:
'500'
,
400
:
'500'
,
};
};
const
fetchButtonTips
=
"1. 新建渠道时,请求通过当前浏览器发出;2. 编辑已有渠道,请求通过后端服务器发出"
function
type2secretPrompt
(
type
)
{
function
type2secretPrompt
(
type
)
{
// inputs.type === 15 ? '按照如下格式输入:APIKey|SecretKey' : (inputs.type === 18 ? '按照如下格式输入:APPID|APISecret|APIKey' : '请输入渠道对应的鉴权密钥')
// inputs.type === 15 ? '按照如下格式输入:APIKey|SecretKey' : (inputs.type === 18 ? '按照如下格式输入:APPID|APISecret|APIKey' : '请输入渠道对应的鉴权密钥')
switch
(
type
)
{
switch
(
type
)
{
...
@@ -90,55 +88,6 @@ const EditChannel = (props) => {
...
@@ -90,55 +88,6 @@ const EditChannel = (props) => {
const
[
basicModels
,
setBasicModels
]
=
useState
([]);
const
[
basicModels
,
setBasicModels
]
=
useState
([]);
const
[
fullModels
,
setFullModels
]
=
useState
([]);
const
[
fullModels
,
setFullModels
]
=
useState
([]);
const
[
customModel
,
setCustomModel
]
=
useState
(
''
);
const
[
customModel
,
setCustomModel
]
=
useState
(
''
);
const
fetchUpstreamModelList
=
async
(
name
)
=>
{
if
(
inputs
[
"type"
]
!==
1
)
{
showError
(
"仅支持 OpenAI 接口格式"
)
return
;
}
const
models
=
inputs
[
"models"
]
||
[]
let
err
=
false
;
if
(
isEdit
)
{
const
res
=
await
API
.
get
(
"/api/channel/fetch_models/"
+
channelId
)
if
(
res
.
data
&&
res
.
data
?.
success
)
{
models
.
push
(...
res
.
data
.
data
)
}
else
{
err
=
true
}
}
else
{
if
(
!
inputs
?.[
"key"
])
{
showError
(
"请填写密钥"
)
return
;
}
try
{
const
host
=
new
URL
((
inputs
[
"base_url"
]
||
"https://api.openai.com"
))
const
url
=
`https://
${
host
.
hostname
}
/v1/models`
;
const
key
=
inputs
[
"key"
];
const
res
=
await
axios
.
get
(
url
,
{
headers
:
{
'Authorization'
:
`Bearer
${
key
}
`
}
})
if
(
res
.
data
&&
res
.
data
?.
success
)
{
models
.
push
(...
es
.
data
.
data
.
map
((
model
)
=>
model
.
id
))
}
else
{
err
=
true
}
}
catch
(
error
)
{
err
=
true
}
}
if
(
!
err
)
{
handleInputChange
(
name
,
Array
.
from
(
new
Set
(
models
)));
showSuccess
(
"获取模型列表成功"
);
}
else
{
showError
(
'获取模型列表失败'
);
}
}
const
handleInputChange
=
(
name
,
value
)
=>
{
const
handleInputChange
=
(
name
,
value
)
=>
{
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
if
(
name
===
'type'
)
{
if
(
name
===
'type'
)
{
...
@@ -284,7 +233,7 @@ const EditChannel = (props) => {
...
@@ -284,7 +233,7 @@ const EditChannel = (props) => {
fetchModels
().
then
();
fetchModels
().
then
();
fetchGroups
().
then
();
fetchGroups
().
then
();
if
(
isEdit
)
{
if
(
isEdit
)
{
loadChannel
().
then
(()
=>
{
});
loadChannel
().
then
(()
=>
{});
}
else
{
}
else
{
setInputs
(
originInputs
);
setInputs
(
originInputs
);
let
localModels
=
getChannelModels
(
inputs
.
type
);
let
localModels
=
getChannelModels
(
inputs
.
type
);
...
@@ -354,17 +303,18 @@ const EditChannel = (props) => {
...
@@ -354,17 +303,18 @@ const EditChannel = (props) => {
const
addCustomModels
=
()
=>
{
const
addCustomModels
=
()
=>
{
if
(
customModel
.
trim
()
===
''
)
return
;
if
(
customModel
.
trim
()
===
''
)
return
;
// 使用逗号分隔字符串,然后去除每个模型名称前后的空格
// 使用逗号分隔字符串,然后去除每个模型名称前后的空格
const
modelArray
=
customModel
.
split
(
','
).
map
(
model
=>
model
.
trim
());
const
modelArray
=
customModel
.
split
(
','
).
map
(
(
model
)
=>
model
.
trim
());
let
localModels
=
[...
inputs
.
models
];
let
localModels
=
[...
inputs
.
models
];
let
localModelOptions
=
[...
modelOptions
];
let
localModelOptions
=
[...
modelOptions
];
let
hasError
=
false
;
let
hasError
=
false
;
modelArray
.
forEach
(
model
=>
{
modelArray
.
forEach
(
(
model
)
=>
{
// 检查模型是否已存在,且模型名称非空
// 检查模型是否已存在,且模型名称非空
if
(
model
&&
!
localModels
.
includes
(
model
))
{
if
(
model
&&
!
localModels
.
includes
(
model
))
{
localModels
.
push
(
model
);
// 添加到模型列表
localModels
.
push
(
model
);
// 添加到模型列表
localModelOptions
.
push
({
// 添加到下拉选项
localModelOptions
.
push
({
// 添加到下拉选项
key
:
model
,
key
:
model
,
text
:
model
,
text
:
model
,
value
:
model
,
value
:
model
,
...
@@ -486,11 +436,15 @@ const EditChannel = (props) => {
...
@@ -486,11 +436,15 @@ const EditChannel = (props) => {
{
inputs
.
type
===
8
&&
(
{
inputs
.
type
===
8
&&
(
<>
<>
<
div
style
=
{{
marginTop
:
10
}}
>
<
div
style
=
{{
marginTop
:
10
}}
>
<
Typography
.
Text
strong
>
Base
URL
:
<
/Typography.Text
>
<
Typography
.
Text
strong
>
完整的
Base
URL
,支持变量
{
'{model}'
}
:
<
/Typography.Text
>
<
/div
>
<
/div
>
<
Input
<
Input
name
=
'base_url'
name
=
'base_url'
placeholder
=
{
'请输入自定义渠道的 Base URL'
}
placeholder
=
{
'请输入完整的URL,例如:https://api.openai.com/v1/chat/completions'
}
onChange
=
{(
value
)
=>
{
onChange
=
{(
value
)
=>
{
handleInputChange
(
'base_url'
,
value
);
handleInputChange
(
'base_url'
,
value
);
}}
}}
...
@@ -723,7 +677,7 @@ const EditChannel = (props) => {
...
@@ -723,7 +677,7 @@ const EditChannel = (props) => {
onChange
=
{()
=>
{
onChange
=
{()
=>
{
setAutoBan
(
!
autoBan
);
setAutoBan
(
!
autoBan
);
}}
}}
// onChange={handleInputChange}
// onChange={handleInputChange}
/
>
/
>
<
Typography
.
Text
strong
>
<
Typography
.
Text
strong
>
是否自动禁用(仅当自动禁用开启时有效),关闭后不会自动禁用该渠道:
是否自动禁用(仅当自动禁用开启时有效),关闭后不会自动禁用该渠道:
...
...
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