From decb3ef2f1f2e5132b4ee1144cb0260b6a021554 Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 8 Jan 2025 15:25:15 +0800 Subject: [PATCH] fix: add a button to last page on logs --- config/theme.ts | 2 +- src/components/auto-image/single-image.tsx | 8 +- src/components/image-editor/index.tsx | 138 ++++++++++++------ .../logs-viewer/logs-pagination.tsx | 54 +++++-- src/components/logs-viewer/parse-worker.ts | 5 + .../logs-viewer/styles/pagination.less | 4 + .../logs-viewer/virtual-log-list.tsx | 63 +++++--- src/locales/en-US/models.ts | 1 + src/locales/en-US/playground.ts | 2 +- src/locales/en-US/resources.ts | 3 +- src/locales/zh-CN/models.ts | 1 + src/locales/zh-CN/resources.ts | 2 +- .../dashboard/components/active-table.tsx | 2 +- src/pages/llmodels/apis/index.ts | 2 +- .../llmodels/components/advance-config.tsx | 1 - .../llmodels/components/hf-model-file.tsx | 12 +- .../llmodels/components/view-logs-modal.tsx | 2 + .../playground/components/audio-input.tsx | 2 +- .../playground/components/params-settings.tsx | 46 +++--- .../components/container-install.tsx | 2 +- src/pages/resources/config/index.ts | 4 + 21 files changed, 237 insertions(+), 119 deletions(-) diff --git a/config/theme.ts b/config/theme.ts index 60496ff7..9a3a3883 100644 --- a/config/theme.ts +++ b/config/theme.ts @@ -29,7 +29,7 @@ export default { contentPadding: '12px 16px' }, Tooltip: { - colorBgSpotlight: 'rgba(110,110,110,1)' + colorBgSpotlight: '#3e3e3e' // sizePopupArrow: 0 }, Slider: { diff --git a/src/components/auto-image/single-image.tsx b/src/components/auto-image/single-image.tsx index 30877701..3cbb0755 100644 --- a/src/components/auto-image/single-image.tsx +++ b/src/components/auto-image/single-image.tsx @@ -1,5 +1,5 @@ import { CloseCircleOutlined } from '@ant-design/icons'; -import { Progress } from 'antd'; +import { Progress, ProgressProps } from 'antd'; import classNames from 'classnames'; import ResizeObserver from 'rc-resize-observer'; import React, { useCallback } from 'react'; @@ -21,6 +21,7 @@ interface SingleImageProps { autoBgColor?: boolean; editable?: boolean; style?: React.CSSProperties; + loadingSize?: ProgressProps['size']; progressType?: 'line' | 'circle' | 'dashboard'; progressColor?: string; progressWidth?: number; @@ -42,10 +43,8 @@ const SingleImage: React.FC = (props) => { dataUrl, style, autoBgColor, - progressColor = 'var(--ant-color-primary)', - progressWidth = 2, preview = true, - progressType = 'dashboard' + loadingSize = 'default' } = props; const imgWrapper = React.useRef(null); @@ -137,6 +136,7 @@ const SingleImage: React.FC = (props) => { ( {progress}% diff --git a/src/components/image-editor/index.tsx b/src/components/image-editor/index.tsx index f23cab8a..667a8df5 100644 --- a/src/components/image-editor/index.tsx +++ b/src/components/image-editor/index.tsx @@ -34,6 +34,9 @@ const CanvasImageEditor: React.FC = ({ onSave, uploadButton }) => { + const MIN_SCALE = 0.4; + const MAX_SCALE = 10; + const zoomFactor = 1.1; const intl = useIntl(); const canvasRef = useRef(null); const overlayCanvasRef = useRef(null); @@ -47,25 +50,20 @@ const CanvasImageEditor: React.FC = ({ const autoScale = useRef(1); const cursorRef = useRef(null); const [imgLoaded, setImgLoaded] = useState(false); - - let scale = 1; - let offsetX = 0; - let offsetY = 0; - - const MIN_SCALE = 0.5; - const MAX_SCALE = 5; + const offsetRef = useRef({ x: 0, y: 0 }); + const originPosition = useRef({ x: 0, y: 0 }); const getTransformedPoint = (event: React.MouseEvent) => { const overlayCanvas = overlayCanvasRef.current!; const rect = overlayCanvas.getBoundingClientRect(); + // 获取鼠标在画布上的原始坐标 const x = event.clientX - rect.left; const y = event.clientY - rect.top; - const transformedX = x - overlayCanvas.width / 2; - const transformedY = y - overlayCanvas.height / 2; - - console.log('Mouse Coordinates (Transformed):', transformedX, transformedY); + // 考虑缩放比例和偏移量 + const transformedX = (x - offsetRef.current.x) / autoScale.current; + const transformedY = (y - offsetRef.current.y) / autoScale.current; return { x: transformedX, y: transformedY }; }; @@ -113,6 +111,10 @@ const CanvasImageEditor: React.FC = ({ overlayCtx!.translate(ctx!.canvas.width / 2, ctx!.canvas.height / 2); ctx!.translate(ctx!.canvas.width / 2, ctx!.canvas.height / 2); offscreenCtx!.translate(ctx!.canvas.width / 2, ctx!.canvas.height / 2); + originPosition.current = { + x: ctx!.canvas.width / 2, + y: ctx!.canvas.height / 2 + }; }, [canvasRef.current, overlayCanvasRef.current]); const scaleCanvasSize = useCallback(() => { @@ -439,8 +441,8 @@ const CanvasImageEditor: React.FC = ({ 1 ); - canvas!.width = img.width * scale; - canvas!.height = img.height * scale; + canvas!.width = img.width; + canvas!.height = img.height; autoScale.current = scale / autoScale.current; @@ -457,6 +459,7 @@ const CanvasImageEditor: React.FC = ({ canvas!.width, canvas!.height ); + canvas!.style.transform = `scale(${scale})`; resolve(); }; }); @@ -502,61 +505,102 @@ const CanvasImageEditor: React.FC = ({ const y = event.clientY - rect.top; // 考虑缩放比例和偏移量 - const transformedX = (x - offsetX) / scale; - const transformedY = (y - offsetY) / scale; + const transformedX = (x - offsetRef.current.x) / autoScale.current; + const transformedY = (y - offsetRef.current.y) / autoScale.current; return { x: transformedX, y: transformedY }; }; - const handleOnWheel = (event: WheelEvent) => { - event.preventDefault(); + const getMousePosition = (event: any) => { + const canvas = overlayCanvasRef.current!; + const rect = canvas.getBoundingClientRect(); + const mouseX = event.clientX - rect.left; + const mouseY = event.clientY - rect.top; - const zoomFactor = event.deltaY < 0 ? 1.1 : 0.9; - const newScale = Math.min( - MAX_SCALE, - Math.max(MIN_SCALE, scale * zoomFactor) - ); + const { x: originX, y: originY } = originPosition.current; + const canvasX = (mouseX - originX) / autoScale.current; + const canvasY = (mouseY - originY) / autoScale.current; + + return { x: canvasX, y: canvasY }; + }; - const rect = canvasRef.current!.getBoundingClientRect(); + const updateCavasTransform = (event: any) => { + const canvas = overlayCanvasRef.current!; + const rect = canvas.getBoundingClientRect(); const mouseX = event.clientX - rect.left; const mouseY = event.clientY - rect.top; - // 计算新的偏移量 - offsetX = mouseX - (mouseX - offsetX) * (newScale / scale); - offsetY = mouseY - (mouseY - offsetY) * (newScale / scale); + // 鼠标在中心坐标系中的位置 + const { x: originX, y: originY } = originPosition.current; + const canvasX = (mouseX - originX) / autoScale.current; + const canvasY = (mouseY - originY) / autoScale.current; // 更新缩放比例 - scale = newScale; + // max scale: 2, min scale: 0.3 + const zoomIn = event.deltaY < 0; + let newScale = autoScale.current; + if (zoomIn) { + newScale = Math.min(MAX_SCALE, autoScale.current * zoomFactor); + } else { + newScale = Math.max(MIN_SCALE, autoScale.current / zoomFactor); + } + + console.log('New Scale:', newScale); + + autoScale.current = newScale; + // 更新原点 + const neworiginX = mouseX - canvasX * newScale; + const neworiginY = mouseY - canvasY * newScale; + originPosition.current = { x: neworiginX, y: neworiginY }; - // 设置画布的变换 const overlayCtx = overlayCanvasRef.current!.getContext('2d')!; - overlayCtx.setTransform(scale, 0, 0, scale, offsetX, offsetY); const canvasCtx = canvasRef.current!.getContext('2d')!; - canvasCtx.setTransform(scale, 0, 0, scale, offsetX, offsetY); - overlayCanvasRef.current!.style.transform = `scale(${scale})`; - canvasRef.current!.style.transform = `scale(${scale})`; + // 更新 Canvas 的变换 + overlayCtx.setTransform( + autoScale.current, + 0, + 0, + autoScale.current, + neworiginX, + neworiginY + ); + canvasCtx.setTransform( + autoScale.current, + 0, + 0, + autoScale.current, + neworiginX, + neworiginY + ); + }; - console.log('Zoom:', scale, offsetX, offsetY); + const handleOnWheel = (event: WheelEvent) => { + event.preventDefault(); + + updateCavasTransform(event); + + overlayCanvasRef.current!.style.transform = `scale(${autoScale.current})`; + canvasRef.current!.style.transform = `scale(${autoScale.current})`; }; useEffect(() => { initializeImage(); }, [initializeImage]); - // useEffect(() => { - // const container = containerRef.current; - // if (!container) return; - // if (container) { - // resizeObserver.current = new ResizeObserver( - // _.throttle(handleResize, 100) - // ); - // resizeObserver.current.observe(container); - // } - - // return () => { - // resizeObserver.current?.disconnect(); - // }; - // }, [handleResize, containerRef.current]); + useEffect(() => { + const container = containerRef.current; + if (!container) return; + if (container) { + resizeObserver.current = new ResizeObserver( + _.throttle(handleResize, 100) + ); + resizeObserver.current.observe(container); + } + + return () => { + resizeObserver.current?.disconnect(); + }; + }, [handleResize, containerRef.current]); useEffect(() => { createOffscreenCanvas(); diff --git a/src/components/logs-viewer/logs-pagination.tsx b/src/components/logs-viewer/logs-pagination.tsx index 77940825..ef1b03f7 100644 --- a/src/components/logs-viewer/logs-pagination.tsx +++ b/src/components/logs-viewer/logs-pagination.tsx @@ -1,4 +1,8 @@ -import { DownOutlined, UpOutlined } from '@ant-design/icons'; +import { + DownOutlined, + UpOutlined, + VerticalLeftOutlined +} from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Tooltip } from 'antd'; import React from 'react'; @@ -10,10 +14,11 @@ interface LogsPaginationProps { pageSize?: number; onPrev?: () => void; onNext?: () => void; + onBackend?: () => void; } const LogsPagination: React.FC = (props) => { - const { page, total, pageSize, onNext, onPrev } = props; + const { page, total, pageSize, onNext, onPrev, onBackend } = props; const intl = useIntl(); const handleOnPrev = () => { @@ -27,6 +32,7 @@ const LogsPagination: React.FC = (props) => { return (
= (props) => { {total} {page < total && ( - - + + - - - + + + )}
); diff --git a/src/components/logs-viewer/parse-worker.ts b/src/components/logs-viewer/parse-worker.ts index eb955122..7cfd1635 100644 --- a/src/components/logs-viewer/parse-worker.ts +++ b/src/components/logs-viewer/parse-worker.ts @@ -150,5 +150,10 @@ self.onmessage = function (event) { content: item.content, uid: item.uid })); + console.log('result===', result); self.postMessage(result); }; + +self.onerror = function (event) { + console.error('parse logs error===', event); +}; diff --git a/src/components/logs-viewer/styles/pagination.less b/src/components/logs-viewer/styles/pagination.less index 25eed798..11b6de15 100644 --- a/src/components/logs-viewer/styles/pagination.less +++ b/src/components/logs-viewer/styles/pagination.less @@ -11,6 +11,10 @@ background-color: rgba(71, 71, 71, 100%) !important; } + .ant-btn { + background-color: rgba(71, 71, 71, 50%) !important; + } + .pages { display: flex; justify-content: center; diff --git a/src/components/logs-viewer/virtual-log-list.tsx b/src/components/logs-viewer/virtual-log-list.tsx index 9fea7edb..2a9c70b7 100644 --- a/src/components/logs-viewer/virtual-log-list.tsx +++ b/src/components/logs-viewer/virtual-log-list.tsx @@ -49,6 +49,7 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ abort() { chunkRequedtRef.current?.current?.abort?.(); + logParseWorker.current?.terminate?.(); } })); @@ -65,6 +66,7 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { logParseWorker.current.onmessage = (event: any) => { const res = event.data; + console.log('res===', res); setLogs(res); }; @@ -73,7 +75,7 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { logParseWorker.current.terminate(); } }; - }, [setLogs, logParseWorker.current]); + }, []); const debounceLoading = _.debounce(() => { setLoading(false); @@ -88,26 +90,26 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { const getLastPage = (data: string) => { const list = _.split(data.trim(), '\n'); - + let result = ''; + console.log('getlastPage===', list.length, enableScorllLoad, pageSize); + setLoading(true); if (!enableScorllLoad) { - return list.join('\n'); - } - - if (list.length <= pageSize) { + result = list.join('\n'); + } else if (list.length <= pageSize) { setTotalPage(1); - return data; - } + result = data; + } else { + const totalPage = Math.ceil(list.length / pageSize); + setTotalPage(totalPage); + setPage(() => totalPage); + pageRef.current = totalPage; + totalPageRef.current = totalPage; + const lastPage = list.slice(-pageSize).join('\n'); - 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); + result = lastPage; + } debounceLoading(); - return lastPage; + return result; }; const getCurrentPage = () => { @@ -116,7 +118,6 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { 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'); @@ -164,6 +165,20 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { }); }, [totalPage, page, pageSize]); + const handleonBackend = useCallback(() => { + const list = _.split(cacheDataRef.current.trim(), '\n'); + let newPage = totalPage; + const start = (newPage - 1) * pageSize; + const end = newPage * pageSize; + const nextPage = list.slice(start, end).join('\n'); + setPage(() => newPage); + setScrollPos(['bottom', newPage]); + pageRef.current = newPage; + logParseWorker.current.postMessage({ + inputStr: nextPage + }); + }, [totalPage, page, pageSize]); + const debounceParseData = _.debounce(() => { if (pageRef.current === totalPageRef.current) { logParseWorker.current.postMessage({ @@ -175,20 +190,25 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { }, 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(); + if (pageRef.current === totalPageRef.current) { + logParseWorker.current.postMessage({ + inputStr: getLastPage(cacheDataRef.current) + }); + } else { + getCurrentPage(); + } }; const createChunkConnection = async () => { cacheDataRef.current = ''; chunkRequedtRef.current?.current?.abort?.(); + chunkRequedtRef.current = setChunkFetch({ url, params: { @@ -287,6 +307,7 @@ const LogsViewer: React.FC = forwardRef((props, ref) => { pageSize={pageSize} onNext={getNextPage} onPrev={getPrePage} + onBackend={handleonBackend} > diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index f1d3655f..19a6a23b 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -74,6 +74,7 @@ export default { 'More {backend} parameter details', 'models.logs.pagination.prev': 'Previous {lines} Lines', 'models.logs.pagination.next': 'Next {lines} Lines', + 'models.logs.pagination.last': 'Last Page', 'models.form.localPath': 'Local Path', 'models.form.filePath': 'Model Path', 'models.form.backendVersion': 'Backend Version', diff --git a/src/locales/en-US/playground.ts b/src/locales/en-US/playground.ts index 429bd92c..80f5864d 100644 --- a/src/locales/en-US/playground.ts +++ b/src/locales/en-US/playground.ts @@ -85,7 +85,7 @@ export default { 'Upload an audio file or start recording', 'playground.audio.enablemic': "Enable microphone access in your browser's settings.", - 'playground.audio.enablemic.doc': 'Refer to', + 'playground.audio.enablemic.doc': 'Refer to this link', 'playground.audio.startrecord': 'Start Recording', 'playground.audio.stoprecord': 'Stop Recording', 'playground.audio.generating.tips': 'Generated text will appear here.', diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index 65f18e73..c55ccc69 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -55,6 +55,5 @@ export default { '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(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.' + 'resources.worker.cann.tips': `Set ASCEND_VISIBLE_DEVICES to the required GPU indices. For GPU0 to GPU3, use ASCEND_VISIBLE_DEVICES=0,1,2,3 or ASCEND_VISIBLE_DEVICES=0-3.` }; diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index f440476a..80487802 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -71,6 +71,7 @@ export default { 'models.form.backend_parameters.vllm.tips': '更多 {backend} 参数说明查看', 'models.logs.pagination.prev': '上一 {lines} 行', 'models.logs.pagination.next': '下一 {lines} 行', + 'models.logs.pagination.last': '最后一页', 'models.form.localPath': '本地路径', 'models.form.filePath': '模型路径', 'models.form.backendVersion': '后端版本', diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index bf262608..aa53bc2c 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -54,5 +54,5 @@ export default { 'resources.worker.script.install': '脚本安装', 'resources.worker.container.install': '容器安装(仅支持 Linux)', 'resources.worker.cann.tips': - '若 GPU 数量为 1,则设 ASCEND_VISIBLE_DEVICES=0;若大于 1,则设为索引范围(如 8 张为 0-7)' + '按需要挂载的 GPU index 设置 ASCEND_VISIBLE_DEVICES,如需挂载 GPU0 - GPU3,则设为 ASCEND_VISIBLE_DEVICES=0,1,2,3ASCEND_VISIBLE_DEVICES=0-3' }; diff --git a/src/pages/dashboard/components/active-table.tsx b/src/pages/dashboard/components/active-table.tsx index 3d63de4b..3eb473ec 100644 --- a/src/pages/dashboard/components/active-table.tsx +++ b/src/pages/dashboard/components/active-table.tsx @@ -50,7 +50,7 @@ const ActiveTable = () => { render: (text: any, record: any) => { return ( - {text} + {text || 'N/A'} ); } diff --git a/src/pages/llmodels/apis/index.ts b/src/pages/llmodels/apis/index.ts index a93cfbfb..7cb1938c 100644 --- a/src/pages/llmodels/apis/index.ts +++ b/src/pages/llmodels/apis/index.ts @@ -151,7 +151,7 @@ export async function queryModelScopeModels( config?: any ) { const tagsCriterion = params.tags?.map((tag: string) => { - return { category: 'tags', predicate: 'contains', values: [tag] }; + return { category: 'libraries', predicate: 'contains', values: [tag] }; }); const tasksCriterion = params.tasks?.map((task: string) => { return { category: 'tasks', predicate: 'contains', values: [task] }; diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index e7489842..ed8cb877 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -303,7 +303,6 @@ const AdvanceConfig: React.FC = (props) => { { backend: backendParamsTips.backend || '' } )}{' '} diff --git a/src/pages/llmodels/components/hf-model-file.tsx b/src/pages/llmodels/components/hf-model-file.tsx index ff3a2aaa..721b1fc9 100644 --- a/src/pages/llmodels/components/hf-model-file.tsx +++ b/src/pages/llmodels/components/hf-model-file.tsx @@ -125,6 +125,10 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { return [...shardFileListResult, ...newGeneralFileList]; }, []); + const hfFileFilter = (file: any) => { + return filterRegGGUF.test(file.path) || _.includes(file.path, '.gguf'); + }; + // hugging face files const getHuggingfaceFiles = async () => { try { @@ -139,7 +143,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { }); const list = _.filter(fileList, (file: any) => { - return filterRegGGUF.test(file.path) || _.includes(file.path, '.gguf'); + return hfFileFilter(file); }); return list; @@ -148,6 +152,10 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { } }; + const modelscopeFileFilter = (file: any) => { + return filterRegGGUF.test(file.Path) && file.Type === 'blob'; + }; + // modelscope files const getModelScopeFiles = async () => { try { @@ -161,7 +169,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { } ); const fileList = _.filter(_.get(data, ['Data', 'Files']), (file: any) => { - return filterRegGGUF.test(file.Path) && file.Type === 'blob'; + return modelscopeFileFilter(file); }); const list = _.map(fileList, (item: any) => { diff --git a/src/pages/llmodels/components/view-logs-modal.tsx b/src/pages/llmodels/components/view-logs-modal.tsx index d35f1010..4990311d 100644 --- a/src/pages/llmodels/components/view-logs-modal.tsx +++ b/src/pages/llmodels/components/view-logs-modal.tsx @@ -51,6 +51,8 @@ const ViewCodeModal: React.FC = (props) => { url: `${MODELS_API}/${props.modelId}/instances`, handler: updateHandler }); + } else { + logsViewerRef.current?.abort(); } return () => { requestRef.current?.current?.cancel?.(); diff --git a/src/pages/playground/components/audio-input.tsx b/src/pages/playground/components/audio-input.tsx index fee5ce96..921779a5 100644 --- a/src/pages/playground/components/audio-input.tsx +++ b/src/pages/playground/components/audio-input.tsx @@ -302,7 +302,7 @@ const AudioInput: React.FC = (props) => { href={`${externalRefer.audioPermission}`} target="_blank" style={{ - color: 'var(--ant-blue-5)' + paddingInline: 0 }} > {intl.formatMessage({ id: 'playground.audio.enablemic.doc' })} diff --git a/src/pages/playground/components/params-settings.tsx b/src/pages/playground/components/params-settings.tsx index 6d7eea94..2bb2fa47 100644 --- a/src/pages/playground/components/params-settings.tsx +++ b/src/pages/playground/components/params-settings.tsx @@ -6,7 +6,7 @@ import { InfoCircleOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Form, InputNumber, Slider, Tooltip } from 'antd'; import _ from 'lodash'; -import { memo, useCallback, useEffect, useId } from 'react'; +import { memo, useCallback, useEffect, useId, useState } from 'react'; import CustomLabelStyles from '../style/custom-label.less'; type ParamsSettingsFormProps = { @@ -29,12 +29,13 @@ type ParamsSettingsProps = { globalParams?: ParamsSettingsFormProps; }; -const METAKEYS: Record = { +const METAKEYS: Record = { seed: 'seed', stop: 'stop', temperature: 'temperature', top_p: 'top_p', - max_tokens: 'n_ctx' + n_slot_ctx: 'max_tokens', + max_model_len: 'max_tokens' }; const ParamsSettings: React.FC = ({ @@ -56,6 +57,8 @@ const ParamsSettings: React.FC = ({ }; const [form] = Form.useForm(); const formId = useId(); + const [metaData, setMetaData] = useState>({}); + const [firstLoad, setFirstLoad] = useState(true); const handleOnFinish = (values: any) => { console.log('handleOnFinish', values); @@ -97,18 +100,16 @@ const ParamsSettings: React.FC = ({ const handleModelChange = (val: string) => { const model = _.find(modelList, { value: val }); const modelMeta = model?.meta || {}; - const keys = Object.keys(METAKEYS).map((k: string) => { - return METAKEYS[k]; - }); - const modelMetaKeys = _.pick(modelMeta, keys); - const obj = _.reduce( - METAKEYS, - (result: any, value: any, key: string) => { - result[key] = modelMetaKeys[value]; - return result; - }, - {} - ); + const modelMetaValue = _.pick(modelMeta, _.keys(METAKEYS)); + const obj = Object.entries(METAKEYS).reduce((acc: any, [key, value]) => { + const val = modelMetaValue[key]; + if (val && _.hasIn(modelMetaValue, key)) { + acc[value] = val; + } + return acc; + }, {}); + form.setFieldsValue(obj); + setMetaData(obj); return obj; }; @@ -127,11 +128,14 @@ const ParamsSettings: React.FC = ({ ...mergeData, model: model }); + setFirstLoad(false); }, [modelList, showModelSelector, selectedModel]); useEffect(() => { - form.setFieldsValue(globalParams); - }, [globalParams]); + if (!firstLoad) { + form.setFieldsValue(globalParams); + } + }, [globalParams, firstLoad]); const renderLabel = (args: { field: string; @@ -196,7 +200,11 @@ const ParamsSettings: React.FC = ({ } ]} > - + )} @@ -246,7 +254,7 @@ const ParamsSettings: React.FC = ({ > = (props) => {

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

diff --git a/src/pages/resources/config/index.ts b/src/pages/resources/config/index.ts index dc6a6d50..e26b2592 100644 --- a/src/pages/resources/config/index.ts +++ b/src/pages/resources/config/index.ts @@ -56,6 +56,10 @@ export const addWorkerGuide: Record = { registerWorker(params: { server: string; tag: string; token: string }) { return `docker run -d --ipc=host --network=host gpustack/gpustack:${params.tag} --server-url ${params.server} --token ${params.token}`; } + }, + container: { + getToken: + 'docker run -it ${gpustack_container_id} cat /var/lib/gpustack/token' } };