From 08e10df88783f3ad23eec921a29e7191b8055e9f Mon Sep 17 00:00:00 2001 From: iszcz <74706321+iszcz@users.noreply.github.com> Date: Wed, 10 Apr 2024 02:51:21 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B8=A0=E9=81=93?= =?UTF-8?q?=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/ChannelsTable.js | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js index 0d2ed57..ebfcf4d 100644 --- a/web/src/components/ChannelsTable.js +++ b/web/src/components/ChannelsTable.js @@ -254,6 +254,19 @@ const ChannelsTable = () => { > 编辑 + { + copySelectedChannel(record.id); + }} + > + + ), }, @@ -340,6 +353,31 @@ const ChannelsTable = () => { setLoading(false); }; + const copySelectedChannel = async (id) => { + const channelToCopy = channels.find(channel => String(channel.id) === String(id)); + console.log(channelToCopy) + channelToCopy.name += '_复制'; + channelToCopy.created_time = null; + channelToCopy.balance = 0; + channelToCopy.used_quota = 0; + if (!channelToCopy) { + showError("渠道未找到,请刷新页面后重试。"); + return; + } + try { + const newChannel = {...channelToCopy, id: undefined}; + const response = await API.post('/api/channel/', newChannel); + if (response.data.success) { + showSuccess("渠道复制成功"); + await refresh(); + } else { + showError(response.data.message); + } + } catch (error) { + showError("渠道复制失败: " + error.message); + } + }; + const refresh = async () => { await loadChannels(activePage - 1, pageSize, idSort); }; From f188147680c66527e6e735f028ebde6a5ba00e4e Mon Sep 17 00:00:00 2001 From: "1808837298@qq.com" <1808837298@qq.com> Date: Wed, 10 Apr 2024 20:10:54 +0800 Subject: [PATCH 02/13] feat: support gpt-4-turbo --- common/model-ratio.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/model-ratio.go b/common/model-ratio.go index 2ff1aa4..404fffd 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -201,7 +201,7 @@ func GetCompletionRatio(name string) float64 { return 4.0 / 3.0 } if strings.HasPrefix(name, "gpt-4") { - if strings.HasSuffix(name, "preview") { + if strings.HasSuffix(name, "gpt-4-turbo") { return 3 } return 2 From 4ef2422b9734508e84689af600a88000295d83f1 Mon Sep 17 00:00:00 2001 From: "1808837298@qq.com" <1808837298@qq.com> Date: Wed, 10 Apr 2024 20:12:56 +0800 Subject: [PATCH 03/13] update model-ratio --- common/model-ratio.go | 1 + 1 file changed, 1 insertion(+) diff --git a/common/model-ratio.go b/common/model-ratio.go index 404fffd..a6f3224 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -26,6 +26,7 @@ var DefaultModelRatio = map[string]float64{ "gpt-4-turbo-preview": 5, // $0.01 / 1K tokens "gpt-4-vision-preview": 5, // $0.01 / 1K tokens "gpt-4-1106-vision-preview": 5, // $0.01 / 1K tokens + "gpt-4-turbo": 5, // $0.01 / 1K tokens "gpt-3.5-turbo": 0.25, // $0.0015 / 1K tokens "gpt-3.5-turbo-0301": 0.75, "gpt-3.5-turbo-0613": 0.75, From bf94893f6ac5703351ee9dc6fa5b2b7b2d01a544 Mon Sep 17 00:00:00 2001 From: xqx333 <141810964+xqx333@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:03:51 +0800 Subject: [PATCH 04/13] Update model-ratio.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复gpt-4-1106-preview和gpt-4-0125-preview的输出倍率错误 --- common/model-ratio.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/model-ratio.go b/common/model-ratio.go index a6f3224..3f9f86c 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -202,7 +202,7 @@ func GetCompletionRatio(name string) float64 { return 4.0 / 3.0 } if strings.HasPrefix(name, "gpt-4") { - if strings.HasSuffix(name, "gpt-4-turbo") { + if strings.HasPrefix(name, "gpt-4-turbo")|| strings.HasSuffix(name, "preview") { return 3 } return 2 From 21250a46a615e38fbb34a83d4acc75bfa2b8b8b1 Mon Sep 17 00:00:00 2001 From: Maple Gao Date: Mon, 15 Apr 2024 14:19:19 +0800 Subject: [PATCH 05/13] feat: support google v1beta and Gemini Ultra --- common/model-ratio.go | 1 + relay/channel/gemini/adaptor.go | 30 +++++++++++++++++++++--------- relay/channel/gemini/constant.go | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/common/model-ratio.go b/common/model-ratio.go index 3f9f86c..d45ec11 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -77,6 +77,7 @@ var DefaultModelRatio = map[string]float64{ "gemini-1.0-pro-vision-001": 1, "gemini-1.0-pro-001": 1, "gemini-1.5-pro": 1, + "gemini-ultra": 1, "chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens "chatglm_pro": 0.7143, // ¥0.01 / 1k tokens "chatglm_std": 0.3572, // ¥0.005 / 1k tokens diff --git a/relay/channel/gemini/adaptor.go b/relay/channel/gemini/adaptor.go index a275175..87c8da2 100644 --- a/relay/channel/gemini/adaptor.go +++ b/relay/channel/gemini/adaptor.go @@ -18,16 +18,28 @@ type Adaptor struct { func (a *Adaptor) Init(info *relaycommon.RelayInfo, request dto.GeneralOpenAIRequest) { } +// 定义一个映射,存储模型名称和对应的版本 +var modelVersionMap = map[string]string{ + "gemini-1.5-pro": "v1beta", + "gemini-ultra": "v1beta", +} + func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) { - version := "v1" - if info.ApiVersion != "" { - version = info.ApiVersion - } - action := "generateContent" - if info.IsStream { - action = "streamGenerateContent" - } - return fmt.Sprintf("%s/%s/models/%s:%s", info.BaseUrl, version, info.UpstreamModelName, action), nil + // 从映射中获取模型名称对应的版本,如果找不到就使用 info.ApiVersion 或默认的版本 "v1" + version, beta := modelVersionMap[info.UpstreamModelName] + if !beta { + if info.ApiVersion != "" { + version = info.ApiVersion + } else { + version = "v1" + } + } + + action := "generateContent" + if info.IsStream { + action = "streamGenerateContent" + } + return fmt.Sprintf("%s/%s/models/%s:%s", info.BaseUrl, version, info.UpstreamModelName, action), nil } func (a *Adaptor) SetupRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.RelayInfo) error { diff --git a/relay/channel/gemini/constant.go b/relay/channel/gemini/constant.go index 582f4c0..d5011c6 100644 --- a/relay/channel/gemini/constant.go +++ b/relay/channel/gemini/constant.go @@ -5,7 +5,7 @@ const ( ) var ModelList = []string{ - "gemini-pro", "gemini-1.0-pro-001", "gemini-1.5-pro", + "gemini-pro", "gemini-1.0-pro-001", "gemini-1.5-pro", "gemini-ultra", "gemini-pro-vision", "gemini-1.0-pro-vision-001", } From 3b6ea51033a5b0d2d229f583c143eb6cd6824f86 Mon Sep 17 00:00:00 2001 From: Maple Gao Date: Mon, 15 Apr 2024 14:22:40 +0800 Subject: [PATCH 06/13] fix: rename the latest Gemini model name --- relay/channel/gemini/constant.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relay/channel/gemini/constant.go b/relay/channel/gemini/constant.go index d5011c6..5e833bc 100644 --- a/relay/channel/gemini/constant.go +++ b/relay/channel/gemini/constant.go @@ -5,8 +5,8 @@ const ( ) var ModelList = []string{ - "gemini-pro", "gemini-1.0-pro-001", "gemini-1.5-pro", "gemini-ultra", - "gemini-pro-vision", "gemini-1.0-pro-vision-001", + "gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.5-pro-latest", "gemini-ultra", + "gemini-1.0-pro-vision-latest", "gemini-1.0-pro-vision-001", } var ChannelName = "google gemini" From 1456992aae22f27fbadfa1f3a1bf91129dbfdf9e Mon Sep 17 00:00:00 2001 From: Maple Gao Date: Mon, 15 Apr 2024 14:25:44 +0800 Subject: [PATCH 07/13] add: new Gemini model default ratio --- common/model-ratio.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/model-ratio.go b/common/model-ratio.go index d45ec11..2d6ae6f 100644 --- a/common/model-ratio.go +++ b/common/model-ratio.go @@ -76,8 +76,10 @@ var DefaultModelRatio = map[string]float64{ "gemini-pro-vision": 1, // $0.00025 / 1k characters -> $0.001 / 1k tokens "gemini-1.0-pro-vision-001": 1, "gemini-1.0-pro-001": 1, - "gemini-1.5-pro": 1, - "gemini-ultra": 1, + "gemini-1.5-pro-latest": 1, + "gemini-1.0-pro-latest": 1, + "gemini-1.0-pro-vision-latest": 1, + "gemini-ultra": 1, "chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens "chatglm_pro": 0.7143, // ¥0.01 / 1k tokens "chatglm_std": 0.3572, // ¥0.005 / 1k tokens From d7e117acf55f7ce2fd03141b7a9a401289d35a2f Mon Sep 17 00:00:00 2001 From: Maple Gao Date: Mon, 15 Apr 2024 14:27:18 +0800 Subject: [PATCH 08/13] fix: Gemini 1.5 name error --- relay/channel/gemini/adaptor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relay/channel/gemini/adaptor.go b/relay/channel/gemini/adaptor.go index 87c8da2..daaadc5 100644 --- a/relay/channel/gemini/adaptor.go +++ b/relay/channel/gemini/adaptor.go @@ -20,7 +20,7 @@ func (a *Adaptor) Init(info *relaycommon.RelayInfo, request dto.GeneralOpenAIReq // 定义一个映射,存储模型名称和对应的版本 var modelVersionMap = map[string]string{ - "gemini-1.5-pro": "v1beta", + "gemini-1.5-pro-latest": "v1beta", "gemini-ultra": "v1beta", } From e9abe5b705a5fe8b153c40fd0a2c99e8817dadbe Mon Sep 17 00:00:00 2001 From: kahosan <15116355657l@gmail.com> Date: Tue, 16 Apr 2024 17:11:39 +0800 Subject: [PATCH 09/13] refactor: dark mode --- web/src/components/HeaderBar.js | 28 +++++++++------------- web/src/context/Theme/index.js | 36 +++++++++++++++++++++++++++++ web/src/index.js | 41 ++++++++++++++++++--------------- 3 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 web/src/context/Theme/index.js diff --git a/web/src/components/HeaderBar.js b/web/src/components/HeaderBar.js index a5da4df..5510d42 100644 --- a/web/src/components/HeaderBar.js +++ b/web/src/components/HeaderBar.js @@ -1,6 +1,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { UserContext } from '../context/User'; +import { useSetTheme, useTheme } from '../context/Theme'; import { API, getLogo, getSystemName, showSuccess } from '../helpers'; import '../index.css'; @@ -34,10 +35,8 @@ const HeaderBar = () => { let navigate = useNavigate(); const [showSidebar, setShowSidebar] = useState(false); - const [dark, setDark] = useState(false); const systemName = getSystemName(); const logo = getLogo(); - var themeMode = localStorage.getItem('theme-mode'); const currentDate = new Date(); // enable fireworks on new year(1.1 and 2.9-2.24) const isNewYear = @@ -66,26 +65,19 @@ const HeaderBar = () => { }, 3000); }; + const theme = useTheme(); + const setTheme = useSetTheme(); + useEffect(() => { - if (themeMode === 'dark') { - switchMode(true); + if (theme === 'dark') { + document.body.setAttribute('theme-mode', 'dark'); } + if (isNewYear) { console.log('Happy New Year!'); } }, []); - const switchMode = (model) => { - const body = document.body; - if (!model) { - body.removeAttribute('theme-mode'); - localStorage.setItem('theme-mode', 'light'); - } else { - body.setAttribute('theme-mode', 'dark'); - localStorage.setItem('theme-mode', 'dark'); - } - setDark(model); - }; return ( <> @@ -132,9 +124,11 @@ const HeaderBar = () => { { + setTheme(checked); + }} /> {userState.user ? ( <> diff --git a/web/src/context/Theme/index.js b/web/src/context/Theme/index.js new file mode 100644 index 0000000..7654988 --- /dev/null +++ b/web/src/context/Theme/index.js @@ -0,0 +1,36 @@ +import { createContext, useCallback, useContext, useState } from 'react'; + +const ThemeContext = createContext(null); +export const useTheme = () => useContext(ThemeContext); + +const SetThemeContext = createContext(null); +export const useSetTheme = () => useContext(SetThemeContext); + +export const ThemeProvider = ({ children }) => { + const [theme, _setTheme] = useState(() => { + try { + return localStorage.getItem('theme-mode') || null; + } catch { + return null; + } + }); + + const setTheme = useCallback((input) => { + _setTheme(input ? 'dark' : 'light'); + + const body = document.body; + if (!input) { + body.removeAttribute('theme-mode'); + localStorage.setItem('theme-mode', 'light'); + } else { + body.setAttribute('theme-mode', 'dark'); + localStorage.setItem('theme-mode', 'dark'); + } + }, []); + + return ( + + {children} + + ); +}; diff --git a/web/src/index.js b/web/src/index.js index c73daef..94b2286 100644 --- a/web/src/index.js +++ b/web/src/index.js @@ -12,6 +12,7 @@ import 'react-toastify/dist/ReactToastify.css'; import { StatusProvider } from './context/Status'; import { Layout } from '@douyinfe/semi-ui'; import SiderBar from './components/SiderBar'; +import { ThemeProvider } from './context/Theme'; // initialization @@ -22,27 +23,29 @@ root.render( - - - - + -
- -
- - - - -
-
+ + + + +
+ +
+ + + + +
+
+
+
- -
+
From 848358d87644d56c20a4d014f6a3e1001bc363b0 Mon Sep 17 00:00:00 2001 From: kahosan <15116355657l@gmail.com> Date: Tue, 16 Apr 2024 17:12:54 +0800 Subject: [PATCH 10/13] fix: the dark mode does not work for the `OperationSetting` and `SystemSetting` panels --- web/src/components/OperationSetting.js | 39 ++++++++++++++++++++------ web/src/components/SystemSetting.js | 25 ++++++++++------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/web/src/components/OperationSetting.js b/web/src/components/OperationSetting.js index 14b70d7..7a112e5 100644 --- a/web/src/components/OperationSetting.js +++ b/web/src/components/OperationSetting.js @@ -8,6 +8,8 @@ import { verifyJSON, } from '../helpers'; +import { useTheme } from '../context/Theme'; + const OperationSetting = () => { let now = new Date(); let [inputs, setInputs] = useState({ @@ -77,6 +79,9 @@ const OperationSetting = () => { } }; + const theme = useTheme(); + const isDark = theme === 'dark'; + useEffect(() => { getOptions().then(); }, []); @@ -219,8 +224,10 @@ const OperationSetting = () => { return ( -
-
通用设置
+ +
+ 通用设置 +
{ 保存通用设置 -
绘图设置
+
+ 绘图设置 +
{ /> -
屏蔽词过滤设置
+
+ 屏蔽词过滤设置 +
{ 保存屏蔽词设置 -
日志设置
+
+ 日志设置 +
{ 清理历史日志 -
数据看板
+
+ 数据看板 +
{ />
-
监控设置
+
+ 监控设置 +
{ 保存监控设置 -
额度设置
+
+ 额度设置 +
{ 保存额度设置 -
倍率设置
+
+ 倍率设置 +
{ let [inputs, setInputs] = useState({ PasswordLoginEnabled: '', @@ -57,6 +59,9 @@ const SystemSetting = () => { const [showPasswordWarningModal, setShowPasswordWarningModal] = useState(false); + const theme = useTheme(); + const isDark = theme === 'dark'; + const getOptions = async () => { const res = await API.get('/api/option/'); const { success, message, data } = res.data; @@ -306,8 +311,8 @@ const SystemSetting = () => { return ( - -
通用设置
+ +
通用设置
{ 更新服务器地址 -
+
支付设置(当前仅支持易支付接口,默认使用上方服务器地址作为回调地址!)
@@ -385,7 +390,7 @@ const SystemSetting = () => { 更新支付设置 -
配置登录注册
+
配置登录注册
{ /> -
+
配置邮箱域名白名单 用以防止恶意用户利用临时邮箱批量注册 @@ -533,7 +538,7 @@ const SystemSetting = () => { 保存邮箱域名白名单设置 -
+
配置 SMTP 用以支持系统的邮件发送
@@ -592,7 +597,7 @@ const SystemSetting = () => { 保存 SMTP 设置 -
+
配置 GitHub OAuth App 用以支持通过 GitHub 进行登录注册, @@ -634,7 +639,7 @@ const SystemSetting = () => { 保存 GitHub OAuth 设置 -
+
配置 WeChat Server 用以支持通过微信进行登录注册, @@ -679,7 +684,7 @@ const SystemSetting = () => { 保存 WeChat Server 设置 -
配置 Telegram 登录
+
配置 Telegram 登录
{ 保存 Telegram 登录设置 -
+
配置 Turnstile 用以支持用户校验, From a4defe6ada92914a5e6e0b372ac490b6ac0d2c1e Mon Sep 17 00:00:00 2001 From: CaIon <1808837298@qq.com> Date: Wed, 17 Apr 2024 15:18:36 +0800 Subject: [PATCH 11/13] fix: test all channel error (close #206) --- relay/channel/xunfei/relay-xunfei.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/relay/channel/xunfei/relay-xunfei.go b/relay/channel/xunfei/relay-xunfei.go index da86002..1690e96 100644 --- a/relay/channel/xunfei/relay-xunfei.go +++ b/relay/channel/xunfei/relay-xunfei.go @@ -179,7 +179,13 @@ func xunfeiHandler(c *gin.Context, textRequest dto.GeneralOpenAIRequest, appId s case stop = <-stopChan: } } - + if len(xunfeiResponse.Payload.Choices.Text) == 0 { + xunfeiResponse.Payload.Choices.Text = []XunfeiChatResponseTextItem{ + { + Content: "", + }, + } + } xunfeiResponse.Payload.Choices.Text[0].Content = content response := responseXunfei2OpenAI(&xunfeiResponse) From 505916b755df6ee719aceea95102b5d88816c426 Mon Sep 17 00:00:00 2001 From: CaIon <1808837298@qq.com> Date: Wed, 17 Apr 2024 20:47:13 +0800 Subject: [PATCH 12/13] update makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index f846d30..05bc6c6 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ all: build-frontend start-backend build-frontend: @echo "Building frontend..." - @cd $(FRONTEND_DIR) && npm install && DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat VERSION) npm run build npm run build + @cd $(FRONTEND_DIR) && npm install && DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(cat VERSION) npm run build npm run build start-backend: @echo "Starting backend dev server..." From 6e54f014352b2743333f4399a35ab740bbcabcfb Mon Sep 17 00:00:00 2001 From: CaIon <1808837298@qq.com> Date: Wed, 17 Apr 2024 20:47:35 +0800 Subject: [PATCH 13/13] update makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 05bc6c6..5042723 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ all: build-frontend start-backend build-frontend: @echo "Building frontend..." - @cd $(FRONTEND_DIR) && npm install && DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(cat VERSION) npm run build npm run build + @cd $(FRONTEND_DIR) && npm install && DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(cat VERSION) npm run build start-backend: @echo "Starting backend dev server..."