diff --git a/src/components/logs-viewer/virtual-log-list.tsx b/src/components/logs-viewer/virtual-log-list.tsx index b5f6f666..9fea7edb 100644 --- a/src/components/logs-viewer/virtual-log-list.tsx +++ b/src/components/logs-viewer/virtual-log-list.tsx @@ -43,6 +43,8 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { const [scrollPos, setScrollPos] = useState([]); const logListRef = useRef(null); const loadMoreDone = useRef(false); + const pageRef = useRef(page); + const totalPageRef = useRef(totalPage); useImperativeHandle(ref, () => ({ abort() { @@ -84,28 +86,47 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { return command === 'J' && n === 2; }, []); - const getLastPage = useCallback( - (data: string) => { - const list = _.split(data.trim(), '\n'); - if (!enableScorllLoad) { - return list.join('\n'); - } + const getLastPage = (data: string) => { + const list = _.split(data.trim(), '\n'); - if (list.length <= pageSize) { - setTotalPage(1); - return data; - } + if (!enableScorllLoad) { + return list.join('\n'); + } - setLoading(true); - const totalPage = Math.ceil(list.length / pageSize); - setTotalPage(totalPage); - setPage(totalPage); - const lastPage = list.slice(-pageSize).join('\n'); - debounceLoading(); - return lastPage; - }, - [pageSize, setTotalPage, setPage, debounceLoading, enableScorllLoad] - ); + if (list.length <= pageSize) { + setTotalPage(1); + return data; + } + + setLoading(true); + const totalPage = Math.ceil(list.length / pageSize); + setTotalPage(totalPage); + setPage(() => totalPage); + pageRef.current = totalPage; + totalPageRef.current = totalPage; + const lastPage = list.slice(-pageSize).join('\n'); + console.log('list.length===', list.length, totalPage, page); + debounceLoading(); + return lastPage; + }; + + const getCurrentPage = () => { + const list = _.split(cacheDataRef.current.trim(), '\n'); + let newPage = page; + if (newPage < 1) { + newPage = 1; + } + console.log('currentpage===', newPage); + const start = (newPage - 1) * pageSize; + const end = newPage * pageSize; + const currentPage = list.slice(start, end).join('\n'); + setPage(() => newPage); + setScrollPos(['bottom', newPage]); + pageRef.current = newPage; + logParseWorker.current.postMessage({ + inputStr: currentPage + }); + }; const getPrePage = useCallback(() => { const list = _.split(cacheDataRef.current.trim(), '\n'); @@ -116,8 +137,10 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { const start = (newPage - 1) * pageSize; const end = newPage * pageSize; const prePage = list.slice(start, end).join('\n'); - setPage(newPage); + console.log('prePage===', newPage); + setPage(() => newPage); setScrollPos(['bottom', newPage]); + pageRef.current = newPage; logParseWorker.current.postMessage({ inputStr: prePage }); @@ -132,29 +155,36 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { const start = (newPage - 1) * pageSize; const end = newPage * pageSize; const nextPage = list.slice(start, end).join('\n'); - setPage(newPage); + console.log('nextPage===', newPage); + setPage(() => newPage); setScrollPos(['top', newPage]); + pageRef.current = newPage; logParseWorker.current.postMessage({ inputStr: nextPage }); }, [totalPage, page, pageSize]); - const updateContent = useCallback( - (inputStr: string) => { - console.log('inputStr===', inputStr); - const data = inputStr.replace(replaceLineRegex, '\n'); - if (isClean(data)) { - cacheDataRef.current = data; - } else { - cacheDataRef.current += data; - } - + const debounceParseData = _.debounce(() => { + if (pageRef.current === totalPageRef.current) { logParseWorker.current.postMessage({ inputStr: getLastPage(cacheDataRef.current) }); - }, - [getLastPage] - ); + } else { + getCurrentPage(); + } + }, 100); + + const updateContent = (inputStr: string) => { + console.log('inputStr===', inputStr); + const data = inputStr.replace(replaceLineRegex, '\n'); + if (isClean(data)) { + cacheDataRef.current = data; + } else { + cacheDataRef.current += data; + } + console.log('page===', pageRef.current, totalPageRef.current); + debounceParseData(); + }; const createChunkConnection = async () => { cacheDataRef.current = ''; @@ -188,12 +218,20 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { createChunkConnection(); loadMoreDone.current = true; } else if (isTop && page <= totalPage && page > 1) { - getPrePage(); + // getPrePage(); } else if (isBottom && page < totalPage) { - getNextPage(); + // getNextPage(); } }, - [loading, logs.length, pageSize, enableScorllLoad, page, totalPage] + [ + loading, + logs.length, + pageSize, + enableScorllLoad, + page, + totalPage, + createChunkConnection + ] ); const debouncedScroll = useCallback( @@ -215,9 +253,9 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { }; }, [url, props.params]); - // useEffect(() => { - // debouncedScroll(); - // }, [scrollPos]); + useEffect(() => { + debouncedScroll(); + }, [scrollPos]); return (
diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index 66e74ada..65f18e73 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -54,7 +54,7 @@ export default { 'resources.worker.select.command': 'Select a label to generate the command and copy it using the copy button.', 'resources.worker.script.install': 'Script Installation', - 'resources.worker.container.install': 'Container Installation', + 'resources.worker.container.install': 'Container Installation(Linux Only)', 'resources.worker.cann.tips': 'Set ASCEND_VISIBLE_DEVICES to 0 for a single GPU or to the index range (e.g., 0-7 for 8 GPUs) for multiple GPUs.' }; diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index 61293c82..bf262608 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -52,7 +52,7 @@ export default { 'resources.worker.driver.install': '在安装 GPUStack 之前,确保系统上安装了所有必需的驱动程序和库', 'resources.worker.script.install': '脚本安装', - 'resources.worker.container.install': '容器安装', + 'resources.worker.container.install': '容器安装(仅支持 Linux)', 'resources.worker.cann.tips': '若 GPU 数量为 1,则设 ASCEND_VISIBLE_DEVICES=0;若大于 1,则设为索引范围(如 8 张为 0-7)' }; diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index 55d99a09..69adbe08 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -23,7 +23,8 @@ import { EditOutlined, ExperimentOutlined, PictureOutlined, - SyncOutlined + SyncOutlined, + WechatWorkOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import { Access, useAccess, useIntl, useNavigate } from '@umijs/max'; @@ -651,6 +652,23 @@ const Models: React.FC = ({ ); } + if (record.categories?.includes(modelCategoriesMap.llm)) { + return ( + } + style={{ + margin: 0, + opacity: 1, + paddingInline: 8, + borderRadius: 12, + transform: 'scale(0.9)' + }} + color="green" + > + LLM + + ); + } return null; }, [intl] diff --git a/src/pages/llmodels/config/index.ts b/src/pages/llmodels/config/index.ts index 46f6bf3f..775bea3b 100644 --- a/src/pages/llmodels/config/index.ts +++ b/src/pages/llmodels/config/index.ts @@ -248,11 +248,13 @@ export const modelCategoriesMap = { text_to_speech: 'text_to_speech', speech_to_text: 'speech_to_text', embedding: 'embedding', - reranker: 'reranker' + reranker: 'reranker', + llm: 'llm' }; export const modelCategories = [ { label: 'common.options.auto', value: null, locale: true }, + { label: 'LLM', value: modelCategoriesMap.llm }, { label: 'Image', value: 'image' }, { label: 'Text-to-speech', value: 'text_to_speech' }, { label: 'Speech-to-text', value: 'speech_to_text' }, diff --git a/src/pages/playground/embedding.tsx b/src/pages/playground/embedding.tsx index 124388b9..29a895c0 100644 --- a/src/pages/playground/embedding.tsx +++ b/src/pages/playground/embedding.tsx @@ -1,5 +1,6 @@ import IconFont from '@/components/icon-font'; import HotKeys from '@/config/hotkeys'; +import { modelCategoriesMap } from '@/pages/llmodels/config'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; import { Button, Space } from 'antd'; @@ -30,7 +31,7 @@ const PlaygroundEmbedding: React.FC = () => { const getModelListByEmbedding = async () => { try { const params = { - categories: 'embedding' + categories: modelCategoriesMap.embedding }; const res = await queryModelsList(params); const list = _.map(res.data || [], (item: any) => { diff --git a/src/pages/playground/images.tsx b/src/pages/playground/images.tsx index 9927370e..87a10069 100644 --- a/src/pages/playground/images.tsx +++ b/src/pages/playground/images.tsx @@ -2,6 +2,7 @@ import IconFont from '@/components/icon-font'; import breakpoints from '@/config/breakpoints'; import HotKeys from '@/config/hotkeys'; import useWindowResize from '@/hooks/use-window-resize'; +import { modelCategoriesMap } from '@/pages/llmodels/config'; import { DiffOutlined, HighlightOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; @@ -85,7 +86,7 @@ const TextToImages: React.FC = () => { const getModelList = async () => { try { const params = { - categories: 'image', + categories: modelCategoriesMap.image, with_meta: true }; const res = await queryModelsList(params); diff --git a/src/pages/playground/index.tsx b/src/pages/playground/index.tsx index 227e8a20..b7b3dee6 100644 --- a/src/pages/playground/index.tsx +++ b/src/pages/playground/index.tsx @@ -2,6 +2,7 @@ import IconFont from '@/components/icon-font'; import breakpoints from '@/config/breakpoints'; import HotKeys from '@/config/hotkeys'; import useWindowResize from '@/hooks/use-window-resize'; +import { modelCategoriesMap } from '@/pages/llmodels/config'; import { MessageOutlined, OneToOneOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; @@ -79,7 +80,7 @@ const Playground: React.FC = () => { const getModelList = async () => { try { const params = { - categories: '', + categories: modelCategoriesMap.llm, with_meta: true }; const res = await queryModelsList(params); diff --git a/src/pages/playground/rerank.tsx b/src/pages/playground/rerank.tsx index 77b3effe..c3d1212e 100644 --- a/src/pages/playground/rerank.tsx +++ b/src/pages/playground/rerank.tsx @@ -1,5 +1,6 @@ import IconFont from '@/components/icon-font'; import HotKeys from '@/config/hotkeys'; +import { modelCategoriesMap } from '@/pages/llmodels/config'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl } from '@umijs/max'; import { Button, Space } from 'antd'; @@ -32,7 +33,7 @@ const PlaygroundRerank: React.FC = () => { const getModelListByReranker = async () => { try { const params = { - categories: 'reranker' + categories: modelCategoriesMap.reranker }; const res = await queryModelsList(params); const list = _.map(res.data || [], (item: any) => { diff --git a/src/pages/playground/speech.tsx b/src/pages/playground/speech.tsx index d424ef21..501578ac 100644 --- a/src/pages/playground/speech.tsx +++ b/src/pages/playground/speech.tsx @@ -2,6 +2,7 @@ import IconFont from '@/components/icon-font'; import breakpoints from '@/config/breakpoints'; import HotKeys from '@/config/hotkeys'; import useWindowResize from '@/hooks/use-window-resize'; +import { modelCategoriesMap } from '@/pages/llmodels/config'; import { AudioOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl, useSearchParams } from '@umijs/max'; @@ -102,7 +103,7 @@ const Playground: React.FC = () => { const getTextToSpeechModels = async () => { try { const params = { - categories: 'text_to_speech', + categories: modelCategoriesMap.text_to_speech, with_meta: true }; const res = await queryModelsList(params); @@ -122,7 +123,7 @@ const Playground: React.FC = () => { const getSpeechToText = async () => { try { const params = { - categories: 'speech_to_text', + categories: modelCategoriesMap.speech_to_text, with_meta: true }; const res = await queryModelsList(params); diff --git a/src/pages/resources/components/add-worker.tsx b/src/pages/resources/components/add-worker.tsx index bd35f497..b5e3322f 100644 --- a/src/pages/resources/components/add-worker.tsx +++ b/src/pages/resources/components/add-worker.tsx @@ -41,7 +41,7 @@ const AddWorker: React.FC = (props) => { width={600} styles={{ body: { - height: 420 + height: 550 } }} footer={null} diff --git a/src/pages/resources/components/container-install.tsx b/src/pages/resources/components/container-install.tsx index 1618a37a..a200a7de 100644 --- a/src/pages/resources/components/container-install.tsx +++ b/src/pages/resources/components/container-install.tsx @@ -1,7 +1,7 @@ import { GPUStackVersionAtom } from '@/atoms/user'; import { getAtomStorage } from '@/atoms/utils'; import HighlightCode from '@/components/highlight-code'; -import { BulbOutlined, WarningOutlined } from '@ant-design/icons'; +import { WarningOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Radio } from 'antd'; import React from 'react'; @@ -31,13 +31,13 @@ const AddWorker: React.FC = (props) => { return commandCode?.registerWorker({ server: origin, tag: version, - token: props.token + token: '${mytoken}' }); } return commandCode?.registerWorker({ server: origin, tag: `${version}-${activeKey}`, - token: props.token + token: '${mytoken}' }); }, [versionInfo, activeKey, props.token, origin]); @@ -78,6 +78,23 @@ const AddWorker: React.FC = (props) => { +

1. {intl.formatMessage({ id: 'resources.worker.add.step1' })}

+ +

+ 2. {intl.formatMessage({ id: 'resources.worker.add.step2' })}{' '} + +

= (props) => { >
)} -

- - {intl.formatMessage({ id: 'resources.worker.add.step3' })} +

+ 3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}

); diff --git a/src/pages/resources/components/script-install.tsx b/src/pages/resources/components/script-install.tsx index 4e452692..8640139a 100644 --- a/src/pages/resources/components/script-install.tsx +++ b/src/pages/resources/components/script-install.tsx @@ -1,5 +1,4 @@ import HighlightCode from '@/components/highlight-code'; -import { BulbOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import React from 'react'; import { addWorkerGuide } from '../config'; @@ -13,11 +12,34 @@ const AddWorker: React.FC = (props) => { return (
+

1. {intl.formatMessage({ id: 'resources.worker.add.step1' })}

+

{intl.formatMessage({ id: 'resources.worker.linuxormaxos' })}

+ +

Windows

+ +

+ 2. {intl.formatMessage({ id: 'resources.worker.add.step2' })}{' '} + +

{intl.formatMessage({ id: 'resources.worker.linuxormaxos' })}

@@ -26,12 +48,11 @@ const AddWorker: React.FC = (props) => { theme="dark" code={addWorkerGuide.win.registerWorker({ server: origin, - token: props.token + token: '${mytoken}' })} > -

- - {intl.formatMessage({ id: 'resources.worker.add.step3' })} +

+ 3. {intl.formatMessage({ id: 'resources.worker.add.step3' })}

);