Support custom channel now

This commit is contained in:
JustSong 2023-04-23 20:35:49 +08:00
parent 57379d8e92
commit b3be4d8f85
8 changed files with 55 additions and 8 deletions

View File

@ -46,6 +46,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
+ [x] [OpenAI-SB](https://openai-sb.com) + [x] [OpenAI-SB](https://openai-sb.com)
+ [x] [OpenAI Max](https://openaimax.com) + [x] [OpenAI Max](https://openaimax.com)
+ [x] [OhMyGPT](https://www.ohmygpt.com) + [x] [OhMyGPT](https://www.ohmygpt.com)
+ [x] 自定义渠道
2. 支持通过负载均衡的方式访问多个渠道。 2. 支持通过负载均衡的方式访问多个渠道。
3. 支持单个访问渠道设置多个 API Key利用起来你的多个 API Key。 3. 支持单个访问渠道设置多个 API Key利用起来你的多个 API Key。
4. 支持 HTTP SSE。 4. 支持 HTTP SSE。

View File

@ -106,6 +106,7 @@ const (
ChannelTypeOpenAISB = 5 ChannelTypeOpenAISB = 5
ChannelTypeOpenAIMax = 6 ChannelTypeOpenAIMax = 6
ChannelTypeOhMyGPT = 7 ChannelTypeOhMyGPT = 7
ChannelTypeCustom = 8
) )
var ChannelBaseURLs = []string{ var ChannelBaseURLs = []string{
@ -117,4 +118,5 @@ var ChannelBaseURLs = []string{
"https://api.openai-sb.com", // 5 "https://api.openai-sb.com", // 5
"https://api.openaimax.com", // 6 "https://api.openaimax.com", // 6
"https://api.ohmygpt.com", // 7 "https://api.ohmygpt.com", // 7
"", // 8
} }

View File

@ -11,6 +11,9 @@ import (
func Relay(c *gin.Context) { func Relay(c *gin.Context) {
channelType := c.GetInt("channel") channelType := c.GetInt("channel")
baseURL := common.ChannelBaseURLs[channelType] baseURL := common.ChannelBaseURLs[channelType]
if channelType == common.ChannelTypeCustom {
baseURL = c.GetString("base_url")
}
req, err := http.NewRequest(c.Request.Method, fmt.Sprintf("%s%s", baseURL, c.Request.URL.String()), c.Request.Body) req, err := http.NewRequest(c.Request.Method, fmt.Sprintf("%s%s", baseURL, c.Request.URL.String()), c.Request.Body)
if err != nil { if err != nil {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{

View File

@ -63,6 +63,9 @@ func Distribute() func(c *gin.Context) {
} }
c.Set("channel", channel.Type) c.Set("channel", channel.Type)
c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", channel.Key)) c.Request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", channel.Key))
if channel.Type == common.ChannelTypeCustom {
c.Set("base_url", channel.BaseURL)
}
c.Next() c.Next()
} }
} }

View File

@ -14,6 +14,7 @@ type Channel struct {
Weight int `json:"weight"` Weight int `json:"weight"`
CreatedTime int64 `json:"created_time" gorm:"bigint"` CreatedTime int64 `json:"created_time" gorm:"bigint"`
AccessedTime int64 `json:"accessed_time" gorm:"bigint"` AccessedTime int64 `json:"accessed_time" gorm:"bigint"`
BaseURL string `json:"base_url" gorm:"column:base_url"`
} }
func GetAllChannels(startIdx int, num int) ([]*Channel, error) { func GetAllChannels(startIdx int, num int) ([]*Channel, error) {

View File

@ -5,5 +5,6 @@ export const CHANNEL_OPTIONS = [
{ key: 4, text: 'CloseAI', value: 4, color: 'teal' }, { key: 4, text: 'CloseAI', value: 4, color: 'teal' },
{ key: 5, text: 'OpenAI-SB', value: 5, color: 'brown' }, { key: 5, text: 'OpenAI-SB', value: 5, color: 'brown' },
{ key: 6, text: 'OpenAI Max', value: 6, color: 'violet' }, { key: 6, text: 'OpenAI Max', value: 6, color: 'violet' },
{ key: 7, text: 'OhMyGPT', value: 7, color: 'purple' } { key: 7, text: 'OhMyGPT', value: 7, color: 'purple' },
{ key: 8, text: '自定义', value: 8, color: 'pink' }
]; ];

View File

@ -7,7 +7,8 @@ const AddChannel = () => {
const originInputs = { const originInputs = {
name: '', name: '',
type: 1, type: 1,
key: '' key: '',
base_url: '',
}; };
const [inputs, setInputs] = useState(originInputs); const [inputs, setInputs] = useState(originInputs);
const { name, type, key } = inputs; const { name, type, key } = inputs;
@ -18,6 +19,9 @@ const AddChannel = () => {
const submit = async () => { const submit = async () => {
if (inputs.name === '' || inputs.key === '') return; if (inputs.name === '' || inputs.key === '') return;
if (inputs.base_url.endsWith('/')) {
inputs.base_url = inputs.base_url.slice(0, inputs.base_url.length - 1);
}
const res = await API.post(`/api/channel/`, inputs); const res = await API.post(`/api/channel/`, inputs);
const { success, message } = res.data; const { success, message } = res.data;
if (success) { if (success) {
@ -42,6 +46,20 @@ const AddChannel = () => {
onChange={handleInputChange} onChange={handleInputChange}
/> />
</Form.Field> </Form.Field>
{
type === 8 && (
<Form.Field>
<Form.Input
label='Base URL'
name='base_url'
placeholder={'请输入自定义渠道的 Base URL'}
onChange={handleInputChange}
value={inputs.base_url}
autoComplete='off'
/>
</Form.Field>
)
}
<Form.Field> <Form.Field>
<Form.Input <Form.Input
label='名称' label='名称'

View File

@ -12,6 +12,7 @@ const EditChannel = () => {
name: '', name: '',
key: '', key: '',
type: 1, type: 1,
base_url: '',
}); });
const handleInputChange = (e, { name, value }) => { const handleInputChange = (e, { name, value }) => {
setInputs((inputs) => ({ ...inputs, [name]: value })); setInputs((inputs) => ({ ...inputs, [name]: value }));
@ -33,6 +34,9 @@ const EditChannel = () => {
}, []); }, []);
const submit = async () => { const submit = async () => {
if (inputs.base_url.endsWith('/')) {
inputs.base_url = inputs.base_url.slice(0, inputs.base_url.length - 1);
}
let res = await API.put(`/api/channel/`, { ...inputs, id: parseInt(channelId) }); let res = await API.put(`/api/channel/`, { ...inputs, id: parseInt(channelId) });
const { success, message } = res.data; const { success, message } = res.data;
if (success) { if (success) {
@ -56,6 +60,20 @@ const EditChannel = () => {
onChange={handleInputChange} onChange={handleInputChange}
/> />
</Form.Field> </Form.Field>
{
inputs.type === 8 && (
<Form.Field>
<Form.Input
label='Base URL'
name='base_url'
placeholder={'请输入新的自定义渠道的 Base URL'}
onChange={handleInputChange}
value={inputs.base_url}
autoComplete='off'
/>
</Form.Field>
)
}
<Form.Field> <Form.Field>
<Form.Input <Form.Input
label='名称' label='名称'