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
d0d3142e
authored
May 15, 2023
by
JustSong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: able to test channels now (#59)
parent
bfcb9b88
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
133 additions
and
1 deletions
+133
-1
controller/channel.go
+99
-0
controller/relay.go
+13
-0
router/api-router.go
+1
-0
web/src/components/ChannelsTable.js
+20
-1
No files found.
controller/channel.go
View file @
d0d3142e
package
controller
import
(
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"one-api/common"
"one-api/model"
"strconv"
"strings"
"time"
)
func
GetAllChannels
(
c
*
gin
.
Context
)
{
...
...
@@ -153,3 +158,97 @@ func UpdateChannel(c *gin.Context) {
})
return
}
func
testChannel
(
channel
*
model
.
Channel
,
request
*
ChatRequest
)
error
{
if
request
.
Model
==
""
{
request
.
Model
=
"gpt-3.5-turbo"
if
channel
.
Type
==
common
.
ChannelTypeAzure
{
request
.
Model
=
"gpt-35-turbo"
}
}
requestURL
:=
common
.
ChannelBaseURLs
[
channel
.
Type
]
if
channel
.
Type
==
common
.
ChannelTypeAzure
{
requestURL
=
fmt
.
Sprintf
(
"%s/openai/deployments/%s/chat/completions?api-version=2023-03-15-preview"
,
channel
.
BaseURL
,
request
.
Model
)
}
else
{
if
channel
.
Type
==
common
.
ChannelTypeCustom
{
requestURL
=
channel
.
BaseURL
}
requestURL
+=
"/v1/chat/completions"
}
jsonData
,
err
:=
json
.
Marshal
(
request
)
if
err
!=
nil
{
return
err
}
req
,
err
:=
http
.
NewRequest
(
"POST"
,
requestURL
,
bytes
.
NewBuffer
(
jsonData
))
if
err
!=
nil
{
return
err
}
if
channel
.
Type
==
common
.
ChannelTypeAzure
{
req
.
Header
.
Set
(
"api-key"
,
channel
.
Key
)
}
else
{
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
channel
.
Key
)
}
req
.
Header
.
Set
(
"Content-Type"
,
"application/json"
)
client
:=
&
http
.
Client
{}
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
return
err
}
defer
resp
.
Body
.
Close
()
var
response
TextResponse
err
=
json
.
NewDecoder
(
resp
.
Body
)
.
Decode
(
&
response
)
if
err
!=
nil
{
return
err
}
if
response
.
Error
.
Type
!=
""
{
return
errors
.
New
(
fmt
.
Sprintf
(
"type %s, code %s, message %s"
,
response
.
Error
.
Type
,
response
.
Error
.
Code
,
response
.
Error
.
Message
))
}
return
nil
}
func
TestChannel
(
c
*
gin
.
Context
)
{
id
,
err
:=
strconv
.
Atoi
(
c
.
Param
(
"id"
))
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
channel
,
err
:=
model
.
GetChannelById
(
id
,
true
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
model_
:=
c
.
Query
(
"model"
)
chatRequest
:=
&
ChatRequest
{
Model
:
model_
,
}
testMessage
:=
Message
{
Role
:
"user"
,
Content
:
"echo hi"
,
}
chatRequest
.
Messages
=
append
(
chatRequest
.
Messages
,
testMessage
)
tik
:=
time
.
Now
()
err
=
testChannel
(
channel
,
chatRequest
)
tok
:=
time
.
Now
()
consumedTime
:=
float64
(
tok
.
Sub
(
tik
)
.
Milliseconds
())
/
1000.0
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
"time"
:
consumedTime
,
})
return
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"time"
:
consumedTime
,
})
return
}
controller/relay.go
View file @
d0d3142e
...
...
@@ -19,6 +19,11 @@ type Message struct {
Content
string
`json:"content"`
}
type
ChatRequest
struct
{
Model
string
`json:"model"`
Messages
[]
Message
`json:"messages"`
}
type
TextRequest
struct
{
Model
string
`json:"model"`
Messages
[]
Message
`json:"messages"`
...
...
@@ -32,8 +37,16 @@ type Usage struct {
TotalTokens
int
`json:"total_tokens"`
}
type
OpenAIError
struct
{
Message
string
`json:"message"`
Type
string
`json:"type"`
Param
string
`json:"param"`
Code
string
`json:"code"`
}
type
TextResponse
struct
{
Usage
`json:"usage"`
Error
OpenAIError
`json:"error"`
}
type
StreamResponse
struct
{
...
...
router/api-router.go
View file @
d0d3142e
...
...
@@ -63,6 +63,7 @@ func SetApiRouter(router *gin.Engine) {
channelRoute
.
GET
(
"/"
,
controller
.
GetAllChannels
)
channelRoute
.
GET
(
"/search"
,
controller
.
SearchChannels
)
channelRoute
.
GET
(
"/:id"
,
controller
.
GetChannel
)
channelRoute
.
GET
(
"/test/:id"
,
controller
.
TestChannel
)
channelRoute
.
POST
(
"/"
,
controller
.
AddChannel
)
channelRoute
.
PUT
(
"/"
,
controller
.
UpdateChannel
)
channelRoute
.
DELETE
(
"/:id"
,
controller
.
DeleteChannel
)
...
...
web/src/components/ChannelsTable.js
View file @
d0d3142e
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Form
,
Label
,
Pagination
,
Popup
,
Table
}
from
'semantic-ui-react'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
API
,
copy
,
showError
,
showSuccess
,
timestamp2string
}
from
'../helpers'
;
import
{
API
,
copy
,
showError
,
show
Info
,
show
Success
,
timestamp2string
}
from
'../helpers'
;
import
{
CHANNEL_OPTIONS
,
ITEMS_PER_PAGE
}
from
'../constants'
;
...
...
@@ -139,6 +139,16 @@ const ChannelsTable = () => {
setSearching
(
false
);
};
const
testChannel
=
async
(
id
,
name
)
=>
{
const
res
=
await
API
.
get
(
`/api/channel/test/
${
id
}
/`
);
const
{
success
,
message
,
time
}
=
res
.
data
;
if
(
success
)
{
showInfo
(
`通道
${
name
}
测试成功,耗时
${
time
}
秒。`
);
}
else
{
showError
(
message
);
}
}
const
handleKeywordChange
=
async
(
e
,
{
value
})
=>
{
setSearchKeyword
(
value
.
trim
());
};
...
...
@@ -244,6 +254,15 @@ const ChannelsTable = () => {
<
Table
.
Cell
>
{
renderTimestamp
(
channel
.
accessed_time
)}
<
/Table.Cell
>
<
Table
.
Cell
>
<
div
>
<
Button
size
=
{
'small'
}
positive
onClick
=
{()
=>
{
testChannel
(
channel
.
id
,
channel
.
name
);
}}
>
测试
<
/Button
>
<
Popup
trigger
=
{
<
Button
size
=
'small'
negative
>
...
...
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