fix: show success message when start model falied
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -19,7 +19,7 @@ const DeleteModal = forwardRef((props, ref) => {
|
||||
title?: string;
|
||||
operation: string;
|
||||
}
|
||||
>({});
|
||||
>({} as any);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: (
|
||||
|
||||
@@ -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>).'
|
||||
};
|
||||
|
||||
@@ -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': 'Модели отсутствуют!',
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -22,6 +22,7 @@ export const requestConfig: RequestConfig = {
|
||||
|
||||
history.push('/login', { replace: true });
|
||||
}
|
||||
console.log('error==============', error);
|
||||
}
|
||||
},
|
||||
requestInterceptors: [
|
||||
|
||||
Reference in New Issue
Block a user