diff --git a/controller/channel-test.go b/controller/channel-test.go
index f8327284c0..971f53826e 100644
--- a/controller/channel-test.go
+++ b/controller/channel-test.go
@@ -76,9 +76,9 @@ func testChannel(channel *model.Channel, request *relaymodel.GeneralOpenAIReques
if len(modelNames) > 0 {
modelName = modelNames[0]
}
- if modelMap != nil && modelMap[modelName] != "" {
- modelName = modelMap[modelName]
- }
+ }
+ if modelMap != nil && modelMap[modelName] != "" {
+ modelName = modelMap[modelName]
}
meta.OriginModelName, meta.ActualModelName = request.Model, modelName
request.Model = modelName
diff --git a/one-api b/one-api
new file mode 100755
index 0000000000..4c9190bb93
Binary files /dev/null and b/one-api differ
diff --git a/relay/adaptor/anthropic/constants.go b/relay/adaptor/anthropic/constants.go
index 143d1efc25..9b4469b29b 100644
--- a/relay/adaptor/anthropic/constants.go
+++ b/relay/adaptor/anthropic/constants.go
@@ -6,4 +6,5 @@ var ModelList = []string{
"claude-3-sonnet-20240229",
"claude-3-opus-20240229",
"claude-3-5-sonnet-20240620",
+ "claude-3-5-sonnet-20241022",
}
diff --git a/relay/adaptor/aws/claude/main.go b/relay/adaptor/aws/claude/main.go
index 7142e46f72..f1a49ec3ad 100644
--- a/relay/adaptor/aws/claude/main.go
+++ b/relay/adaptor/aws/claude/main.go
@@ -31,6 +31,7 @@ var AwsModelIDMap = map[string]string{
"claude-2.1": "anthropic.claude-v2:1",
"claude-3-sonnet-20240229": "anthropic.claude-3-sonnet-20240229-v1:0",
"claude-3-5-sonnet-20240620": "anthropic.claude-3-5-sonnet-20240620-v1:0",
+ "claude-3-5-sonnet-20241022": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"claude-3-opus-20240229": "anthropic.claude-3-opus-20240229-v1:0",
"claude-3-haiku-20240307": "anthropic.claude-3-haiku-20240307-v1:0",
}
diff --git a/relay/adaptor/gemini/main.go b/relay/adaptor/gemini/main.go
index 51fd6aa801..d6ab45d489 100644
--- a/relay/adaptor/gemini/main.go
+++ b/relay/adaptor/gemini/main.go
@@ -4,11 +4,12 @@ import (
"bufio"
"encoding/json"
"fmt"
- "github.com/songquanpeng/one-api/common/render"
"io"
"net/http"
"strings"
+ "github.com/songquanpeng/one-api/common/render"
+
"github.com/songquanpeng/one-api/common"
"github.com/songquanpeng/one-api/common/config"
"github.com/songquanpeng/one-api/common/helper"
@@ -28,6 +29,11 @@ const (
VisionMaxImageNum = 16
)
+var mimeTypeMap = map[string]string{
+ "json_object": "application/json",
+ "text": "text/plain",
+}
+
// Setting safety to the lowest possible values since Gemini is already powerless enough
func ConvertRequest(textRequest model.GeneralOpenAIRequest) *ChatRequest {
geminiRequest := ChatRequest{
@@ -56,6 +62,15 @@ func ConvertRequest(textRequest model.GeneralOpenAIRequest) *ChatRequest {
MaxOutputTokens: textRequest.MaxTokens,
},
}
+ if textRequest.ResponseFormat != nil {
+ if mimeType, ok := mimeTypeMap[textRequest.ResponseFormat.Type]; ok {
+ geminiRequest.GenerationConfig.ResponseMimeType = mimeType
+ }
+ if textRequest.ResponseFormat.JsonSchema != nil {
+ geminiRequest.GenerationConfig.ResponseSchema = textRequest.ResponseFormat.JsonSchema.Schema
+ geminiRequest.GenerationConfig.ResponseMimeType = mimeTypeMap["json_object"]
+ }
+ }
if textRequest.Tools != nil {
functions := make([]model.Function, 0, len(textRequest.Tools))
for _, tool := range textRequest.Tools {
diff --git a/relay/adaptor/gemini/model.go b/relay/adaptor/gemini/model.go
index f7179ea48e..f6a3b25042 100644
--- a/relay/adaptor/gemini/model.go
+++ b/relay/adaptor/gemini/model.go
@@ -65,10 +65,12 @@ type ChatTools struct {
}
type ChatGenerationConfig struct {
- Temperature float64 `json:"temperature,omitempty"`
- TopP float64 `json:"topP,omitempty"`
- TopK float64 `json:"topK,omitempty"`
- MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
- CandidateCount int `json:"candidateCount,omitempty"`
- StopSequences []string `json:"stopSequences,omitempty"`
+ ResponseMimeType string `json:"responseMimeType,omitempty"`
+ ResponseSchema any `json:"responseSchema,omitempty"`
+ Temperature float64 `json:"temperature,omitempty"`
+ TopP float64 `json:"topP,omitempty"`
+ TopK float64 `json:"topK,omitempty"`
+ MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
+ CandidateCount int `json:"candidateCount,omitempty"`
+ StopSequences []string `json:"stopSequences,omitempty"`
}
diff --git a/relay/adaptor/groq/constants.go b/relay/adaptor/groq/constants.go
index 559851eea0..9c19df393d 100644
--- a/relay/adaptor/groq/constants.go
+++ b/relay/adaptor/groq/constants.go
@@ -4,14 +4,21 @@ package groq
var ModelList = []string{
"gemma-7b-it",
- "mixtral-8x7b-32768",
- "llama3-8b-8192",
- "llama3-70b-8192",
"gemma2-9b-it",
- "llama-3.1-405b-reasoning",
"llama-3.1-70b-versatile",
"llama-3.1-8b-instant",
+ "llama-3.2-11b-text-preview",
+ "llama-3.2-11b-vision-preview",
+ "llama-3.2-1b-preview",
+ "llama-3.2-3b-preview",
+ "llama-3.2-90b-text-preview",
+ "llama-guard-3-8b",
+ "llama3-70b-8192",
+ "llama3-8b-8192",
"llama3-groq-70b-8192-tool-use-preview",
"llama3-groq-8b-8192-tool-use-preview",
+ "llava-v1.5-7b-4096-preview",
+ "mixtral-8x7b-32768",
+ "distil-whisper-large-v3-en",
"whisper-large-v3",
}
diff --git a/relay/adaptor/openai/adaptor.go b/relay/adaptor/openai/adaptor.go
index 5dc395adfa..6946e402a8 100644
--- a/relay/adaptor/openai/adaptor.go
+++ b/relay/adaptor/openai/adaptor.go
@@ -75,6 +75,13 @@ func (a *Adaptor) ConvertRequest(c *gin.Context, relayMode int, request *model.G
if request == nil {
return nil, errors.New("request is nil")
}
+ if request.Stream {
+ // always return usage in stream mode
+ if request.StreamOptions == nil {
+ request.StreamOptions = &model.StreamOptions{}
+ }
+ request.StreamOptions.IncludeUsage = true
+ }
return request, nil
}
diff --git a/relay/adaptor/vertexai/gemini/adapter.go b/relay/adaptor/vertexai/gemini/adapter.go
index 43e6cbcde3..ceff1ed2a0 100644
--- a/relay/adaptor/vertexai/gemini/adapter.go
+++ b/relay/adaptor/vertexai/gemini/adapter.go
@@ -15,7 +15,7 @@ import (
)
var ModelList = []string{
- "gemini-1.5-pro-001", "gemini-1.5-flash-001", "gemini-pro", "gemini-pro-vision",
+ "gemini-1.5-pro-001", "gemini-1.5-flash-001", "gemini-pro", "gemini-pro-vision", "gemini-1.5-pro-002", "gemini-1.5-flash-002",
}
type Adaptor struct {
diff --git a/relay/adaptor/xunfei/constants.go b/relay/adaptor/xunfei/constants.go
index c2992c98e4..5b82ac292f 100644
--- a/relay/adaptor/xunfei/constants.go
+++ b/relay/adaptor/xunfei/constants.go
@@ -7,5 +7,6 @@ var ModelList = []string{
"SparkDesk-v3.1",
"SparkDesk-v3.1-128K",
"SparkDesk-v3.5",
+ "SparkDesk-v3.5-32K",
"SparkDesk-v4.0",
}
diff --git a/relay/adaptor/xunfei/main.go b/relay/adaptor/xunfei/main.go
index 99c4d1f4a8..16b89bca2b 100644
--- a/relay/adaptor/xunfei/main.go
+++ b/relay/adaptor/xunfei/main.go
@@ -292,6 +292,8 @@ func apiVersion2domain(apiVersion string) string {
return "pro-128k"
case "v3.5":
return "generalv3.5"
+ case "v3.5-32K":
+ return "max-32k"
case "v4.0":
return "4.0Ultra"
}
@@ -303,7 +305,10 @@ func getXunfeiAuthUrl(apiVersion string, apiKey string, apiSecret string) (strin
domain := apiVersion2domain(apiVersion)
switch apiVersion {
case "v3.1-128K":
- authUrl = buildXunfeiAuthUrl(fmt.Sprintf("wss://spark-api.xf-yun.com/%s/pro-128k", apiVersion), apiKey, apiSecret)
+ authUrl = buildXunfeiAuthUrl(fmt.Sprintf("wss://spark-api.xf-yun.com/chat/pro-128k"), apiKey, apiSecret)
+ break
+ case "v3.5-32K":
+ authUrl = buildXunfeiAuthUrl(fmt.Sprintf("wss://spark-api.xf-yun.com/chat/max-32k"), apiKey, apiSecret)
break
default:
authUrl = buildXunfeiAuthUrl(fmt.Sprintf("wss://spark-api.xf-yun.com/%s/chat", apiVersion), apiKey, apiSecret)
diff --git a/relay/billing/ratio/model.go b/relay/billing/ratio/model.go
index cf5268756d..00f5bd0a0c 100644
--- a/relay/billing/ratio/model.go
+++ b/relay/billing/ratio/model.go
@@ -81,6 +81,7 @@ var ModelRatio = map[string]float64{
"claude-3-haiku-20240307": 0.25 / 1000 * USD,
"claude-3-sonnet-20240229": 3.0 / 1000 * USD,
"claude-3-5-sonnet-20240620": 3.0 / 1000 * USD,
+ "claude-3-5-sonnet-20241022": 3.0 / 1000 * USD,
"claude-3-opus-20240229": 15.0 / 1000 * USD,
// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/hlrk4akp7
"ERNIE-4.0-8K": 0.120 * RMB,
@@ -130,6 +131,7 @@ var ModelRatio = map[string]float64{
"SparkDesk-v3.1": 1.2858, // ¥0.018 / 1k tokens
"SparkDesk-v3.1-128K": 1.2858, // ¥0.018 / 1k tokens
"SparkDesk-v3.5": 1.2858, // ¥0.018 / 1k tokens
+ "SparkDesk-v3.5-32K": 1.2858, // ¥0.018 / 1k tokens
"SparkDesk-v4.0": 1.2858, // ¥0.018 / 1k tokens
"360GPT_S2_V9": 0.8572, // ¥0.012 / 1k tokens
"embedding-bert-512-v1": 0.0715, // ¥0.001 / 1k tokens
@@ -161,15 +163,21 @@ var ModelRatio = map[string]float64{
"mistral-embed": 0.1 / 1000 * USD,
// https://wow.groq.com/#:~:text=inquiries%C2%A0here.-,Model,-Current%20Speed
"gemma-7b-it": 0.07 / 1000000 * USD,
- "mixtral-8x7b-32768": 0.24 / 1000000 * USD,
- "llama3-8b-8192": 0.05 / 1000000 * USD,
- "llama3-70b-8192": 0.59 / 1000000 * USD,
"gemma2-9b-it": 0.20 / 1000000 * USD,
- "llama-3.1-405b-reasoning": 0.89 / 1000000 * USD,
"llama-3.1-70b-versatile": 0.59 / 1000000 * USD,
"llama-3.1-8b-instant": 0.05 / 1000000 * USD,
+ "llama-3.2-11b-text-preview": 0.05 / 1000000 * USD,
+ "llama-3.2-11b-vision-preview": 0.05 / 1000000 * USD,
+ "llama-3.2-1b-preview": 0.05 / 1000000 * USD,
+ "llama-3.2-3b-preview": 0.05 / 1000000 * USD,
+ "llama-3.2-90b-text-preview": 0.59 / 1000000 * USD,
+ "llama-guard-3-8b": 0.05 / 1000000 * USD,
+ "llama3-70b-8192": 0.59 / 1000000 * USD,
+ "llama3-8b-8192": 0.05 / 1000000 * USD,
"llama3-groq-70b-8192-tool-use-preview": 0.89 / 1000000 * USD,
"llama3-groq-8b-8192-tool-use-preview": 0.19 / 1000000 * USD,
+ "mixtral-8x7b-32768": 0.24 / 1000000 * USD,
+
// https://platform.lingyiwanwu.com/docs#-计费单元
"yi-34b-chat-0205": 2.5 / 1000 * RMB,
"yi-34b-chat-200k": 12.0 / 1000 * RMB,
diff --git a/relay/model/constant.go b/relay/model/constant.go
index f6cf1924d1..c9d6d645c6 100644
--- a/relay/model/constant.go
+++ b/relay/model/constant.go
@@ -1,6 +1,7 @@
package model
const (
- ContentTypeText = "text"
- ContentTypeImageURL = "image_url"
+ ContentTypeText = "text"
+ ContentTypeImageURL = "image_url"
+ ContentTypeInputAudio = "input_audio"
)
diff --git a/relay/model/general.go b/relay/model/general.go
index aacc8467d1..fe73779ed7 100644
--- a/relay/model/general.go
+++ b/relay/model/general.go
@@ -12,9 +12,20 @@ type JSONSchema struct {
Strict *bool `json:"strict,omitempty"`
}
+type Audio struct {
+ Voice string `json:"voice,omitempty"`
+ Format string `json:"format,omitempty"`
+}
+
+type StreamOptions struct {
+ IncludeUsage bool `json:"include_usage,omitempty"`
+}
+
type GeneralOpenAIRequest struct {
Messages []Message `json:"messages,omitempty"`
Model string `json:"model,omitempty"`
+ Modalities []string `json:"modalities,omitempty"`
+ Audio *Audio `json:"audio,omitempty"`
FrequencyPenalty float64 `json:"frequency_penalty,omitempty"`
MaxTokens int `json:"max_tokens,omitempty"`
N int `json:"n,omitempty"`
@@ -23,6 +34,7 @@ type GeneralOpenAIRequest struct {
Seed float64 `json:"seed,omitempty"`
Stop any `json:"stop,omitempty"`
Stream bool `json:"stream,omitempty"`
+ StreamOptions *StreamOptions `json:"stream_options,omitempty"`
Temperature float64 `json:"temperature,omitempty"`
TopP float64 `json:"top_p,omitempty"`
TopK int `json:"top_k,omitempty"`
@@ -37,7 +49,7 @@ type GeneralOpenAIRequest struct {
Dimensions int `json:"dimensions,omitempty"`
Instruction string `json:"instruction,omitempty"`
Size string `json:"size,omitempty"`
- NumCtx int `json:"num_ctx,omitempty"`
+ NumCtx int `json:"num_ctx,omitempty"`
}
func (r GeneralOpenAIRequest) ParseInput() []string {
diff --git a/web/air/src/components/TokensTable.js b/web/air/src/components/TokensTable.js
index c87657dc13..48836c859a 100644
--- a/web/air/src/components/TokensTable.js
+++ b/web/air/src/components/TokensTable.js
@@ -395,7 +395,7 @@ const TokensTable = () => {
url = mjLink + `/#/?settings={"key":"sk-${key}","url":"${serverAddress}"}`;
break;
case 'lobechat':
- url = chatLink + `/?settings={"keyVaults":{"openai":{"apiKey":"sk-${key}","baseURL":"${serverAddress}"/v1"}}}`;
+ url = chatLink + `/?settings={"keyVaults":{"openai":{"apiKey":"sk-${key}","baseURL":"${serverAddress}/v1"}}}`;
break;
default:
if (!chatLink) {
diff --git a/web/air/src/pages/Channel/EditChannel.js b/web/air/src/pages/Channel/EditChannel.js
index b50a6e77de..fa1ab2768b 100644
--- a/web/air/src/pages/Channel/EditChannel.js
+++ b/web/air/src/pages/Channel/EditChannel.js
@@ -63,7 +63,7 @@ const EditChannel = (props) => {
let localModels = [];
switch (value) {
case 14:
- localModels = ["claude-instant-1.2", "claude-2", "claude-2.0", "claude-2.1", "claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307", "claude-3-5-sonnet-20240620"];
+ localModels = ["claude-instant-1.2", "claude-2", "claude-2.0", "claude-2.1", "claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307", "claude-3-5-sonnet-20240620", "claude-3-5-sonnet-20241022"];
break;
case 11:
localModels = ['PaLM-2'];
@@ -78,7 +78,7 @@ const EditChannel = (props) => {
localModels = ['chatglm_pro', 'chatglm_std', 'chatglm_lite'];
break;
case 18:
- localModels = ['SparkDesk', 'SparkDesk-v1.1', 'SparkDesk-v2.1', 'SparkDesk-v3.1', 'SparkDesk-v3.1-128K', 'SparkDesk-v3.5', 'SparkDesk-v4.0'];
+ localModels = ['SparkDesk', 'SparkDesk-v1.1', 'SparkDesk-v2.1', 'SparkDesk-v3.1', 'SparkDesk-v3.1-128K', 'SparkDesk-v3.5', 'SparkDesk-v3.5-32K', 'SparkDesk-v4.0'];
break;
case 19:
localModels = ['360GPT_S2_V9', 'embedding-bert-512-v1', 'embedding_s1_v1', 'semantic_similarity_s1_v1'];
diff --git a/web/berry/src/views/Channel/type/Config.js b/web/berry/src/views/Channel/type/Config.js
index 4a8fc27a0e..1fa67364b1 100644
--- a/web/berry/src/views/Channel/type/Config.js
+++ b/web/berry/src/views/Channel/type/Config.js
@@ -91,7 +91,7 @@ const typeConfig = {
other: '版本号'
},
input: {
- models: ['SparkDesk', 'SparkDesk-v1.1', 'SparkDesk-v2.1', 'SparkDesk-v3.1', 'SparkDesk-v3.1-128K', 'SparkDesk-v3.5', 'SparkDesk-v4.0']
+ models: ['SparkDesk', 'SparkDesk-v1.1', 'SparkDesk-v2.1', 'SparkDesk-v3.1', 'SparkDesk-v3.1-128K', 'SparkDesk-v3.5', 'SparkDesk-v3.5-32K', 'SparkDesk-v4.0']
},
prompt: {
key: '按照如下格式输入:APPID|APISecret|APIKey',
diff --git a/web/berry/src/views/Token/component/TableRow.js b/web/berry/src/views/Token/component/TableRow.js
index 0a7efd9837..4306be5edf 100644
--- a/web/berry/src/views/Token/component/TableRow.js
+++ b/web/berry/src/views/Token/component/TableRow.js
@@ -33,7 +33,7 @@ const COPY_OPTIONS = [
},
{ key: 'ama', text: 'BotGem', url: 'ama://set-api-key?server={serverAddress}&key=sk-{key}', encode: true },
{ key: 'opencat', text: 'OpenCat', url: 'opencat://team/join?domain={serverAddress}&token=sk-{key}', encode: true },
- { key: 'lobechat', text: 'LobeChat', url: 'https://lobehub.com/?settings={"keyVaults":{"openai":{"apiKey":"user-key","baseURL":"https://your-proxy.com/v1"}}}', encode: true }
+ { key: 'lobechat', text: 'LobeChat', url: 'https://lobehub.com/?settings={"keyVaults":{"openai":{"apiKey":"sk-{key}","baseURL":"{serverAddress}"}}}', encode: true }
];
function replacePlaceholders(text, key, serverAddress) {
diff --git a/web/default/src/components/ChannelsTable.js b/web/default/src/components/ChannelsTable.js
index 48f476a7b8..6e0ec05d2f 100644
--- a/web/default/src/components/ChannelsTable.js
+++ b/web/default/src/components/ChannelsTable.js
@@ -59,6 +59,12 @@ function renderBalance(type, balance) {
}
}
+function isShowDetail() {
+ return localStorage.getItem("show_detail") === "true";
+}
+
+const promptID = "detail"
+
const ChannelsTable = () => {
const [channels, setChannels] = useState([]);
const [loading, setLoading] = useState(true);
@@ -66,7 +72,8 @@ const ChannelsTable = () => {
const [searchKeyword, setSearchKeyword] = useState('');
const [searching, setSearching] = useState(false);
const [updatingBalance, setUpdatingBalance] = useState(false);
- const [showPrompt, setShowPrompt] = useState(shouldShowPrompt("channel-test"));
+ const [showPrompt, setShowPrompt] = useState(shouldShowPrompt(promptID));
+ const [showDetail, setShowDetail] = useState(isShowDetail());
const loadChannels = async (startIdx) => {
const res = await API.get(`/api/channel/?p=${startIdx}`);
@@ -120,6 +127,11 @@ const ChannelsTable = () => {
await loadChannels(activePage - 1);
};
+ const toggleShowDetail = () => {
+ setShowDetail(!showDetail);
+ localStorage.setItem("show_detail", (!showDetail).toString());
+ }
+
useEffect(() => {
loadChannels(0)
.then()
@@ -364,11 +376,13 @@ const ChannelsTable = () => {
showPrompt && (
渠道测试仅支持 chat 模型,优先使用 gpt-3.5-turbo,如果该模型不可用则使用你所配置的模型列表中的第一个模型。
+
+ 点击下方详情按钮可以显示余额以及设置额外的测试模型。