feat: support Tencent TokenHub API key via OpenAI-compatible protocol (#6232)
* feat: support tencent tokenhub api key via openai-compatible protocol * fix: use tokenhub base url for tencent api key channels * test: cover tencent key-format dispatch and add TokenHub key prompt locales
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package tencent
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/QuantumNous/new-api/constant"
|
||||
"github.com/QuantumNous/new-api/relay/channel"
|
||||
"github.com/QuantumNous/new-api/relay/channel/openai"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
)
|
||||
|
||||
const tokenHubBaseURL = "https://tokenhub.tencentmaas.com"
|
||||
|
||||
// DispatchAdaptor 按密钥格式分流:三段式 ak/sk 走原生 TC3,单段 TokenHub key 走 OpenAI 兼容。
|
||||
type DispatchAdaptor struct {
|
||||
channel.Adaptor
|
||||
}
|
||||
|
||||
func (a *DispatchAdaptor) Init(info *relaycommon.RelayInfo) {
|
||||
if strings.Contains(info.ApiKey, "|") {
|
||||
a.Adaptor = &Adaptor{}
|
||||
} else {
|
||||
a.Adaptor = &openai.Adaptor{}
|
||||
if info.ChannelBaseUrl == "" || info.ChannelBaseUrl == constant.ChannelBaseURLs[constant.ChannelTypeTencent] {
|
||||
info.ChannelBaseUrl = tokenHubBaseURL
|
||||
}
|
||||
}
|
||||
a.Adaptor.Init(info)
|
||||
}
|
||||
|
||||
func (a *DispatchAdaptor) GetModelList() []string {
|
||||
return ModelList
|
||||
}
|
||||
|
||||
func (a *DispatchAdaptor) GetChannelName() string {
|
||||
return ChannelName
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package tencent
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/QuantumNous/new-api/constant"
|
||||
"github.com/QuantumNous/new-api/relay/channel/openai"
|
||||
relaycommon "github.com/QuantumNous/new-api/relay/common"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDispatchAdaptorInit(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
apiKey string
|
||||
baseURL string
|
||||
wantTC3 bool
|
||||
wantBaseURL string
|
||||
}{
|
||||
{
|
||||
name: "legacy three-segment key selects TC3 adaptor and keeps base url",
|
||||
apiKey: "1300000000|AKIDxxxxxxxx|secretxxxxxxxx",
|
||||
baseURL: constant.ChannelBaseURLs[constant.ChannelTypeTencent],
|
||||
wantTC3: true,
|
||||
wantBaseURL: constant.ChannelBaseURLs[constant.ChannelTypeTencent],
|
||||
},
|
||||
{
|
||||
name: "tokenhub key with default base url rewrites to tokenhub",
|
||||
apiKey: "sk-xxxxxxxxxxxxxxxx",
|
||||
baseURL: constant.ChannelBaseURLs[constant.ChannelTypeTencent],
|
||||
wantTC3: false,
|
||||
wantBaseURL: tokenHubBaseURL,
|
||||
},
|
||||
{
|
||||
name: "tokenhub key with empty base url rewrites to tokenhub",
|
||||
apiKey: "sk-xxxxxxxxxxxxxxxx",
|
||||
baseURL: "",
|
||||
wantTC3: false,
|
||||
wantBaseURL: tokenHubBaseURL,
|
||||
},
|
||||
{
|
||||
name: "tokenhub key with custom base url is preserved",
|
||||
apiKey: "sk-xxxxxxxxxxxxxxxx",
|
||||
baseURL: "https://proxy.example.com",
|
||||
wantTC3: false,
|
||||
wantBaseURL: "https://proxy.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
info := &relaycommon.RelayInfo{ChannelMeta: &relaycommon.ChannelMeta{
|
||||
ChannelType: constant.ChannelTypeTencent,
|
||||
ApiKey: tt.apiKey,
|
||||
ChannelBaseUrl: tt.baseURL,
|
||||
}}
|
||||
|
||||
dispatch := &DispatchAdaptor{}
|
||||
dispatch.Init(info)
|
||||
|
||||
require.NotNil(t, dispatch.Adaptor)
|
||||
if tt.wantTC3 {
|
||||
assert.IsType(t, &Adaptor{}, dispatch.Adaptor)
|
||||
} else {
|
||||
assert.IsType(t, &openai.Adaptor{}, dispatch.Adaptor)
|
||||
}
|
||||
assert.Equal(t, tt.wantBaseURL, info.ChannelBaseUrl)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -342,6 +342,7 @@ var streamSupportedChannels = map[int]bool{
|
||||
constant.ChannelTypeMiniMax: true,
|
||||
constant.ChannelTypeSiliconFlow: true,
|
||||
constant.ChannelTypeAdvancedCustom: true,
|
||||
constant.ChannelTypeTencent: true,
|
||||
}
|
||||
|
||||
func GenRelayInfoWs(c *gin.Context, ws *websocket.Conn) *RelayInfo {
|
||||
|
||||
@@ -66,7 +66,7 @@ func GetAdaptor(apiType int) channel.Adaptor {
|
||||
case constant.APITypePaLM:
|
||||
return &palm.Adaptor{}
|
||||
case constant.APITypeTencent:
|
||||
return &tencent.Adaptor{}
|
||||
return &tencent.DispatchAdaptor{}
|
||||
case constant.APITypeXunfei:
|
||||
return &xunfei.Adaptor{}
|
||||
case constant.APITypeZhipu:
|
||||
|
||||
@@ -386,7 +386,7 @@ export const TYPE_TO_KEY_PROMPT: Record<number, string> = {
|
||||
15: 'Format: APIKey|SecretKey',
|
||||
18: 'Format: APPID|APISecret|APIKey',
|
||||
22: 'Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041',
|
||||
23: 'Format: AppId|SecretId|SecretKey',
|
||||
23: 'Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey',
|
||||
33: 'Format: Ak|Sk|Region',
|
||||
50: 'Format: AccessKey|SecretKey (or just ApiKey if upstream is New API)',
|
||||
51: 'Format: Access Key ID|Secret Access Key',
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "Format: APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "Format: APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "Format: AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "Forward requests directly to upstream providers without any post-processing.",
|
||||
"Frames per second": "Frames per second",
|
||||
"Free": "Free",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "Format : APIKey-AppId, par ex. fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "Format : APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "Format : APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "Format : AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "Format : TokenHub API Key, ou l'ancien format AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "Transférer les requêtes directement aux fournisseurs amont sans aucun post-traitement.",
|
||||
"Frames per second": "Images par seconde",
|
||||
"Free": "Libre",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "形式: APIKey-AppId、例: fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "形式: APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "形式: APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "形式: AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "形式: TokenHub API Key、または旧形式の AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "ポストプロセスなしで、リクエストをアップストリームプロバイダーに直接転送します。",
|
||||
"Frames per second": "フレームレート",
|
||||
"Free": "空き",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "Формат: APIKey-AppId, напр., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "Формат: APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "Формат: APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "Формат: AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "Формат: TokenHub API Key или устаревший AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "Перенаправлять запросы напрямую upstream-провайдерам без какой-либо постобработки.",
|
||||
"Frames per second": "Кадров в секунду",
|
||||
"Free": "Свободно",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "Định dạng: APIKey-AppId, ví dụ: fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "Định dạng: APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "Định dạng: APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "Định dạng: AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "Định dạng: TokenHub API Key, hoặc định dạng cũ AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "Chuyển tiếp các yêu cầu trực tiếp đến các nhà cung cấp ngược dòng mà không cần xử lý hậu kỳ nào.",
|
||||
"Frames per second": "Khung hình / giây",
|
||||
"Free": "Trống",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "格式:APIKey-AppId,例如:fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "格式:APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "格式:APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "格式:AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "格式:TokenHub API Key,或舊版 AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "將請求直接轉發給上游供應商,不進行任何後處理。",
|
||||
"Frames per second": "幀率",
|
||||
"Free": "可用",
|
||||
|
||||
@@ -2052,7 +2052,7 @@
|
||||
"Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041": "格式:APIKey-AppId,例如:fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041",
|
||||
"Format: APIKey|SecretKey": "格式:APIKey|SecretKey",
|
||||
"Format: APPID|APISecret|APIKey": "格式:APPID|APISecret|APIKey",
|
||||
"Format: AppId|SecretId|SecretKey": "格式:AppId|SecretId|SecretKey",
|
||||
"Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey": "格式:TokenHub API Key,或旧版 AppId|SecretId|SecretKey",
|
||||
"Forward requests directly to upstream providers without any post-processing.": "将请求直接转发给上游提供商,不进行任何后处理。",
|
||||
"Frames per second": "帧率",
|
||||
"Free": "可用",
|
||||
|
||||
Reference in New Issue
Block a user