diff --git a/src/locales/en-US/clusters.ts b/src/locales/en-US/clusters.ts index 3a79308a..6cf54728 100644 --- a/src/locales/en-US/clusters.ts +++ b/src/locales/en-US/clusters.ts @@ -81,6 +81,7 @@ Same applies to the /opt/dtk directory.`, 'clusters.addworker.extraVolume.holder': 'e.g. /data/models (path must start with /)', 'clusters.addworker.vendorNotes.title': 'Notes for {vendor} Device', - 'clusters.button.genToken': 'Generate Token', + 'clusters.button.genToken': + 'Need to create a new token? Click here.', 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.` }; diff --git a/src/locales/en-US/playground.ts b/src/locales/en-US/playground.ts index 8e81c42a..84eb5c8a 100644 --- a/src/locales/en-US/playground.ts +++ b/src/locales/en-US/playground.ts @@ -156,5 +156,10 @@ export default { 'playground.image.generate.error': 'Something went wrong. The image could not be generated.', 'playground.uploadfile.sizeError': - 'File size exceeds the limit. Maximum allowed: {size}.' + 'File size exceeds the limit. Maximum allowed: {size}.', + 'playground.uploadImage.url.invalid': + 'Please enter a direct .png or .jpg image URL (e.g. https://.../image.png). Press ESC to cancel.', + 'playground.uploadImage.url.holder': + 'Enter an image URL (supports .png, .jpeg, .jpg)', + 'playground.uploadImage.url.button': 'Add Image from URL' }; diff --git a/src/locales/ja-JP/clusters.ts b/src/locales/ja-JP/clusters.ts index 2218af5f..27c4fa51 100644 --- a/src/locales/ja-JP/clusters.ts +++ b/src/locales/ja-JP/clusters.ts @@ -81,7 +81,8 @@ Same applies to the /opt/dtk directory.`, 'clusters.addworker.extraVolume.holder': 'e.g. /data/models (path must start with /)', 'clusters.addworker.vendorNotes.title': 'Notes for {vendor} Device', - 'clusters.button.genToken': 'Generate Token', + 'clusters.button.genToken': + 'Need to create a new token? Click here.', 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.` }; @@ -154,6 +155,6 @@ Same applies to the /opt/dtk directory.`, // 66. 'clusters.addworker.autoDetect': 'Auto-detect', // 67. 'clusters.addworker.extraVolume.holder': 'e.g. /data/models (path must start with /)' // 68. 'clusters.addworker.vendorNotes.title': 'Notes for {vendor} Device', -// 69. 'clusters.button.genToken': 'Generate Token', +// 69. 'clusters.button.genToken': 'Need to create a new token? Click here.', // 70. 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.` // ========== End of To-Do List ========== diff --git a/src/locales/ja-JP/playground.ts b/src/locales/ja-JP/playground.ts index 736e00b5..9e24427b 100644 --- a/src/locales/ja-JP/playground.ts +++ b/src/locales/ja-JP/playground.ts @@ -159,11 +159,19 @@ export default { 'playground.image.generate.error': 'Something went wrong. The image could not be generated.', 'playground.uploadfile.sizeError': - 'File size exceeds the limit. Maximum allowed: {size}.' + 'File size exceeds the limit. Maximum allowed: {size}.', + 'playground.uploadImage.url.invalid': + 'Please enter a direct .png or .jpg image URL (e.g. https://.../image.png). Press ESC to cancel.', + 'playground.uploadImage.url.holder': + 'Enter an image URL (supports .png, .jpeg, .jpg)', + 'playground.uploadImage.url.button': 'Add Image from URL' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== // 1. 'playground.rerank.query.validate': 'The query is required.' // 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.', // 3. 'playground.uploadfile.sizeError': 'File size exceeds the limit. Maximum allowed: {size}.' +// 4. 'playground.uploadImage.url.invalid': 'Please enter a direct .png or .jpg image URL(e.g. https://.../image.png). Press ESC to cancel.', +// 5. 'playground.uploadImage.url.holder': 'Enter an image URL (supports .png, .jpeg, .jpg)' +// 6. 'playground.uploadImage.url.button': 'Add Image from URL' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/clusters.ts b/src/locales/ru-RU/clusters.ts index 34ee9167..354a5798 100644 --- a/src/locales/ru-RU/clusters.ts +++ b/src/locales/ru-RU/clusters.ts @@ -81,10 +81,12 @@ export default { 'clusters.addworker.extraVolume.holder': 'напр. /data/models (путь должен начинаться с /)', 'clusters.addworker.vendorNotes.title': 'Примечания для устройств {vendor}', - 'clusters.button.genToken': 'Сгенерировать токен', + 'clusters.button.genToken': + 'Need to create a new token? Click here.', 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.` }; // ========== To-Do: Translate Keys (Remove After Translation) ========== -// 1. 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.` +// 1. 'clusters.addworker.amdNotes-01': `If the /opt/rocm directory does not exist, please create a symbolic link pointing to the ROCm installed path: ln -s /path/to/rocm /opt/rocm.`, +// 2. 'clusters.button.genToken': 'Need to create a new token? Click here.', // ================================================================ diff --git a/src/locales/ru-RU/playground.ts b/src/locales/ru-RU/playground.ts index d38dae7f..8a12541b 100644 --- a/src/locales/ru-RU/playground.ts +++ b/src/locales/ru-RU/playground.ts @@ -150,10 +150,19 @@ export default { 'playground.model.noavailable.tips2': 'Если нужная модель не отображается, убедитесь, что она запущена и ей присвоена правильная категория. Если категория указана неверно, её можно изменить вручную в настройках модели.', 'playground.rerank.query.validate': 'Необходимо указать запрос.', - 'playground.image.generate.error': 'Произошла ошибка. Не удалось сгенерировать изображение.', - 'playground.uploadfile.sizeError': 'Размер файла превышает ограничение. Максимальный размер: {size}.' + 'playground.image.generate.error': + 'Произошла ошибка. Не удалось сгенерировать изображение.', + 'playground.uploadfile.sizeError': + 'Размер файла превышает ограничение. Максимальный размер: {size}.', + 'playground.uploadImage.url.invalid': + 'Please enter a direct .png or .jpg image URL (e.g. https://.../image.png). Press ESC to cancel.', + 'playground.uploadImage.url.holder': + 'Enter an image URL (supports .png, .jpeg, .jpg)', + 'playground.uploadImage.url.button': 'Add Image from URL' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== - +// 1. 'playground.uploadImage.url.invalid': 'Please enter a direct .png or .jpg image URL(e.g. https://.../image.png). Press ESC to cancel.', +// 2. 'playground.uploadImage.url.holder': 'Enter an image URL (supports .png, .jpeg, .jpg)', +// 3. 'playground.uploadImage.url.button': 'Add Image from URL' // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/clusters.ts b/src/locales/zh-CN/clusters.ts index 836a277f..9e8638e0 100644 --- a/src/locales/zh-CN/clusters.ts +++ b/src/locales/zh-CN/clusters.ts @@ -79,7 +79,8 @@ export default { 'clusters.addworker.extraVolume.holder': '例如:/data/models(路径需以 / 开头)', 'clusters.addworker.vendorNotes.title': '{vendor}设备注意事项', - 'clusters.button.genToken': '生成令牌', + 'clusters.button.genToken': + '需要创建令牌?点击这里。', 'clusters.addworker.amdNotes-01': '如果 /opt/rocm 目录不存在,请创建一个指向已安装 ROCm 路径的符号链接:ln -s /path/to/rocm /opt/rocm。' }; diff --git a/src/locales/zh-CN/playground.ts b/src/locales/zh-CN/playground.ts index ed1b654a..d89b2320 100644 --- a/src/locales/zh-CN/playground.ts +++ b/src/locales/zh-CN/playground.ts @@ -148,5 +148,11 @@ export default { '若预期的模型未显示,请检查模型是否已正常运行并被正确分类。如分类不正确,请编辑模型并手动调整其类别。', 'playground.rerank.query.validate': '查询内容不能为空', 'playground.image.generate.error': '出了一点问题,图片未能生成。', - 'playground.uploadfile.sizeError': '上传的文件大小超过限制,最大允许 {size}。' + 'playground.uploadfile.sizeError': + '上传的文件大小超过限制,最大允许 {size}。', + 'playground.uploadImage.url.invalid': + '请输入直接的 .png 或 .jpg 图片链接(例如:https://…/image.png)。按 ESC 可取消。', + 'playground.uploadImage.url.holder': + '请输入图片链接(支持 .png、.jpeg、.jpg 格式)', + 'playground.uploadImage.url.button': '从链接添加图片' }; diff --git a/src/pages/backends/config/index.ts b/src/pages/backends/config/index.ts index 257ea793..506e8318 100644 --- a/src/pages/backends/config/index.ts +++ b/src/pages/backends/config/index.ts @@ -198,7 +198,7 @@ export const yamlTemplate = `# ---------------------------------------- # - must be endwith '-custom' # version_configs: # - image_name: required -# - run_command: required +# - run_command: optional # - custom_framework: # - optional # - choose from: ${Object.values(GPUDriverMap).join(', ')}, CPU diff --git a/src/pages/cluster-management/components/add-credential.tsx b/src/pages/cluster-management/components/add-credential.tsx index d8b18f32..b8fab881 100644 --- a/src/pages/cluster-management/components/add-credential.tsx +++ b/src/pages/cluster-management/components/add-credential.tsx @@ -4,9 +4,8 @@ import SealInput from '@/components/seal-form/seal-input'; import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; import useAppUtils from '@/hooks/use-app-utils'; -import { ExportOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { Form, Typography } from 'antd'; +import { Form } from 'antd'; import React, { useEffect } from 'react'; import styled from 'styled-components'; import { ProviderType, ProviderValueMap } from '../config'; @@ -117,17 +116,21 @@ const AddModal: React.FC = ({ id: 'clusters.credential.token' })} required={action === PageAction.CREATE} + description={ + + } > - - - {intl.formatMessage({ id: 'clusters.button.genToken' })}{' '} - - - )} diff --git a/src/pages/playground/components/message-input.tsx b/src/pages/playground/components/message-input.tsx index 6c6dbd10..9aa1ba8d 100644 --- a/src/pages/playground/components/message-input.tsx +++ b/src/pages/playground/components/message-input.tsx @@ -1,4 +1,5 @@ import SimpleAudio from '@/components/audio-player/simple-audio'; +import DropDownActions from '@/components/drop-down-actions'; import IconFont from '@/components/icon-font'; import UploadAudio from '@/components/upload-audio'; import HotKeys, { KeyMap } from '@/config/hotkeys'; @@ -10,8 +11,11 @@ import { import { ClearOutlined, CustomerServiceOutlined, + LinkOutlined, + PictureOutlined, SendOutlined, - SwapOutlined + SwapOutlined, + UploadOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Checkbox, Divider, Input, Tooltip } from 'antd'; @@ -163,8 +167,11 @@ const MessageInput: React.FC = forwardRef( content: '', imgs: [] }); + const [isFromUrl, setIsFromUrl] = useState(false); + const [openImgTips, setOpenImgTips] = useState(false); const uidCountRef = useRef(0); const inputRef = useRef(null); + const inputImgRef = useRef(null); const updateUidCount = () => { uidCountRef.current += 1; @@ -293,6 +300,39 @@ const MessageInput: React.FC = forwardRef( }); }; + const handleInputImageUrl = (e: any) => { + const url = e.target.value; + // ends with .png, .jpg, .jpeg + const regex = /(https?:\/\/\S+\.(png|jpg|jpeg))/gi; + const isValid = regex.test(url); + setOpenImgTips(!isValid); + if (!isValid) { + return; + } + handleUpdateImgList([ + { + uid: updateUidCount(), + dataUrl: e.target.value + } + ]); + setIsFromUrl(false); + setOpenImgTips(false); + }; + + const handleOnEscape = (e: any) => { + if (e.key === 'Escape') { + setIsFromUrl(false); + setOpenImgTips(false); + } + }; + + const handleAddImgFromUrl = () => { + setIsFromUrl(true); + setTimeout(() => { + inputImgRef.current?.focus?.(); + }, 100); + }; + const handleUploadAudioChange = async (data: { file: any; fileList: any[]; @@ -412,11 +452,41 @@ const MessageInput: React.FC = forwardRef( )} {actions.includes('upload') && message.role === Roles.User && ( - + + {intl.formatMessage({ id: 'playground.img.upload' })} + + ), + key: 'upload_image', + icon: + }, + { + label: intl.formatMessage({ + id: 'playground.uploadImage.url.button' + }), + key: 'add_image_url', + icon: , + onClick: handleAddImgFromUrl + } + ] + }} + > + + )} + {actions.includes('upload') && message.role === Roles.User && ( = forwardRef( )} + {isFromUrl && ( + + + + )}
{actions.includes('paste') ? (