Compare commits

..
13 Commits
Author SHA1 Message Date
jialin 66e8f83395 fix: did not cache workers and clusters in model files 2025-12-31 10:23:15 +08:00
jialin 41ebceca8f chore: static iconfont files 2025-12-29 15:40:36 +08:00
jialin 632685672c fix: wheel event passive 2025-12-29 15:28:40 +08:00
jialin bd2e4bb633 docs: hygon notes 2025-12-29 09:36:48 +08:00
jialin 835633d44b fix: help menu item clickable area 2025-12-26 18:18:32 +08:00
EVGENY Mandjialin 75773e6b00 Update models.ts 2025-12-26 18:16:33 +08:00
EVGENY Mandjialin a21b9b5244 Update users.ts 2025-12-26 18:16:02 +08:00
EVGENY Mandjialin 38bf76dc14 Update common.ts 2025-12-26 18:15:29 +08:00
EVGENY Mandjialin 9461341104 Update clusters.ts 2025-12-26 18:15:05 +08:00
jialin 5b5b2c6364 fix: chat compare switch model meta 2025-12-26 17:29:36 +08:00
jialin a006263e51 fix: add worker to default cluster 2025-12-26 12:08:30 +08:00
jialin febdd38f7c fix: set submitloading as false in catch 2025-12-26 09:48:10 +08:00
jialin 1b4d335b09 fix: store hideModel value in global session 2025-12-25 20:36:48 +08:00
36 changed files with 302 additions and 242 deletions
+13
View File
@@ -344,3 +344,16 @@ textarea:hover {
.text-success { .text-success {
color: var(--ant-color-success); color: var(--ant-color-success);
} }
.desc-fill {
font-weight: 600;
color: var(--ant-color-text);
background-color: var(--ant-color-fill-content);
line-height: 1.5;
padding: 2px 6px;
border-radius: 4px;
}
.line-6 {
line-height: 24px;
}
+13
View File
@@ -20,17 +20,30 @@ export const getRequestId = () => {
return store.get(requestIdAtom); return store.get(requestIdAtom);
}; };
// store for cluster list: res.items from api
export const clusterListAtom = atom< export const clusterListAtom = atom<
{ {
label: string; label: string;
value: number; value: number;
provider: string;
state: string;
is_default: boolean;
workers: number;
ready_workers: number;
gpus: number;
}[] }[]
>([]); >([]);
// store for worker list: res.items from api
export const workerListAtom = atom< export const workerListAtom = atom<
{ {
label: string; label: string;
value: number; value: number;
cluster_id: number;
state: string;
id: number;
labels: Record<string, any>;
name: string;
}[] }[]
>([]); >([]);
+1
View File
@@ -54,3 +54,4 @@ export const userSettingsHelperAtom = atom(
}); });
} }
); );
export const hideModalTemporarilyAtom = atom<boolean>(false);
+15 -3
View File
@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: iconfont; /* Project id 4613488 */ font-family: iconfont; /* Project id 4613488 */
src: url('iconfont.woff2?t=1763436184844') format('woff2'), src: url('iconfont.woff2?t=1766993792323') format('woff2'),
url('iconfont.woff?t=1763436184844') format('woff'), url('iconfont.woff?t=1766993792323') format('woff'),
url('iconfont.ttf?t=1763436184844') format('truetype'); url('iconfont.ttf?t=1766993792323') format('truetype');
} }
.iconfont { .iconfont {
@@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-cloud::before {
content: "\e6bc";
}
.icon-server02::before {
content: "\e6bd";
}
.icon-drag_handle::before {
content: "\e6b9";
}
.icon-basic::before { .icon-basic::before {
content: "\e6bb"; content: "\e6bb";
} }
File diff suppressed because one or more lines are too long
@@ -5,6 +5,27 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "46296038",
"name": "cloud",
"font_class": "cloud",
"unicode": "e6bc",
"unicode_decimal": 59068
},
{
"icon_id": "46296037",
"name": "server",
"font_class": "server02",
"unicode": "e6bd",
"unicode_decimal": 59069
},
{
"icon_id": "46272083",
"name": "drag_handle",
"font_class": "drag_handle",
"unicode": "e6b9",
"unicode_decimal": 59065
},
{ {
"icon_id": "46055620", "icon_id": "46055620",
"name": "basic", "name": "basic",
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -1,8 +1,8 @@
import { createFromIconfontCN } from '@ant-design/icons'; import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js'; import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4613488_xvmo08q7urm.js' scriptUrl: ''
}); });
export default IconFont; export default IconFont;
+5 -2
View File
@@ -168,14 +168,17 @@ export default function useOverlayScroller(data?: {
// add wheel event // add wheel event
const handleWheelEvent = () => { const handleWheelEvent = () => {
scrollElementRef.current?.addEventListener?.('wheel', handleWheelCallback); scrollElementRef.current?.addEventListener?.('wheel', handleWheelCallback, {
passive: true
});
}; };
// remove wheel event // remove wheel event
const removeWheelEvent = () => { const removeWheelEvent = () => {
scrollElementRef.current?.removeEventListener?.( scrollElementRef.current?.removeEventListener?.(
'wheel', 'wheel',
handleWheelCallback handleWheelCallback,
{ passive: true }
); );
}; };
+9 -16
View File
@@ -202,23 +202,16 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
items: helpList.map((item) => ({ items: helpList.map((item) => ({
key: item.key, key: item.key,
label: ( label: (
<span className="flex flex-center"> <a
className="flex flex-center gap-8"
href={item.url}
target="_blank"
rel="noreferrer"
>
{item.icon} {item.icon}
<a {item.label}
className="m-l-8 " </a>
href={item.url} )
target="_blank"
rel="noreferrer"
>
{item.label}
</a>
</span>
),
onClick() {
if (item.key === 'version') {
showVersion();
}
}
})) }))
}; };
+1 -2
View File
@@ -19,8 +19,7 @@ export default {
'backend.mode.yaml': 'YAML Mode', 'backend.mode.yaml': 'YAML Mode',
'backend.form.healthCheckPath': 'Health Check Path', 'backend.form.healthCheckPath': 'Health Check Path',
'backend.form.defaultExecuteCommand': 'Default Execution Command', 'backend.form.defaultExecuteCommand': 'Default Execution Command',
'backend.form.defaultExecuteCommand.tips': 'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
'{{model_path}}, {{port}}, {{worker_ip}} and {{model_name}} are placeholders that will be substituted with the actual values during deployment.',
'backend.form.defaultBackendParameters': 'Default Backend Parameters', 'backend.form.defaultBackendParameters': 'Default Backend Parameters',
'backend.form.versionConfig': 'Versions Config', 'backend.form.versionConfig': 'Versions Config',
'backend.form.addParameter': 'Add Parameter', 'backend.form.addParameter': 'Add Parameter',
+1 -2
View File
@@ -51,8 +51,7 @@ export default {
'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.', 'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.',
'clusters.addworker.nvidiaNotes-02': 'clusters.addworker.nvidiaNotes-02':
'If a model directory already exists on the worker, you can specify the path to mount it.', 'If a model directory already exists on the worker, you can specify the path to mount it.',
'clusters.addworker.hygonNotes': `If the <span class="bold-text">/opt/hyhal</span> directory does not exist, create a symbolic link to the Hygon installation path. 'clusters.addworker.hygonNotes': `If <span class="bold-text">/opt/hyhal</span> or <span class="bold-text">/opt/dtk</span> does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: <span class="desc-fill">ln -s /path/to/hyhal /opt/hyhal</span> <span class="desc-fill">ln -s /path/to/dtk /opt/dtk</span>.`,
Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
'clusters.addworker.corexNotes': `If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path: 'clusters.addworker.corexNotes': `If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path:
<span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.`, <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.`,
'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path: 'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path:
+1 -2
View File
@@ -19,8 +19,7 @@ export default {
'backend.mode.yaml': 'YAML Mode', 'backend.mode.yaml': 'YAML Mode',
'backend.form.healthCheckPath': 'Health Check Path', 'backend.form.healthCheckPath': 'Health Check Path',
'backend.form.defaultExecuteCommand': 'Default Execution Command', 'backend.form.defaultExecuteCommand': 'Default Execution Command',
'backend.form.defaultExecuteCommand.tips': 'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
'{{model_path}}, {{port}}, {{worker_ip}} and {{model_name}} are placeholders that will be substituted with the actual values during deployment.',
'backend.form.defaultBackendParameters': 'Default Backend Parameters', 'backend.form.defaultBackendParameters': 'Default Backend Parameters',
'backend.form.versionConfig': 'Versions Config', 'backend.form.versionConfig': 'Versions Config',
'backend.form.addParameter': 'Add Parameter', 'backend.form.addParameter': 'Add Parameter',
+2 -3
View File
@@ -51,8 +51,7 @@ export default {
'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.', 'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.',
'clusters.addworker.nvidiaNotes-02': 'clusters.addworker.nvidiaNotes-02':
'If a model directory already exists on the worker, you can specify the path to mount it.', 'If a model directory already exists on the worker, you can specify the path to mount it.',
'clusters.addworker.hygonNotes': `If the <span class="bold-text">/opt/hyhal</span> directory does not exist, create a symbolic link to the Hygon installation path. 'clusters.addworker.hygonNotes': `If <span class="bold-text">/opt/hyhal</span> or <span class="bold-text">/opt/dtk</span> does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: <span class="desc-fill">ln -s /path/to/hyhal /opt/hyhal</span> <span class="desc-fill">ln -s /path/to/dtk /opt/dtk</span>.`,
Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
'clusters.addworker.corexNotes': `If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path: 'clusters.addworker.corexNotes': `If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path:
<span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.`, <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.`,
'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path: 'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path:
@@ -165,7 +164,7 @@ Same applies to the <span class="bold-text">/opt/dtk</span> directory.`,
// 43. 'cluster.provider.comingsoon': 'Coming soon', // 43. 'cluster.provider.comingsoon': 'Coming soon',
// 44. 'clusters.addworker.nvidiaNotes-01': 'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.', // 44. 'clusters.addworker.nvidiaNotes-01': 'If multiple outbound IPs exist, specify the one you want the worker to use. Please double-check with <span class="bold-text">hostname -I | xargs -n1</span>.',
// 45. 'clusters.addworker.nvidiaNotes-02': 'If a model directory already exists on the worker, you can specify the path to mount it.', // 45. 'clusters.addworker.nvidiaNotes-02': 'If a model directory already exists on the worker, you can specify the path to mount it.',
// 46. 'clusters.addworker.hygonNotes': 'If the <span class="bold-text">/opt/hyhal</span> directory does not exist, create a symbolic link to the Hygon installation path. Same applies to the <span class="bold-text">/opt/dtk</span> directory.', // 46. 'clusters.addworker.hygonNotes': `If <span class="bold-text">/opt/hyhal</span> or <span class="bold-text">/opt/dtk</span> does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: <span class="desc-fill">ln -s /path/to/hyhal /opt/hyhal</span> <span class="desc-fill">ln -s /path/to/dtk /opt/dtk</span>.`,
// 47. 'clusters.addworker.corexNotes': 'If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path: <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.', // 47. 'clusters.addworker.corexNotes': 'If the <span class="bold-text">/lib/modules</span> directory does not exist, create a symbolic link to the Iluvatar installation path: <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Same applies to the <span class="bold-text">/usr/local/corex</span> directory.',
// 48. 'clusters.addworker.metaxNotes': 'If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path: <span class="bold-text">ln -s /path/to/metax /opt/mxdriver</span>. Same applies to the <span class="bold-text">/opt/maca</span> directory.', // 48. 'clusters.addworker.metaxNotes': 'If the <span class="bold-text">/opt/mxdriver</span> directory does not exist, create a symbolic link to the MetaX installation path: <span class="bold-text">ln -s /path/to/metax /opt/mxdriver</span>. Same applies to the <span class="bold-text">/opt/maca</span> directory.',
// 49. 'clusters.addworker.cambriconNotes': 'If the <span class="bold-text">/usr/local/neuware</span> directory does not exist, create a symbolic link to the Cambricon installation path: <span class="bold-text">ln -s /path/to/neuware /usr/local/neuware</span>.' // 49. 'clusters.addworker.cambriconNotes': 'If the <span class="bold-text">/usr/local/neuware</span> directory does not exist, create a symbolic link to the Cambricon installation path: <span class="bold-text">ln -s /path/to/neuware /usr/local/neuware</span>.'
+1 -2
View File
@@ -19,8 +19,7 @@ export default {
'backend.mode.yaml': 'Режим YAML', 'backend.mode.yaml': 'Режим YAML',
'backend.form.healthCheckPath': 'Путь проверки здоровья', 'backend.form.healthCheckPath': 'Путь проверки здоровья',
'backend.form.defaultExecuteCommand': 'Команда выполнения по умолчанию', 'backend.form.defaultExecuteCommand': 'Команда выполнения по умолчанию',
'backend.form.defaultExecuteCommand.tips': 'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' и '{{'model_name'}}' заполняются реальными значениями во время запуска`,
'{{model_path}}, {{port}}, {{worker_ip}} и {{model_name}} заполняются реальными значениями во время запуска',
'backend.form.defaultBackendParameters': 'Параметры бэкенда по умолчанию', 'backend.form.defaultBackendParameters': 'Параметры бэкенда по умолчанию',
'backend.form.versionConfig': 'Конфигурация версий', 'backend.form.versionConfig': 'Конфигурация версий',
'backend.form.addParameter': 'Добавить параметр', 'backend.form.addParameter': 'Добавить параметр',
+18 -37
View File
@@ -51,8 +51,7 @@ export default {
'Если существует несколько исходящих IP-адресов, укажите тот, который должен использовать воркер. Пожалуйста, перепроверьте с помощью <span class="bold-text">hostname -I | xargs -n1</span>.', 'Если существует несколько исходящих IP-адресов, укажите тот, который должен использовать воркер. Пожалуйста, перепроверьте с помощью <span class="bold-text">hostname -I | xargs -n1</span>.',
'clusters.addworker.nvidiaNotes-02': 'clusters.addworker.nvidiaNotes-02':
'Если директория с моделями уже существует на воркере, вы можете указать путь для её монтирования.', 'Если директория с моделями уже существует на воркере, вы можете указать путь для её монтирования.',
'clusters.addworker.hygonNotes': 'clusters.addworker.hygonNotes': `If <span class="bold-text">/opt/hyhal</span> or <span class="bold-text">/opt/dtk</span> does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: <span class="desc-fill">ln -s /path/to/hyhal /opt/hyhal</span> <span class="desc-fill">ln -s /path/to/dtk /opt/dtk</span>.`,
'Если директория <span class="bold-text">/opt/hyhal</span> не существует, создайте символическую ссылку на путь установки Hygon: <span class="bold-text">/opt/hyhal</span>. Аналогично для директории <span class="bold-text">/opt/dtk</span>.',
'clusters.addworker.corexNotes': 'clusters.addworker.corexNotes':
'Если директория <span class="bold-text">/lib/modules</span> не существует, создайте символическую ссылку на путь установки Iluvatar: <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Аналогично для директории <span class="bold-text">/usr/local/corex</span>.', 'Если директория <span class="bold-text">/lib/modules</span> не существует, создайте символическую ссылку на путь установки Iluvatar: <span class="bold-text">ln -s /path/to/corex /lib/modules</span>. Аналогично для директории <span class="bold-text">/usr/local/corex</span>.',
'clusters.addworker.metaxNotes': 'clusters.addworker.metaxNotes':
@@ -97,47 +96,29 @@ export default {
'напр. /data/cache (путь должен начинаться с /)', 'напр. /data/cache (путь должен начинаться с /)',
'clusters.addworker.vendorNotes.title': 'Примечания для устройств {vendor}', 'clusters.addworker.vendorNotes.title': 'Примечания для устройств {vendor}',
'clusters.button.genToken': 'clusters.button.genToken':
'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.', 'Нужен новый токен? Нажмите <a href="{link}" target="_blank">здесь</a>.',
'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`, 'clusters.addworker.amdNotes-01': `Если директория <span class="bold-text">/opt/rocm</span> не существует, создайте символическую ссылку на путь установки ROCm: <span class="bold-text">ln -s /путь/к/rocm /opt/rocm</span>.`,
'clusters.addworker.message.success_single': 'clusters.addworker.message.success_single':
'{count} new worker has been added to the cluster.', '{count} новый воркер был добавлен в кластер.',
'clusters.addworker.message.success_multiple': 'clusters.addworker.message.success_multiple':
'{count} new workers have been added to the cluster.', '{count} новых воркеров были добавлены в кластер.',
'clusters.create.serverUrl': 'Server URL', 'clusters.create.serverUrl': 'URL сервера',
'clusters.create.workerConfig': 'Worker Configuration', 'clusters.create.workerConfig': 'Конфигурация воркера',
'clusters.addworker.containerName': 'Worker Container Name', 'clusters.addworker.containerName': 'Имя контейнера воркера',
'clusters.addworker.containerName.tips': 'clusters.addworker.containerName.tips':
'Specify a name for the worker container.', 'Укажите имя для контейнера воркера.',
'clusters.addworker.dataVolume': 'GPUStack Data Volume', 'clusters.addworker.dataVolume': 'Том данных GPUStack',
'clusters.addworker.dataVolume.tips': 'clusters.addworker.dataVolume.tips':
'Specify a data storage path for GPUStack.', 'Укажите путь для хранения данных GPUStack.',
'clusters.table.ip.internal': 'Internal', 'clusters.table.ip.internal': 'Внутренний',
'clusters.table.ip.external': 'External', 'clusters.table.ip.external': 'Внешний',
'clusters.form.serverUrl.tips': 'clusters.form.serverUrl.tips':
'Specify the server URL accessible from your cloud provider.', 'Укажите URL сервера, доступный из вашего облачного провайдера.',
'clusters.form.setDefault': 'Set as Default', 'clusters.form.setDefault': 'Установить по умолчанию',
'clusters.form.setDefault.tips': 'Default for deployment.' 'clusters.form.setDefault.tips':
'Использовать по умолчанию для развертывания.'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'clusters.addworker.amdNotes-01': `If the <span class="bold-text">/opt/rocm</span> directory does not exist, please create a symbolic link pointing to the ROCm installed path: <span class="bold-text">ln -s /path/to/rocm /opt/rocm</span>.`, // 1. 'clusters.addworker.hygonNotes': `If <span class="bold-text">/opt/hyhal</span> or <span class="bold-text">/opt/dtk</span> does not exist, create symbolic links pointing to the corresponding Hygon installation paths, for example: <span class="desc-fill">ln -s /path/to/hyhal /opt/hyhal</span> <span class="desc-fill">ln -s /path/to/dtk /opt/dtk</span>.`,
// 2. 'clusters.button.genToken': 'Need to create a new token? Click <a href="{link}" target="_blank">here</a>.',
// 3. 'clusters.addworker.cacheVolume': 'Model Cache Volume Mount',
// 4. 'clusters.addworker.cacheVolume.tips': 'If you want to customize the model cache directory, you can specify the path to mount it.',
// 5. 'clusters.addworker.message.success_single': '{count} new worker has been added to the cluster.',
// 6. 'clusters.addworker.message.success_multiple': '{count} new workers have been added to the cluster.',
// 7. 'clusters.create.serverUrl': 'Server URL',
// 8. 'clusters.create.workerConfig': 'Worker Configuration'
// 9. 'clusters.addworker.containerName': 'Worker Container Name',
// 10. 'clusters.addworker.containerName.tips':'Specify a name for the worker container.',
// 11. 'clusters.addworker.dataVolume': 'GPUStack Data Volume',
// 12. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for GPUStack.',
// 10. 'clusters.table.ip.internal': 'Internal',
// 11. 'clusters.table.ip.external': 'External',
// 12. 'clusters.form.serverUrl.tips': 'Specify the server URL accessible from your cloud provider.'
// 13. 'clusters.addworker.specifyWorkerIP': 'Specify Worker IP <span class="text-tertiary">{type}</span>',
// 14. 'clusters.form.setDefault': 'Set as Default',
// 15. 'clusters.form.setDefault.tips': 'Default for deployment',
// 16. 'clusters.addworker.enterWorkerAddress': 'Enter worker external address',
// 17. 'clusters.addworker.enterWorkerAddress.error': 'Please enter the worker external address.',
// ================================================================ // ================================================================
+5 -8
View File
@@ -265,15 +265,12 @@ export default {
'common.form.rule.selectInput': 'Выберите или введите {name}', 'common.form.rule.selectInput': 'Выберите или введите {name}',
'common.tag.experimental': 'Экспериментальный', 'common.tag.experimental': 'Экспериментальный',
'common.title.example': 'Пример', 'common.title.example': 'Пример',
'common.button.dontshowagain': "Don't show again", 'common.button.dontshowagain': "Больше не показывать",
'common.sorter.tips.ascend': 'Click to sort ascending', 'common.sorter.tips.ascend': 'Нажмите для сортировки по возрастанию',
'common.sorter.tips.descend': 'Click to sort descending', 'common.sorter.tips.descend': 'Нажмите для сортировки по убыванию',
'common.sorter.tips.cancel': 'Click to cancel sorting' 'common.sorter.tips.cancel': 'Нажмите, чтобы отменить сортировку'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'common.button.dontshowagain': "Don't show again",
// 2. 'common.sorter.tips.ascend': 'Click to sort ascending',
// 3. 'common.sorter.tips.descend': 'Click to sort descending',
// 4. 'common.sorter.tips.cancel': 'Click to cancel sorting'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+8 -14
View File
@@ -268,24 +268,18 @@ export default {
'Используйте следующий префикс пути и укажите имя модели либо в заголовке запроса <span class="bold-text">X-GPUStack-Model</span>, либо в поле model в теле запроса. Все запросы с этим префиксом пути будут перенаправлены в бэкенд вывода.', 'Используйте следующий префикс пути и укажите имя модели либо в заголовке запроса <span class="bold-text">X-GPUStack-Model</span>, либо в поле model в теле запроса. Все запросы с этим префиксом пути будут перенаправлены в бэкенд вывода.',
'models.form.backendVersion.deprecated': 'Устаревший', 'models.form.backendVersion.deprecated': 'Устаревший',
'models.accessSettings.public.desc': 'models.accessSettings.public.desc':
'Accessible to anyone without authentication.', 'Доступно всем без аутентификации.',
'models.accessSettings.authed.tips': 'models.accessSettings.authed.tips':
'Accessible to all authenticated platform users.', 'Доступно всем аутентифицированным пользователям платформы.',
'models.accessSettings.allowedUsers.tips': 'models.accessSettings.allowedUsers.tips':
'Only designated users can access the model.', 'Доступ к модели имеют только назначенные пользователи.',
'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`, 'models.form.backendVersions.tips': `Чтобы использовать больше версий, перейдите на страницу {link} и отредактируйте бэкенд для добавления версий.`,
'models.catalog.nogpus.tips': 'models.catalog.nogpus.tips':
'No compatible GPUs are available in the selected cluster for this model.', 'В выбранном кластере нет доступных GPU, совместимых с этой моделью.',
'models.form.modelfile.notfound': `The model file path you specified does not exist on the GPUStack server. It's recommended to place the model file at the same path on both the GPUStack server and GPUStack workers. This helps GPUStack make better decisions.`, 'models.form.modelfile.notfound': `Указанный путь к файлу модели не существует на сервере GPUStack. Рекомендуется размещать файл модели по одному и тому же пути как на сервере GPUStack, так и на воркерах GPUStack. Это поможет системе принимать лучшие решения по распределению ресурсов.`,
'models.form.readyWorkers': 'workers ready' 'models.form.readyWorkers': 'воркеров готово'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'models.accessSettings.public.desc': 'Accessible to anyone without authentication.',
// 2. 'models.accessSettings.authed.tips': 'Accessible to all authenticated platform users.',
// 3. 'models.accessSettings.allowedUsers.tips': 'Only designated users can access the model.',
// 4. 'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
// 5. 'models.catalog.nogpus.tips': 'No compatible GPUs are available in the selected cluster for this model.',
// 6. 'models.form.modelfile.notfound': `The model file path you specified does not exist on the GPUStack server. It's recommended to place the model file at the same path on both the GPUStack server and GPUStack workers. This helps GPUStack make better decisions.`,
// 7. 'models.form.readyWorkers': 'workers ready'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+2 -2
View File
@@ -40,9 +40,9 @@ export default {
'users.status.deactivate': 'Деактивировать аккаунт', 'users.status.deactivate': 'Деактивировать аккаунт',
'users.status.inactiveAccount': 'Неактивный аккаунт', 'users.status.inactiveAccount': 'Неактивный аккаунт',
'users.login.getInitialPassword': 'users.login.getInitialPassword':
'Run the following command on your server to retrieve the initial admin password.' 'Выполните следующую команду на вашем сервере, чтобы получить начальный пароль администратора.'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'users.login.getInitialPassword': 'Run the following command on your server to retrieve the initial admin password.'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+1 -2
View File
@@ -19,8 +19,7 @@ export default {
'backend.mode.yaml': 'YAML 模式', 'backend.mode.yaml': 'YAML 模式',
'backend.form.healthCheckPath': '健康检查路径', 'backend.form.healthCheckPath': '健康检查路径',
'backend.form.defaultExecuteCommand': '默认执行命令', 'backend.form.defaultExecuteCommand': '默认执行命令',
'backend.form.defaultExecuteCommand.tips': 'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}'、'{{'port'}}'、'{{'worker_ip'}}' 和 '{{'model_name'}}' 都是占位符,在部署过程中会被替换为实际的值。`,
'{{model_path}}、{{port}}、{{worker_ip}} 和 {{model_name}} 都是占位符,在部署过程中会被替换为实际的值。',
'backend.form.defaultBackendParameters': '默认后端参数', 'backend.form.defaultBackendParameters': '默认后端参数',
'backend.form.versionConfig': '版本配置', 'backend.form.versionConfig': '版本配置',
'backend.form.addParameter': '添加参数', 'backend.form.addParameter': '添加参数',
+3 -2
View File
@@ -49,8 +49,9 @@ export default {
'如果节点有多个出站 IP 地址,请填写 <span class="bold-text">WORKER_IP</span>,以确保使用指定的 IP。可通过命令 <span class="bold-text">hostname -I | xargs -n1</span> 进行确认。', '如果节点有多个出站 IP 地址,请填写 <span class="bold-text">WORKER_IP</span>,以确保使用指定的 IP。可通过命令 <span class="bold-text">hostname -I | xargs -n1</span> 进行确认。',
'clusters.addworker.nvidiaNotes-02': 'clusters.addworker.nvidiaNotes-02':
'如果节点上已经存在模型目录,你可以指定该路径进行挂载。', '如果节点上已经存在模型目录,你可以指定该路径进行挂载。',
'clusters.addworker.hygonNotes': 'clusters.addworker.hygonNotes': `如果 <span class="bold-text">/opt/hyhal</span> 或 <span class="bold-text">/opt/dtk</span> 不存在,请创建指向对应海光安装路径的符号链接,例如:
'如果 <span class="bold-text">/opt/hyhal</span> 目录不存在,请创建指向海光安装路径的符号链接:<span class="bold-text">/opt/hyhal</span>。与 <span class="bold-text">/opt/dtk</span> 目录相同。', <span class="desc-fill line-6">ln -s /path/to/hyhal /opt/hyhal</span>
<span class="desc-fill line-6">ln -s /path/to/dtk /opt/dtk</span>`,
'clusters.addworker.corexNotes': 'clusters.addworker.corexNotes':
'如果 <span class="bold-text">/lib/modules</span> 目录不存在,请创建指向天数智芯安装路径的符号链接:<span class="bold-text">ln -s /path/to/corex /lib/modules</span>。与 <span class="bold-text">/usr/local/corex</span> 目录相同。', '如果 <span class="bold-text">/lib/modules</span> 目录不存在,请创建指向天数智芯安装路径的符号链接:<span class="bold-text">ln -s /path/to/corex /lib/modules</span>。与 <span class="bold-text">/usr/local/corex</span> 目录相同。',
'clusters.addworker.metaxNotes': 'clusters.addworker.metaxNotes':
@@ -164,6 +164,7 @@ const ClusterCreate = () => {
setCurrentStep((prev) => Math.min(prev + 1, steps.length - 1)); setCurrentStep((prev) => Math.min(prev + 1, steps.length - 1));
} }
} catch (error) { } catch (error) {
setSubmitLoading(false);
console.log('next error:', error); console.log('next error:', error);
} }
}; };
+10 -13
View File
@@ -37,11 +37,7 @@ import {
K8sStepsFromCluter K8sStepsFromCluter
} from './components/add-worker/config'; } from './components/add-worker/config';
import PoolRows from './components/pool-rows'; import PoolRows from './components/pool-rows';
import { import { ProviderType, ProviderValueMap } from './config';
ClusterStatusValueMap,
ProviderType,
ProviderValueMap
} from './config';
import { import {
ClusterListItem, ClusterListItem,
CredentialListItem, CredentialListItem,
@@ -79,7 +75,8 @@ const Clusters: React.FC = () => {
useExpandedRowKeys(expandAtom); useExpandedRowKeys(expandAtom);
const navigate = useNavigate(); const navigate = useNavigate();
const intl = useIntl(); const intl = useIntl();
const { handleAddWorker, AddWorkerModal, setStepList } = useAddWorker({}); const { handleAddWorker, checkDefaultCluster, AddWorkerModal, setStepList } =
useAddWorker({});
const [openAddModal, setOpenAddModal] = useState<{ const [openAddModal, setOpenAddModal] = useState<{
open: boolean; open: boolean;
@@ -265,12 +262,12 @@ const Clusters: React.FC = () => {
dataSource.loadend && dataSource.loadend &&
dataSource.dataList?.length > 0 dataSource.dataList?.length > 0
) { ) {
const targetCluster = dataSource.dataList.find( const list = dataSource.dataList?.map((item) => ({
(cluster) => label: item.name,
cluster.state === ClusterStatusValueMap.Ready && value: item.id,
!cluster.workers && ...item
!cluster.worker_pools?.length }));
); const targetCluster = checkDefaultCluster(list);
if (targetCluster) { if (targetCluster) {
const actionMap = { const actionMap = {
@@ -280,7 +277,7 @@ const Clusters: React.FC = () => {
}; };
handleSelect( handleSelect(
actionMap[targetCluster.provider as string], actionMap[targetCluster.provider as string],
targetCluster targetCluster as ListItem
); );
// reset session // reset session
setClusterSession(null); setClusterSession(null);
@@ -17,7 +17,7 @@ interface AddWorkerContextProps {
token: string; token: string;
image: string; image: string;
server_url: string; server_url: string;
cluster_id: number; cluster_id: number | null;
}; };
registerField: (key: SummaryDataKey) => () => void; registerField: (key: SummaryDataKey) => () => void;
updateField: (key: SummaryDataKey, value: any) => void; updateField: (key: SummaryDataKey, value: any) => void;
@@ -41,7 +41,7 @@ type AddWorkerProps = {
token: string; token: string;
image: string; image: string;
server_url: string; server_url: string;
cluster_id: number; cluster_id: number | null;
[key: string]: any; [key: string]: any;
}; };
}; };
@@ -32,12 +32,12 @@ type AddWorkerProps = {
stepList: StepName[]; stepList: StepName[];
onClusterChange?: (value: number, row?: any) => void; onClusterChange?: (value: number, row?: any) => void;
onCancel: () => void; onCancel: () => void;
cluster_id: number; cluster_id: number | null;
registrationInfo?: { registrationInfo?: {
token: string; token: string;
image: string; image: string;
server_url: string; server_url: string;
cluster_id: number; cluster_id: number | null;
}; };
}; };
@@ -64,12 +64,12 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
token: string; token: string;
image: string; image: string;
server_url: string; server_url: string;
cluster_id: number; cluster_id: number | null;
}>({ }>({
token: '', token: '',
image: '', image: '',
server_url: '', server_url: '',
cluster_id: 0 cluster_id: null
}); });
const handleOnClusterChange = async (value: number, row?: any) => { const handleOnClusterChange = async (value: number, row?: any) => {
@@ -21,12 +21,12 @@ const useAddWorker = (props: {
open: boolean; open: boolean;
provider: ProviderType; provider: ProviderType;
title: string; title: string;
cluster_id: number; cluster_id: number | null;
}>({ }>({
open: false, open: false,
provider: null, provider: null,
title: '', title: '',
cluster_id: 0 cluster_id: null
}); });
const handleAddWorker = async (row: ClusterListItem) => { const handleAddWorker = async (row: ClusterListItem) => {
@@ -43,7 +43,12 @@ const useAddWorker = (props: {
open: true, open: true,
title: title, title: title,
provider: row.provider as ProviderType, provider: row.provider as ProviderType,
cluster_id: row.id cluster_id: [
ProviderValueMap.Docker,
ProviderValueMap.Kubernetes
].includes(row.provider as string)
? row.id
: null
}); });
} catch (error: any) { } catch (error: any) {
message.error(error?.message || 'Failed to fetch cluster token'); message.error(error?.message || 'Failed to fetch cluster token');
@@ -67,6 +72,38 @@ const useAddWorker = (props: {
.filter((item) => item.state === ClusterStatusValueMap.Ready); .filter((item) => item.state === ClusterStatusValueMap.Ready);
}, [clusterList]); }, [clusterList]);
const checkDefaultCluster = (
clusterList: Global.BaseOption<number, ClusterListItem>[]
) => {
// select default and ready cluster first, digitalocean no READY state
let currentData = clusterList.find(
(item) => item.is_default && item.state === ClusterStatusValueMap.Ready
);
if (!currentData) {
// select docker ready cluster
currentData = clusterList.find(
(item) =>
item.provider === ProviderValueMap.Docker &&
item.state === ClusterStatusValueMap.Ready
);
}
if (!currentData) {
// select any ready cluster
currentData = clusterList.find(
(item) => item.state === ClusterStatusValueMap.Ready
);
}
if (!currentData) {
// maybe no ready a digitalocean cluster
currentData = clusterList[0];
}
return currentData || null;
};
const AddWorkerModal = ( const AddWorkerModal = (
<AddWorker <AddWorker
title={openAddWorker.title} title={openAddWorker.title}
@@ -82,7 +119,7 @@ const useAddWorker = (props: {
open: false, open: false,
provider: null, provider: null,
title: '', title: '',
cluster_id: 0 cluster_id: null
}) })
} }
></AddWorker> ></AddWorker>
@@ -90,6 +127,7 @@ const useAddWorker = (props: {
return { return {
handleAddWorker, handleAddWorker,
checkDefaultCluster,
AddWorkerModal, AddWorkerModal,
setStepList setStepList
}; };
@@ -1,4 +1,5 @@
import { clusterSessionAtom } from '@/atoms/clusters'; import { clusterSessionAtom } from '@/atoms/clusters';
import { hideModalTemporarilyAtom } from '@/atoms/settings';
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import ScrollerModal from '@/components/scroller-modal/index'; import ScrollerModal from '@/components/scroller-modal/index';
import { PageAction } from '@/config'; import { PageAction } from '@/config';
@@ -60,7 +61,9 @@ export default function useAddResource(options?: { onCreated?: () => void }) {
const navigate = useNavigate(); const navigate = useNavigate();
const { setUserSettings, userSettings } = useUserSettings(); const { setUserSettings, userSettings } = useUserSettings();
const [, setClusterSession] = useAtom(clusterSessionAtom); const [, setClusterSession] = useAtom(clusterSessionAtom);
const [hideModalTemporarily, setHideModalTemporarily] = useState(false); const [hideModalTemporarily, setHideModalTemporarily] = useAtom(
hideModalTemporarilyAtom
);
const { fetchResource, resourceCount, resourceAtom } = useClusterList(); const { fetchResource, resourceCount, resourceAtom } = useClusterList();
const [loadingStatus, setLoadingStatus] = useState({ const [loadingStatus, setLoadingStatus] = useState({
@@ -153,6 +153,8 @@ export const useGenerateWorkerOptions = () => {
{ state: string; labels: Record<string, string>; cluster_id: number } { state: string; labels: Record<string, string>; cluster_id: number }
>[] >[]
>([]); >([]);
const [, setClusterListAtom] = useAtom(clusterListAtom);
const [, setWorkerListAtom] = useAtom(workerListAtom);
const generateCascaderWorkerOptions = ( const generateCascaderWorkerOptions = (
workerList: WorkerListItem[], workerList: WorkerListItem[],
@@ -201,29 +203,31 @@ export const useGenerateWorkerOptions = () => {
const data = await getDataList(); const data = await getDataList();
const [workerList, clusterList] = data; const [workerList, clusterList] = data;
generateCascaderWorkerOptions(workerList, clusterList); generateCascaderWorkerOptions(workerList, clusterList);
setWorkersList(
workerList.map((item) => ({ const workerOptions = workerList.map((item) => ({
cluster_id: item.cluster_id, cluster_id: item.cluster_id,
state: item.state, state: item.state,
label: item.name, label: item.name,
value: item.id, value: item.id,
id: item.id, id: item.id,
labels: item.labels || {}, labels: item.labels || {},
name: item.name name: item.name
})) }));
); const clusterOptions = clusterList.map((item) => ({
setClusterList( label: item.name,
clusterList.map((item) => ({ value: item.id,
label: item.name, provider: item.provider as string,
value: item.id, state: item.state,
provider: item.provider as string, is_default: item.is_default,
state: item.state, workers: item.workers,
is_default: item.is_default, ready_workers: item.ready_workers,
workers: item.workers, gpus: item.gpus
ready_workers: item.ready_workers, }));
gpus: item.gpus
})) setWorkersList(workerOptions);
); setClusterList(clusterOptions);
setWorkerListAtom(workerOptions);
setClusterListAtom(clusterOptions);
}; };
return { return {
getWorkerOptionList, getWorkerOptionList,
@@ -280,7 +284,12 @@ export default function useFormInitialValues() {
const list = const list =
data.items?.map((item) => ({ data.items?.map((item) => ({
label: item.name, label: item.name,
value: item.id value: item.id,
cluster_id: item.cluster_id,
state: item.state,
id: item.id,
labels: item.labels || {},
name: item.name
})) || []; })) || [];
setWorkerList(data.items); setWorkerList(data.items);
setWorkerListAtom(list); setWorkerListAtom(list);
+2
View File
@@ -1,3 +1,4 @@
import { hideModalTemporarilyAtom } from '@/atoms/settings';
import { userAtom } from '@/atoms/user'; import { userAtom } from '@/atoms/user';
import { clearAtomStorage, clearStorageUserSettings } from '@/atoms/utils'; import { clearAtomStorage, clearStorageUserSettings } from '@/atoms/utils';
import { request } from '@umijs/max'; import { request } from '@umijs/max';
@@ -29,6 +30,7 @@ export const logout = async (userInfo?: any) => {
}); });
clearStorageUserSettings(); clearStorageUserSettings();
clearAtomStorage(userAtom); clearAtomStorage(userAtom);
clearAtomStorage(hideModalTemporarilyAtom);
if (res?.logout_url) { if (res?.logout_url) {
window.location.href = res.logout_url; window.location.href = res.logout_url;
@@ -14,6 +14,7 @@ interface ActiveModelsProps {
const ActiveModels: React.FC<ActiveModelsProps> = (props) => { const ActiveModels: React.FC<ActiveModelsProps> = (props) => {
const { spans, modelSelections, setModelRefs } = props; const { spans, modelSelections, setModelRefs } = props;
return ( return (
<Row gutter={[16, 0]} style={{ height: '100%' }}> <Row gutter={[16, 0]} style={{ height: '100%' }}>
{modelSelections.map((model, index) => ( {modelSelections.map((model, index) => (
@@ -21,7 +22,8 @@ const ActiveModels: React.FC<ActiveModelsProps> = (props) => {
span={spans.span} span={spans.span}
key={`${model.value || 'empty'}-${model.uid}`} key={`${model.value || 'empty'}-${model.uid}`}
style={{ style={{
height: spans.count < 4 ? 'calc(100% - 16px)' : 'calc(50% - 16px)' height: spans.count < 4 ? 'calc(100% - 16px)' : 'calc(50% - 16px)',
overflow: 'hidden'
}} }}
> >
<ModelItem <ModelItem
@@ -47,7 +47,8 @@ interface ModelItemProps {
} }
const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => { const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => {
const { modelList, model, instanceId } = props; const { modelList, ...restProps } = props;
const { model, instanceId } = restProps;
const { const {
globalParams, globalParams,
setGlobalParams, setGlobalParams,
@@ -66,14 +67,20 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => {
paramsConfig, paramsConfig,
initialValues, initialValues,
parameters parameters
} = useInitLLmMeta(props, { } = useInitLLmMeta(
defaultValues: { {
...llmInitialValues, ...restProps,
model: model modelList: modelFullList
}, },
defaultParamsConfig: ChatParamsConfig, {
metaKeys: LLM_METAKEYS defaultValues: {
}); ...llmInitialValues,
model: model
},
defaultParamsConfig: ChatParamsConfig,
metaKeys: LLM_METAKEYS
}
);
const intl = useIntl(); const intl = useIntl();
const isApplyToAllModels = useRef(false); const isApplyToAllModels = useRef(false);
const [systemMessage, setSystemMessage] = useState<string>(''); const [systemMessage, setSystemMessage] = useState<string>('');
+54 -67
View File
@@ -12,13 +12,7 @@ import { generateRandomNumber } from '@/utils';
import { useSearchParams } from '@umijs/max'; import { useSearchParams } from '@umijs/max';
import { useMemoizedFn } from 'ahooks'; import { useMemoizedFn } from 'ahooks';
import _ from 'lodash'; import _ from 'lodash';
import React, { import React, { useEffect, useMemo, useRef, useState } from 'react';
useCallback,
useEffect,
useMemo,
useRef,
useState
} from 'react';
import { ParamsSchema } from '../config/types'; import { ParamsSchema } from '../config/types';
import { import {
IMG_METAKEYS, IMG_METAKEYS,
@@ -133,37 +127,34 @@ export const useInitLLmMeta = (
return fields?.join(','); return fields?.join(',');
}, [paramsConfig]); }, [paramsConfig]);
const handleOnModelChange = useCallback( const handleOnModelChange = useMemoizedFn((val: string) => {
(val: string) => { if (!val) return;
if (!val) return; const model = modelList.find((item) => item.value === val);
const model = modelList.find((item) => item.value === val); const { form: initialData, meta } = extractLLMMeta(model?.meta);
const { form: initialData, meta } = extractLLMMeta(model?.meta); setModelMeta(meta);
setModelMeta(meta); setInitialValues({
setInitialValues({ ...initialData,
...initialData, model: val
model: val });
}); setParams({
setParams({ ...initialData,
...initialData, model: val
model: val });
}); const config = defaultParamsConfig.map((item) => {
const config = defaultParamsConfig.map((item) => { return {
return { ...item,
...item, attrs:
attrs: item.name === 'max_tokens'
item.name === 'max_tokens' ? { ...item.attrs, max: meta.max_tokens }
? { ...item.attrs, max: meta.max_tokens } : {
: { ...item.attrs
...item.attrs }
} };
}; });
}); setParamsConfig(config);
setParamsConfig(config); });
},
[modelList, defaultParamsConfig]
);
const handleOnValuesChange = useCallback( const handleOnValuesChange = useMemoizedFn(
(changeValues: Record<string, any>, allValues: Record<string, any>) => { (changeValues: Record<string, any>, allValues: Record<string, any>) => {
if (changeValues.model) { if (changeValues.model) {
handleOnModelChange(changeValues.model); handleOnModelChange(changeValues.model);
@@ -172,8 +163,7 @@ export const useInitLLmMeta = (
setParams(allValues); setParams(allValues);
setInitialValues(allValues); setInitialValues(allValues);
} }
}, }
[handleOnModelChange]
); );
useEffect(() => { useEffect(() => {
@@ -405,35 +395,32 @@ export const useInitImageMeta = (
return fields?.join(','); return fields?.join(',');
}, [paramsConfig]); }, [paramsConfig]);
const handleOnModelChange = useCallback( const handleOnModelChange = useMemoizedFn((val: string) => {
(val: string) => { if (!val) return;
if (!val) return; const model = modelList.find((item) => item.value === val);
const model = modelList.find((item) => item.value === val); const { form: initialData, sizeOptions } = extractIMGMeta(model?.meta);
const { form: initialData, sizeOptions } = extractIMGMeta(model?.meta); const newParamsConfig = generateImageParamsConfig(model, sizeOptions);
const newParamsConfig = generateImageParamsConfig(model, sizeOptions);
if (!isOpenaiCompatible) { if (!isOpenaiCompatible) {
setParamsConfig([...newParamsConfig, ...ImageAdvancedParamsConfig]); setParamsConfig([...newParamsConfig, ...ImageAdvancedParamsConfig]);
} else { } else {
setParamsConfig(newParamsConfig); setParamsConfig(newParamsConfig);
} }
setBasicParamsConfig(newParamsConfig); setBasicParamsConfig(newParamsConfig);
setImageSizeOptions(sizeOptions); setImageSizeOptions(sizeOptions);
setModelMeta(model?.meta || {}); setModelMeta(model?.meta || {});
setInitialValues({ setInitialValues({
...initialData, ...initialData,
seed: parameters.seed, seed: parameters.seed,
model: val model: val
}); });
setParams({ setParams({
...initialData, ...initialData,
seed: parameters.seed, seed: parameters.seed,
model: val model: val
}); });
updateCacheFormData(initialData); updateCacheFormData(initialData);
}, });
[modelList, isOpenaiCompatible]
);
const handleOnValuesChange = useMemoizedFn( const handleOnValuesChange = useMemoizedFn(
(changeValues: Record<string, any>, allValues: Record<string, any>) => { (changeValues: Record<string, any>, allValues: Record<string, any>) => {
+9 -18
View File
@@ -5,10 +5,6 @@ import useTableFetch from '@/hooks/use-table-fetch';
import PageBox from '@/pages/_components/page-box'; import PageBox from '@/pages/_components/page-box';
import { queryClusterList } from '@/pages/cluster-management/apis'; import { queryClusterList } from '@/pages/cluster-management/apis';
import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config'; import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add-worker/config';
import {
ClusterStatusValueMap,
ProviderValueMap
} from '@/pages/cluster-management/config';
import { ClusterListItem } from '@/pages/cluster-management/config/types'; import { ClusterListItem } from '@/pages/cluster-management/config/types';
import useAddWorker from '@/pages/cluster-management/hooks/use-add-worker'; import useAddWorker from '@/pages/cluster-management/hooks/use-add-worker';
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result'; import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
@@ -82,10 +78,11 @@ const Workers: React.FC = () => {
open: false, open: false,
currentData: null currentData: null
}); });
const { handleAddWorker, AddWorkerModal, setStepList } = useAddWorker({ const { handleAddWorker, checkDefaultCluster, AddWorkerModal, setStepList } =
clusterList: clusterData.list, useAddWorker({
clusterLoading: clusterData.loading clusterList: clusterData.list,
}); clusterLoading: clusterData.loading
});
const getClusterList = async () => { const getClusterList = async () => {
try { try {
@@ -105,6 +102,7 @@ const Workers: React.FC = () => {
value: item.id, value: item.id,
id: item.id, id: item.id,
state: item.state, state: item.state,
is_default: item.is_default,
provider: item.provider provider: item.provider
})); }));
setClusterData({ setClusterData({
@@ -193,16 +191,9 @@ const Workers: React.FC = () => {
}); });
const handleOnAddWorker = () => { const handleOnAddWorker = () => {
let currentData = clusterData.list.find( const targetCluster = checkDefaultCluster(clusterData.list);
(item) => if (targetCluster) {
item.provider === ProviderValueMap.Docker && handleAddWorker(targetCluster as ClusterListItem);
item.state === ClusterStatusValueMap.Ready
);
if (!currentData) {
currentData = clusterData.list[0];
}
if (currentData) {
handleAddWorker(currentData as ClusterListItem);
} else { } else {
message.info(intl.formatMessage({ id: 'noresult.resources.cluster' })); message.info(intl.formatMessage({ id: 'noresult.resources.cluster' }));
} }