feat: add model Provider GPUStack

This commit is contained in:
alexcodelf 2025-03-14 10:53:57 +08:00 committed by 亢奋猫
parent d7cbba8f5b
commit c7bd1918a9
14 changed files with 160 additions and 7 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1780,7 +1780,8 @@ export const SYSTEM_MODELS: Record<string, Model[]> = {
name: 'DeepSeek V3',
group: 'DeepSeek'
}
]
],
gpustack: []
}
export const TEXT_TO_IMAGES_MODELS = [

View File

@ -12,6 +12,7 @@ import FireworksProviderLogo from '@renderer/assets/images/providers/fireworks.p
import GiteeAIProviderLogo from '@renderer/assets/images/providers/gitee-ai.png'
import GithubProviderLogo from '@renderer/assets/images/providers/github.png'
import GoogleProviderLogo from '@renderer/assets/images/providers/google.png'
import GPUStackProviderLogo from '@renderer/assets/images/providers/gpustack.svg'
import GraphRagProviderLogo from '@renderer/assets/images/providers/graph-rag.png'
import GrokProviderLogo from '@renderer/assets/images/providers/grok.png'
import GroqProviderLogo from '@renderer/assets/images/providers/groq.png'
@ -123,6 +124,8 @@ export function getProviderLogo(providerId: string) {
return O3ProviderLogo
case 'tencent-cloud-ti':
return TencentCloudProviderLogo
case 'gpustack':
return GPUStackProviderLogo
default:
return undefined
}
@ -572,5 +575,15 @@ export const PROVIDER_CONFIG = {
docs: 'https://cloud.tencent.com/document/product/1772',
models: 'https://console.cloud.tencent.com/tione/v2/aimarket'
}
},
gpustack: {
api: {
url: ''
},
websites: {
official: 'https://gpustack.ai/',
docs: 'https://docs.gpustack.ai/latest/',
models: 'https://docs.gpustack.ai/latest/overview/#supported-models'
}
}
}

View File

@ -0,0 +1,18 @@
import store, { useAppSelector } from '@renderer/store'
import { setGPUStackKeepAliveTime } from '@renderer/store/llm'
import { useDispatch } from 'react-redux'
export function useGPUStackSettings() {
const settings = useAppSelector((state) => state.llm.settings.gpustack)
const dispatch = useDispatch()
return { ...settings, setKeepAliveTime: (time: number) => dispatch(setGPUStackKeepAliveTime(time)) }
}
export function getGPUStackSettings() {
return store.getState().llm.settings.gpustack
}
export function getGPUStackKeepAliveTime() {
return store.getState().llm.settings.gpustack.keepAliveTime + 'm'
}

View File

