feat: add context length
This commit is contained in:
@@ -78,6 +78,7 @@
|
||||
"remark-breaks": "^4.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
"semver": "^7.7.3",
|
||||
"simplebar-react": "^3.2.6",
|
||||
"styled-components": "^6.1.15",
|
||||
"tinycolor2": "^1.6.0",
|
||||
@@ -88,6 +89,7 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.1",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@umijs/case-sensitive-paths-webpack-plugin": "^1.0.1",
|
||||
"@umijs/plugins": "^4.4.11",
|
||||
"babel-plugin-named-asset-import": "^0.3.8",
|
||||
|
||||
Generated
+8
-4
@@ -195,6 +195,9 @@ dependencies:
|
||||
remark-math:
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.0
|
||||
semver:
|
||||
specifier: ^7.7.3
|
||||
version: 7.7.3
|
||||
simplebar-react:
|
||||
specifier: ^3.2.6
|
||||
version: 3.3.2(react@18.3.1)
|
||||
@@ -221,6 +224,9 @@ devDependencies:
|
||||
'@types/react-dom':
|
||||
specifier: ^18.3.0
|
||||
version: 18.3.7(@types/react@18.3.27)
|
||||
'@types/semver':
|
||||
specifier: ^7.7.1
|
||||
version: 7.7.1
|
||||
'@umijs/case-sensitive-paths-webpack-plugin':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
@@ -4110,7 +4116,7 @@ packages:
|
||||
resolution: {integrity: sha512-hy8b7Y1J8OGe6LbAjj3xniQrj3v6lsivCcrmf4TzSgPzLkhIeKgc5IZnT7ReIqmEuodjfO8EYAuoFvIrHi/+jQ==, tarball: https://registry.npmjs.org/@types/history/-/history-5.0.0.tgz}
|
||||
deprecated: This is a stub types definition. history provides its own type definitions, so you do not need this installed.
|
||||
dependencies:
|
||||
history: 4.10.1
|
||||
history: 5.3.0
|
||||
|
||||
/@types/hoist-non-react-statics@3.3.7(@types/react@18.3.27):
|
||||
resolution: {integrity: sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==, tarball: https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz}
|
||||
@@ -4234,7 +4240,7 @@ packages:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.3.27
|
||||
'@types/react-router': 5.1.20
|
||||
redux: 3.7.2
|
||||
redux: 4.2.1
|
||||
|
||||
/@types/react-router@5.1.20:
|
||||
resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==, tarball: https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz}
|
||||
@@ -4254,7 +4260,6 @@ packages:
|
||||
|
||||
/@types/semver@7.7.1:
|
||||
resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==, tarball: https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz}
|
||||
dev: false
|
||||
|
||||
/@types/stylis@4.2.5:
|
||||
resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==, tarball: https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz}
|
||||
@@ -9400,7 +9405,6 @@ packages:
|
||||
resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==, tarball: https://registry.npmjs.org/history/-/history-5.3.0.tgz}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.28.4
|
||||
dev: false
|
||||
|
||||
/hmac-drbg@1.0.1:
|
||||
resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, tarball: https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz}
|
||||
|
||||
@@ -48,7 +48,7 @@ const SealSlider: React.FC<SealSliderProps> = (props) => {
|
||||
props.onChange?.(newValue);
|
||||
};
|
||||
|
||||
const renderLabel = React.useMemo(() => {
|
||||
const renderLabel = () => {
|
||||
return (
|
||||
<span
|
||||
className="slider-label"
|
||||
@@ -70,13 +70,13 @@ const SealSlider: React.FC<SealSliderProps> = (props) => {
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}, [label, labelWidth, description, value, max, min, step, defaultValue]);
|
||||
};
|
||||
return (
|
||||
<SliderWrapper className="slider-wrapper">
|
||||
<Wrapper
|
||||
required={required}
|
||||
status={checkStatus || status}
|
||||
label={renderLabel}
|
||||
label={renderLabel()}
|
||||
isFocus={true}
|
||||
variant="borderless"
|
||||
>
|
||||
|
||||
@@ -175,7 +175,7 @@ const SimpleSelect: React.FC<SelectProps & { ref?: any; showTags?: boolean }> =
|
||||
|
||||
return (
|
||||
<TagWrapper
|
||||
bordered={false}
|
||||
variant="filled"
|
||||
closable={props.closable}
|
||||
onClose={props.onClose}
|
||||
style={{
|
||||
|
||||
@@ -231,7 +231,12 @@ const Wrapper: FC<WrapperProps> = ({
|
||||
onClick={onClick}
|
||||
>
|
||||
{label && (
|
||||
<Label $isFocus={isFocus} $hasPrefix={hasPrefix} onClick={onClick}>
|
||||
<Label
|
||||
$isFocus={isFocus}
|
||||
$hasPrefix={hasPrefix}
|
||||
onClick={onClick}
|
||||
className="label-wrapper"
|
||||
>
|
||||
<LabelInfo
|
||||
label={label}
|
||||
required={required}
|
||||
|
||||
@@ -6,6 +6,9 @@ const SliderWrapper = styled.div`
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
.label-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.borderless {
|
||||
background-color: transparent;
|
||||
@@ -38,7 +41,7 @@ const SliderWrapper = styled.div`
|
||||
.label-val {
|
||||
position: absolute !important;
|
||||
top: -14px;
|
||||
right: -10px;
|
||||
right: 0px;
|
||||
width: 80px;
|
||||
border-radius: var(--border-radius-base);
|
||||
text-align: center;
|
||||
|
||||
@@ -2,7 +2,6 @@ import { COLOR_PRIMARY } from './index';
|
||||
|
||||
export default {
|
||||
'root-entry-name': 'variable',
|
||||
// cssVar: true,
|
||||
hashed: false,
|
||||
components: {
|
||||
Input: {
|
||||
@@ -72,9 +71,9 @@ export default {
|
||||
optionSelectedFontWeight: 400
|
||||
},
|
||||
Slider: {
|
||||
handleSize: 10,
|
||||
handleSizeHover: 10,
|
||||
railSize: 5,
|
||||
handleSize: 8,
|
||||
handleSizeHover: 8,
|
||||
railSize: 4,
|
||||
handleActiveOutlineColor: '#646464', // disable default outline
|
||||
handleActiveColor: '#656565', // same as the rail color
|
||||
handleColor: '#474747', // same as the rail color
|
||||
|
||||
@@ -2,7 +2,6 @@ import { COLOR_PRIMARY } from './index';
|
||||
|
||||
export default {
|
||||
'root-entry-name': 'variable',
|
||||
// cssVar: true,
|
||||
hashed: false,
|
||||
components: {
|
||||
Input: {
|
||||
@@ -70,9 +69,9 @@ export default {
|
||||
optionSelectedFontWeight: 400
|
||||
},
|
||||
Slider: {
|
||||
handleSize: 10,
|
||||
handleSizeHover: 10,
|
||||
railSize: 5,
|
||||
handleSize: 8,
|
||||
handleSizeHover: 8,
|
||||
railSize: 4,
|
||||
handleActiveOutlineColor: '#B4B4B4', // disable default outline
|
||||
handleActiveColor: '#D0D0D0', // same as the rail color
|
||||
handleColor: '#D0D0D0', // same as the rail color
|
||||
|
||||
@@ -272,5 +272,6 @@ export default {
|
||||
'models.catalog.nogpus.tips':
|
||||
'No compatible GPUs are available in the selected cluster for this model.',
|
||||
'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.readyWorkers': 'workers ready'
|
||||
'models.form.readyWorkers': 'workers ready',
|
||||
'models.form.maxContextLength': 'Maximum Context Length'
|
||||
};
|
||||
|
||||
@@ -272,7 +272,8 @@ export default {
|
||||
'models.catalog.nogpus.tips':
|
||||
'No compatible GPUs are available in the selected cluster for this model.',
|
||||
'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.readyWorkers': 'workers ready'
|
||||
'models.form.readyWorkers': 'workers ready',
|
||||
'models.form.maxContextLength': 'Maximum Context Length'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
@@ -367,5 +368,6 @@ export default {
|
||||
// 72. 'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
||||
// 73. 'models.catalog.nogpus.tips': 'No compatible GPUs are available in the selected cluster for this model.',
|
||||
// 74. '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.`,
|
||||
// 75. 'models.form.readyWorkers': 'workers ready'
|
||||
// 75. 'models.form.readyWorkers': 'workers ready',
|
||||
// 76. 'models.form.maxContextLength': 'Maximum Context Length'
|
||||
// ========== End of To-Do List ==========
|
||||
|
||||
@@ -267,8 +267,7 @@ export default {
|
||||
'models.table.genericProxy':
|
||||
'Используйте следующий префикс пути и укажите имя модели либо в заголовке запроса <span class="bold-text">X-GPUStack-Model</span>, либо в поле model в теле запроса. Все запросы с этим префиксом пути будут перенаправлены в бэкенд вывода.',
|
||||
'models.form.backendVersion.deprecated': 'Устаревший',
|
||||
'models.accessSettings.public.desc':
|
||||
'Доступно всем без аутентификации.',
|
||||
'models.accessSettings.public.desc': 'Доступно всем без аутентификации.',
|
||||
'models.accessSettings.authed.tips':
|
||||
'Доступно всем аутентифицированным пользователям платформы.',
|
||||
'models.accessSettings.allowedUsers.tips':
|
||||
@@ -277,9 +276,10 @@ export default {
|
||||
'models.catalog.nogpus.tips':
|
||||
'В выбранном кластере нет доступных GPU, совместимых с этой моделью.',
|
||||
'models.form.modelfile.notfound': `Указанный путь к файлу модели не существует на сервере GPUStack. Рекомендуется размещать файл модели по одному и тому же пути как на сервере GPUStack, так и на воркерах GPUStack. Это поможет системе принимать лучшие решения по распределению ресурсов.`,
|
||||
'models.form.readyWorkers': 'воркеров готово'
|
||||
'models.form.readyWorkers': 'воркеров готово',
|
||||
'models.form.maxContextLength': 'Maximum Context Length'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
|
||||
// 1. 'models.form.maxContextLength': 'Maximum Context Length'
|
||||
// ========== End of To-Do List ==========
|
||||
|
||||
@@ -256,5 +256,6 @@ export default {
|
||||
'models.catalog.nogpus.tips': '所选集群中没有兼容该模型的 GPU。',
|
||||
'models.form.modelfile.notfound':
|
||||
'你指定的模型文件路径在 GPUStack 服务器上不存在。建议在 GPUStack 服务器和 GPUStack 节点上使用相同的模型文件路径,这有助于 GPUStack 做出更优的调度与决策。',
|
||||
'models.form.readyWorkers': '节点就绪'
|
||||
'models.form.readyWorkers': '节点就绪',
|
||||
'models.form.maxContextLength': '最大上下文长度'
|
||||
};
|
||||
|
||||
@@ -8,6 +8,8 @@ import { useIntl } from '@umijs/max';
|
||||
import { Button, Tag } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import semverCoerce from 'semver/functions/coerce';
|
||||
import semverGt from 'semver/functions/gt';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
backendActions,
|
||||
@@ -140,7 +142,7 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
|
||||
const icon = customIcons[data.id % customIcons.length];
|
||||
|
||||
return (
|
||||
<TagInner color={color} bordered={false}>
|
||||
<TagInner color={color} variant="filled">
|
||||
{icon}
|
||||
</TagInner>
|
||||
);
|
||||
@@ -157,13 +159,28 @@ const BackendCard: React.FC<BackendCardProps> = ({ data, onSelect }) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const sortVersions = (v2: string, v1: string) => {
|
||||
const sv1 = semverCoerce(v1);
|
||||
const sv2 = semverCoerce(v2);
|
||||
|
||||
if (!sv1 && !sv2) return 0;
|
||||
if (!sv1) return 1;
|
||||
if (!sv2) return -1;
|
||||
|
||||
if (semverGt(sv1, sv2)) return -1;
|
||||
return 1;
|
||||
};
|
||||
|
||||
const renderTag = (item: any) => {
|
||||
return (
|
||||
<AutoTooltip
|
||||
ghost
|
||||
minWidth={20}
|
||||
showTitle
|
||||
title={_.join(data.framework_index_map?.[item], ', ') || false}
|
||||
title={
|
||||
_.join(data.framework_index_map?.[item].sort(sortVersions), ', ') ||
|
||||
false
|
||||
}
|
||||
>
|
||||
<ThemeTag
|
||||
key={item}
|
||||
|
||||
@@ -454,3 +454,20 @@ export async function queryDraftModelList(params?: Global.SearchParams) {
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
export async function queryModelContextLength(params: {
|
||||
model: {
|
||||
source: string;
|
||||
model_scope_model_id?: string;
|
||||
huggingface_repo_id?: string;
|
||||
local_path?: string;
|
||||
};
|
||||
}) {
|
||||
return request<{ native: number; scaled: number }>(
|
||||
`${MODELS_API}/context-length`,
|
||||
{
|
||||
method: 'POST',
|
||||
data: params
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -575,7 +575,6 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
modelSource={props.source}
|
||||
setIsGGUF={handleSetIsGGUF}
|
||||
></ModelCard>
|
||||
|
||||
{isGGUF && (
|
||||
<HFModelFile
|
||||
ref={modelFileRef}
|
||||
@@ -590,7 +589,6 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
</ColWrapper>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormWrapper>
|
||||
<ColumnWrapper
|
||||
styles={{
|
||||
|
||||
@@ -82,7 +82,7 @@ const IncompatiableInfo: React.FC<IncompatiableInfoProps> = (props) => {
|
||||
|
||||
if (isEvaluating) {
|
||||
return (
|
||||
<CompatibleTag color="blue" bordered={false}>
|
||||
<CompatibleTag color="blue" variant="filled">
|
||||
<Tooltip title={intl.formatMessage({ id: 'models.form.evaluating' })}>
|
||||
<LoadingOutlined />
|
||||
</Tooltip>
|
||||
|
||||
@@ -695,7 +695,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<span
|
||||
style={{ paddingLeft: '50px', gap: 4 }}
|
||||
style={{ paddingLeft: '40px', gap: 4 }}
|
||||
className="flex-center"
|
||||
>
|
||||
<InstanceStatusTag
|
||||
|
||||
@@ -22,6 +22,7 @@ interface FormContextProps {
|
||||
workerLabelOptions: CascaderOption[];
|
||||
backendOptions: BackendOption[];
|
||||
initialValues?: FormData; // for editing model
|
||||
modelContextData?: Record<string, any>;
|
||||
clearCacheFormValues?: () => void;
|
||||
onValuesChange?: (changedValues: any, allValues: any) => void;
|
||||
onBackendChange: (backend: string, option: any) => void;
|
||||
|
||||
@@ -358,7 +358,8 @@ export const DO_NOT_TRIGGER_CHECK_COMPATIBILITY = [
|
||||
'extended_kv_cache.enabled',
|
||||
'extended_kv_cache.ram_size',
|
||||
'speculative_config.enabled',
|
||||
'speculative_config.draft_model'
|
||||
'speculative_config.draft_model',
|
||||
'max_context_len'
|
||||
];
|
||||
|
||||
// ignore to compare old and new data when these fields change in updating model
|
||||
|
||||
@@ -17,7 +17,8 @@ const AdvanceConfig = () => {
|
||||
const form = Form.useFormInstance();
|
||||
const EnviromentVars = Form.useWatch('env', form);
|
||||
const backend = Form.useWatch('backend', form);
|
||||
const { onValuesChange, backendOptions, formKey } = useFormContext();
|
||||
const { onValuesChange, backendOptions, isGGUF, modelContextData } =
|
||||
useFormContext();
|
||||
|
||||
const currentBackendOptions = useMemo(() => {
|
||||
return backendOptions?.find((item) => item.value === backend);
|
||||
@@ -46,6 +47,10 @@ const AdvanceConfig = () => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
const handleContextLengthChange = _.debounce((value: number) => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
}, 300);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item<FormData>
|
||||
@@ -63,10 +68,22 @@ const AdvanceConfig = () => {
|
||||
options={modelCategories}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
<Form.Item<FormData> name="max_context_len">
|
||||
<SealSlider label="Max Context Length" inputnumber></SealSlider>
|
||||
</Form.Item>
|
||||
|
||||
{!isGGUF && modelContextData?.native && (
|
||||
<Form.Item<FormData> name="max_context_len">
|
||||
<SealSlider
|
||||
label={intl.formatMessage({ id: 'models.form.maxContextLength' })}
|
||||
inputnumber={true}
|
||||
onChange={handleContextLengthChange}
|
||||
included={true}
|
||||
max={modelContextData?.scaled || 163840}
|
||||
tooltip={{}}
|
||||
marks={{
|
||||
[modelContextData?.native]: 'native',
|
||||
[modelContextData?.scaled]: 'scaled'
|
||||
}}
|
||||
></SealSlider>
|
||||
</Form.Item>
|
||||
)}
|
||||
<BackendParametersList></BackendParametersList>
|
||||
<Form.Item<FormData> name="env">
|
||||
<LabelSelector
|
||||
|
||||
@@ -8,7 +8,12 @@ import { useIntl } from '@umijs/max';
|
||||
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
|
||||
import { Form } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||
import React, {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo
|
||||
} from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
DeployFormKeyMap,
|
||||
@@ -29,6 +34,7 @@ import { generateGPUIds } from '../config/utils';
|
||||
import useFieldScroll from '../hooks/use-field-scroll';
|
||||
import { useGenerateGPUOptions } from '../hooks/use-form-initial-values';
|
||||
import useQueryBackends from '../hooks/use-query-backends';
|
||||
import { useQueryContextLength } from '../services/use-query-context-length';
|
||||
import AdvanceConfig from './advance-config';
|
||||
import BasicForm from './basic';
|
||||
import Performance from './performance';
|
||||
@@ -103,6 +109,10 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
const intl = useIntl();
|
||||
const [activeKey, setActiveKey] = React.useState<string[]>([]);
|
||||
const [target, setTarget] = React.useState<string>(TABKeysMap.BASIC);
|
||||
const { modelContextData, fetchContextLength } = useQueryContextLength();
|
||||
const localPath = Form.useWatch('local_path', form);
|
||||
const modelScopeModelId = Form.useWatch('model_scope_model_id', form);
|
||||
const huggingfaceRepoId = Form.useWatch('huggingface_repo_id', form);
|
||||
|
||||
const segmentOptions = [
|
||||
{
|
||||
@@ -390,6 +400,23 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isGGUF || (!localPath && !modelScopeModelId && !huggingfaceRepoId)) {
|
||||
return;
|
||||
}
|
||||
let params = {};
|
||||
if (source === modelSourceMap.local_path_value) {
|
||||
params = { local_path: localPath };
|
||||
} else if (source === modelSourceMap.modelscope_value) {
|
||||
params = { model_scope_model_id: modelScopeModelId };
|
||||
} else if (source === modelSourceMap.huggingface_value) {
|
||||
params = { huggingface_repo_id: huggingfaceRepoId };
|
||||
}
|
||||
|
||||
// TODO
|
||||
// fetchContextLength({ ...params, source });
|
||||
}, [isGGUF, source, localPath, modelScopeModelId, huggingfaceRepoId]);
|
||||
|
||||
return (
|
||||
<FormContext.Provider
|
||||
value={{
|
||||
@@ -401,6 +428,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
backendOptions: backendOptions,
|
||||
workerLabelOptions: workerLabelOptions,
|
||||
initialValues: initialValues,
|
||||
modelContextData: modelContextData,
|
||||
clearCacheFormValues: clearCacheFormValues,
|
||||
onValuesChange: onValuesChange,
|
||||
onBackendChange: handleBackendChange
|
||||
|
||||
@@ -115,7 +115,7 @@ const useModelsColumns = ({
|
||||
title: intl.formatMessage({ id: 'models.table.replicas.edit' })
|
||||
},
|
||||
render: (text: number, record: ListItem) => (
|
||||
<span style={{ paddingLeft: 10, minWidth: '33px' }}>
|
||||
<span style={{ minWidth: '23px' }}>
|
||||
{record.ready_replicas} / {record.replicas}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useState } from 'react';
|
||||
import { queryModelContextLength } from '../apis';
|
||||
|
||||
export const useQueryContextLength = () => {
|
||||
const [modelContextData, setModelContextData] = useState<{
|
||||
native: number;
|
||||
scaled: number;
|
||||
}>({} as any);
|
||||
const fetchContextLength = async (params: {
|
||||
source: string;
|
||||
model_scope_model_id?: string;
|
||||
huggingface_repo_id?: string;
|
||||
local_path?: string;
|
||||
}) => {
|
||||
try {
|
||||
const res = await queryModelContextLength({
|
||||
model: params
|
||||
});
|
||||
setModelContextData(res);
|
||||
} catch (error) {
|
||||
setModelContextData({} as any);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
modelContextData,
|
||||
fetchContextLength
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user