fix: query modelscope files by recursive

This commit is contained in:
jialin
2024-09-27 16:50:09 +08:00
parent 7e985991cd
commit 49c0467428
26 changed files with 292 additions and 118 deletions
+1
View File
@@ -38,6 +38,7 @@
"lodash": "^4.17.21",
"marked": "^14.1.0",
"numeral": "^2.0.6",
"overlayscrollbars-react": "^0.5.6",
"query-string": "^9.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+20
View File
@@ -86,6 +86,12 @@ dependencies:
numeral:
specifier: ^2.0.6
version: 2.0.6
overlayscrollbars:
specifier: ^2.10.0
version: 2.10.0
overlayscrollbars-react:
specifier: ^0.5.6
version: 0.5.6(overlayscrollbars@2.10.0)(react@18.2.0)
query-string:
specifier: ^9.0.0
version: 9.0.0
@@ -12606,6 +12612,20 @@ packages:
mem: 5.1.1
dev: false
/overlayscrollbars-react@0.5.6(overlayscrollbars@2.10.0)(react@18.2.0):
resolution: {integrity: sha512-E5To04bL5brn9GVCZ36SnfGanxa2I2MDkWoa4Cjo5wol7l+diAgi4DBc983V7l2nOk/OLJ6Feg4kySspQEGDBw==, tarball: https://registry.npmjs.org/overlayscrollbars-react/-/overlayscrollbars-react-0.5.6.tgz}
peerDependencies:
overlayscrollbars: ^2.0.0
react: '>=16.8.0'
dependencies:
overlayscrollbars: 2.10.0
react: 18.2.0
dev: false
/overlayscrollbars@2.10.0:
resolution: {integrity: sha512-diNMeEafWTE0A4GJfwRpdBp2rE/BEvrhptBdBcDu8/UeytWcdCy9Td8tZWnztJeJ26f8/uHCWfPnPUC/dtgJdw==, tarball: https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.10.0.tgz}
dev: false
/p-defer@1.0.0:
resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==, tarball: https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz}
engines: {node: '>=4'}
@@ -8,7 +8,7 @@
padding-block: 1.2em;
&::-webkit-scrollbar {
height: 8px;
height: var(--scrollbar-size);
}
&::-webkit-scrollbar-thumb {
@@ -0,0 +1,15 @@
.list-item {
display: flex;
align-items: center;
justify-content: flex-start;
width: 100%;
margin-bottom: 12px;
.field-wrapper {
flex: 1;
}
.btn {
margin-left: 10px;
}
}
+2 -2
View File
@@ -32,8 +32,8 @@
overflow-y: auto !important;
// custom scrollbar
&::-webkit-scrollbar {
width: 8px;
height: 6px;
width: var(--scrollbar-size);
height: var(--scrollbar-size);
}
&::-webkit-scrollbar-thumb {
@@ -79,7 +79,7 @@ const TableRow: React.FC<
}, []);
const renderChildrenData = () => {
return renderChildren?.(childrenData);
return renderChildren?.(childrenData, record);
};
const handlePolling = async () => {
+1 -1
View File
@@ -52,7 +52,7 @@ export interface SealTableProps {
onCell?: (record: any, dataIndex: string) => void;
onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void;
onExpand?: (expanded: boolean, record: any, rowKey: any) => void;
renderChildren?: (data: any) => React.ReactNode;
renderChildren?: (data: any, parent?: any) => React.ReactNode;
loadChildren?: (record: any) => Promise<any[]>;
loadChildrenAPI?: (record: any) => string;
contentRendered?: () => void;
-1
View File
@@ -37,7 +37,6 @@
}
.ant-input {
/* 只隐藏垂直滚动条轨道 */
&::-webkit-scrollbar-track {
width: 0 !important;
color: transparent;
+20 -2
View File
@@ -13,6 +13,9 @@ html {
--color-text-light-1: rgba(255, 255, 255, 90%);
--color-fill-1: var(--ant-color-fill-tertiary);
--color-scrollbar-thumb: rgba(193, 193, 193, 80%);
--scrollbar-size: 6px;
--scrollbar-handle-bg: rgba(0, 0, 0, 44%);
--scrollbar-handle-hover-bg: rgba(0, 0, 0, 55%);
--color-editor-dark: #282c34;
--color-editor-light: #fafafa;
--color-scrollbar-track: var(--ant-color-fill-tertiary);
@@ -476,7 +479,7 @@ body {
.custome-scrollbar {
&::-webkit-scrollbar {
width: 8px;
width: var(--scrollbar-size);
}
&::-webkit-scrollbar-thumb {
@@ -498,7 +501,7 @@ body {
.custom-scrollbar-horizontal {
&::-webkit-scrollbar {
height: 8px;
height: var(--scrollbar-size);
}
&::-webkit-scrollbar-thumb {
@@ -518,6 +521,21 @@ body {
}
}
.simplebar-scrollbar.simplebar-visible::before {
opacity: 1;
}
.simplebar-scrollbar::before {
background: var(--scrollbar-handle-bg);
width: var(--scrollbar-size);
}
.simplebar-scrollbar.simplebar-visible.simplebar-hover {
&::before {
background: var(--scrollbar-handle-hover-bg);
}
}
.ant-dropdown-menu
.ant-dropdown-menu-item.ant-dropdown-menu-item-danger:not(
.ant-dropdown-menu-item-disabled
+72
View File
@@ -0,0 +1,72 @@
import { throttle } from 'lodash';
import {
useOverlayScrollbars,
UseOverlayScrollbarsParams
} from 'overlayscrollbars-react';
import React from 'react';
export const overlaySollerOptions: UseOverlayScrollbarsParams = {
options: {
update: {
debounce: 0
},
overflow: {
x: 'hidden'
},
scrollbars: {
autoHide: 'scroll',
autoHideDelay: 600,
clickScroll: 'instant'
}
},
defer: true
};
export default function useOverlayScroller() {
const scrollEventElement = React.useRef<any>(null);
const instanceRef = React.useRef<any>(null);
const [initialize, instance] = useOverlayScrollbars({
...overlaySollerOptions
});
instanceRef.current = instance?.();
scrollEventElement.current =
instanceRef.current?.elements()?.scrollEventElement;
const throttledScroll = React.useMemo(
() =>
throttle(() => {
scrollEventElement.current?.scrollTo?.({
top: scrollEventElement.current.scrollHeight,
behavior: 'smooth'
});
instanceRef.current?.update?.();
}, 300),
[scrollEventElement, instanceRef]
);
const throttledUpdateScrollerPosition = React.useCallback(() => {
throttledScroll();
}, [throttledScroll]);
// const createInstance = React.useCallback((el: any) => {
// if (el) {
// instanceRef.current?.destroy?.();
// initialize(el);
// instanceRef.current = instance?.();
// scrollEventElement.current =
// instanceRef.current?.elements()?.scrollEventElement;
// }
// }, []);
React.useEffect(() => {
return () => {
instanceRef.current?.destroy?.();
};
}, []);
return {
initialize,
instance: instanceRef.current,
updateScrollerPosition: throttledUpdateScrollerPosition
};
}
+1
View File
@@ -203,6 +203,7 @@ export async function queryModelScopeModelFiles(
const res = await fetch(
`${MODE_SCOPE_MODEL_FIELS_API}${params.name}/repo/files?${qs.stringify({
Revision: 'master',
Recursive: true,
Root: ''
})}`,
{
@@ -192,6 +192,32 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
</Form.Item>
</>
)}
{scheduleType === 'manual' && (
<Form.Item<FormData>
name="gpu_selector"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.select'
},
{
name: 'gpu_selector'
}
)
}
]}
>
<SealSelect label="GPU Selector" required>
{gpuOptions.map((item) => (
<Select.Option key={item.value} value={item.value}>
<GPUCard data={item}></GPUCard>
</Select.Option>
))}
</SealSelect>
</Form.Item>
)}
<Form.Item name="backend">
<SealSelect
label={intl.formatMessage({ id: 'models.form.backend' })}
@@ -219,32 +245,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
options={paramsConfig}
></ListInput>
</Form.Item>
{scheduleType === 'manual' && (
<Form.Item<FormData>
name="gpu_selector"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.select'
},
{
name: 'gpu_selector'
}
)
}
]}
>
<SealSelect label="GPU Selector" required>
{gpuOptions.map((item) => (
<Select.Option key={item.value} value={item.value}>
<GPUCard data={item}></GPUCard>
</Select.Option>
))}
</SealSelect>
</Form.Item>
)}
{isGGUF && (
<div style={{ paddingBottom: 22, paddingLeft: 10 }}>
<Form.Item<FormData>
@@ -35,6 +35,7 @@ const pattern = /^(.*)-(\d+)-of-(\d+)\.(.*)$/;
const filterReg = /\.(safetensors|gguf)$/i;
const includeReg = /\.(safetensors|gguf)$/i;
const filterRegGGUF = /\.(gguf)$/i;
const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
const { collapsed, modelSource } = props;
@@ -159,8 +160,11 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
}
);
const fileList = _.filter(_.get(data, ['Data', 'Files']), (file: any) => {
return filterReg.test(file.Path) || _.includes(includeReg, file.Path);
return (
filterRegGGUF.test(file.Path) || _.includes(filterRegGGUF, file.Path)
);
});
const list = _.map(fileList, (item: any) => {
return {
path: item.Path,
@@ -23,6 +23,7 @@ interface InstanceItemProps {
list: ModelInstanceListItem[];
gpuDeviceList: GPUDeviceItem[];
workerList: WorkerListItem[];
modelData?: any;
handleChildSelect: (
val: string,
item: ModelInstanceListItem,
@@ -33,6 +34,7 @@ interface InstanceItemProps {
const InstanceItem: React.FC<InstanceItemProps> = ({
list,
workerList,
modelData,
handleChildSelect
}) => {
const intl = useIntl();
@@ -98,6 +100,10 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
{intl.formatMessage({ id: 'models.table.gpuindex' })}: [
{_.join(item.gpu_indexes?.sort?.(), ',')}]
</div>
<div>
{intl.formatMessage({ id: 'models.form.backend' })}:{' '}
{modelData?.backend || ''}
</div>
</div>
);
};
@@ -8,6 +8,7 @@ import {
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Empty, Spin, Tag, Tooltip } from 'antd';
import 'overlayscrollbars/overlayscrollbars.css';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css';
+5 -4
View File
@@ -402,10 +402,11 @@ const Models: React.FC<ModelsProps> = ({
);
const renderChildren = useCallback(
(list: any) => {
(list: any, parent?: any) => {
return (
<InstanceItem
list={list}
modelData={parent}
gpuDeviceList={gpuDeviceList}
workerList={workerList}
handleChildSelect={handleChildSelect}
@@ -417,12 +418,12 @@ const Models: React.FC<ModelsProps> = ({
const generateSource = useCallback((record: ListItem) => {
if (record.source === modelSourceMap.modelscope_value) {
return `${modelSourceMap.modelScope} / ${record.model_scope_file_path || record.model_scope_model_id}`;
return `${modelSourceMap.modelScope}/${record.model_scope_file_path || record.model_scope_model_id}`;
}
if (record.source === modelSourceMap.huggingface_value) {
return `${modelSourceMap.huggingface} / ${record.huggingface_filename || record.huggingface_repo_id}`;
return `${modelSourceMap.huggingface}/${record.huggingface_filename || record.huggingface_repo_id}`;
}
return `${modelSourceMap.ollama_library} / ${record.ollama_library_model_name}`;
return `${modelSourceMap.ollama_library}/${record.ollama_library_model_name}`;
}, []);
const handleCloseViewCode = useCallback(() => {
+22 -15
View File
@@ -2,6 +2,20 @@ import { StatusMaps } from '@/config';
import { EditOutlined } from '@ant-design/icons';
export const ollamaModelOptions = [
{
label: 'llama3.2',
value: 'llama3.2',
name: 'llama3.2',
id: 'llama3.2',
tags: ['Tools', '1B', '3B']
},
{
label: 'qwen2.5',
value: 'qwen2.5',
name: 'qwen2.5',
tags: ['Tools', '0.5B', '1.5B', '3B', '7B', '14B', '32B', '72B'],
id: 'gemma2'
},
{
label: 'llama3.1',
value: 'llama3.1',
@@ -9,20 +23,20 @@ export const ollamaModelOptions = [
id: 'llama3.1',
tags: ['8B', '70B', '405B']
},
{
label: 'llama3',
value: 'llama3',
name: 'llama3',
tags: ['8B', '70B'],
id: 'llama3'
},
{
label: 'gemma2',
value: 'gemma2',
name: 'gemma2',
tags: ['9B', '27B'],
tags: ['2B', '9B', '27B'],
id: 'gemma2'
},
{
label: 'llava',
value: 'llava',
name: 'llava',
tags: ['7B', '13B', '34B'],
id: 'llava'
},
{
label: 'mistral-nemo',
value: 'mistral-nemo',
@@ -44,13 +58,6 @@ export const ollamaModelOptions = [
tags: ['7B'],
id: 'mistral'
},
{
label: 'llava',
value: 'llava',
name: 'llava',
tags: ['7B', '13B', '34B'],
id: 'llava'
},
{
label: 'qwen2',
value: 'qwen2',
+18 -2
View File
@@ -1,11 +1,12 @@
export default [
const options = [
{
label: '--chat-template',
value: '--chat-template'
},
{
label: '--ctx-size',
value: '--ctx-size'
value: '--ctx-size',
options: ['8192']
},
{
label: '--flash-attn',
@@ -24,3 +25,18 @@ export default [
value: '--ubatch-size'
}
];
const resultList = options.map((option) => {
return {
label: option.label,
value: option.value,
opts: option.options?.map((opt) => {
return {
label: opt,
value: opt
};
})
};
});
export default resultList;
+1 -1
View File
@@ -183,7 +183,7 @@ const options = [
{
label: '--max-model-len',
value: '--max-model-len',
options: []
options: ['8192']
},
{
label: '--guided-decoding-backend',
+1 -1
View File
@@ -5,7 +5,7 @@
}
.simplebar-scrollbar::before {
background: rgba(0, 0, 0, 50%);
width: var(--scrollbar-size);
}
.column-wrapper-footer {
@@ -8,10 +8,6 @@
// height: calc(100vh - 194px);
}
.simplebar-scrollbar::before {
background: rgba(0, 0, 0, 50%);
}
.search-bar {
left: 0;
right: 0;
+24 -25
View File
@@ -1,9 +1,10 @@
import useContainerScroll from '@/hooks/use-container-scorll';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data';
import { useIntl, useSearchParams } from '@umijs/max';
import { Spin } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
import {
forwardRef,
memo,
@@ -12,7 +13,6 @@ import {
useRef,
useState
} from 'react';
import 'simplebar-react/dist/simplebar.min.css';
import { CHAT_API } from '../apis';
import { Roles } from '../config';
import { MessageItem } from '../config/types';
@@ -48,21 +48,10 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
const controllerRef = useRef<any>(null);
const scroller = useRef<any>(null);
const currentMessageRef = useRef<any>(null);
const paramsScroller = useRef<any>(null);
const leftSimple = useRef<any>(null);
const { updateScrollerPosition, handleContentWheel } = useContainerScroll(
scroller,
{ toBottom: true }
);
const paramsRef = useRef<any>(null);
useEffect(() => {
updateScrollerPosition();
}, [messageList]);
useEffect(() => {
paramsScroller.current?.recalculate();
leftSimple.current?.recalculate();
}, [collapse]);
const { initialize, updateScrollerPosition } = useOverlayScroller();
const { initialize: innitializeParams } = useOverlayScroller();
useImperativeHandle(ref, () => {
return {
@@ -200,9 +189,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
setLoading(false);
} catch (error) {
console.log('error=====', error);
setMessageList((pre) => {
return [...pre, ...currentMessageRef.current];
});
setLoading(false);
}
};
@@ -243,14 +230,26 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
setMessageList(userMsg);
};
useEffect(() => {
if (scroller.current) {
initialize(scroller.current);
}
}, [scroller.current, initialize]);
useEffect(() => {
if (paramsRef.current) {
innitializeParams(paramsRef.current);
}
}, [paramsRef.current, innitializeParams]);
useEffect(() => {
updateScrollerPosition();
}, [messageList]);
return (
<div className="ground-left-wrapper">
<div className="ground-left">
<div
className="message-list-wrap custome-scrollbar"
onWheel={handleContentWheel}
ref={scroller}
>
<div className="message-list-wrap" ref={scroller}>
<div
style={{
marginBottom: 20
@@ -305,11 +304,11 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
/>
</div>
</div>
<div
className={classNames('params-wrapper', {
collapsed: collapse
})}
ref={paramsRef}
>
<div className="box">
<ParamsSettings
@@ -1,4 +1,6 @@
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import CompareContext from '../../config/compare-context';
import { MessageItem, ModelSelectionItem } from '../../config/types';
@@ -14,6 +16,7 @@ interface MultiCompareProps {
}
const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
const { initialize } = useOverlayScroller();
const [loadingStatus, setLoadingStatus] = useState<Record<symbol, boolean>>(
{}
);
@@ -36,6 +39,7 @@ const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
});
const modelsCounterMap = useRef<Record<string, number>>({});
const modelRefs = useRef<any>({});
const chatListScrollRef = useRef<any>(null);
const boxHeight = 'calc(100vh - 72px)';
const isLoading = useMemo(() => {
@@ -249,29 +253,33 @@ const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
setModelSelections(resultList);
}, [modelList]);
useEffect(() => {
if (chatListScrollRef.current) {
initialize(chatListScrollRef.current);
}
}, [chatListScrollRef.current, initialize]);
return (
<div className="multiple-chat" style={{ height: boxHeight }}>
<div className="chat-list">
<div className="chat-list-inner">
<CompareContext.Provider
value={{
spans,
globalParams,
loadingStatus,
modelFullList: modelList,
handleApplySystemChangeToAll,
setGlobalParams,
setLoadingStatus: handleSetLoadingStatus,
handleDeleteModel: handleDeleteModel
}}
>
<ActiveModels
spans={spans}
modelSelections={modelSelections}
setModelRefs={setModelRefs}
></ActiveModels>
</CompareContext.Provider>
</div>
<div className="chat-list" ref={chatListScrollRef}>
<CompareContext.Provider
value={{
spans,
globalParams,
loadingStatus,
modelFullList: modelList,
handleApplySystemChangeToAll,
setGlobalParams,
setLoadingStatus: handleSetLoadingStatus,
handleDeleteModel: handleDeleteModel
}}
>
<ActiveModels
spans={spans}
modelSelections={modelSelections}
setModelRefs={setModelRefs}
></ActiveModels>
</CompareContext.Provider>
</div>
<div>
<MessageInput
@@ -31,6 +31,7 @@ const MessageContent: React.FC<MessageContentProps> = ({
newMessageList.splice(index, 1);
setMessageList?.(newMessageList);
};
return (
<>
{!!messageList.length && (
@@ -1,4 +1,5 @@
import IconFont from '@/components/icon-font';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data';
import {
ClearOutlined,
@@ -9,6 +10,7 @@ import {
import { useIntl } from '@umijs/max';
import { Button, Checkbox, Dropdown, Popover, Select, Spin } from 'antd';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
import React, {
forwardRef,
useContext,
@@ -18,7 +20,6 @@ import React, {
useRef,
useState
} from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css';
import { CHAT_API } from '../../apis';
import { Roles } from '../../config';
@@ -62,6 +63,9 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
const contentRef = useRef<any>('');
const controllerRef = useRef<any>(null);
const currentMessageRef = useRef<MessageItem[]>([]);
const modelScrollRef = useRef<any>(null);
const { initialize } = useOverlayScroller();
const setMessageId = () => {
messageId.current = messageId.current + 1;
@@ -122,8 +126,6 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
setMessageList((preList) => {
return [...preList, ...currentMessageRef.current];
});
console.log('currentMessageRef.current 1:', currentMessageRef.current);
console.log('currentMessage==========4', messageList);
const messages = _.map(
[...messageList, ...currentMessageRef.current],
(item: MessageItem) => {
@@ -194,9 +196,6 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
});
setLoadingStatus(instanceId, false);
} catch (error) {
setMessageList((preList) => {
return [...preList, ...currentMessageRef.current];
});
setLoadingStatus(instanceId, false);
}
};
@@ -333,6 +332,12 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
};
}, []);
useEffect(() => {
if (modelScrollRef.current) {
initialize(modelScrollRef.current);
}
}, [modelScrollRef.current, initialize]);
useImperativeHandle(ref, () => {
return {
submit: handleSubmit,
@@ -410,8 +415,12 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
applyToAll={handleApplySystemChangeToAll}
setSystemMessage={setSystemMessage}
></SystemMessage>
<SimpleBar style={{ maxHeight: maxHeight }}>
<div className="content">
<div
className="content"
ref={modelScrollRef}
style={{ maxHeight: maxHeight }}
>
<div>
<MessageContent
spans={spans}
messageList={messageList}
@@ -424,7 +433,7 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
style={{ width: '100%' }}
/>
</div>
</SimpleBar>
</div>
<ViewCodeModal
open={show}
systemMessage={systemMessage}
@@ -44,7 +44,7 @@
}
textarea::-webkit-scrollbar {
width: 8px;
width: var(--scrollbar-size);
}
textarea::-webkit-scrollbar-track {