diff --git a/src/components/highlight-code/styles/index.less b/src/components/highlight-code/styles/index.less index c2fc3f4a..3b857b68 100644 --- a/src/components/highlight-code/styles/index.less +++ b/src/components/highlight-code/styles/index.less @@ -43,6 +43,7 @@ padding-inline: 12px 12px; border-radius: 0 0 var(--border-radius-mini) var(--border-radius-mini); position: relative; + white-space: pre-wrap; code { line-height: 1.5; diff --git a/src/components/image-editor/hooks/use-drawing.ts b/src/components/image-editor/hooks/use-drawing.ts index 7007121c..c1e8cdc6 100644 --- a/src/components/image-editor/hooks/use-drawing.ts +++ b/src/components/image-editor/hooks/use-drawing.ts @@ -24,6 +24,7 @@ export default function useDrawing(props: { const mouseDownState = useRef(false); const canvasRef = useRef(null); const overlayCanvasRef = useRef(null); + const offscreenCanvasRef = useRef(null); const currentStroke = useRef([]); const strokesRef = useRef([]); const isDrawing = useRef(false); @@ -101,20 +102,29 @@ export default function useDrawing(props: { onSave({ mask, img }); }; + const creatOffscreenCanvas = useCallback(() => { + if (!offscreenCanvasRef.current) { + offscreenCanvasRef.current = document.createElement('canvas'); + } + }, []); + const setTransform = useCallback(() => { + creatOffscreenCanvas(); const ctx = canvasRef.current?.getContext('2d'); const overlayCtx = overlayCanvasRef.current?.getContext('2d'); + const offCtx = offscreenCanvasRef.current?.getContext('2d'); if (!ctx || !overlayCtx) return; ctx!.resetTransform(); overlayCtx!.resetTransform(); + offCtx!.resetTransform(); const { current: scale } = autoScale; const { x: translateX, y: translateY } = translatePos.current; ctx!.setTransform(scale, 0, 0, scale, translateX, translateY); - overlayCtx!.setTransform(scale, 0, 0, scale, translateX, translateY); + offCtx!.setTransform(scale, 0, 0, scale, translateX, translateY); }, []); const getTransformedPoint = useCallback( @@ -134,9 +144,13 @@ export default function useDrawing(props: { [] ); - const getTransformLineWidth = useCallback((lineWidth = 1) => { - return lineWidth / autoScale.current; - }, []); + const getTransformLineWidth = useCallback( + (w = 1) => { + const width = w || lineWidth; + return width / autoScale.current; + }, + [lineWidth] + ); const drawLine = useCallback( ( @@ -180,6 +194,7 @@ export default function useDrawing(props: { ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.globalCompositeOperation = compositeOperation; + ctx.save(); ctx.beginPath(); @@ -196,6 +211,7 @@ export default function useDrawing(props: { ctx.strokeStyle = color; } ctx.stroke(); + ctx.restore(); }, [getTransformLineWidth, getTransformedPoint] ); @@ -323,6 +339,9 @@ export default function useDrawing(props: { const clearOverlayCanvas = useCallback(() => { const ctx = overlayCanvasRef.current!.getContext('2d'); + const offCtx = offscreenCanvasRef.current?.getContext('2d'); + + offCtx!.resetTransform(); ctx!.resetTransform(); ctx!.clearRect( 0, @@ -330,33 +349,48 @@ export default function useDrawing(props: { overlayCanvasRef.current!.width, overlayCanvasRef.current!.height ); + offCtx!.clearRect( + 0, + 0, + overlayCanvasRef.current!.width, + overlayCanvasRef.current!.height + ); }, []); const clearCanvas = useCallback(() => { const canvas = canvasRef.current!; const ctx = canvasRef.current!.getContext('2d'); + const offCtx = offscreenCanvasRef.current?.getContext('2d'); ctx!.resetTransform(); ctx!.clearRect(0, 0, canvas.width, canvas.height); + + offCtx!.resetTransform(); + offCtx!.clearRect(0, 0, canvas.width, canvas.height); }, []); const resetCanvas = useCallback(() => { const canvas = canvasRef.current!; const overlayCanvas = overlayCanvasRef.current!; + const offscreenCanvas = offscreenCanvasRef.current!; const ctx = canvas.getContext('2d'); const overlayCtx = overlayCanvas.getContext('2d'); + const offCtx = offscreenCanvasRef.current?.getContext('2d'); autoScale.current = 1; baseScale.current = 1; translatePos.current = { x: 0, y: 0 }; contentPos.current = { x: 0, y: 0 }; + canvas.style.transform = 'scale(1)'; overlayCanvas.style.transform = 'scale(1)'; + offscreenCanvas.style.transform = 'scale(1)'; cursorRef.current!.style.width = `${lineWidth}px`; cursorRef.current!.style.height = `${lineWidth}px`; ctx!.resetTransform(); overlayCtx!.resetTransform(); + offCtx!.resetTransform(); }, []); const fitView = () => { @@ -366,11 +400,13 @@ export default function useDrawing(props: { setTransform(); overlayCanvasRef.current!.style.transform = `scale(${autoScale.current})`; canvasRef.current!.style.transform = `scale(${autoScale.current})`; + offscreenCanvasRef.current!.style.transform = `scale(${autoScale.current})`; }; return { canvasRef, overlayCanvasRef, + offscreenCanvasRef, cursorRef, strokesRef, currentStroke, @@ -379,6 +415,7 @@ export default function useDrawing(props: { autoScale, baseScale, maskStorkeRef, + creatOffscreenCanvas, setMaskStrokes, fitView, setStrokes, diff --git a/src/components/image-editor/hooks/use-zoom.ts b/src/components/image-editor/hooks/use-zoom.ts index 6fd902bb..3dde76af 100644 --- a/src/components/image-editor/hooks/use-zoom.ts +++ b/src/components/image-editor/hooks/use-zoom.ts @@ -4,6 +4,7 @@ import { MutableRefObject, useState } from 'react'; export default function useZoom(props: { overlayCanvasRef: any; canvasRef: any; + offscreenCanvasRef: any; cursorRef: any; lineWidth: number; autoScale: MutableRefObject; @@ -16,6 +17,7 @@ export default function useZoom(props: { const { overlayCanvasRef, canvasRef, + offscreenCanvasRef, cursorRef, lineWidth, translatePos, @@ -34,7 +36,6 @@ export default function useZoom(props: { return; } - console.log('Setting transform origin:', autoScale.current); const rect = overlayCanvasRef.current!.getBoundingClientRect(); const mouseX = e.clientX - rect.left; const mouseY = e.clientY - rect.top; @@ -44,6 +45,7 @@ export default function useZoom(props: { overlayCanvasRef.current!.style.transformOrigin = `${originX * 100}% ${originY * 100}%`; canvasRef.current!.style.transformOrigin = `${originX * 100}% ${originY * 100}%`; + offscreenCanvasRef.current!.style.transformOrigin = `${originX * 100}% ${originY * 100}%`; }; const updateZoom = (scaleChange: number, mouseX: number, mouseY: number) => { @@ -77,6 +79,8 @@ export default function useZoom(props: { overlayCanvasRef.current!.style.transform = `scale(${autoScale.current})`; canvasRef.current!.style.transform = `scale(${autoScale.current})`; + offscreenCanvasRef.current!.style.transform = `scale(${autoScale.current})`; + setCanvasTransformOrigin(event); updateZoom(scaleChange, mouseX, mouseY); }; diff --git a/src/components/image-editor/index.tsx b/src/components/image-editor/index.tsx index aa75dbc0..50b8f666 100644 --- a/src/components/image-editor/index.tsx +++ b/src/components/image-editor/index.tsx @@ -62,6 +62,7 @@ const CanvasImageEditor: React.FC = forwardRef( const { canvasRef, overlayCanvasRef, + offscreenCanvasRef, cursorRef, strokesRef, currentStroke, @@ -79,6 +80,7 @@ const CanvasImageEditor: React.FC = forwardRef( handleMouseEnter, saveImage, resetCanvas, + creatOffscreenCanvas, generateMask, getTransformLineWidth, getTransformedPoint, @@ -99,6 +101,7 @@ const CanvasImageEditor: React.FC = forwardRef( const { handleOnWheel, setActiveScale, activeScale } = useZoom({ overlayCanvasRef, canvasRef, + offscreenCanvasRef, cursorRef, lineWidth, translatePos, @@ -114,9 +117,12 @@ const CanvasImageEditor: React.FC = forwardRef( const updateCanvasSize = useCallback(() => { const canvas = canvasRef.current!; const overlayCanvas = overlayCanvasRef.current!; + const offscreenCanvas = offscreenCanvasRef.current!; overlayCanvas.width = canvas.width; overlayCanvas.height = canvas.height; + offscreenCanvas.width = canvas.width; + offscreenCanvas.height = canvas.height; }, []); const downloadMask = useCallback(() => { @@ -135,26 +141,26 @@ const CanvasImageEditor: React.FC = forwardRef( options: { lineWidth?: number; color: string; + isInitial?: boolean; } ) => { - const { color } = options; + const { color, isInitial } = options; stroke.forEach((point) => { const { x, y } = getTransformedPoint(point.x, point.y); const width = getTransformLineWidth(point.lineWidth); - - ctx.save(); - - // erase the previous stroke - ctx.globalCompositeOperation = 'destination-out'; - ctx.fillRect(x - width / 2, y - width / 2, width, width); + if (isInitial) { + ctx.save(); + ctx.fillStyle = 'rgba(0,0,0,1)'; + ctx.globalCompositeOperation = 'destination-out'; + ctx.fillRect(x - width / 2, y - width / 2, width, width); + ctx.restore(); + } // draw the new stroke ctx.globalCompositeOperation = 'source-over'; ctx.fillStyle = color; ctx.fillRect(x - width / 2, y - width / 2, width, width); - - ctx.restore(); }); }, [getTransformLineWidth, getTransformedPoint] @@ -168,27 +174,31 @@ const CanvasImageEditor: React.FC = forwardRef( console.log('Resetting strokes', currentStroke.current); }, []); - const loadMaskPixs = (strokes: Stroke[]) => { - clearOverlayCanvas(); + const loadMaskPixs = (strokes: Stroke[], isInitial?: boolean) => { if (!strokes.length) { return; } - console.log('loadin mask pixs:'); - const overlayCanvas = overlayCanvasRef.current!; - const overlayCtx = overlayCanvas!.getContext('2d')!; - setTransform(); + const overlayCanvas = overlayCanvasRef.current!; + const overlayCtx = overlayCanvas.getContext('2d')!; - strokes?.forEach((stroke: Point[], index) => { + strokes.forEach((stroke: Point[]) => { drawFillRect(overlayCtx, stroke, { - color: COLOR + color: COLOR, + isInitial: isInitial }); }); }; - const redrawStrokes = (strokes: Stroke[], type?: string) => { - console.log('Redrawing strokes:', strokes, type); + + const redrawStrokes = (strokes: Stroke[]) => { clearOverlayCanvas(); - if (!strokes.length) { + setTransform(); + console.log( + 'Redrawing strokes:', + strokes.length, + maskStorkeRef.current.length + ); + if (!strokes.length && !maskStorkeRef.current.length) { return; } @@ -198,8 +208,6 @@ const CanvasImageEditor: React.FC = forwardRef( // clear offscreen canvas - setTransform(); - overlayCtx.save(); loadMaskPixs(maskStorkeRef.current); strokes?.forEach((stroke: Point[], index) => { @@ -213,10 +221,9 @@ const CanvasImageEditor: React.FC = forwardRef( compositeOperation: 'source-over' }); }); - overlayCtx.restore(); }; - const undo = () => { + const undo = useCallback(() => { if ( strokesRef.current.length === 0 && maskStorkeRef.current.length === 0 @@ -225,25 +232,23 @@ const CanvasImageEditor: React.FC = forwardRef( return; } + const lastlength = strokesRef.current.length; + const newStrokes = strokesRef.current.slice(0, -1); setStrokes(newStrokes); - console.log( - 'newstrokes=======', - newStrokes.length, + if ( + !newStrokes.length && + lastlength === 0 && maskStorkeRef.current.length - ); - - if (strokesRef.current.length) { - clearTimeout(timer.current); - timer.current = setTimeout(() => { - redrawStrokes(strokesRef.current); - }, 100); - } else if (maskStorkeRef.current.length) { - loadMaskPixs(maskStorkeRef.current); + ) { setMaskStrokes([]); } - }; + clearTimeout(timer.current); + timer.current = setTimeout(() => { + redrawStrokes(newStrokes); + }, 100); + }, []); const downloadOriginImage = () => { const canvas = canvasRef.current!; @@ -308,7 +313,7 @@ const CanvasImageEditor: React.FC = forwardRef( // fit the image to the container autoScale.current = 1; - + creatOffscreenCanvas(); updateCanvasSize(); clearCanvas(); @@ -335,7 +340,7 @@ const CanvasImageEditor: React.FC = forwardRef( setTransform(); ctx.globalCompositeOperation = 'destination-out'; - strokesRef.current.forEach((stroke) => { + [...strokesRef.current, ...maskStorkeRef.current].forEach((stroke) => { stroke.forEach((point: Point) => { const { x, y } = getTransformedPoint(point.x, point.y); const lineWidth = getTransformLineWidth(point.lineWidth); @@ -369,14 +374,14 @@ const CanvasImageEditor: React.FC = forwardRef( onReset(); resetCanvas(); } else if ( - strokesRef.current.length && + (strokesRef.current.length || maskStorkeRef.current.length) && imageStatus.isOriginal && !invertMask ) { redrawStrokes(strokesRef.current); saveImage(); } else if ( - strokesRef.current.length && + (strokesRef.current.length || maskStorkeRef.current.length) && imageStatus.isOriginal && invertMask ) { @@ -456,7 +461,9 @@ const CanvasImageEditor: React.FC = forwardRef( loadMaskPixs(strokes: Stroke[]) { setMaskStrokes(strokes); setStrokes([]); - loadMaskPixs(strokes); + setTransform(); + clearOverlayCanvas(); + loadMaskPixs(strokes, true); } })); diff --git a/src/components/tooltip-list/index.tsx b/src/components/tooltip-list/index.tsx index cd5b4c5d..4e90ebd3 100644 --- a/src/components/tooltip-list/index.tsx +++ b/src/components/tooltip-list/index.tsx @@ -1,11 +1,13 @@ +import { useIntl } from '@umijs/max'; import { Typography } from 'antd'; import React from 'react'; interface TooltipListProps { - list: { title: React.ReactNode; tips: React.ReactNode }[]; + list: { title: any; tips: string }[]; } const TooltipList: React.FC = (props) => { + const intl = useIntl(); const { list } = props; return (
    @@ -20,7 +22,10 @@ const TooltipList: React.FC = (props) => { marginBottom: 0 }} > - {item.title}: + {item.title?.locale + ? intl.formatMessage({ id: item.title?.text || '' }) + : item.title} + : = (props) => { lineHeight: 1.5 }} > - {item.tips} + {intl.formatMessage({ id: item.tips })} ); diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 7648e305..06e98f3d 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -81,7 +81,7 @@ export default { 'models.form.filePath': 'Model Path', 'models.form.backendVersion': 'Backend Version', 'models.form.backendVersion.tips': - 'To use the desired version of vLLM/llama-box/vox-box, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}', + 'To use the desired version of {backend}, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}', 'models.form.gpuselector': 'GPU Selector', 'models.form.backend.llamabox': 'For GGUF format models, supports Linux, macOS, and Windows.', @@ -114,6 +114,8 @@ export default { 'models.table.vram.allocated': 'Allocated VRAM', 'models.form.backend.warning': 'The backend for GGUF format models uses llama-box.', + 'models.form.ollama.warning': + 'Deploy the Ollama model backend using llama-box.', 'models.form.backend.warning.llamabox': 'To use the llama-box backend, specify the full path to the model file (e.g.,/data/models/model.gguf). For sharded models, provide the path to the first shard (e.g.,/data/models/model-00001-of-00004.gguf).' }; diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index 40179631..19d11480 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -81,7 +81,7 @@ export default { 'models.form.filePath': 'Путь к модели', 'models.form.backendVersion': 'Версия бэкенда', 'models.form.backendVersion.tips': - 'To use the desired version of vLLM/llama-box/vox-box, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}', + 'To use the desired version of {backend}, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}', 'models.form.gpuselector': 'Селектор GPU', 'models.form.backend.llamabox': 'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.', @@ -113,6 +113,8 @@ export default { 'models.table.vram.allocated': 'Allocated VRAM', 'models.form.backend.warning': 'The backend for GGUF format models uses llama-box.', + 'models.form.ollama.warning': + 'Deploy the Ollama model backend using llama-box.', 'models.form.backend.warning.llamabox': `To use the llama-box backend, specify the full path to the model file (e.g.,/data/models/model.gguf). For sharded models, provide the path to the first shard (e.g.,/data/models/model-00001-of-00004.gguf).` }; @@ -122,5 +124,6 @@ export default { // 2. models.form.backend.warning // 3. models.form.backend.warning.llamabox // 4. models.table.vram.allocated +// 5. models.form.ollama.warning // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index 86c52424..068c6717 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -78,7 +78,7 @@ export default { 'models.form.filePath': '模型路径', 'models.form.backendVersion': '后端版本', 'models.form.backendVersion.tips': - '固定以使用期望的 vLLM/llama-box/vox-box 版本,在线环境会自动创建虚拟环境安装对应版本的vLLM/llama-box/vox-box。在 GPUStack 升级后也将保持固定的后端版本。{link}', + '固定以使用期望的 {backend} 版本,在线环境会自动创建虚拟环境安装对应版本的 {backend}。在 GPUStack 升级后也将保持固定的后端版本。{link}', 'models.form.gpuselector': 'GPU 选择器', 'models.form.backend.llamabox': '用于 GGUF 格式模型,支持 Linux, macOS 和 Windows', @@ -108,6 +108,7 @@ export default { 'models.form.moreparameters': '参数说明', 'models.table.vram.allocated': '分配显存', 'models.form.backend.warning': 'GGUF 格式模型后端用 llama-box。', + 'models.form.ollama.warning': '部署 Ollama 模型后端使用 llama-box。', 'models.form.backend.warning.llamabox': '要使用 llama-box 后端,请指定模型文件的完整路径(例如:/data/models/model.gguf)。对于分片模型,请提供第一个分片的路径(例如:/data/models/model-00001-of-00004.gguf)。' }; diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index 63d8a685..7cdc4d89 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -340,6 +340,7 @@ const AdvanceConfig: React.FC = (props) => { id: 'models.form.backendVersion.tips' }, { + backend: backend, link: backendParamsTips?.releases && ( = forwardRef((props, ref) => { const localPathCache = useRef(''); - const backendTipsList = [ - { - title: 'llama-box', - tips: intl.formatMessage({ id: 'models.form.backend.llamabox' }) - }, - { - title: 'vLLM', - tips: intl.formatMessage({ id: 'models.form.backend.vllm' }) - }, - { - title: 'vox-box', - tips: intl.formatMessage({ id: 'models.form.backend.voxbox' }) - } - ]; - - const localPathTipsList = [ - { - title: intl.formatMessage({ id: 'models.localpath.gguf.tips.title' }), - tips: intl.formatMessage({ id: 'models.localpath.gguf.tips' }) - }, - { - title: intl.formatMessage({ id: 'models.localpath.shared.tips.title' }), - tips: intl.formatMessage({ id: 'models.localpath.chunks.tips' }) - }, - { - title: intl.formatMessage({ id: 'models.localpat.safe.tips.title' }), - tips: intl.formatMessage({ id: 'models.localpath.safe.tips' }) - } - ]; - const handleSumit = () => { form.submit(); }; diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index 607a6e5f..3d66a3d5 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -81,39 +81,34 @@ const AddModal: React.FC = (props) => { const updateShowWarning = (backend: string) => { const localPath = form.current?.getFieldValue?.('local_path'); - const isBlobFile = localPath?.split('/').pop()?.includes('sha256'); - - if (isBlobFile) { - setWarningStatus({ - show: false, - message: '' - }); - return; - } if (source !== modelSourceMap.local_path_value || !localPath) { return; } - if (localPath.endsWith('.gguf') && backend !== backendOptionsMap.llamaBox) { - setWarningStatus({ - show: true, - message: 'models.form.backend.warning' - }); + const isBlobFile = localPath?.split('/').pop()?.includes('sha256'); + const isOllamaModel = localPath?.includes('ollama'); + const isGGUFFile = localPath.endsWith('.gguf'); + + let warningMessage = ''; + if (isBlobFile && isOllamaModel && backend === backendOptionsMap.llamaBox) { + warningMessage = ''; } else if ( - !localPath.endsWith('.gguf') && - backend === backendOptionsMap.llamaBox + isBlobFile && + isOllamaModel && + backend !== backendOptionsMap.llamaBox ) { - setWarningStatus({ - show: true, - message: 'models.form.backend.warning.llamabox' - }); - } else { - setWarningStatus({ - show: false, - message: '' - }); + warningMessage = 'models.form.ollama.warning'; + } else if (isGGUFFile && backend !== backendOptionsMap.llamaBox) { + warningMessage = 'models.form.backend.warning'; + } else if (!isGGUFFile && backend === backendOptionsMap.llamaBox) { + warningMessage = 'models.form.backend.warning.llamabox'; } + + setWarningStatus({ + show: !!warningMessage, + message: warningMessage + }); }; const handleBackendChange = (backend: string) => { diff --git a/src/pages/llmodels/components/update-modal.tsx b/src/pages/llmodels/components/update-modal.tsx index 16e2c442..c99bb082 100644 --- a/src/pages/llmodels/components/update-modal.tsx +++ b/src/pages/llmodels/components/update-modal.tsx @@ -4,6 +4,7 @@ import ModalFooter from '@/components/modal-footer'; import SealAutoComplete from '@/components/seal-form/auto-complete'; import SealInput from '@/components/seal-form/seal-input'; import SealSelect from '@/components/seal-form/seal-select'; +import TooltipList from '@/components/tooltip-list'; import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; import { useIntl } from '@umijs/max'; @@ -12,6 +13,8 @@ import _ from 'lodash'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { backendOptionsMap, + backendTipsList, + localPathTipsList, modelSourceMap, ollamaModelOptions } from '../config'; @@ -98,39 +101,34 @@ const UpdateModal: React.FC = (props) => { const updateShowWarning = (backend: string) => { const localPath = form.getFieldValue?.('local_path'); - const isBlobFile = localPath?.split('/').pop()?.includes('sha256'); - - if (isBlobFile) { - setWarningStatus({ - show: false, - message: '' - }); - return; - } - if (formData?.source !== modelSourceMap.local_path_value || !localPath) { return; } - if (localPath.endsWith('.gguf') && backend !== backendOptionsMap.llamaBox) { - setWarningStatus({ - show: true, - message: 'models.form.backend.warning' - }); + const isBlobFile = localPath?.split('/').pop()?.includes('sha256'); + const isOllamaModel = localPath?.includes('ollama'); + const isGGUFFile = localPath.endsWith('.gguf'); + + let warningMessage = ''; + + if (isBlobFile && isOllamaModel && backend === backendOptionsMap.llamaBox) { + warningMessage = ''; } else if ( - !localPath.endsWith('.gguf') && - backend === backendOptionsMap.llamaBox + isBlobFile && + isOllamaModel && + backend !== backendOptionsMap.llamaBox ) { - setWarningStatus({ - show: true, - message: 'models.form.backend.warning.llamabox' - }); - } else { - setWarningStatus({ - show: false, - message: '' - }); + warningMessage = 'models.form.ollama.warning'; + } else if (isGGUFFile && backend !== backendOptionsMap.llamaBox) { + warningMessage = 'models.form.backend.warning'; + } else if (!isGGUFFile && backend === backendOptionsMap.llamaBox) { + warningMessage = 'models.form.backend.warning.llamabox'; } + + setWarningStatus({ + show: !!warningMessage, + message: warningMessage + }); }; const handleBackendChange = (val: string) => { @@ -284,6 +282,7 @@ const UpdateModal: React.FC = (props) => { onFocus={handleOnFocus} disabled={false} label={intl.formatMessage({ id: 'models.form.filePath' })} + description={} required > @@ -519,6 +518,7 @@ const UpdateModal: React.FC = (props) => { required onChange={handleBackendChange} label={intl.formatMessage({ id: 'models.form.backend' })} + description={} options={[ { label: `llama-box`, diff --git a/src/pages/llmodels/config/index.ts b/src/pages/llmodels/config/index.ts index 3fbae452..42a2d8d1 100644 --- a/src/pages/llmodels/config/index.ts +++ b/src/pages/llmodels/config/index.ts @@ -88,6 +88,45 @@ export const ollamaModelOptions = [ } ]; +export const backendTipsList = [ + { + title: 'llama-box', + tips: 'models.form.backend.llamabox' + }, + { + title: 'vLLM', + tips: 'models.form.backend.vllm' + }, + { + title: 'vox-box', + tips: 'models.form.backend.voxbox' + } +]; + +export const localPathTipsList = [ + { + title: { + text: 'models.localpath.gguf.tips.title', + locale: true + }, + tips: 'models.localpath.gguf.tips' + }, + { + title: { + text: 'models.localpath.shared.tips.title', + locale: true + }, + tips: 'models.localpath.chunks.tips' + }, + { + title: { + text: 'models.localpat.safe.tips.title', + locale: true + }, + tips: 'models.localpath.safe.tips' + } +]; + export const backendOptionsMap = { llamaBox: 'llama-box', vllm: 'vllm',