feat: add context length
This commit is contained in:
@@ -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