diff --git a/src/components/alert-info/block.tsx b/src/components/alert-info/block.tsx index 32c3f2e9..d7270723 100644 --- a/src/components/alert-info/block.tsx +++ b/src/components/alert-info/block.tsx @@ -14,6 +14,7 @@ interface AlertInfoProps { style?: React.CSSProperties; contentStyle?: React.CSSProperties; title?: React.ReactNode; + maxHeight?: number; } const TitleWrapper = styled.div` @@ -39,7 +40,8 @@ const AlertInfo: React.FC = (props) => { style, title, contentStyle, - icon + icon, + maxHeight = 86 } = props; return ( @@ -65,7 +67,7 @@ const AlertInfo: React.FC = (props) => { {title && ( {title} )} - + Current Version (v0.6.1): Ollama models are currently available for use.', + 'models.ollama.deprecated.upcoming': + 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', + 'models.ollama.deprecated.following': + 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', + 'models.ollama.deprecated.issue': + 'See the related issue: #1979 on GitHub.' }; diff --git a/src/locales/ja-JP/models.ts b/src/locales/ja-JP/models.ts index d4d3dd6c..615eb621 100644 --- a/src/locales/ja-JP/models.ts +++ b/src/locales/ja-JP/models.ts @@ -101,7 +101,7 @@ export default { 'models.localpath.gguf.tips': 'モデルファイルを指定してください。例: /data/models/model.gguf。', 'models.localpath.safe.tips': - 'config.jsonファイルを含む.safetensorsディレクトリを指定してください。例: /data/models/model/。', + 'config.jsonファイルを含む.safetensorsディレクトリを指定してください。例: /data/models/model。', 'models.localpath.chunks.tips': `モデルの最初のシャードファイルを指定してください。例: /data/models/model-00001-of-00004.gguf。`, 'models.form.replicas.tips': '複数のレプリカにより、{api} 推論リクエストの負荷分散が可能になります。', @@ -148,5 +148,22 @@ export default { 'models.table.apiAccessInfo.jinaCompatible': 'Jina互換', 'models.table.apiAccessInfo.gotoCreate': '作成に移動', 'models.search.parts': '{n} 部分', - 'models.search.evaluate.error': '評価中にエラーが発生しました: ' + 'models.search.evaluate.error': '評価中にエラーが発生しました: ', + 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', + 'models.ollama.deprecated.current': + 'Current Version (v0.6.1): Ollama models are currently available for use.', + 'models.ollama.deprecated.upcoming': + 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', + 'models.ollama.deprecated.following': + 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', + 'models.ollama.deprecated.issue': + 'See the related issue: #1979 on GitHub.' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', +// 2. 'models.ollama.deprecated.current':'Current Version (v0.6.1): Ollama models are currently available for use.', +// 3. 'models.ollama.deprecated.upcoming': 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', +// 4. 'models.ollama.deprecated.following': 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', +// 5. 'models.ollama.deprecated.issue': 'See the related issue: #1979 on GitHub.' +// ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index a2f693e7..8409e776 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -149,9 +149,22 @@ export default { 'models.table.apiAccessInfo.jinaCompatible': 'Совместимо с Jina', 'models.table.apiAccessInfo.gotoCreate': 'Перейти к созданию', 'models.search.parts': '{n} частей', - 'models.search.evaluate.error': 'Возникла ошибка при вычислении: ' + 'models.search.evaluate.error': 'Возникла ошибка при вычислении: ', + 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', + 'models.ollama.deprecated.current': + 'Current Version (v0.6.1): Ollama models are currently available for use.', + 'models.ollama.deprecated.upcoming': + 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', + 'models.ollama.deprecated.following': + 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', + 'models.ollama.deprecated.issue': + 'See the related issue: #1979 on GitHub.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== - +// 1. 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', +// 2. 'models.ollama.deprecated.current':'Current Version (v0.6.1): Ollama models are currently available for use.', +// 3. 'models.ollama.deprecated.upcoming': 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', +// 4. 'models.ollama.deprecated.following': 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', +// 5. 'models.ollama.deprecated.issue': 'See the related issue: #1979 on GitHub.' // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index 1faef89c..3377d971 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -100,7 +100,7 @@ export default { 'models.localpath.shared.tips.title': '分片的 GGUF 格式模型', 'models.localpath.gguf.tips': '指向模型文件,例如 /data/models/model.gguf', 'models.localpath.safe.tips': - '指向包含 .safetensors, config.json 文件的模型目录,例如 /data/models/model/', + '指向包含 .safetensors, config.json 文件的模型目录,例如 /data/models/model', 'models.localpath.chunks.tips': '指向模型第一个分片文件,例如 /data/models/model-00001-of-00004.gguf', 'models.form.replicas.tips': '多副本数实现 { api } 接口推理请求的负载均衡', @@ -141,5 +141,14 @@ export default { 'models.table.apiAccessInfo.jinaCompatible': 'Jina 兼容', 'models.table.apiAccessInfo.gotoCreate': '去创建', 'models.search.parts': '{n} 个文件', - 'models.search.evaluate.error': '评估过程中发生了错误:' + 'models.search.evaluate.error': '评估过程中发生了错误:', + 'models.ollama.deprecated.title': 'Ollama 模型源即将被移除', + 'models.ollama.deprecated.current': + '当前版本(v0.6.1):Ollama 模型目前仍可使用。', + 'models.ollama.deprecated.upcoming': + '即将发布的版本(v0.7.0):Ollama 模型源将在 UI 中被移除。', + 'models.ollama.deprecated.following': + '在 v0.7.0 更新后: 所有先前部署的模型仍将正常运行。', + 'models.ollama.deprecated.issue': + '参见 GitHub 上的问题 #1979。' }; diff --git a/src/pages/llmodels/catalog.tsx b/src/pages/llmodels/catalog.tsx index 62cc821d..910c6a83 100644 --- a/src/pages/llmodels/catalog.tsx +++ b/src/pages/llmodels/catalog.tsx @@ -3,7 +3,7 @@ import PageTools from '@/components/page-tools'; import { PageAction } from '@/config'; import useBodyScroll from '@/hooks/use-body-scroll'; import { IS_FIRST_LOGIN, writeState } from '@/utils/localstore/index'; -import { SyncOutlined } from '@ant-design/icons'; +import { DoubleRightOutlined, SyncOutlined } from '@ant-design/icons'; import { PageContainer } from '@ant-design/pro-components'; import { useIntl, useNavigate } from '@umijs/max'; import { Button, Input, Pagination, Select, Space, message } from 'antd'; @@ -22,6 +22,18 @@ const PageWrapper = styled.div` margin-block: 32px 16px; `; +const MoreWrapper = styled.div` + display: flex; + justify-content: center; + margin-block: 16px; + opacity: 1; + transition: opacity 0.3s; + &.loading { + opacity: 0; + transition: opacity 0.3s ease-in-out; + } +`; + const Catalog: React.FC = () => { const intl = useIntl(); const { saveScrollHeight, restoreScrollHeight } = useBodyScroll(); @@ -41,7 +53,7 @@ const Catalog: React.FC = () => { }); const [queryParams, setQueryParams] = useState({ page: 1, - perPage: 12, + perPage: 30, search: '', categories: '' }); @@ -159,8 +171,6 @@ const Catalog: React.FC = () => { const handleCreateModel = useCallback( async (data: FormData) => { try { - console.log('data:', data, openDeployModal); - const modelData = await createModel({ data: { ..._.omit(data, ['size', 'quantization']) @@ -213,6 +223,13 @@ const Catalog: React.FC = () => { }); }; + const loadMore = () => { + fetchData({ + ...queryParams, + page: queryParams.page + 1 + }); + }; + useEffect(() => { fetchData(); }, []); @@ -298,6 +315,18 @@ const Catalog: React.FC = () => { activeId={-1} isFirst={isFirst} > + {queryParams.page < dataSource.totalPage && ( + + + + )} = (props) => { )} + = (props) => { } > <> + {source === modelSourceMap.ollama_library_value && ( + + )} {SEARCH_SOURCE.includes(source) && deploymentType === 'modelList' && ( diff --git a/src/pages/llmodels/components/ollama-tips.tsx b/src/pages/llmodels/components/ollama-tips.tsx new file mode 100644 index 00000000..588a632e --- /dev/null +++ b/src/pages/llmodels/components/ollama-tips.tsx @@ -0,0 +1,128 @@ +import AlertBlockInfo from '@/components/alert-info/block'; +import IconFont from '@/components/icon-font'; +import { useIntl } from '@umijs/max'; +import { Button } from 'antd'; +import { useState } from 'react'; +import styled from 'styled-components'; + +const Wrapper = styled.div` + padding-inline: 24px; +`; + +const Tips = styled.div` + margin-top: 8px !important; + ul { + margin: 0 !important; + padding: 0 !important; + margin-top: 8px !important; + li { + position: relative; + list-style: none; + line-height: 24px; + margin: 0 !important; + padding-inline: 16px 0 !important; + &::before { + content: ''; + position: absolute; + left: 0px; + top: 0; + width: 6px; + height: 6px; + border-radius: 50%; + background-color: var(--ant-color-text-secondary); + margin-top: 8px; + } + } + } + .bold { + font-weight: 700; + color: var(--ant-color-text); + } + .notice { + margin-top: 8px !important; + } +`; + +const TitleWrapper = styled.div` + display: flex; + align-items: center; + font-weight: 700; + color: var(--ant-color-text); + justify-content: space-between; +`; + +const RenderMessage = () => { + const intl = useIntl(); + return ( + +
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+
+ ); +}; + +const OllamaTips = () => { + const intl = useIntl(); + const [maxHeight, setMaxHeight] = useState(1); + const handleShowMore = () => { + setMaxHeight(maxHeight === 1 ? 600 : 1); + }; + return ( + + } + title={ + +
+ {intl.formatMessage({ id: 'models.ollama.deprecated.title' })} +
+ +
+ } + type={'warning'} + >
+
+ ); +}; + +export default OllamaTips; diff --git a/src/pages/llmodels/download/target-form.tsx b/src/pages/llmodels/download/target-form.tsx index 56802160..f8ae9ae3 100644 --- a/src/pages/llmodels/download/target-form.tsx +++ b/src/pages/llmodels/download/target-form.tsx @@ -9,6 +9,7 @@ import { useIntl } from '@umijs/max'; import { Form, Typography } from 'antd'; import _ from 'lodash'; import React, { forwardRef, useImperativeHandle, useMemo } from 'react'; +import OllamaTips from '../components/ollama-tips'; import { localPathTipsList, modelSourceMap, @@ -38,6 +39,18 @@ const TargetForm: React.FC = forwardRef((props, ref) => { onOk(data); }; + const handleOnLocalPathBlur = (e: any) => { + let { value } = e.target; + // remove the last slash: windows or linux + const lastChar = value.slice(-1); + if (lastChar === '/' || lastChar === '\\') { + value = value.slice(0, -1); + } + form.setFieldsValue({ + local_path: value + }); + }; + const renderLocalPathFields = () => { return ( <> @@ -54,6 +67,7 @@ const TargetForm: React.FC = forwardRef((props, ref) => { } > @@ -119,84 +133,89 @@ const TargetForm: React.FC = forwardRef((props, ref) => { }, [props.source, intl]); return ( -
- - name="source" - rules={[ - { - required: true, - message: getRuleMessage('select', 'models.form.source') - } - ]} +
+ {source === modelSourceMap.ollama_library_value && ( + + )} + - { - - } - - {renderFieldsBySource} - - { - - } - - {source !== modelSourceMap.local_path_value && ( - name="local_dir" + name="source" rules={[ { - required: false, - message: getRuleMessage( - 'input', - 'resources.modelfiles.form.localdir' - ) + required: true, + message: getRuleMessage('select', 'models.form.source') } ]} > - - } - label={intl.formatMessage({ - id: 'resources.modelfiles.form.localdir' - })} - > + { + + } - )} - + {renderFieldsBySource} + + { + + } + + {source !== modelSourceMap.local_path_value && ( + + name="local_dir" + rules={[ + { + required: false, + message: getRuleMessage( + 'input', + 'resources.modelfiles.form.localdir' + ) + } + ]} + > + + } + label={intl.formatMessage({ + id: 'resources.modelfiles.form.localdir' + })} + > + + )} + +
); });