diff --git a/common/utils/array.go b/common/utils/array.go new file mode 100644 index 00000000..72437d4f --- /dev/null +++ b/common/utils/array.go @@ -0,0 +1,13 @@ +package utils + +func DeDuplication(slice []string) []string { + m := make(map[string]bool) + for _, v := range slice { + m[v] = true + } + result := make([]string, 0, len(m)) + for v := range m { + result = append(result, v) + } + return result +} diff --git a/model/ability.go b/model/ability.go index 2db72518..5cfb9949 100644 --- a/model/ability.go +++ b/model/ability.go @@ -2,10 +2,13 @@ package model import ( "context" - "github.com/songquanpeng/one-api/common" - "gorm.io/gorm" "sort" "strings" + + "gorm.io/gorm" + + "github.com/songquanpeng/one-api/common" + "github.com/songquanpeng/one-api/common/utils" ) type Ability struct { @@ -49,6 +52,7 @@ func GetRandomSatisfiedChannel(group string, model string, ignoreFirstPriority b func (channel *Channel) AddAbilities() error { models_ := strings.Split(channel.Models, ",") + models_ = utils.DeDuplication(models_) groups_ := strings.Split(channel.Group, ",") abilities := make([]Ability, 0, len(models_)) for _, model := range models_ { diff --git a/relay/adaptor/baiduv2/constants.go b/relay/adaptor/baiduv2/constants.go new file mode 100644 index 00000000..aad9e584 --- /dev/null +++ b/relay/adaptor/baiduv2/constants.go @@ -0,0 +1,30 @@ +package baiduv2 + +// https://console.bce.baidu.com/support/?_=1692863460488×tamp=1739074632076#/api?product=QIANFAN&project=%E5%8D%83%E5%B8%86ModelBuilder&parent=%E5%AF%B9%E8%AF%9DChat%20V2&api=v2%2Fchat%2Fcompletions&method=post +// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu#%E6%94%AF%E6%8C%81%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8 + +var ModelList = []string{ + "ernie-4.0-8k-latest", + "ernie-4.0-8k-preview", + "ernie-4.0-8k", + "ernie-4.0-turbo-8k-latest", + "ernie-4.0-turbo-8k-preview", + "ernie-4.0-turbo-8k", + "ernie-4.0-turbo-128k", + "ernie-3.5-8k-preview", + "ernie-3.5-8k", + "ernie-3.5-128k", + "ernie-speed-8k", + "ernie-speed-128k", + "ernie-speed-pro-128k", + "ernie-lite-8k", + "ernie-lite-pro-128k", + "ernie-tiny-8k", + "ernie-char-8k", + "ernie-char-fiction-8k", + "ernie-novel-8k", + "deepseek-v3", + "deepseek-r1", + "deepseek-r1-distill-qwen-32b", + "deepseek-r1-distill-qwen-14b", +} diff --git a/relay/adaptor/baiduv2/main.go b/relay/adaptor/baiduv2/main.go new file mode 100644 index 00000000..d305e1d9 --- /dev/null +++ b/relay/adaptor/baiduv2/main.go @@ -0,0 +1,17 @@ +package baiduv2 + +import ( + "fmt" + + "github.com/songquanpeng/one-api/relay/meta" + "github.com/songquanpeng/one-api/relay/relaymode" +) + +func GetRequestURL(meta *meta.Meta) (string, error) { + switch meta.Mode { + case relaymode.ChatCompletions: + return fmt.Sprintf("%s/v2/chat/completions", meta.BaseURL), nil + default: + } + return "", fmt.Errorf("unsupported relay mode %d for baidu v2", meta.Mode) +} diff --git a/relay/adaptor/openai/adaptor.go b/relay/adaptor/openai/adaptor.go index 6946e402..3907a0db 100644 --- a/relay/adaptor/openai/adaptor.go +++ b/relay/adaptor/openai/adaptor.go @@ -8,7 +8,9 @@ import ( "strings" "github.com/gin-gonic/gin" + "github.com/songquanpeng/one-api/relay/adaptor" + "github.com/songquanpeng/one-api/relay/adaptor/baiduv2" "github.com/songquanpeng/one-api/relay/adaptor/doubao" "github.com/songquanpeng/one-api/relay/adaptor/minimax" "github.com/songquanpeng/one-api/relay/adaptor/novita" @@ -52,6 +54,8 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) { return doubao.GetRequestURL(meta) case channeltype.Novita: return novita.GetRequestURL(meta) + case channeltype.BaiduV2: + return baiduv2.GetRequestURL(meta) default: return GetFullRequestURL(meta.BaseURL, meta.RequestURLPath, meta.ChannelType), nil } diff --git a/relay/adaptor/openai/compatible.go b/relay/adaptor/openai/compatible.go index 15b4dcc0..99424e49 100644 --- a/relay/adaptor/openai/compatible.go +++ b/relay/adaptor/openai/compatible.go @@ -3,6 +3,7 @@ package openai import ( "github.com/songquanpeng/one-api/relay/adaptor/ai360" "github.com/songquanpeng/one-api/relay/adaptor/baichuan" + "github.com/songquanpeng/one-api/relay/adaptor/baiduv2" "github.com/songquanpeng/one-api/relay/adaptor/deepseek" "github.com/songquanpeng/one-api/relay/adaptor/doubao" "github.com/songquanpeng/one-api/relay/adaptor/groq" @@ -34,6 +35,7 @@ var CompatibleChannels = []int{ channeltype.Novita, channeltype.SiliconFlow, channeltype.XAI, + channeltype.BaiduV2, } func GetCompatibleChannelMeta(channelType int) (string, []string) { @@ -68,6 +70,8 @@ func GetCompatibleChannelMeta(channelType int) (string, []string) { return "siliconflow", siliconflow.ModelList case channeltype.XAI: return "xai", xai.ModelList + case channeltype.BaiduV2: + return "baiduv2", baiduv2.ModelList default: return "openai", ModelList } diff --git a/relay/channeltype/define.go b/relay/channeltype/define.go index f54d0e30..a74c6269 100644 --- a/relay/channeltype/define.go +++ b/relay/channeltype/define.go @@ -48,5 +48,6 @@ const ( SiliconFlow XAI Replicate + BaiduV2 Dummy ) diff --git a/relay/channeltype/url.go b/relay/channeltype/url.go index 8e271f4e..6279fee2 100644 --- a/relay/channeltype/url.go +++ b/relay/channeltype/url.go @@ -48,6 +48,7 @@ var ChannelBaseURLs = []string{ "https://api.siliconflow.cn", // 44 "https://api.x.ai", // 45 "https://api.replicate.com/v1/models/", // 46 + "https://qianfan.baidubce.com", // 47 } func init() { diff --git a/web/default/src/constants/channel.constants.js b/web/default/src/constants/channel.constants.js index b030805b..a2a048b6 100644 --- a/web/default/src/constants/channel.constants.js +++ b/web/default/src/constants/channel.constants.js @@ -21,6 +21,13 @@ export const CHANNEL_OPTIONS = [ color: 'blue', tip: '请前往此处获取 AK(API Key)以及 SK(Secret Key)', }, + { + key: 47, + text: '百度文心千帆 V2', + value: 47, + color: 'blue', + tip: '请前往此处获取 API Key', + }, {key: 17, text: '阿里通义千问', value: 17, color: 'orange'}, {key: 18, text: '讯飞星火认知', value: 18, color: 'blue'}, {key: 16, text: '智谱 ChatGLM', value: 16, color: 'violet'},