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
3379ea5e
authored
Jul 22, 2023
by
JustSong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support claude now (close #150)
parent
cfd220cf
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
285 additions
and
14 deletions
+285
-14
README.md
+1
-0
common/constants.go
+2
-0
common/model-ratio.go
+2
-0
controller/model.go
+18
-0
controller/relay-claude.go
+40
-0
controller/relay-text.go
+197
-10
controller/relay.go
+24
-4
web/src/constants/channel.constants.js
+1
-0
No files found.
README.md
View file @
3379ea5e
...
@@ -60,6 +60,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
...
@@ -60,6 +60,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
## 功能
## 功能
1.
支持多种 API 访问渠道:
1.
支持多种 API 访问渠道:
+
[
x
]
OpenAI 官方通道(支持配置镜像)
+
[
x
]
OpenAI 官方通道(支持配置镜像)
+
[
x
]
[
Anthropic Claude 系列模型
]
(https://anthropic.com)
+
[
x
]
**Azure OpenAI API**
+
[
x
]
**Azure OpenAI API**
+
[
x
]
[
API Distribute
]
(https://api.gptjk.top/register?aff=QGxj)
+
[
x
]
[
API Distribute
]
(https://api.gptjk.top/register?aff=QGxj)
+
[
x
]
[
OpenAI-SB
]
(https://openai-sb.com)
+
[
x
]
[
OpenAI-SB
]
(https://openai-sb.com)
...
...
common/constants.go
View file @
3379ea5e
...
@@ -151,6 +151,7 @@ const (
...
@@ -151,6 +151,7 @@ const (
ChannelTypePaLM
=
11
ChannelTypePaLM
=
11
ChannelTypeAPI2GPT
=
12
ChannelTypeAPI2GPT
=
12
ChannelTypeAIGC2D
=
13
ChannelTypeAIGC2D
=
13
ChannelTypeAnthropic
=
14
)
)
var
ChannelBaseURLs
=
[]
string
{
var
ChannelBaseURLs
=
[]
string
{
...
@@ -168,4 +169,5 @@ var ChannelBaseURLs = []string{
...
@@ -168,4 +169,5 @@ var ChannelBaseURLs = []string{
""
,
// 11
""
,
// 11
"https://api.api2gpt.com"
,
// 12
"https://api.api2gpt.com"
,
// 12
"https://api.aigc2d.com"
,
// 13
"https://api.aigc2d.com"
,
// 13
"https://api.anthropic.com"
,
// 14
}
}
common/model-ratio.go
View file @
3379ea5e
...
@@ -36,6 +36,8 @@ var ModelRatio = map[string]float64{
...
@@ -36,6 +36,8 @@ var ModelRatio = map[string]float64{
"text-moderation-stable"
:
0.1
,
"text-moderation-stable"
:
0.1
,
"text-moderation-latest"
:
0.1
,
"text-moderation-latest"
:
0.1
,
"dall-e"
:
8
,
"dall-e"
:
8
,
"claude-instant-1"
:
0.75
,
"claude-2"
:
30
,
}
}
func
ModelRatio2JSONString
()
string
{
func
ModelRatio2JSONString
()
string
{
...
...
controller/model.go
View file @
3379ea5e
...
@@ -270,6 +270,24 @@ func init() {
...
@@ -270,6 +270,24 @@ func init() {
Root
:
"ChatGLM2"
,
Root
:
"ChatGLM2"
,
Parent
:
nil
,
Parent
:
nil
,
},
},
{
Id
:
"claude-instant-1"
,
Object
:
"model"
,
Created
:
1677649963
,
OwnedBy
:
"anturopic"
,
Permission
:
permission
,
Root
:
"claude-instant-1"
,
Parent
:
nil
,
},
{
Id
:
"claude-2"
,
Object
:
"model"
,
Created
:
1677649963
,
OwnedBy
:
"anturopic"
,
Permission
:
permission
,
Root
:
"claude-2"
,
Parent
:
nil
,
},
}
}
openAIModelsMap
=
make
(
map
[
string
]
OpenAIModels
)
openAIModelsMap
=
make
(
map
[
string
]
OpenAIModels
)
for
_
,
model
:=
range
openAIModels
{
for
_
,
model
:=
range
openAIModels
{
...
...
controller/relay-claude.go
0 → 100644
View file @
3379ea5e
package
controller
type
ClaudeMetadata
struct
{
UserId
string
`json:"user_id"`
}
type
ClaudeRequest
struct
{
Model
string
`json:"model"`
Prompt
string
`json:"prompt"`
MaxTokensToSample
int
`json:"max_tokens_to_sample"`
StopSequences
[]
string
`json:"stop_sequences,omitempty"`
Temperature
float64
`json:"temperature,omitempty"`
TopP
float64
`json:"top_p,omitempty"`
TopK
int
`json:"top_k,omitempty"`
//ClaudeMetadata `json:"metadata,omitempty"`
Stream
bool
`json:"stream,omitempty"`
}
type
ClaudeError
struct
{
Type
string
`json:"type"`
Message
string
`json:"message"`
}
type
ClaudeResponse
struct
{
Completion
string
`json:"completion"`
StopReason
string
`json:"stop_reason"`
Model
string
`json:"model"`
Error
ClaudeError
`json:"error"`
}
func
stopReasonClaude2OpenAI
(
reason
string
)
string
{
switch
reason
{
case
"stop_sequence"
:
return
"stop"
case
"max_tokens"
:
return
"length"
default
:
return
reason
}
}
controller/relay-text.go
View file @
3379ea5e
...
@@ -15,6 +15,12 @@ import (
...
@@ -15,6 +15,12 @@ import (
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
)
const
(
APITypeOpenAI
=
iota
APITypeClaude
APITypePaLM
)
func
relayTextHelper
(
c
*
gin
.
Context
,
relayMode
int
)
*
OpenAIErrorWithStatusCode
{
func
relayTextHelper
(
c
*
gin
.
Context
,
relayMode
int
)
*
OpenAIErrorWithStatusCode
{
channelType
:=
c
.
GetInt
(
"channel"
)
channelType
:=
c
.
GetInt
(
"channel"
)
tokenId
:=
c
.
GetInt
(
"token_id"
)
tokenId
:=
c
.
GetInt
(
"token_id"
)
...
@@ -71,12 +77,18 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -71,12 +77,18 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
isModelMapped
=
true
isModelMapped
=
true
}
}
}
}
apiType
:=
APITypeOpenAI
if
strings
.
HasPrefix
(
textRequest
.
Model
,
"claude"
)
{
apiType
=
APITypeClaude
}
baseURL
:=
common
.
ChannelBaseURLs
[
channelType
]
baseURL
:=
common
.
ChannelBaseURLs
[
channelType
]
requestURL
:=
c
.
Request
.
URL
.
String
()
requestURL
:=
c
.
Request
.
URL
.
String
()
if
c
.
GetString
(
"base_url"
)
!=
""
{
if
c
.
GetString
(
"base_url"
)
!=
""
{
baseURL
=
c
.
GetString
(
"base_url"
)
baseURL
=
c
.
GetString
(
"base_url"
)
}
}
fullRequestURL
:=
fmt
.
Sprintf
(
"%s%s"
,
baseURL
,
requestURL
)
fullRequestURL
:=
fmt
.
Sprintf
(
"%s%s"
,
baseURL
,
requestURL
)
switch
apiType
{
case
APITypeOpenAI
:
if
channelType
==
common
.
ChannelTypeAzure
{
if
channelType
==
common
.
ChannelTypeAzure
{
// https://learn.microsoft.com/en-us/azure/cognitive-services/openai/chatgpt-quickstart?pivots=rest-api&tabs=command-line#rest-api
// https://learn.microsoft.com/en-us/azure/cognitive-services/openai/chatgpt-quickstart?pivots=rest-api&tabs=command-line#rest-api
query
:=
c
.
Request
.
URL
.
Query
()
query
:=
c
.
Request
.
URL
.
Query
()
...
@@ -95,9 +107,12 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -95,9 +107,12 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
model_
=
strings
.
TrimSuffix
(
model_
,
"-0314"
)
model_
=
strings
.
TrimSuffix
(
model_
,
"-0314"
)
model_
=
strings
.
TrimSuffix
(
model_
,
"-0613"
)
model_
=
strings
.
TrimSuffix
(
model_
,
"-0613"
)
fullRequestURL
=
fmt
.
Sprintf
(
"%s/openai/deployments/%s/%s"
,
baseURL
,
model_
,
task
)
fullRequestURL
=
fmt
.
Sprintf
(
"%s/openai/deployments/%s/%s"
,
baseURL
,
model_
,
task
)
}
else
if
channelType
==
common
.
ChannelTypePaLM
{
}
err
:=
relayPaLM
(
textRequest
,
c
)
case
APITypeClaude
:
return
err
fullRequestURL
=
"https://api.anthropic.com/v1/complete"
if
baseURL
!=
""
{
fullRequestURL
=
fmt
.
Sprintf
(
"%s/v1/complete"
,
baseURL
)
}
}
}
var
promptTokens
int
var
promptTokens
int
var
completionTokens
int
var
completionTokens
int
...
@@ -142,17 +157,59 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -142,17 +157,59 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
}
else
{
}
else
{
requestBody
=
c
.
Request
.
Body
requestBody
=
c
.
Request
.
Body
}
}
switch
apiType
{
case
APITypeClaude
:
claudeRequest
:=
ClaudeRequest
{
Model
:
textRequest
.
Model
,
Prompt
:
""
,
MaxTokensToSample
:
textRequest
.
MaxTokens
,
StopSequences
:
nil
,
Temperature
:
textRequest
.
Temperature
,
TopP
:
textRequest
.
TopP
,
Stream
:
textRequest
.
Stream
,
}
if
claudeRequest
.
MaxTokensToSample
==
0
{
claudeRequest
.
MaxTokensToSample
=
1000000
}
prompt
:=
""
for
_
,
message
:=
range
textRequest
.
Messages
{
if
message
.
Role
==
"user"
{
prompt
+=
fmt
.
Sprintf
(
"
\n\n
Human: %s"
,
message
.
Content
)
}
else
if
message
.
Role
==
"assistant"
{
prompt
+=
fmt
.
Sprintf
(
"
\n\n
Assistant: %s"
,
message
.
Content
)
}
else
{
// ignore other roles
}
prompt
+=
"
\n\n
Assistant:"
}
claudeRequest
.
Prompt
=
prompt
jsonStr
,
err
:=
json
.
Marshal
(
claudeRequest
)
if
err
!=
nil
{
return
errorWrapper
(
err
,
"marshal_text_request_failed"
,
http
.
StatusInternalServerError
)
}
requestBody
=
bytes
.
NewBuffer
(
jsonStr
)
}
req
,
err
:=
http
.
NewRequest
(
c
.
Request
.
Method
,
fullRequestURL
,
requestBody
)
req
,
err
:=
http
.
NewRequest
(
c
.
Request
.
Method
,
fullRequestURL
,
requestBody
)
if
err
!=
nil
{
if
err
!=
nil
{
return
errorWrapper
(
err
,
"new_request_failed"
,
http
.
StatusInternalServerError
)
return
errorWrapper
(
err
,
"new_request_failed"
,
http
.
StatusInternalServerError
)
}
}
apiKey
:=
c
.
Request
.
Header
.
Get
(
"Authorization"
)
apiKey
=
strings
.
TrimPrefix
(
apiKey
,
"Bearer "
)
switch
apiType
{
case
APITypeOpenAI
:
if
channelType
==
common
.
ChannelTypeAzure
{
if
channelType
==
common
.
ChannelTypeAzure
{
key
:=
c
.
Request
.
Header
.
Get
(
"Authorization"
)
req
.
Header
.
Set
(
"api-key"
,
apiKey
)
key
=
strings
.
TrimPrefix
(
key
,
"Bearer "
)
req
.
Header
.
Set
(
"api-key"
,
key
)
}
else
{
}
else
{
req
.
Header
.
Set
(
"Authorization"
,
c
.
Request
.
Header
.
Get
(
"Authorization"
))
req
.
Header
.
Set
(
"Authorization"
,
c
.
Request
.
Header
.
Get
(
"Authorization"
))
}
}
case
APITypeClaude
:
req
.
Header
.
Set
(
"x-api-key"
,
apiKey
)
anthropicVersion
:=
c
.
Request
.
Header
.
Get
(
"anthropic-version"
)
if
anthropicVersion
==
""
{
anthropicVersion
=
"2023-06-01"
}
req
.
Header
.
Set
(
"anthropic-version"
,
anthropicVersion
)
}
req
.
Header
.
Set
(
"Content-Type"
,
c
.
Request
.
Header
.
Get
(
"Content-Type"
))
req
.
Header
.
Set
(
"Content-Type"
,
c
.
Request
.
Header
.
Get
(
"Content-Type"
))
req
.
Header
.
Set
(
"Accept"
,
c
.
Request
.
Header
.
Get
(
"Accept"
))
req
.
Header
.
Set
(
"Accept"
,
c
.
Request
.
Header
.
Get
(
"Accept"
))
//req.Header.Set("Connection", c.Request.Header.Get("Connection"))
//req.Header.Set("Connection", c.Request.Header.Get("Connection"))
...
@@ -219,22 +276,20 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -219,22 +276,20 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
}
}
}
}
}()
}()
switch
apiType
{
case
APITypeOpenAI
:
if
isStream
{
if
isStream
{
scanner
:=
bufio
.
NewScanner
(
resp
.
Body
)
scanner
:=
bufio
.
NewScanner
(
resp
.
Body
)
scanner
.
Split
(
func
(
data
[]
byte
,
atEOF
bool
)
(
advance
int
,
token
[]
byte
,
err
error
)
{
scanner
.
Split
(
func
(
data
[]
byte
,
atEOF
bool
)
(
advance
int
,
token
[]
byte
,
err
error
)
{
if
atEOF
&&
len
(
data
)
==
0
{
if
atEOF
&&
len
(
data
)
==
0
{
return
0
,
nil
,
nil
return
0
,
nil
,
nil
}
}
if
i
:=
strings
.
Index
(
string
(
data
),
"
\n
"
);
i
>=
0
{
if
i
:=
strings
.
Index
(
string
(
data
),
"
\n
"
);
i
>=
0
{
return
i
+
1
,
data
[
0
:
i
],
nil
return
i
+
1
,
data
[
0
:
i
],
nil
}
}
if
atEOF
{
if
atEOF
{
return
len
(
data
),
data
,
nil
return
len
(
data
),
data
,
nil
}
}
return
0
,
nil
,
nil
return
0
,
nil
,
nil
})
})
dataChan
:=
make
(
chan
string
)
dataChan
:=
make
(
chan
string
)
...
@@ -339,4 +394,136 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -339,4 +394,136 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
}
}
return
nil
return
nil
}
}
case
APITypeClaude
:
if
isStream
{
responseId
:=
fmt
.
Sprintf
(
"chatcmpl-%s"
,
common
.
GetUUID
())
createdTime
:=
common
.
GetTimestamp
()
scanner
:=
bufio
.
NewScanner
(
resp
.
Body
)
scanner
.
Split
(
func
(
data
[]
byte
,
atEOF
bool
)
(
advance
int
,
token
[]
byte
,
err
error
)
{
if
atEOF
&&
len
(
data
)
==
0
{
return
0
,
nil
,
nil
}
if
i
:=
strings
.
Index
(
string
(
data
),
"
\r\n\r\n
"
);
i
>=
0
{
return
i
+
4
,
data
[
0
:
i
],
nil
}
if
atEOF
{
return
len
(
data
),
data
,
nil
}
return
0
,
nil
,
nil
})
dataChan
:=
make
(
chan
string
)
stopChan
:=
make
(
chan
bool
)
go
func
()
{
for
scanner
.
Scan
()
{
data
:=
scanner
.
Text
()
if
!
strings
.
HasPrefix
(
data
,
"event: completion"
)
{
continue
}
data
=
strings
.
TrimPrefix
(
data
,
"event: completion
\r\n
data: "
)
dataChan
<-
data
}
stopChan
<-
true
}()
c
.
Writer
.
Header
()
.
Set
(
"Content-Type"
,
"text/event-stream"
)
c
.
Writer
.
Header
()
.
Set
(
"Cache-Control"
,
"no-cache"
)
c
.
Writer
.
Header
()
.
Set
(
"Connection"
,
"keep-alive"
)
c
.
Writer
.
Header
()
.
Set
(
"Transfer-Encoding"
,
"chunked"
)
c
.
Writer
.
Header
()
.
Set
(
"X-Accel-Buffering"
,
"no"
)
c
.
Stream
(
func
(
w
io
.
Writer
)
bool
{
select
{
case
data
:=
<-
dataChan
:
// some implementations may add \r at the end of data
data
=
strings
.
TrimSuffix
(
data
,
"
\r
"
)
var
claudeResponse
ClaudeResponse
err
=
json
.
Unmarshal
([]
byte
(
data
),
&
claudeResponse
)
if
err
!=
nil
{
common
.
SysError
(
"error unmarshalling stream response: "
+
err
.
Error
())
return
true
}
streamResponseText
+=
claudeResponse
.
Completion
var
choice
ChatCompletionsStreamResponseChoice
choice
.
Delta
.
Content
=
claudeResponse
.
Completion
choice
.
FinishReason
=
stopReasonClaude2OpenAI
(
claudeResponse
.
StopReason
)
var
response
ChatCompletionsStreamResponse
response
.
Id
=
responseId
response
.
Created
=
createdTime
response
.
Object
=
"chat.completion.chunk"
response
.
Model
=
textRequest
.
Model
response
.
Choices
=
[]
ChatCompletionsStreamResponseChoice
{
choice
}
jsonStr
,
err
:=
json
.
Marshal
(
response
)
if
err
!=
nil
{
common
.
SysError
(
"error marshalling stream response: "
+
err
.
Error
())
return
true
}
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
"data: "
+
string
(
jsonStr
)})
return
true
case
<-
stopChan
:
c
.
Render
(
-
1
,
common
.
CustomEvent
{
Data
:
"data: [DONE]"
})
return
false
}
})
err
=
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
errorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
)
}
return
nil
}
else
{
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
errorWrapper
(
err
,
"read_response_body_failed"
,
http
.
StatusInternalServerError
)
}
err
=
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
errorWrapper
(
err
,
"close_response_body_failed"
,
http
.
StatusInternalServerError
)
}
var
claudeResponse
ClaudeResponse
err
=
json
.
Unmarshal
(
responseBody
,
&
claudeResponse
)
if
err
!=
nil
{
return
errorWrapper
(
err
,
"unmarshal_response_body_failed"
,
http
.
StatusInternalServerError
)
}
if
claudeResponse
.
Error
.
Type
!=
""
{
return
&
OpenAIErrorWithStatusCode
{
OpenAIError
:
OpenAIError
{
Message
:
claudeResponse
.
Error
.
Message
,
Type
:
claudeResponse
.
Error
.
Type
,
Param
:
""
,
Code
:
claudeResponse
.
Error
.
Type
,
},
StatusCode
:
resp
.
StatusCode
,
}
}
choice
:=
OpenAITextResponseChoice
{
Index
:
0
,
Message
:
Message
{
Role
:
"assistant"
,
Content
:
strings
.
TrimPrefix
(
claudeResponse
.
Completion
,
" "
),
Name
:
nil
,
},
FinishReason
:
stopReasonClaude2OpenAI
(
claudeResponse
.
StopReason
),
}
completionTokens
:=
countTokenText
(
claudeResponse
.
Completion
,
textRequest
.
Model
)
fullTextResponse
:=
OpenAITextResponse
{
Id
:
fmt
.
Sprintf
(
"chatcmpl-%s"
,
common
.
GetUUID
()),
Object
:
"chat.completion"
,
Created
:
common
.
GetTimestamp
(),
Choices
:
[]
OpenAITextResponseChoice
{
choice
},
Usage
:
Usage
{
PromptTokens
:
promptTokens
,
CompletionTokens
:
completionTokens
,
TotalTokens
:
promptTokens
+
promptTokens
,
},
}
textResponse
.
Usage
=
fullTextResponse
.
Usage
jsonResponse
,
err
:=
json
.
Marshal
(
fullTextResponse
)
if
err
!=
nil
{
return
errorWrapper
(
err
,
"marshal_response_body_failed"
,
http
.
StatusInternalServerError
)
}
c
.
Writer
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
c
.
Writer
.
WriteHeader
(
resp
.
StatusCode
)
_
,
err
=
c
.
Writer
.
Write
(
jsonResponse
)
return
nil
}
default
:
return
errorWrapper
(
errors
.
New
(
"unknown api type"
),
"unknown_api_type"
,
http
.
StatusInternalServerError
)
}
}
}
controller/relay.go
View file @
3379ea5e
...
@@ -85,6 +85,20 @@ type TextResponse struct {
...
@@ -85,6 +85,20 @@ type TextResponse struct {
Error
OpenAIError
`json:"error"`
Error
OpenAIError
`json:"error"`
}
}
type
OpenAITextResponseChoice
struct
{
Index
int
`json:"index"`
Message
`json:"message"`
FinishReason
string
`json:"finish_reason"`
}
type
OpenAITextResponse
struct
{
Id
string
`json:"id"`
Object
string
`json:"object"`
Created
int64
`json:"created"`
Choices
[]
OpenAITextResponseChoice
`json:"choices"`
Usage
`json:"usage"`
}
type
ImageResponse
struct
{
type
ImageResponse
struct
{
Created
int
`json:"created"`
Created
int
`json:"created"`
Data
[]
struct
{
Data
[]
struct
{
...
@@ -92,13 +106,19 @@ type ImageResponse struct {
...
@@ -92,13 +106,19 @@ type ImageResponse struct {
}
}
}
}
type
ChatCompletionsStreamResponse
struct
{
type
ChatCompletionsStreamResponseChoice
struct
{
Choices
[]
struct
{
Delta
struct
{
Delta
struct
{
Content
string
`json:"content"`
Content
string
`json:"content"`
}
`json:"delta"`
}
`json:"delta"`
FinishReason
string
`json:"finish_reason"`
FinishReason
string
`json:"finish_reason,omitempty"`
}
`json:"choices"`
}
type
ChatCompletionsStreamResponse
struct
{
Id
string
`json:"id"`
Object
string
`json:"object"`
Created
int64
`json:"created"`
Model
string
`json:"model"`
Choices
[]
ChatCompletionsStreamResponseChoice
`json:"choices"`
}
}
type
CompletionsStreamResponse
struct
{
type
CompletionsStreamResponse
struct
{
...
...
web/src/constants/channel.constants.js
View file @
3379ea5e
export
const
CHANNEL_OPTIONS
=
[
export
const
CHANNEL_OPTIONS
=
[
{
key
:
1
,
text
:
'OpenAI'
,
value
:
1
,
color
:
'green'
},
{
key
:
1
,
text
:
'OpenAI'
,
value
:
1
,
color
:
'green'
},
{
key
:
14
,
text
:
'Anthropic'
,
value
:
14
,
color
:
'black'
},
{
key
:
8
,
text
:
'自定义'
,
value
:
8
,
color
:
'pink'
},
{
key
:
8
,
text
:
'自定义'
,
value
:
8
,
color
:
'pink'
},
{
key
:
3
,
text
:
'Azure'
,
value
:
3
,
color
:
'olive'
},
{
key
:
3
,
text
:
'Azure'
,
value
:
3
,
color
:
'olive'
},
{
key
:
2
,
text
:
'API2D'
,
value
:
2
,
color
:
'blue'
},
{
key
:
2
,
text
:
'API2D'
,
value
:
2
,
color
:
'blue'
},
...
...
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