@ -561,6 +561,12 @@
},
"title": "PlantUML Diagram"
},
"gpustack": {
"keep_alive_time.description": "The time in minutes to keep the connection alive, default is 5 minutes.",
"keep_alive_time.placeholder": "Minutes",
"keep_alive_time.title": "Keep Alive Time",
"title": "GPUStack"
},
"prompts": {
"explanation": "Explain this concept to me",
"summarize": "Summarize this text",
@ -608,7 +614,8 @@
"xirang": "State Cloud Xirang",
"yi": "Yi",
"zhinao": "360AI",
"zhipu": "ZHIPU AI"
"zhipu": "ZHIPU AI",
"gpustack": "GPUStack"
},
"restore": {
"confirm": "Are you sure you want to restore data?",

View File

@ -561,6 +561,12 @@
},
"title": "PlantUML 図表"
},
"gpustack": {
"keep_alive_time.description": "モデルがメモリに保持される時間デフォルト5分",
"keep_alive_time.placeholder": "分",
"keep_alive_time.title": "保持時間",
"title": "GPUStack"
},
"prompts": {
"explanation": "この概念を説明してください",
"summarize": "このテキストを要約してください",
@ -608,7 +614,8 @@
"xirang": "天翼クラウド 息壤",
"yi": "零一万物",
"zhinao": "360智脳",
"zhipu": "智譜AI"
"zhipu": "智譜AI",
"gpustack": "GPUStack"
},
"restore": {
"confirm": "データを復元しますか?",

View File

@ -388,6 +388,12 @@
},
"title": "Диаграмма Mermaid"
},
"gpustack": {
"keep_alive_time.description": "Время в минутах, в течение которого модель остается активной, по умолчанию 5 минут.",
"keep_alive_time.placeholder": "Минуты",
"keep_alive_time.title": "Время жизни модели",
"title": "GPUStack"
},
"message": {
"api.check.model.title": "Выберите модель для проверки",
"api.connection.failed": "Соединение не удалось",
@ -608,7 +614,8 @@
"xirang": "State Cloud Xirang",
"yi": "Yi",
"zhinao": "360AI",
"zhipu": "ZHIPU AI"
"zhipu": "ZHIPU AI",
"gpustack": "GPUStack"
},
"restore": {
"confirm": "Вы уверены, что хотите восстановить данные?",

View File

@ -608,7 +608,8 @@
"xirang": "天翼云息壤",
"yi": "零一万物",
"zhinao": "360智脑",
"zhipu": "智谱AI"
"zhipu": "智谱AI",
"gpustack": "GPUStack"
},
"restore": {
"confirm": "确定要恢复数据吗?",
@ -624,6 +625,12 @@
},
"title": "数据恢复"
},
"gpustack": {
"keep_alive_time.description": "模型在内存中保持的时间默认5分钟",
"keep_alive_time.placeholder": "分钟",
"keep_alive_time.title": "保持活跃时间",
"title": "GPUStack"
},
"settings": {
"about": "关于我们",
"about.checkingUpdate": "正在检查更新...",

View File

@ -608,7 +608,8 @@
"xirang": "天翼雲息壤",
"yi": "零一萬物",
"zhinao": "360 智腦",
"zhipu": "智譜 AI"
"zhipu": "智譜 AI",
"gpustack": "GPUStack"
},
"restore": {
"confirm": "確定要復原資料嗎?",
@ -624,6 +625,12 @@
},
"title": "資料復原"
},
"gpustack": {
"keep_alive_time.description": "模型在記憶體中保持的時間(預設為 5 分鐘)。",
"keep_alive_time.placeholder": "分鐘",
"keep_alive_time.title": "保持活躍時間",
"title": "GPUStack"
},
"settings": {
"about": "關於與回饋",
"about.checkingUpdate": "正在檢查更新...",

View File

@ -0,0 +1,34 @@
import { useGPUStackSettings } from '@renderer/hooks/useGPUStack'
import { InputNumber } from 'antd'
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { SettingHelpText, SettingHelpTextRow, SettingSubtitle } from '..'
const GPUStackSettings: FC = () => {
const { keepAliveTime, setKeepAliveTime } = useGPUStackSettings()
const [keepAliveMinutes, setKeepAliveMinutes] = useState(keepAliveTime)
const { t } = useTranslation()
return (
<Container>
<SettingSubtitle style={{ marginBottom: 5 }}>{t('gpustack.keep_alive_time.title')}</SettingSubtitle>
<InputNumber
style={{ width: '100%' }}
value={keepAliveMinutes}
onChange={(e) => setKeepAliveMinutes(Number(e))}
onBlur={() => setKeepAliveTime(keepAliveMinutes)}
suffix={t('gpustack.keep_alive_time.placeholder')}
step={5}
/>
<SettingHelpTextRow>
<SettingHelpText>{t('gpustack.keep_alive_time.description')}</SettingHelpText>
</SettingHelpTextRow>
</Container>
)
}
const Container = styled.div``
export default GPUStackSettings

View File

@ -28,6 +28,7 @@ import {
SettingTitle
} from '..'
import ApiCheckPopup from './ApiCheckPopup'
import GPUStackSettings from './GPUStackSettings'
import GraphRAGSettings from './GraphRAGSettings'
import HealthCheckPopup from './HealthCheckPopup'
import LMStudioSettings from './LMStudioSettings'
@ -345,6 +346,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
)}
{provider.id === 'ollama' && <OllamSettings />}
{provider.id === 'lmstudio' && <LMStudioSettings />}
{provider.id === 'gpustack' && <GPUStackSettings />}
{provider.id === 'graphrag-kylin-mountain' && provider.models.length > 0 && (
<GraphRAGSettings provider={provider} />
)}

View File

@ -36,7 +36,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 78,
version: 79,
blacklist: ['runtime', 'messages'],
migrate
},

View File

@ -11,6 +11,9 @@ type LlmSettings = {
lmstudio: {
keepAliveTime: number
}
gpustack: {
keepAliveTime: number
}
}
export interface LlmState {
@ -426,6 +429,16 @@ const initialState: LlmState = {
models: SYSTEM_MODELS['tencent-cloud-ti'],
isSystem: true,
enabled: false
},
{
id: 'gpustack',
name: 'GPUStack',
type: 'openai',
apiKey: '',
apiHost: '',
models: SYSTEM_MODELS.gpustack,
isSystem: true,
enabled: false
}
],
settings: {
@ -434,6 +447,9 @@ const initialState: LlmState = {
},
lmstudio: {
keepAliveTime: 0
},
gpustack: {
keepAliveTime: 0
}
}
}
@ -462,6 +478,9 @@ const getIntegratedInitialState = () => {
},
lmstudio: {
keepAliveTime: 3600
},
gpustack: {
keepAliveTime: 3600
}
}
} as LlmState
@ -534,6 +553,9 @@ const settingsSlice = createSlice({
setLMStudioKeepAliveTime: (state, action: PayloadAction<number>) => {
state.settings.lmstudio.keepAliveTime = action.payload
},
setGPUStackKeepAliveTime: (state, action: PayloadAction<number>) => {
state.settings.gpustack.keepAliveTime = action.payload
},
updateModel: (
state,
action: PayloadAction<{
@ -564,6 +586,7 @@ export const {
setTranslateModel,
setOllamaKeepAliveTime,
setLMStudioKeepAliveTime,
setGPUStackKeepAliveTime,
updateModel
} = settingsSlice.actions

View File

@ -1243,6 +1243,19 @@ const migrateConfig = {
state.llm.providers = moveProvider(state.llm.providers, 'infini', 10)
removeMiniAppIconsFromState(state)
return state
},
'79': (state: RootState) => {
state.llm.providers.push({
id: 'gpustack',
name: 'GPUStack',
type: 'openai',
apiKey: '',
apiHost: '',
models: SYSTEM_MODELS.gpustack,
isSystem: true,
enabled: false
})
return state
}
}