fix(styles): my models
This commit is contained in:
@@ -2,20 +2,39 @@ import IconFont from '@/components/icon-font';
|
|||||||
import StatusTag from '@/components/status-tag';
|
import StatusTag from '@/components/status-tag';
|
||||||
import ThemeTag from '@/components/tags-wrapper/theme-tag';
|
import ThemeTag from '@/components/tags-wrapper/theme-tag';
|
||||||
import Card from '@/components/templates/card';
|
import Card from '@/components/templates/card';
|
||||||
|
import { StatusMaps } from '@/config';
|
||||||
import { useIntl, useNavigate } from '@umijs/max';
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import {
|
import { modelCategories, modelCategoriesMap, modelSourceMap } from '../config';
|
||||||
InstanceStatusMapValue,
|
|
||||||
modelCategories,
|
|
||||||
modelCategoriesMap,
|
|
||||||
modelSourceMap
|
|
||||||
} from '../config';
|
|
||||||
import { categoryToPathMap } from '../config/button-actions';
|
import { categoryToPathMap } from '../config/button-actions';
|
||||||
|
|
||||||
|
const MyModelsStatusValueMap = {
|
||||||
|
Inactive: 'Inactive',
|
||||||
|
Starting: 'Starting',
|
||||||
|
Degrade: 'Degrade',
|
||||||
|
Active: 'Active'
|
||||||
|
};
|
||||||
|
|
||||||
|
const MyModelsStatusMap = {
|
||||||
|
[MyModelsStatusValueMap.Inactive]: StatusMaps.inactive,
|
||||||
|
[MyModelsStatusValueMap.Starting]: StatusMaps.transitioning,
|
||||||
|
[MyModelsStatusValueMap.Degrade]: StatusMaps.warning,
|
||||||
|
[MyModelsStatusValueMap.Active]: StatusMaps.success
|
||||||
|
};
|
||||||
|
|
||||||
|
const CardWrapper = styled.div`
|
||||||
|
&:hover {
|
||||||
|
.content {
|
||||||
|
.btn {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const ModelItemContent = styled.div`
|
const ModelItemContent = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -24,7 +43,6 @@ const ModelItemContent = styled.div`
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
@@ -37,11 +55,7 @@ const ModelItemContent = styled.div`
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
|
||||||
.btn {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.time {
|
.time {
|
||||||
color: var(--ant-color-text-secondary);
|
color: var(--ant-color-text-secondary);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
@@ -51,7 +65,6 @@ const ModelItemContent = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 16px;
|
|
||||||
.tag-item {
|
.tag-item {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -80,7 +93,7 @@ const Header = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: var(--font-size-middle);
|
font-size: var(--font-size-middle);
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
color: var(--ant-color-text);
|
color: var(--ant-color-text);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -119,59 +132,100 @@ const ModelItem: React.FC<{
|
|||||||
navigate(`/playground/chat?model=${model.name}`);
|
navigate(`/playground/chat?model=${model.name}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// context length
|
||||||
|
const maxToken = useMemo(() => {
|
||||||
|
const meta = model.meta || {};
|
||||||
|
const { max_model_len, n_ctx, n_slot, max_total_tokens } = meta || {};
|
||||||
|
|
||||||
|
let max_tokens: number = 0;
|
||||||
|
|
||||||
|
if (n_ctx && n_slot) {
|
||||||
|
max_tokens = _.divide(n_ctx, n_slot);
|
||||||
|
} else if (max_model_len) {
|
||||||
|
max_tokens = max_model_len;
|
||||||
|
} else if (max_total_tokens) {
|
||||||
|
max_tokens = max_total_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_tokens / 1024;
|
||||||
|
}, [model]);
|
||||||
|
|
||||||
|
const status = useMemo(() => {
|
||||||
|
if (!model.replicas && !model.ready_replicas) {
|
||||||
|
return MyModelsStatusValueMap.Inactive;
|
||||||
|
}
|
||||||
|
if (model.replicas > 0 && !model.ready_replicas) {
|
||||||
|
return MyModelsStatusValueMap.Starting;
|
||||||
|
}
|
||||||
|
if (model.replicas > 1 && model.replicas !== model.ready_replicas) {
|
||||||
|
return MyModelsStatusValueMap.Degrade;
|
||||||
|
}
|
||||||
|
if (model.replicas === model.ready_replicas && model.replicas > 0) {
|
||||||
|
return MyModelsStatusValueMap.Active;
|
||||||
|
}
|
||||||
|
return MyModelsStatusValueMap.Inactive;
|
||||||
|
}, [model]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<CardWrapper>
|
||||||
onClick={() => onClick(model)}
|
<Card
|
||||||
clickable={false}
|
height={140}
|
||||||
ghost
|
onClick={() => onClick(model)}
|
||||||
header={
|
clickable={false}
|
||||||
<Header>
|
hoverable={true}
|
||||||
<span className="text">
|
ghost
|
||||||
<IconFont
|
header={
|
||||||
type={sourceIconMap[model.source]}
|
<Header>
|
||||||
style={{ marginRight: 8 }}
|
<span className="text">
|
||||||
/>
|
<IconFont
|
||||||
<span>{model.name}</span>
|
type={sourceIconMap[model.source]}
|
||||||
</span>
|
style={{ marginRight: 8, fontSize: 24 }}
|
||||||
<StatusTag
|
/>
|
||||||
maxTooltipWidth={400}
|
<span>{model.name}</span>
|
||||||
statusValue={{
|
|
||||||
status: model.state as any,
|
|
||||||
text: InstanceStatusMapValue[model.state],
|
|
||||||
message: model.state_message
|
|
||||||
}}
|
|
||||||
></StatusTag>
|
|
||||||
</Header>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ModelItemContent>
|
|
||||||
<div className="content">
|
|
||||||
<div className="extra-info">
|
|
||||||
<ThemeTag className="tag-item" color="blue">
|
|
||||||
{_.find(modelCategories, { value: model.categories?.[0] })
|
|
||||||
?.label || model.categories?.[0]}
|
|
||||||
</ThemeTag>
|
|
||||||
<ThemeTag className="tag-item" color="purple">
|
|
||||||
128K context
|
|
||||||
</ThemeTag>
|
|
||||||
</div>
|
|
||||||
<div className="footer">
|
|
||||||
<span className="time">
|
|
||||||
{dayjs(model.created_at).format('YYYY-MM-DD HH:mm:ss')}
|
|
||||||
</span>
|
</span>
|
||||||
<Button
|
<StatusTag
|
||||||
size="middle"
|
maxTooltipWidth={400}
|
||||||
className="btn"
|
statusValue={{
|
||||||
variant="filled"
|
status: MyModelsStatusMap[status],
|
||||||
color="default"
|
text: status,
|
||||||
onClick={handleOpenPlayGround}
|
message: model.state_message
|
||||||
>
|
}}
|
||||||
{intl.formatMessage({ id: 'models.openinplayground' })}
|
></StatusTag>
|
||||||
</Button>
|
</Header>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ModelItemContent>
|
||||||
|
<div className="content">
|
||||||
|
<div className="footer">
|
||||||
|
<div className="extra-info">
|
||||||
|
<ThemeTag className="tag-item" color="blue">
|
||||||
|
{_.find(modelCategories, { value: model.categories?.[0] })
|
||||||
|
?.label || model.categories?.[0]}
|
||||||
|
</ThemeTag>
|
||||||
|
{maxToken > 0 && (
|
||||||
|
<ThemeTag className="tag-item" color="purple">
|
||||||
|
{maxToken}K context
|
||||||
|
</ThemeTag>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{[
|
||||||
|
MyModelsStatusValueMap.Active,
|
||||||
|
MyModelsStatusValueMap.Degrade
|
||||||
|
].includes(status) && (
|
||||||
|
<Button
|
||||||
|
size="middle"
|
||||||
|
className="btn"
|
||||||
|
type="primary"
|
||||||
|
onClick={handleOpenPlayGround}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: 'models.openinplayground' })}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ModelItemContent>
|
||||||
</ModelItemContent>
|
</Card>
|
||||||
</Card>
|
</CardWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -243,6 +243,9 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setOriginalFormData();
|
setOriginalFormData();
|
||||||
initGPUSelector();
|
initGPUSelector();
|
||||||
|
formRef.current?.getBackendOptions?.({
|
||||||
|
cluster_id: formData.cluster_id
|
||||||
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
if (!open) {
|
if (!open) {
|
||||||
|
|||||||
@@ -61,11 +61,6 @@ export const ActionList: ActionItem[] = [
|
|||||||
key: 'api',
|
key: 'api',
|
||||||
icon: icons.ApiOutlined
|
icon: icons.ApiOutlined
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'models.button.accessSettings',
|
|
||||||
key: 'accessControl',
|
|
||||||
icon: icons.Private
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'common.button.stop',
|
label: 'common.button.stop',
|
||||||
key: 'stop',
|
key: 'stop',
|
||||||
@@ -76,6 +71,11 @@ export const ActionList: ActionItem[] = [
|
|||||||
key: 'start',
|
key: 'start',
|
||||||
icon: icons.Play
|
icon: icons.Play
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'models.button.accessSettings',
|
||||||
|
key: 'accessControl',
|
||||||
|
icon: icons.Private
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'common.button.delete',
|
label: 'common.button.delete',
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import AutoComplete from '@/components/seal-form/auto-complete';
|
|||||||
import SealInput from '@/components/seal-form/seal-input';
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
import TooltipList from '@/components/tooltip-list';
|
import TooltipList from '@/components/tooltip-list';
|
||||||
import { PageAction } from '@/config';
|
|
||||||
import useAppUtils from '@/hooks/use-app-utils';
|
import useAppUtils from '@/hooks/use-app-utils';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form, Typography } from 'antd';
|
import { Form, Typography } from 'antd';
|
||||||
@@ -11,8 +10,7 @@ import React, { useMemo } from 'react';
|
|||||||
import {
|
import {
|
||||||
backendLabelMap,
|
backendLabelMap,
|
||||||
backendTipsList,
|
backendTipsList,
|
||||||
getBackendParamsTips,
|
getBackendParamsTips
|
||||||
modelSourceMap
|
|
||||||
} from '../config';
|
} from '../config';
|
||||||
import { backendOptionsMap } from '../config/backend-parameters';
|
import { backendOptionsMap } from '../config/backend-parameters';
|
||||||
import { useFormContext } from '../config/form-context';
|
import { useFormContext } from '../config/form-context';
|
||||||
@@ -68,10 +66,6 @@ const BackendFields: React.FC = () => {
|
|||||||
label={intl.formatMessage({ id: 'models.form.backend' })}
|
label={intl.formatMessage({ id: 'models.form.backend' })}
|
||||||
description={<TooltipList list={backendTipsList}></TooltipList>}
|
description={<TooltipList list={backendTipsList}></TooltipList>}
|
||||||
options={backendOptions}
|
options={backendOptions}
|
||||||
disabled={
|
|
||||||
action === PageAction.EDIT &&
|
|
||||||
source !== modelSourceMap.local_path_value
|
|
||||||
}
|
|
||||||
></SealSelect>
|
></SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{backendOptionsMap.custom !== backend && (
|
{backendOptionsMap.custom !== backend && (
|
||||||
|
|||||||
Reference in New Issue
Block a user