fix: show success message when start model falied

This commit is contained in:
jialin
2025-03-14 18:50:45 +08:00
parent 38ff16f3cd
commit db0a5875fa
12 changed files with 149 additions and 175 deletions
+5 -1
View File
@@ -2,7 +2,7 @@
padding: 6px 10px;
position: relative;
padding-top: 35px;
text-align: center;
text-align: left;
border-radius: var(--border-radius-base);
margin: 0;
border: 1px solid transparent;
@@ -21,6 +21,10 @@
background-color: var(--ant-color-warning-bg);
}
.content {
word-break: break-all;
}
.title {
position: absolute;
left: 0;
+1 -1
View File
@@ -37,7 +37,7 @@ const AlertInfo: React.FC<AlertInfoProps> = (props) => {
<WarningFilled className={classNames('info-icon', type)} />
<span className="text">{title}</span>
</div>
{message}
<span className="content">{message}</span>
</Typography.Paragraph>
</div>
) : null}
+1 -1
View File
@@ -19,7 +19,7 @@ const DeleteModal = forwardRef((props, ref) => {
title?: string;
operation: string;
}
>({});
>({} as any);
useImperativeHandle(ref, () => ({
show: (
+5 -5
View File
@@ -81,7 +81,7 @@ export default {
'models.form.filePath': 'Model Path',
'models.form.backendVersion': 'Backend Version',
'models.form.backendVersion.tips':
'Pin a specific version to keep the backend stable across GPUStack upgrades.',
'To use the desired version of vLLM/llama-box/vox-box, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}',
'models.form.gpuselector': 'GPU Selector',
'models.form.backend.llamabox':
'For GGUF format models, supports Linux, macOS, and Windows.',
@@ -98,10 +98,10 @@ export default {
'models.localpat.safe.tips.title': 'Safetensors format model',
'models.localpath.shared.tips.title': 'Sharded GGUF Format Model',
'models.localpath.gguf.tips':
' Specify the model file, e.g., /usr/local/models/model.gguf.',
' Specify the model file, e.g., /data/models/model.gguf.',
'models.localpath.safe.tips':
'Specify the model directory that contains .safetensors and config.json files, e.g., /usr/local/models/model/.',
'models.localpath.chunks.tips': `Specify the first shard file of the model, e.g., /usr/local/models/model-00001-of-00004.gguf.`,
'Specify the model directory that contains .safetensors and config.json files, e.g., /data/models/model/.',
'models.localpath.chunks.tips': `Specify the first shard file of the model, e.g., /data/models/model-00001-of-00004.gguf.`,
'models.form.replicas.tips':
'Multiple replicas enable load balancing for { api } inference requests.',
'models.table.list.empty': 'No Models yet!',
@@ -115,5 +115,5 @@ export default {
'models.form.backend.warning':
'The backend for GGUF format models uses llama-box.',
'models.form.backend.warning.llamabox':
'Use the llama-box backend, set the absolute model path to the model file, such as <span style="font-weight: 700">/usr/local/models/model.gguf</span>. For sharded models, set the first shard file of the model, such as <span style="font-weight: 700">/usr/local/models/model-00001-of-00004.gguf</span>.'
'To use the llama-box backend, specify the full path to the model file (e.g.,<span style="font-weight: 700">/data/models/model.gguf</span>). For sharded models, provide the path to the first shard (e.g.,<span style="font-weight: 700">/data/models/model-00001-of-00004.gguf</span>).'
};
+3 -3
View File
@@ -81,7 +81,7 @@ export default {
'models.form.filePath': 'Путь к модели',
'models.form.backendVersion': 'Версия бэкенда',
'models.form.backendVersion.tips':
'Фиксация версии обеспечивает стабильность бэкенда при обновлениях GPUStack.',
'TODO: Translate key "models.form.backendVersion.tips"',
'models.form.gpuselector': 'Селектор GPU',
'models.form.backend.llamabox':
'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.',
@@ -97,10 +97,10 @@ export default {
'models.localpat.safe.tips.title': 'Модель формата Safetensors',
'models.localpath.shared.tips.title': 'Шардированная GGUF-модель',
'models.localpath.gguf.tips':
'Укажите файл модели, например: /usr/local/models/model.gguf.',
'Укажите файл модели, например: /data/models/model.gguf.',
'models.localpath.safe.tips':
'Укажите директорию модели с файлами .safetensors и config.json.',
'models.localpath.chunks.tips': `Укажите первый шард модели, например: /usr/local/models/model-00001-of-00004.gguf.`,
'models.localpath.chunks.tips': `Укажите первый шард модели, например: /data/models/model-00001-of-00004.gguf.`,
'models.form.replicas.tips':
'Несколько реплик обеспечивают балансировку нагрузки для { api } запросов.',
'models.table.list.empty': 'Модели отсутствуют!',
+5 -6
View File
@@ -78,7 +78,7 @@ export default {
'models.form.filePath': '模型路径',
'models.form.backendVersion': '后端版本',
'models.form.backendVersion.tips':
'固定指定版本以保持后端在 GPUStack 升级过程中的稳定性',
'固定以使用期望的 vLLM/llama-box/vox-box 版本,在线环境会自动创建虚拟环境安装对应版本的vLLM/llama-box/vox-box。在 GPUStack 升级后也将保持固定的后端版本。{link}',
'models.form.gpuselector': 'GPU 选择器',
'models.form.backend.llamabox':
'用于 GGUF 格式模型,支持 Linux, macOS 和 Windows',
@@ -93,12 +93,11 @@ export default {
'models.localpath.gguf.tips.title': 'GGUF 格式模型',
'models.localpat.safe.tips.title': 'safetensors 格式模型',
'models.localpath.shared.tips.title': '分片的 GGUF 格式模型',
'models.localpath.gguf.tips':
'指向模型文件,例如 /usr/local/models/model.gguf',
'models.localpath.gguf.tips': '指向模型文件,例如 /data/models/model.gguf',
'models.localpath.safe.tips':
'指向包含 .safetensors, config.json 文件的模型目录,例如 /usr/local/models/model/',
'指向包含 .safetensors, config.json 文件的模型目录,例如 /data/models/model/',
'models.localpath.chunks.tips':
'指向模型第一个分片文件,例如 /usr/local/models/model-00001-of-00004.gguf',
'指向模型第一个分片文件,例如 /data/models/model-00001-of-00004.gguf',
'models.form.replicas.tips': '多副本数实现 { api } 接口推理请求的负载均衡',
'models.table.list.empty': '暂无已部署模型',
'models.table.list.getStart':
@@ -110,5 +109,5 @@ export default {
'models.table.vram.allocated': '分配显存',
'models.form.backend.warning': 'GGUF 格式模型后端用 llama-box。',
'models.form.backend.warning.llamabox':
'使用 llama-box 后端时,设置模型文件的绝对路径,如 <span style="font-weight: 700">/usr/local/models/model.gguf</span>。对于分片模型,设置模型的第一个分片文件,如 <span style="font-weight: 700">/usr/local/models/model-00001-of-00004.gguf</span>。'
'使用 llama-box 后端,请指定模型文件的完整路径(例如:<span style="font-weight: 700">/data/models/model.gguf</span>。对于分片模型,请提供第一个分片的路径(例如:<span style="font-weight: 700">/data/models/model-00001-of-00004.gguf</span>。'
};
@@ -1,4 +1,5 @@
import AutoTooltip from '@/components/auto-tooltip';
import IconFont from '@/components/icon-font';
import LabelSelector from '@/components/label-selector';
import ListInput from '@/components/list-input';
import SealCascader from '@/components/seal-form/seal-cascader';
@@ -326,28 +327,35 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
<Form.Item name="backend_version">
<SealInput.Input
label={intl.formatMessage({ id: 'models.form.backendVersion' })}
description={intl.formatMessage({
id: 'models.form.backendVersion.tips'
})}
labelExtra={
backendParamsTips?.releases && (
<span
style={{
marginLeft: 5
}}
>
(
<Typography.Link
style={{ lineHeight: 1 }}
href={backendParamsTips?.releases}
target="_blank"
description={intl.formatMessage(
{
id: 'models.form.backendVersion.tips'
},
{
link: backendParamsTips?.releases && (
<span
style={{
marginLeft: 5
}}
>
{intl.formatMessage({ id: 'models.form.releases' })}
</Typography.Link>
)
</span>
)
}
<Typography.Link
className="flex-center"
style={{ lineHeight: 1 }}
href={backendParamsTips?.releases}
target="_blank"
>
<span>
{intl.formatMessage({ id: 'models.form.releases' })}
</span>
<IconFont
type="icon-external-link"
className="font-size-14 m-l-4"
></IconFont>
</Typography.Link>
</span>
)
}
)}
></SealInput.Input>
</Form.Item>
@@ -367,20 +375,26 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
dataList={form.getFieldValue('backend_parameters') || []}
onChange={handleBackendParametersChange}
options={paramsConfig}
labelExtra={
backendParamsTips?.link && (
<span style={{ marginLeft: 5 }}>
(
description={
backendParamsTips && (
<span>
{intl.formatMessage(
{ id: 'models.form.backend_parameters.vllm.tips' },
{ backend: backendParamsTips.backend || '' }
)}{' '}
<Typography.Link
style={{ lineHeight: 1 }}
href={backendParamsTips?.link}
className="flex-center"
href={backendParamsTips.link}
target="_blank"
>
{intl.formatMessage({
id: 'models.form.moreparameters'
})}
<span>
{intl.formatMessage({ id: 'common.text.here' })}
</span>
<IconFont
type="icon-external-link"
className="font-size-14 m-l-4"
></IconFont>
</Typography.Link>
)
</span>
)
}
+13 -14
View File
@@ -6,7 +6,7 @@ import TooltipList from '@/components/tooltip-list';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Form, Tooltip, Typography } from 'antd';
import { Form, Typography } from 'antd';
import _ from 'lodash';
import React, {
forwardRef,
@@ -300,25 +300,24 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
defaultActiveFirstOption
disabled={false}
options={ollamaModelOptions}
label={
<>
{intl.formatMessage({ id: 'model.form.ollama.model' })}{' '}
description={
<span>
<span>
{intl.formatMessage({ id: 'models.form.ollamalink' })}
</span>
<Typography.Link
className="flex-center"
href="https://www.ollama.com/library"
target="_blank"
>
<Tooltip
title={intl.formatMessage({ id: 'models.form.ollamalink' })}
placement="topRight"
>
<IconFont
type="icon-external-link"
className="font-size-14"
></IconFont>
</Tooltip>
<IconFont
type="icon-external-link"
className="font-size-14"
></IconFont>
</Typography.Link>
</>
</span>
}
label={intl.formatMessage({ id: 'model.form.ollama.model' })}
placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })}
required
></SealAutoComplete>
@@ -248,6 +248,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
ellipsis={false}
message={
<span
style={{}}
dangerouslySetInnerHTML={{
__html: intl.formatMessage({
id: warningStatus.message
+56 -99
View File
@@ -403,44 +403,36 @@ const Models: React.FC<ModelsProps> = ({
}, []);
const handleStartModel = async (row: ListItem) => {
try {
await updateModel({
id: row.id,
data: {
..._.omit(row, [
'id',
'ready_replicas',
'created_at',
'updated_at',
'rowIndex'
]),
replicas: 1
}
});
} catch (error) {
// ingore
}
await updateModel({
id: row.id,
data: {
..._.omit(row, [
'id',
'ready_replicas',
'created_at',
'updated_at',
'rowIndex'
]),
replicas: 1
}
});
};
const handleStopModel = async (row: ListItem) => {
try {
await updateModel({
id: row.id,
data: {
..._.omit(row, [
'id',
'ready_replicas',
'created_at',
'updated_at',
'rowIndex'
]),
replicas: 0
}
});
removeExpandedRowKey([row.id]);
} catch (error) {
// ingore
}
await updateModel({
id: row.id,
data: {
..._.omit(row, [
'id',
'ready_replicas',
'created_at',
'updated_at',
'rowIndex'
]),
replicas: 0
}
});
removeExpandedRowKey([row.id]);
};
const handleModalOk = useCallback(
@@ -639,32 +631,36 @@ const Models: React.FC<ModelsProps> = ({
const handleSelect = useCallback(
async (val: any, row: ListItem) => {
if (val === 'edit') {
handleEdit(row);
}
if (val === 'chat') {
handleOpenPlayGround(row);
}
if (val === 'delete') {
handleDelete(row);
}
if (val === 'start') {
await handleStartModel(row);
message.success(intl.formatMessage({ id: 'common.message.success' }));
updateExpandedRowKeys([row.id, ...expandedRowKeys]);
}
try {
if (val === 'edit') {
handleEdit(row);
}
if (val === 'chat') {
handleOpenPlayGround(row);
}
if (val === 'delete') {
handleDelete(row);
}
if (val === 'start') {
await handleStartModel(row);
message.success(intl.formatMessage({ id: 'common.message.success' }));
updateExpandedRowKeys([row.id, ...expandedRowKeys]);
}
if (val === 'stop') {
modalRef.current.show({
content: 'models.instances',
title: 'common.title.stop.confirm',
okText: 'common.button.stop',
operation: 'common.stop.single.confirm',
name: row.name,
async onOk() {
await handleStopModel(row);
}
});
if (val === 'stop') {
modalRef.current.show({
content: 'models.instances',
title: 'common.title.stop.confirm',
okText: 'common.button.stop',
operation: 'common.stop.single.confirm',
name: row.name,
async onOk() {
await handleStopModel(row);
}
});
}
} catch (error) {
// ignore
}
},
[handleEdit, handleOpenPlayGround, handleDelete, expandedRowKeys]
@@ -998,45 +994,6 @@ const Models: React.FC<ModelsProps> = ({
disabled={!rowSelection.selectedRowKeys.length}
onSelect={handleActionSelect}
/>
{/* <Button
icon={<IconFont type="icon-outline-play"></IconFont>}
onClick={handleStartBatch}
disabled={!rowSelection.selectedRows.length}
>
<span>
{intl?.formatMessage?.({ id: 'common.button.start' })}
{rowSelection.selectedRows.length > 0 && (
<span>({rowSelection.selectedRows?.length})</span>
)}
</span>
</Button>
<Button
icon={<IconFont type="icon-stop1"></IconFont>}
onClick={handleStopBatch}
disabled={!rowSelection.selectedRows.length}
>
<span>
{intl?.formatMessage?.({ id: 'common.button.stop' })}
{rowSelection.selectedRows.length > 0 && (
<span>({rowSelection.selectedRows?.length})</span>
)}
</span>
</Button>
<Access accessible={access.canDelete}>
<Button
icon={<DeleteOutlined />}
danger
onClick={handleDeleteBatch}
disabled={!rowSelection.selectedRowKeys.length}
>
<span>
{intl?.formatMessage?.({ id: 'common.button.delete' })}
{rowSelection.selectedRowKeys.length > 0 && (
<span>({rowSelection.selectedRowKeys?.length})</span>
)}
</span>
</Button>
</Access> */}
</Space>
}
></PageTools>
+13 -14
View File
@@ -7,7 +7,7 @@ import SealSelect from '@/components/seal-form/seal-select';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max';
import { Form, Modal, Tooltip, Typography } from 'antd';
import { Form, Modal, Typography } from 'antd';
import _ from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
@@ -236,25 +236,24 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
disabled={false}
options={ollamaModelOptions}
placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })}
label={
<>
{intl.formatMessage({ id: 'model.form.ollama.model' })}{' '}
description={
<span>
<span>
{intl.formatMessage({ id: 'models.form.ollamalink' })}
</span>
<Typography.Link
className="flex-center"
href="https://www.ollama.com/library"
target="_blank"
>
<Tooltip
title={intl.formatMessage({ id: 'models.form.ollamalink' })}
placement="topRight"
>
<IconFont
type="icon-external-link"
className="font-size-14"
></IconFont>
</Tooltip>
<IconFont
type="icon-external-link"
className="font-size-14"
></IconFont>
</Typography.Link>
</>
</span>
}
label={intl.formatMessage({ id: 'model.form.ollama.model' })}
required
></SealAutoComplete>
</Form.Item>
+1
View File
@@ -22,6 +22,7 @@ export const requestConfig: RequestConfig = {
history.push('/login', { replace: true });
}
console.log('error==============', error);
}
},
requestInterceptors: [