From d389b035b7d51d807ffe4341025b655fd488fb05 Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 3 Mar 2026 15:23:15 +0800 Subject: [PATCH] refactor: playground params form --- config/routes.ts | 11 + src/pages/playground/chat/forms/index.tsx | 81 +++++++ src/pages/playground/chat/index.tsx | 4 +- .../chat/{page.tsx => single-chat.tsx} | 45 ++-- .../playground/components/dynamic-params.tsx | 202 ---------------- .../playground/components/model-select.tsx | 52 ++++ .../components/multiple-chat/model-item.tsx | 24 +- .../playground/components/params-fields.tsx | 107 +++++++++ src/pages/playground/config/form-context.ts | 2 + src/pages/playground/config/params-config.ts | 67 ------ .../embedding/forms/advance-config.tsx | 25 ++ .../playground/embedding/forms/index.tsx | 78 ++++++ src/pages/playground/embedding/page.tsx | 51 ++-- .../{use-init-meta.ts => use-init-image.ts} | 172 +------------- src/pages/playground/hooks/use-init-llm.ts | 171 +++++++++++++ src/pages/playground/images/create.tsx | 9 +- src/pages/playground/images/edit.tsx | 8 +- src/pages/playground/images/forms/index.tsx | 125 ++++++++++ .../rerank/forms/advance-config.tsx | 25 ++ src/pages/playground/rerank/forms/index.tsx | 81 +++++++ src/pages/playground/rerank/page.tsx | 97 ++------ src/pages/playground/rerank/params-config.ts | 21 ++ .../playground/speech/forms/stt-form.tsx | 132 +++++++++++ .../{form.tsx => forms/tts-advance.tsx} | 6 +- .../playground/speech/forms/tts-form.tsx | 202 ++++++++++++++++ src/pages/playground/speech/params-config.ts | 59 ----- src/pages/playground/speech/stt.tsx | 80 +------ src/pages/playground/speech/tts.tsx | 224 +----------------- src/pages/playground/video/forms/index.tsx | 85 +++++++ src/pages/playground/video/page.tsx | 4 +- 30 files changed, 1299 insertions(+), 951 deletions(-) create mode 100644 src/pages/playground/chat/forms/index.tsx rename src/pages/playground/chat/{page.tsx => single-chat.tsx} (86%) delete mode 100644 src/pages/playground/components/dynamic-params.tsx create mode 100644 src/pages/playground/components/model-select.tsx create mode 100644 src/pages/playground/components/params-fields.tsx create mode 100644 src/pages/playground/embedding/forms/advance-config.tsx create mode 100644 src/pages/playground/embedding/forms/index.tsx rename src/pages/playground/hooks/{use-init-meta.ts => use-init-image.ts} (67%) create mode 100644 src/pages/playground/hooks/use-init-llm.ts create mode 100644 src/pages/playground/images/forms/index.tsx create mode 100644 src/pages/playground/rerank/forms/advance-config.tsx create mode 100644 src/pages/playground/rerank/forms/index.tsx create mode 100644 src/pages/playground/speech/forms/stt-form.tsx rename src/pages/playground/speech/{form.tsx => forms/tts-advance.tsx} (96%) create mode 100644 src/pages/playground/speech/forms/tts-form.tsx create mode 100644 src/pages/playground/video/forms/index.tsx diff --git a/config/routes.ts b/config/routes.ts index 207120d5..b866133f 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -74,6 +74,17 @@ export default [ defaultIcon: 'icon-audio1', component: './playground/speech/index' } + // { + // name: 'video', + // title: 'Video', + // path: '/playground/video', + // key: 'video', + // icon: 'icon-video-outline', + // hideInMenu: false, + // selectedIcon: 'icon-video-filled02', + // defaultIcon: 'icon-video-outline', + // component: './playground/video' + // } ] }, { diff --git a/src/pages/playground/chat/forms/index.tsx b/src/pages/playground/chat/forms/index.tsx new file mode 100644 index 00000000..4ec9db0f --- /dev/null +++ b/src/pages/playground/chat/forms/index.tsx @@ -0,0 +1,81 @@ +import { Form } from 'antd'; +import React, { forwardRef, useImperativeHandle } from 'react'; +import ModelSelect from '../../components/model-select'; +import ParamsFields from '../../components/params-fields'; +import { FormContext } from '../../config/form-context'; +import { ParamsSchema } from '../../config/types'; + +type ParamsSettingsProps = { + ref?: any; + parametersTitle?: React.ReactNode; + showModelSelector?: boolean; + modelList?: Global.BaseOption[]; + onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + initialValues?: Record; // for initial values when switch model, aviod update values from setParams + meta?: Record; + paramsConfig?: ParamsSchema[]; +}; + +const ParamsSettings: React.FC = forwardRef( + ( + { + onValuesChange, + onModelChange, + onFinish, + onFinishFailed, + parametersTitle, + initialValues, + modelList, + showModelSelector = true, + meta, + paramsConfig + }, + ref + ) => { + const [form] = Form.useForm(); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + return ( + +
+ + +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/chat/index.tsx b/src/pages/playground/chat/index.tsx index ac51e6d9..406a9055 100644 --- a/src/pages/playground/chat/index.tsx +++ b/src/pages/playground/chat/index.tsx @@ -16,7 +16,7 @@ import { queryModelsList } from '../apis'; import MultipleChat from '../components/multiple-chat'; import ViewCodeButtons from '../components/view-code-buttons'; import '../style/play-ground.less'; -import GroundChat from './page'; +import SingleChat from './single-chat'; const Playground: React.FC = () => { const intl = useIntl(); @@ -65,7 +65,7 @@ const Playground: React.FC = () => { label: 'Chat', icon: , children: ( - + ) }, { diff --git a/src/pages/playground/chat/page.tsx b/src/pages/playground/chat/single-chat.tsx similarity index 86% rename from src/pages/playground/chat/page.tsx rename to src/pages/playground/chat/single-chat.tsx index 0b171f13..54be9df2 100644 --- a/src/pages/playground/chat/page.tsx +++ b/src/pages/playground/chat/single-chat.tsx @@ -8,7 +8,6 @@ import React, { useState } from 'react'; import { CHAT_API } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import MessageInput from '../components/message-input'; import MessageContent from '../components/multiple-chat/message-content'; import SystemMessage from '../components/multiple-chat/system-message'; @@ -16,13 +15,14 @@ import ReferenceParams from '../components/reference-params'; import RightContainer from '../components/right-container'; import ViewCommonCode from '../components/view-common-code'; import { Roles, generateMessagesByListContent } from '../config'; -import { MessageItem, MessageItemAction } from '../config/types'; +import { MessageItem } from '../config/types'; import { LLM_METAKEYS, llmInitialValues } from '../hooks/config'; import useChatCompletion from '../hooks/use-chat-completion'; -import { useInitLLmMeta } from '../hooks/use-init-meta'; +import { useInitLLmMeta } from '../hooks/use-init-llm'; import '../style/ground-llm.less'; import '../style/system-message-wrap.less'; import { generateLLMCode } from '../view-code/llm'; +import DataForm from './forms'; import { ChatParamsConfig } from './params-config'; interface MessageProps { @@ -37,12 +37,6 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { const [show, setShow] = useState(false); const [collapse, setCollapse] = useState(false); const scroller = useRef(null); - const [actions, setActions] = useState([ - 'upload', - 'delete', - 'copy', - 'edit' - ]); const { submitMessage, @@ -54,23 +48,15 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { messageList, loading } = useChatCompletion(scroller); - const { - handleOnValuesChange, - formRef, - paramsConfig, - initialValues, - parameters - } = useInitLLmMeta( - { modelList, isChat: true }, - { - defaultValues: { - ...llmInitialValues, - model: modelList[0]?.value - }, - defaultParamsConfig: ChatParamsConfig, - metaKeys: LLM_METAKEYS - } - ); + const { handleOnValuesChange, formRef, paramsConfig, parameters } = + useInitLLmMeta( + { modelList, isChat: true }, + { + defaultValues: llmInitialValues, + defaultParamsConfig: ChatParamsConfig, + metaKeys: LLM_METAKEYS + } + ); useImperativeHandle(ref, () => { return { @@ -146,7 +132,7 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { setMessageList={setMessageList} editable={true} loading={loading} - actions={actions} + actions={['upload', 'delete', 'copy', 'edit']} /> {loading && ( @@ -180,13 +166,12 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { - []; - onValuesChange?: (changeValues: any, value: Record) => void; - onModelChange?: (model: string) => void; - paramsConfig?: ParamsSchema[]; - initialValues?: Record; // for initial values when switch model, aviod update values from setParams - extra?: React.ReactNode; - watchFields?: string[]; - formFields?: string; - meta?: Record; -}; - -const ParamsSettings: React.FC = forwardRef( - ( - { - onValuesChange, - onModelChange, - parametersTitle, - initialValues, - paramsConfig, - modelList, - showModelSelector = true, - extra, - meta - }, - ref - ) => { - const intl = useIntl(); - const [form] = Form.useForm(); - const formId = useId(); - - useImperativeHandle(ref, () => ({ - form - })); - - useEffect(() => { - form.setFieldsValue({ - ...initialValues - }); - }, [initialValues]); - - const handleOnFinish = (values: any) => { - console.log('handleOnFinish', values); - }; - - const handleOnFinishFailed = (errorInfo: any) => { - console.log('handleOnFinishFailed', errorInfo); - }; - - const handleOnModelChange = (model: string) => { - onModelChange?.(model); - }; - - const handleValuesChange = useCallback( - (changedValues: any, allValues: any) => { - const normalizedValues = Object.fromEntries( - Object.entries(changedValues).map(([key, value]: [string, any]) => [ - key, - value?.target?.checked ?? value?.target?.value ?? value - ]) - ); - form.setFieldsValue(normalizedValues); - console.log('handleValuesChange', normalizedValues, allValues); - onValuesChange?.(normalizedValues, { - ...allValues, - ...normalizedValues - }); - }, - [onValuesChange] - ); - - const renderDescription = useCallback( - (description: any) => { - let desc = description?.text; - if (description?.isLocalized) { - desc = intl.formatMessage({ id: description?.text }); - } - if (description?.html) { - return
; - } - - return desc; - }, - [intl] - ); - - const renderFields = () => { - if (!paramsConfig?.length) { - return null; - } - const values = form.getFieldsValue(); - const formValues = _.isEmpty(values) ? initialValues || {} : values; - return paramsConfig?.map((item: ParamsSchema) => { - return ( - - - - ); - }); - }; - - return ( - -
-
- { - <> -

- {parametersTitle || ( - - {intl.formatMessage({ id: 'playground.parameters' })} - - )} -

- {showModelSelector && ( - - - - )} - - } - {renderFields()} - {extra} -
-
-
- ); - } -); - -export default ParamsSettings; diff --git a/src/pages/playground/components/model-select.tsx b/src/pages/playground/components/model-select.tsx new file mode 100644 index 00000000..070eb96d --- /dev/null +++ b/src/pages/playground/components/model-select.tsx @@ -0,0 +1,52 @@ +import SealSelect from '@/components/seal-form/seal-select'; +import { useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import React from 'react'; +import { useFormContext } from '../config/form-context'; + +const ModelSelect: React.FC<{ + title?: React.ReactNode; + showModelSelector?: boolean; +}> = ({ title, showModelSelector = true }) => { + const intl = useIntl(); + const { onModelChange, modelList } = useFormContext(); + return ( + <> +

+ {title || ( + {intl.formatMessage({ id: 'playground.parameters' })} + )} +

+ {showModelSelector && ( + + + + )} + + ); +}; + +export default ModelSelect; diff --git a/src/pages/playground/components/multiple-chat/model-item.tsx b/src/pages/playground/components/multiple-chat/model-item.tsx index 48c65cf7..821dd594 100644 --- a/src/pages/playground/components/multiple-chat/model-item.tsx +++ b/src/pages/playground/components/multiple-chat/model-item.tsx @@ -24,16 +24,16 @@ import React, { } from 'react'; import 'simplebar-react/dist/simplebar.min.css'; import { CHAT_API } from '../../apis'; +import DataForm from '../../chat/forms'; import { ChatParamsConfig } from '../../chat/params-config'; import { Roles, generateMessagesByListContent } from '../../config'; import CompareContext from '../../config/compare-context'; import { MessageItem, ModelSelectionItem } from '../../config/types'; import { LLM_METAKEYS, llmInitialValues } from '../../hooks/config'; import useChatCompletion from '../../hooks/use-chat-completion'; -import { useInitLLmMeta } from '../../hooks/use-init-meta'; +import { useInitLLmMeta } from '../../hooks/use-init-llm'; import '../../style/model-item.less'; import { generateLLMCode } from '../../view-code/llm'; -import DynamicParams from '../dynamic-params'; import ReferenceParams from '../reference-params'; import ViewCommonCode from '../view-common-code'; import MessageContent from './message-content'; @@ -62,10 +62,8 @@ const ModelItem: React.FC = forwardRef((props, ref) => { handleOnValuesChange, handleOnModelChange, setParams, - setInitialValues, formRef, paramsConfig, - initialValues, parameters } = useInitLLmMeta( { @@ -73,10 +71,7 @@ const ModelItem: React.FC = forwardRef((props, ref) => { modelList: modelFullList }, { - defaultValues: { - ...llmInitialValues, - model: model - }, + defaultValues: llmInitialValues, defaultParamsConfig: ChatParamsConfig, metaKeys: LLM_METAKEYS } @@ -87,6 +82,8 @@ const ModelItem: React.FC = forwardRef((props, ref) => { const [show, setShow] = useState(false); const scroller = useRef(null); + console.log('render model item', formRef); + const { submitMessage, handleAddNewMessage, @@ -217,11 +214,8 @@ const ModelItem: React.FC = forwardRef((props, ref) => { ...globalParams }; }); - setInitialValues((prev: any) => { - return { - ...prev, - ...globalParams - }; + formRef.current?.setFieldsValue({ + ...globalParams }); }, [globalParams]); @@ -313,11 +307,11 @@ const ModelItem: React.FC = forwardRef((props, ref) => { style={{ paddingInline: '24px' }} oppositeTheme={true} > - diff --git a/src/pages/playground/components/params-fields.tsx b/src/pages/playground/components/params-fields.tsx new file mode 100644 index 00000000..1ee85011 --- /dev/null +++ b/src/pages/playground/components/params-fields.tsx @@ -0,0 +1,107 @@ +import FieldComponent from '@/components/seal-form/field-component'; +import { useIntl } from '@umijs/max'; +import { Form } from 'antd'; +import _ from 'lodash'; +import React from 'react'; +import { useFormContext } from '../config/form-context'; +import { ParamsSchema } from '../config/types'; + +interface ParamsFieldsProps { + paramsConfig?: ParamsSchema[]; +} + +const ParamsFields: React.FC = ({ paramsConfig = [] }) => { + const intl = useIntl(); + const form = Form.useFormInstance(); + const { meta } = useFormContext(); + + const renderDescription = (description: any) => { + let desc = description?.text; + if (description?.isLocalized) { + desc = intl.formatMessage({ id: description?.text }); + } + if (description?.html) { + return
; + } + + return desc; + }; + + return paramsConfig?.map((item: ParamsSchema) => { + const comProps = { + ...item.attrs, + label: item.label.isLocalized + ? intl.formatMessage({ id: item.label.text }) + : item.label.text + }; + // if no disabledConfig, render directly + if (!item.disabledConfig) { + return ( + + + + ); + } + + // if has disabledConfig, wrap with another Form.Item to listen the dependencies change + return ( + { + return ( + item.disabledConfig?.depends.some( + (dep) => prevValues[dep] !== currentValues[dep] + ) ?? false + ); + }} + key={item.name} + > + {() => ( + + + + )} + + ); + }); +}; + +export default ParamsFields; diff --git a/src/pages/playground/config/form-context.ts b/src/pages/playground/config/form-context.ts index d25d49f0..040b6569 100644 --- a/src/pages/playground/config/form-context.ts +++ b/src/pages/playground/config/form-context.ts @@ -2,7 +2,9 @@ import { createContext, useContext } from 'react'; export interface FormContextProps { meta?: Record; + modelList: Global.BaseOption[]; onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; } /** diff --git a/src/pages/playground/config/params-config.ts b/src/pages/playground/config/params-config.ts index d7ebc10d..3f9bbba5 100644 --- a/src/pages/playground/config/params-config.ts +++ b/src/pages/playground/config/params-config.ts @@ -31,30 +31,6 @@ export const imageSizeOptions: { { label: '2048x2048(1:1)', value: '2048x2048', width: 2048, height: 2048 } ]; -export const RealtimeParamsConfig: ParamsSchema[] = [ - { - type: 'Select', - name: 'language', - options: [ - { label: 'Auto', value: 'auto' }, - { label: 'English', value: 'en' }, - { label: '中文', value: 'zh' }, - { label: '日本語', value: 'ja' }, - { label: 'Français', value: 'fr' }, - { label: 'Deutsch', value: 'de' } - ], - label: { - text: 'playground.params.language', - isLocalized: true - }, - rules: [ - { - required: true - } - ] - } -]; - export const ImageParamsConfig: ParamsSchema[] = [ { type: 'InputNumber', @@ -403,49 +379,6 @@ const advancedConfig = [ } ]; -export const ImageAdvancedParamsConfig: ParamsSchema[] = [ - { - type: 'InputNumber', - name: 'seed', - label: { - text: 'playground.image.params.seed', - isLocalized: true - }, - attrs: { - min: 0 - }, - dependencies: ['random_seed'], - disabledConfig: { - depends: ['random_seed'], - when: (values: Record): boolean => values?.random_seed - }, - rules: [ - { - required: false - } - ] - }, - { - type: 'Checkbox', - name: 'random_seed', - label: { - text: 'playground.image.params.randomseed', - isLocalized: true - }, - style: { - marginBottom: 20 - }, - formItemAttrs: { - noStyle: true - }, - rules: [ - { - required: false - } - ] - } -]; - export const CustomSizeConfig: ParamsSchema[] = [ { type: 'Slider', diff --git a/src/pages/playground/embedding/forms/advance-config.tsx b/src/pages/playground/embedding/forms/advance-config.tsx new file mode 100644 index 00000000..27872db0 --- /dev/null +++ b/src/pages/playground/embedding/forms/advance-config.tsx @@ -0,0 +1,25 @@ +import SealInputNumber from '@/components/seal-form/input-number'; +import { Form } from 'antd'; +import _ from 'lodash'; +import React from 'react'; +import { useFormContext } from '../../config/form-context'; + +const AdvanceConfig: React.FC = () => { + const { meta: modelMeta } = useFormContext(); + + return ( + <> + {modelMeta?.n_ctx && modelMeta?.n_slot && ( + + + + )} + + ); +}; + +export default AdvanceConfig; diff --git a/src/pages/playground/embedding/forms/index.tsx b/src/pages/playground/embedding/forms/index.tsx new file mode 100644 index 00000000..37c16af9 --- /dev/null +++ b/src/pages/playground/embedding/forms/index.tsx @@ -0,0 +1,78 @@ +import { Form } from 'antd'; +import React, { forwardRef, useImperativeHandle } from 'react'; +import ModelSelect from '../../components/model-select'; +import { FormContext } from '../../config/form-context'; +import AdvanceConfig from './advance-config'; + +type ParamsSettingsProps = { + ref?: any; + parametersTitle?: React.ReactNode; + showModelSelector?: boolean; + modelList?: Global.BaseOption[]; + onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + initialValues?: Record; // for initial values when switch model, aviod update values from setParams + meta?: Record; +}; + +const ParamsSettings: React.FC = forwardRef( + ( + { + onValuesChange, + onModelChange, + onFinish, + onFinishFailed, + parametersTitle, + initialValues, + modelList, + showModelSelector = true, + meta + }, + ref + ) => { + const [form] = Form.useForm(); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + return ( + +
+ + +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/embedding/page.tsx b/src/pages/playground/embedding/page.tsx index 1ac0c417..9e6d11e7 100644 --- a/src/pages/playground/embedding/page.tsx +++ b/src/pages/playground/embedding/page.tsx @@ -13,6 +13,7 @@ import { SendOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; +import { useMemoizedFn } from 'ahooks'; import { Button, Checkbox, Form, Segmented, Spin, Tabs, Tooltip } from 'antd'; import _ from 'lodash'; import 'overlayscrollbars/overlayscrollbars.css'; @@ -26,7 +27,6 @@ import React, { useState } from 'react'; import { EMBEDDING_API, handleEmbedding } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import FileList from '../components/file-list'; import InputList from '../components/input-list'; import RightContainer from '../components/right-container'; @@ -36,10 +36,11 @@ import { extractErrorMessage } from '../config'; import { embeddingSamples } from '../config/samples'; import { LLM_METAKEYS } from '../hooks/config'; import useEmbeddingWorker from '../hooks/use-embedding-worker'; -import { useInitLLmMeta } from '../hooks/use-init-meta'; +import { useInitLLmMeta } from '../hooks/use-init-llm'; import '../style/ground-llm.less'; import '../style/rerank.less'; import { generateEmbeddingCode } from '../view-code/embedding'; +import DataForm from './forms'; interface MessageProps { modelList: Global.BaseOption[]; @@ -103,25 +104,18 @@ const GroundEmbedding: React.FC = forwardRef((props, ref) => { const { initialize, updateScrollerPosition: updateDocumentScrollerPosition } = useOverlayScroller(); - const { - handleOnValuesChange, - formRef, - paramsConfig, - initialValues, - parameters, - modelMeta, - formFields - } = useInitLLmMeta( - { - modelList, - isChat: true - }, - { - defaultValues: {}, - defaultParamsConfig: [], - metaKeys: LLM_METAKEYS - } - ); + const { handleOnValuesChange, formRef, parameters, modelMeta } = + useInitLLmMeta( + { + modelList, + isChat: true + }, + { + defaultValues: {}, + defaultParamsConfig: [], + metaKeys: LLM_METAKEYS + } + ); useImperativeHandle(ref, () => { return { @@ -143,14 +137,14 @@ const GroundEmbedding: React.FC = forwardRef((props, ref) => { return generateEmbeddingCode({ api: EMBEDDING_API, parameters: { - ..._.pick(parameters, ['model', ..._.split(formFields, ',')]), + ...parameters, input: [ ...textList.map((item) => item.text).filter((item) => item), ...fileList.map((item) => item.text).filter((item) => item) ] } }); - }, [parameters, formFields, textList, fileList]); + }, [parameters, textList, fileList]); const inputEmpty = useMemo(() => { const list = [...textList, ...fileList]; @@ -441,15 +435,14 @@ const GroundEmbedding: React.FC = forwardRef((props, ref) => { ]; }, [outputHeight, collapse, scatterData, embeddingData]); - const onValuesChange = useCallback( + const onValuesChange = useMemoizedFn( (changeValues: Record, allValues: Record) => { if (changeValues.model) { setScatterData([]); setTokenResult(null); } handleOnValuesChange(changeValues, allValues); - }, - [] + } ); useEffect(() => { @@ -710,13 +703,11 @@ const GroundEmbedding: React.FC = forwardRef((props, ref) => { - | string[]; - defaultValues?: Record; - defaultParamsConfig?: ParamsSchema[]; -} - -// init not image meta, for params form -export const useInitLLmMeta = ( - props: MessageProps, - options: InitMetaOptions -) => { - const { modelList, model, isChat } = props; - const { - metaKeys = {}, - defaultValues = {}, - defaultParamsConfig = [] - } = options; - const formRef = useRef(null); - const [searchParams] = useSearchParams(); - const [modelMeta, setModelMeta] = useState({}); - const [initialValues, setInitialValues] = useState({ - ...defaultValues, - model: '' - }); - const [parameters, setParams] = useState({ - model: '' - }); - const [paramsConfig, setParamsConfig] = - useState(defaultParamsConfig); - - const defaultModel = useMemo(() => { - if (isChat) { - return searchParams.get('model') || model || modelList?.[0]?.value; - } - // use for multiple chat - return model; - }, [model, modelList, isChat]); - - const getMaxTokens = (meta: any) => { - const { max_model_len, n_ctx, n_slot, max_total_tokens } = meta || {}; - - let max_tokens: number = 0; - - if (n_ctx && n_slot) { - max_tokens = _.floor(_.divide(n_ctx, n_slot)); - } else if (max_model_len) { - max_tokens = max_model_len; - } else if (max_total_tokens) { - max_tokens = max_total_tokens; - } - - return { - max_tokens: max_tokens || 16 * 1024, - defaultFormValue: max_tokens ? _.floor(_.divide(max_tokens, 2)) : 1024 - }; - }; - - const extractLLMMeta = (meta: any) => { - const towKeys = new Set(precisionTwoKeys); - const modelMeta = meta || {}; - const modelMetaValue = _.pick(modelMeta, _.keys(metaKeys)); - const obj = Object.entries(metaKeys).reduce((acc: any, [key, value]) => { - const val = modelMetaValue[key]; - if (_.hasIn(modelMetaValue, key)) { - acc[value] = towKeys.has(key) ? _.round(val, 2) : val; - } - return acc; - }, {}); - - const tokensRes = getMaxTokens(obj); - - return { - form: _.merge({}, defaultValues, { - ..._.omit(obj, [ - 'n_ctx', - 'n_slot', - 'max_model_len', - 'max_total_tokens' - ]), - seed: obj.seed === -1 ? null : obj.seed, - max_tokens: tokensRes.defaultFormValue - }), - meta: { - ...obj, - max_tokens: tokensRes.max_tokens - } - }; - }; - - const formFields = useMemo(() => { - const fields = paramsConfig?.map((item) => item.name); - return fields?.join(','); - }, [paramsConfig]); - - const handleOnModelChange = useMemoizedFn((val: string) => { - if (!val) return; - const model = modelList.find((item) => item.value === val); - const { form: initialData, meta } = extractLLMMeta(model?.meta); - setModelMeta(meta); - setInitialValues({ - ...initialData, - model: val - }); - setParams({ - ...initialData, - model: val - }); - const config = defaultParamsConfig.map((item) => { - return { - ...item, - attrs: - item.name === 'max_tokens' - ? { ...item.attrs, max: meta.max_tokens } - : { - ...item.attrs - } - }; - }); - setParamsConfig(config); - }); - - const handleOnValuesChange = useMemoizedFn( - (changeValues: Record, allValues: Record) => { - if (changeValues.model) { - handleOnModelChange(changeValues.model); - return; - } else { - setParams(allValues); - setInitialValues(allValues); - } - } - ); - - useEffect(() => { - if (defaultModel && modelList.length) { - handleOnModelChange(defaultModel); - } - }, [defaultModel, modelList.length]); - - return { - extractLLMMeta, - handleOnModelChange, - handleOnValuesChange, - setModelMeta, - setInitialValues, - setParams, - setParamsConfig, - formRef, - paramsConfig, - initialValues, - parameters, - modelMeta, - formFields - }; -}; - export const useInitImageMeta = ( props: MessageProps, options: { type: string } ) => { const { modelList } = props; - const ImageAdvancedParamsConfig = - options.type === 'edit' - ? ImgAdvancedParamsConfig - : ImgAdvancedParamsConfig.filter((item) => item.name !== 'strength'); + const ImageAdvancedParamsConfig: ParamsSchema[] = []; const form = useRef(null); const [searchParams] = useSearchParams(); @@ -380,11 +219,6 @@ export const useInitImageMeta = ( }); }; - const formFields = useMemo(() => { - const fields = paramsConfig?.map((item) => item.name); - return fields?.join(','); - }, [paramsConfig]); - const handleOnModelChange = useMemoizedFn((val: string) => { if (!val) return; const model = modelList.find((item) => item.value === val); @@ -488,7 +322,6 @@ export const useInitImageMeta = ( setParamsConfig, form, modelMeta, - formFields, paramsConfig, initialValues, parameters, @@ -498,7 +331,6 @@ export const useInitImageMeta = ( imageSizeOptions, openaiCompatibleFieldsDefaultValus, advancedFieldsDefaultValus, - ImageAdvancedParamsConfig, imgInitialValues, ImageCountConfig, ImageSizeConfig, diff --git a/src/pages/playground/hooks/use-init-llm.ts b/src/pages/playground/hooks/use-init-llm.ts new file mode 100644 index 00000000..3de5e4c7 --- /dev/null +++ b/src/pages/playground/hooks/use-init-llm.ts @@ -0,0 +1,171 @@ +import { useSearchParams } from '@umijs/max'; +import { useMemoizedFn } from 'ahooks'; +import _ from 'lodash'; +import { useEffect, useRef, useState } from 'react'; +import { ParamsSchema } from '../config/types'; +import { precisionTwoKeys } from './config'; + +interface MessageProps { + modelList: Global.BaseOption[]; + model?: string; + loaded?: boolean; + isChat?: boolean; + ref?: any; +} + +interface InitMetaOptions { + metaKeys?: Record | string[]; + defaultValues?: Record; + defaultParamsConfig?: ParamsSchema[]; +} + +// init not image meta, for params form +export const useInitLLmMeta = ( + props: MessageProps, + options: InitMetaOptions +) => { + const { modelList, model, isChat } = props; + const { + metaKeys = {}, + defaultValues = {}, + defaultParamsConfig = [] + } = options; + const formRef = useRef(null); + const [searchParams] = useSearchParams(); + const [modelMeta, setModelMeta] = useState({}); + const [parameters, setParams] = useState({ + model: '' + }); + const [paramsConfig, setParamsConfig] = + useState(defaultParamsConfig); + const initializedRef = useRef(false); + + const getMaxTokens = (meta: any) => { + const { max_model_len, n_ctx, n_slot, max_total_tokens } = meta || {}; + + let max_tokens: number = 0; + + if (n_ctx && n_slot) { + max_tokens = _.floor(_.divide(n_ctx, n_slot)); + } else if (max_model_len) { + max_tokens = max_model_len; + } else if (max_total_tokens) { + max_tokens = max_total_tokens; + } + + return { + max_tokens: max_tokens || 16 * 1024, + defaultFormValue: max_tokens ? _.floor(_.divide(max_tokens, 2)) : 1024 + }; + }; + + const extractLLMMeta = (meta: any) => { + const towKeys = new Set(precisionTwoKeys); + const modelMeta = meta || {}; + const modelMetaValue = _.pick(modelMeta, _.keys(metaKeys)); + const obj = Object.entries(metaKeys).reduce((acc: any, [key, value]) => { + const val = modelMetaValue[key]; + if (_.hasIn(modelMetaValue, key)) { + acc[value] = towKeys.has(key) ? _.round(val, 2) : val; + } + return acc; + }, {}); + + const tokensRes = getMaxTokens(obj); + + return { + form: _.merge({}, defaultValues, { + ..._.omit(obj, [ + 'n_ctx', + 'n_slot', + 'max_model_len', + 'max_total_tokens' + ]), + seed: obj.seed === -1 ? null : obj.seed, + max_tokens: tokensRes.defaultFormValue + }), + meta: { + ...obj, + max_tokens: tokensRes.max_tokens + } + }; + }; + + const setFormValues = (values: Record) => { + formRef.current?.setFieldsValue(values); + }; + + const handleOnModelChange = useMemoizedFn((val: string) => { + if (!val) return; + const model = modelList.find((item) => item.value === val); + const { form: initialData, meta } = extractLLMMeta(model?.meta); + setModelMeta(meta); + setFormValues({ + ...initialData, + model: val + }); + setParams({ + ...initialData, + model: val + }); + + // update max_tokens in paramsConfig when model change, because max_tokens value depend on model meta + const hasMaxTokensField = defaultParamsConfig.some( + (item) => item.name === 'max_tokens' + ); + + if (!hasMaxTokensField) { + const config = defaultParamsConfig.map((item) => { + return { + ...item, + attrs: + item.name === 'max_tokens' + ? { ...item.attrs, max: meta.max_tokens } + : { + ...item.attrs + } + }; + }); + setParamsConfig(config); + } + }); + + const handleOnValuesChange = useMemoizedFn( + (changeValues: Record, allValues: Record) => { + if (changeValues.model) { + return; + } + setParams(allValues); + setFormValues(allValues); + } + ); + + useEffect(() => { + if (initializedRef.current || !modelList.length) { + return; + } + let defaultModel = model; + if (isChat) { + defaultModel = + searchParams.get('model') || model || modelList?.[0]?.value; + } + + if (defaultModel && modelList.length && !initializedRef.current) { + handleOnModelChange(defaultModel); + initializedRef.current = true; + } + }, [modelList, isChat, model]); + + return { + extractLLMMeta, + handleOnModelChange, + handleOnValuesChange, + setModelMeta, + setParams, + setParamsConfig, + paramsConfig, + formRef, + parameters, + modelMeta + }; +}; diff --git a/src/pages/playground/images/create.tsx b/src/pages/playground/images/create.tsx index 663171cf..d5b3bced 100644 --- a/src/pages/playground/images/create.tsx +++ b/src/pages/playground/images/create.tsx @@ -18,16 +18,15 @@ import React, { useState } from 'react'; import { CREAT_IMAGE_API } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import MessageInput from '../components/message-input'; import RightContainer from '../components/right-container'; import ViewCommonCode from '../components/view-common-code'; -import { useInitImageMeta } from '../hooks/use-init-meta'; +import { useInitImageMeta } from '../hooks/use-init-image'; import useTextImage from '../hooks/use-text-image'; import '../style/ground-llm.less'; import '../style/system-message-wrap.less'; import { generateImageCode, generateOpenaiImageCode } from '../view-code/image'; - +import DataForm from './forms'; interface MessageProps { modelList: Global.BaseOption[]; loaded?: boolean; @@ -48,7 +47,6 @@ const GroundImages: React.FC = forwardRef((props, ref) => { handleToggleParamsStyle, setParams, form, - formFields, paramsConfig, initialValues, parameters, @@ -264,9 +262,8 @@ const GroundImages: React.FC = forwardRef((props, ref) => { - []; @@ -75,7 +75,6 @@ const GroundImages: React.FC = forwardRef((props, ref) => { setParamsConfig, form, modelMeta, - formFields, paramsConfig, initialValues, parameters, @@ -529,9 +528,8 @@ const GroundImages: React.FC = forwardRef((props, ref) => { } > - []; + onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + initialValues?: Record; // for initial values when switch model, aviod update values from setParams + meta?: Record; + paramsConfig?: ParamsSchema[]; +}; + +const ParamsSettings: React.FC = forwardRef( + ( + { + onValuesChange, + onModelChange, + onFinish, + onFinishFailed, + parametersTitle, + initialValues, + modelList, + showModelSelector = true, + meta, + paramsConfig + }, + ref + ) => { + const intl = useIntl(); + const [form] = Form.useForm(); + const randomSeed = Form.useWatch('random_seed', form); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + const handleOnValuesChange = ( + changeValues: any, + allValues: Record + ) => { + const normalizedValues = Object.fromEntries( + Object.entries(changeValues).map(([key, value]: [string, any]) => [ + key, + value?.target?.checked ?? value?.target?.value ?? value + ]) + ); + form.setFieldsValue(normalizedValues); + onValuesChange?.(normalizedValues, { + ...allValues, + ...normalizedValues + }); + }; + + useEffect(() => { + form.setFieldsValue(initialValues); + }, [initialValues]); + + return ( + +
+ + + + + + + + +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/rerank/forms/advance-config.tsx b/src/pages/playground/rerank/forms/advance-config.tsx new file mode 100644 index 00000000..27872db0 --- /dev/null +++ b/src/pages/playground/rerank/forms/advance-config.tsx @@ -0,0 +1,25 @@ +import SealInputNumber from '@/components/seal-form/input-number'; +import { Form } from 'antd'; +import _ from 'lodash'; +import React from 'react'; +import { useFormContext } from '../../config/form-context'; + +const AdvanceConfig: React.FC = () => { + const { meta: modelMeta } = useFormContext(); + + return ( + <> + {modelMeta?.n_ctx && modelMeta?.n_slot && ( + + + + )} + + ); +}; + +export default AdvanceConfig; diff --git a/src/pages/playground/rerank/forms/index.tsx b/src/pages/playground/rerank/forms/index.tsx new file mode 100644 index 00000000..2eef117d --- /dev/null +++ b/src/pages/playground/rerank/forms/index.tsx @@ -0,0 +1,81 @@ +import { Form } from 'antd'; +import React, { forwardRef, useImperativeHandle } from 'react'; +import ModelSelect from '../../components/model-select'; +import ParamsFields from '../../components/params-fields'; +import { FormContext } from '../../config/form-context'; +import { fieldConfig } from '../params-config'; +import AdvanceConfig from './advance-config'; + +type ParamsSettingsProps = { + ref?: any; + parametersTitle?: React.ReactNode; + showModelSelector?: boolean; + modelList?: Global.BaseOption[]; + onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + initialValues?: Record; // for initial values when switch model, aviod update values from setParams + meta?: Record; +}; + +const ParamsSettings: React.FC = forwardRef( + ( + { + onValuesChange, + onModelChange, + onFinish, + onFinishFailed, + parametersTitle, + initialValues, + modelList, + showModelSelector = true, + meta + }, + ref + ) => { + const [form] = Form.useForm(); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + return ( + +
+ + + +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/rerank/page.tsx b/src/pages/playground/rerank/page.tsx index b8891df3..3a631dc3 100644 --- a/src/pages/playground/rerank/page.tsx +++ b/src/pages/playground/rerank/page.tsx @@ -1,5 +1,4 @@ import AlertInfo from '@/components/alert-info'; -import SealInputNumber from '@/components/seal-form/input-number'; import useOverlayScroller from '@/hooks/use-overlay-scroller'; import useRequestToken from '@/hooks/use-request-token'; import { @@ -9,16 +8,7 @@ import { SendOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { - Button, - Checkbox, - Form, - Input, - Spin, - Tag, - Tooltip, - Typography -} from 'antd'; +import { Button, Checkbox, Input, Spin, Tag, Tooltip, Typography } from 'antd'; import _ from 'lodash'; import 'overlayscrollbars/overlayscrollbars.css'; import React, { @@ -32,21 +22,21 @@ import React, { } from 'react'; import styled from 'styled-components'; import { RERANKER_API, rerankerQuery } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import InputList from '../components/input-list'; import RightContainer from '../components/right-container'; import TokenUsage from '../components/token-usage'; import ViewCommonCode from '../components/view-common-code'; import { extractErrorMessage } from '../config'; import { rerankerSamples } from '../config/samples'; -import { ParamsSchema } from '../config/types'; import { LLM_METAKEYS } from '../hooks/config'; -import { useInitLLmMeta } from '../hooks/use-init-meta'; +import { useInitLLmMeta } from '../hooks/use-init-llm'; import '../style/ground-llm.less'; import '../style/rerank.less'; import '../style/system-message-wrap.less'; import { generateRerankCode } from '../view-code/rerank'; +import DataForm from './forms'; import useRerankerResponse from './hooks/use-reranker-response'; +import { fieldConfig } from './params-config'; const { Text } = Typography; @@ -67,26 +57,6 @@ interface MessageProps { ref?: any; } -const fieldConfig: ParamsSchema[] = [ - { - type: 'InputNumber', - name: 'top_n', - label: { - text: 'Top N', - isLocalized: false - }, - attrs: { - min: 1 - }, - rules: [ - { - required: true, - message: 'Top N is required' - } - ] - } -]; - const GroundReranker: React.FC = forwardRef((props, ref) => { const { modelList } = props; const { handleSGlangResponse } = useRerankerResponse(); @@ -146,25 +116,18 @@ const GroundReranker: React.FC = forwardRef((props, ref) => { const { initialize, updateScrollerPosition: updateDocumentScrollerPosition } = useOverlayScroller(); - const { - handleOnValuesChange, - formRef, - paramsConfig, - initialValues, - parameters, - modelMeta, - formFields - } = useInitLLmMeta( - { - modelList, - isChat: true - }, - { - defaultValues: { top_n: 3 }, - defaultParamsConfig: fieldConfig, - metaKeys: LLM_METAKEYS - } - ); + const { handleOnValuesChange, formRef, parameters, modelMeta } = + useInitLLmMeta( + { + modelList, + isChat: true + }, + { + defaultValues: { top_n: 3 }, + defaultParamsConfig: fieldConfig, + metaKeys: LLM_METAKEYS + } + ); useImperativeHandle(ref, () => { return { @@ -206,14 +169,14 @@ const GroundReranker: React.FC = forwardRef((props, ref) => { return generateRerankCode({ api: RERANKER_API, parameters: { - ..._.pick(parameters, ['model', ..._.split(formFields, ',')]), + ...parameters, query: queryValue, documents: [...textList, ...fileList] .map((item) => item.text) .filter((text) => text) } }); - }, [parameters, formFields, queryValue, textList, fileList]); + }, [parameters, queryValue, textList, fileList]); // [0.1, 1.0] const normalizValue = (data: { min: number; max: number; value: number }) => { @@ -453,21 +416,6 @@ const GroundReranker: React.FC = forwardRef((props, ref) => { } }; - const renderExtra = useMemo(() => { - if (modelMeta?.n_ctx && modelMeta?.n_slot) { - return ( - - - - ); - } - return null; - }, [modelMeta]); - const handleClearDocuments = () => { setTextList([ { @@ -637,14 +585,13 @@ const GroundReranker: React.FC = forwardRef((props, ref) => { - + meta={modelMeta} + > []; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + updateParams: (values: Record) => void; +}; + +const STTForm: React.FC = forwardRef( + ({ onFinish, onFinishFailed, modelList, updateParams }, ref) => { + const intl = useIntl(); + const [form] = Form.useForm(); + const [meta, setModelMeta] = React.useState>({}); + const [languageOptions, setLanguageOptions] = useState< + Global.BaseOption[] + >([]); + const [searchParams] = useSearchParams(); + const modelType = searchParams.get('type') || ''; + const selectModel = searchParams.get('model') + ? modelType === 'stt' && searchParams.get('model') + : ''; + const initializeRef = useRef(false); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + const updateLanguages = (meta: Record) => { + const languages = meta?.languages || []; + if (languages.length === 0) { + return defaultLanguages; + } + + const currentLanguage: { label: string; value: string }[] = []; + languages.forEach((langCode: string) => { + const langItem = allLanguages.find((item) => item.value === langCode); + if (langItem) { + currentLanguage.push(langItem); + } + }); + setLanguageOptions(currentLanguage); + return currentLanguage; + }; + + const handleSelectModel = (model: string) => { + if (!model) return; + const selected = modelList?.find((item) => item.value === model); + setModelMeta(selected?.meta || {}); + const languages = updateLanguages(selected?.meta || {}); + + const values = { + language: selected?.meta?.language || languages[0]?.value || 'auto', + model: model + }; + + updateParams(values); + form.setFieldsValue(values); + }; + + const handleOnValuesChange = (changedValues: any, allValues: any) => { + if (changedValues.model) { + return; + } + updateParams(allValues); + }; + + useEffect(() => { + if (initializeRef.current || !modelList?.length) return; + + const defaultModel = selectModel || modelList?.[0]?.value || ''; + handleSelectModel(defaultModel); + initializeRef.current = true; + }, [modelList, selectModel]); + + return ( + +
+ + + + +
+
+ ); + } +); + +export default STTForm; diff --git a/src/pages/playground/speech/form.tsx b/src/pages/playground/speech/forms/tts-advance.tsx similarity index 96% rename from src/pages/playground/speech/form.tsx rename to src/pages/playground/speech/forms/tts-advance.tsx index edf360ae..081a6501 100644 --- a/src/pages/playground/speech/form.tsx +++ b/src/pages/playground/speech/forms/tts-advance.tsx @@ -8,7 +8,7 @@ import { useIntl } from '@umijs/max'; import { Form } from 'antd'; import React from 'react'; import styled from 'styled-components'; -import { useFormContext } from '../config/form-context'; +import { useFormContext } from '../../config/form-context'; const SuffixWrapper = styled.div.attrs({ className: 'suffix-wrapper' @@ -36,7 +36,7 @@ const Container = styled.div` } `; -export const RefAudioFormItem: React.FC = () => { +const TTSAdvanceConfig: React.FC = () => { const { getRuleMessage } = useAppUtils(); const { meta, onValuesChange } = useFormContext(); const form = Form.useFormInstance(); @@ -127,3 +127,5 @@ export const RefAudioFormItem: React.FC = () => { ); }; + +export default TTSAdvanceConfig; diff --git a/src/pages/playground/speech/forms/tts-form.tsx b/src/pages/playground/speech/forms/tts-form.tsx new file mode 100644 index 00000000..a3b9c732 --- /dev/null +++ b/src/pages/playground/speech/forms/tts-form.tsx @@ -0,0 +1,202 @@ +import AutoComplete from '@/components/seal-form/auto-complete'; +import SealSelect from '@/components/seal-form/seal-select'; +import CollapsePanel from '@/pages/_components/collapse-panel'; +import { getLocale, useIntl, useSearchParams } from '@umijs/max'; +import { useMemoizedFn } from 'ahooks'; +import { Form } from 'antd'; +import _ from 'lodash'; +import React, { + forwardRef, + useEffect, + useImperativeHandle, + useState +} from 'react'; +import ModelSelect from '../../components/model-select'; +import ParamsFields from '../../components/params-fields'; +import { FormContext } from '../../config/form-context'; +import { TTSAdvancedParamsConfig } from '../params-config'; +import AdvanceConfig from './tts-advance'; + +const MetaFields = [ + 'task_type', + 'language', + 'instructions', + 'max_new_tokens', + 'ref_audio' +]; + +type ParamsSettingsProps = { + ref?: any; + modelList?: Global.BaseOption[]; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + updatateParams: (values: Record) => void; +}; + +const ParamsSettings: React.FC = forwardRef( + ({ onFinish, onFinishFailed, updatateParams, modelList = [] }, ref) => { + const [searchParams] = useSearchParams(); + const modelType = searchParams.get('type') || ''; + const selectModel = searchParams.get('model') + ? modelType === 'tts' && searchParams.get('model') + : ''; + const locale = getLocale(); + const intl = useIntl(); + const [form] = Form.useForm(); + const [activeKey, setActiveKey] = useState( + 'advanced_config' + ); + const [vociceOptions, setVoiceOptions] = useState< + Global.BaseOption[] + >([]); + const [meta, setModelMeta] = useState>({}); + const initializeRef = React.useRef(false); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + const handleOnCollapse = (keys: string | string[]) => { + setActiveKey(keys); + }; + + const sortVoiceList = ( + locale: string, + voiceDataList: Global.BaseOption[] + ) => { + const lang = locale === 'en-US' ? 'english' : 'chinese'; + + const list = voiceDataList.sort((a, b) => { + const aContains = a.value.toLowerCase().includes(lang) ? 1 : 0; + const bContains = b.value.toLowerCase().includes(lang) ? 1 : 0; + return bContains - aContains; + }); + return list; + }; + + const updateVoiceOptions = (model: Global.BaseOption) => { + const list = _.map(model?.meta?.voices || [], (item: any) => { + return { + label: item, + value: item + }; + }); + + const newList = sortVoiceList(locale, list); + setVoiceOptions(newList); + return newList; + }; + + const handleSelectModel = useMemoizedFn(async (value: string) => { + if (!value) { + return; + } + + const model = modelList.find((item) => item.value === value); + const newList = updateVoiceOptions(model!); + setModelMeta(model?.meta || {}); + + const values = { + ..._.pick(model?.meta || {}, MetaFields), + task_type: model?.meta?.task_type, + model: value, + language: model?.meta?.languages?.[0] || '', + voice: newList[0]?.value + }; + updatateParams(values); + form.setFieldsValue(values); + }); + + const handleOnValuesChange = ( + changeValues: Record, + allValues: Record + ) => { + if (changeValues.model) { + return; + } + updatateParams(allValues); + }; + + useEffect(() => { + if (initializeRef.current || !modelList.length) return; + const defaultModel = selectModel || modelList[0]?.value || ''; + + if (defaultModel && modelList.length) { + handleSelectModel(defaultModel); + initializeRef.current = true; + } + }, [selectModel, modelList.length]); + + return ( + +
+ + + + + + + + + + + + ) + } + ]} + > +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/speech/params-config.ts b/src/pages/playground/speech/params-config.ts index 9cde5290..9f8bb623 100644 --- a/src/pages/playground/speech/params-config.ts +++ b/src/pages/playground/speech/params-config.ts @@ -99,62 +99,3 @@ export const TTSAdvancedParamsConfig: ParamsSchema[] = [ ] } ]; - -export const TTSParamsConfig: ParamsSchema[] = [ - { - type: 'AutoComplete', - name: 'voice', - options: [], - label: { - text: 'playground.params.voice', - isLocalized: true - }, - rules: [ - { - required: false, - message: 'Voice is required' - } - ] - }, - { - type: 'Select', - name: 'response_format', - options: [ - { label: 'mp3', value: 'mp3' }, - // { label: 'opus', value: 'opus' }, - // { label: 'aac', value: 'aac' }, - // { label: 'flac', value: 'flac' }, - { label: 'wav', value: 'wav' } - // { label: 'pcm', value: 'pcm' } - ], - label: { - text: 'playground.params.format', - isLocalized: true - }, - rules: [ - { - required: false - } - ] - } - // { - // type: 'Select', - // name: 'speed', - // options: [ - // { label: '0.25x', value: 0.25 }, - // { label: '0.5x', value: 0.5 }, - // { label: '1x', value: 1 }, - // { label: '2x', value: 2 }, - // { label: '4x', value: 4 } - // ], - // label: { - // text: 'playground.params.speed', - // isLocalized: true - // }, - // rules: [ - // { - // required: false - // } - // ] - // } -]; diff --git a/src/pages/playground/speech/stt.tsx b/src/pages/playground/speech/stt.tsx index 845a9e1d..a4659ea6 100644 --- a/src/pages/playground/speech/stt.tsx +++ b/src/pages/playground/speech/stt.tsx @@ -11,9 +11,8 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller'; import { useCancelToken } from '@/hooks/use-request-token'; import { readAudioFile } from '@/utils/load-audio-file'; import { SendOutlined } from '@ant-design/icons'; -import { useIntl, useSearchParams } from '@umijs/max'; +import { useIntl } from '@umijs/max'; import { Button, Spin, Tooltip } from 'antd'; -import _ from 'lodash'; import React, { forwardRef, useCallback, @@ -25,21 +24,14 @@ import React, { } from 'react'; import { AUDIO_SPEECH_TO_TEXT_API, speechToText } from '../apis'; import AudioInput from '../components/audio-input'; -import DynamicParams from '../components/dynamic-params'; import RightContainer from '../components/right-container'; import ViewCommonCode from '../components/view-common-code'; -import { - SpeechToTextFormat, - defaultLanguages, - extractErrorMessage -} from '../config'; -import { allLanguages } from '../config/languages'; -import { RealtimeParamsConfig as paramsConfig } from '../config/params-config'; -import { ParamsSchema } from '../config/types'; +import { SpeechToTextFormat, extractErrorMessage } from '../config'; import '../style/ground-llm.less'; import '../style/speech-to-text.less'; import '../style/system-message-wrap.less'; import { speechToTextCode } from '../view-code/audio'; +import STTForm from './forms/stt-form'; interface MessageProps { modelList: Global.BaseOption[]; @@ -53,14 +45,8 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { const [messageList, setMessageList] = useState< { uid: number; content: string }[] >([]); - const [searchParams] = useSearchParams(); - const modelType = searchParams.get('type') || ''; - const selectModel = searchParams.get('model') - ? modelType === 'stt' && searchParams.get('model') - : ''; - const defaultModel = selectModel || modelList[0]?.value || ''; const [parameters, setParams] = useState({ - model: defaultModel, + model: '', language: 'auto' }); const [show, setShow] = useState(false); @@ -80,9 +66,6 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { useCancelToken(); const { initialize, updateScrollerPosition } = useOverlayScroller(); - const [modelMeta, setModelMeta] = useState(null); - const [fieldsConfig, setFieldsConfig] = - useState(paramsConfig); useImperativeHandle(ref, () => { return { @@ -273,53 +256,15 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { ); }; - const handleSelectModel = (model: string) => { - if (!model) return; - const selected = modelList.find((item) => item.value === model); - setModelMeta(selected?.meta || {}); - const languages = selected?.meta?.languages || []; - let currentLanguage = [...defaultLanguages]; - if (languages.length > 0) { - // sort languages based on the order in the model meta - currentLanguage = []; - - languages.forEach((langCode: string) => { - const langItem = allLanguages.find((item) => item.value === langCode); - if (langItem) { - currentLanguage.push(langItem); - } - }); - - const newConfig = paramsConfig.map((item) => { - const oItem = _.cloneDeep(item); - if (item.name === 'language') { - return { - ...oItem, - options: currentLanguage - }; - } - return oItem; - }); - setFieldsConfig(newConfig); - } - setParams((pre: any) => { + const updateParams = (values: any) => { + setParams((pre: Record) => { return { ...pre, - language: - selected?.meta?.language || currentLanguage[0]?.value || 'auto', - model: model + ...values }; }); }; - const handleOnValuesChange = (changedValues: any, allValues: any) => { - if (changedValues.model) { - handleSelectModel(changedValues.model); - } else { - setParams(allValues); - } - }; - useEffect(() => { if (scroller.current) { initialize(scroller.current); @@ -332,11 +277,6 @@ const GroundSTT: React.FC = forwardRef((props, ref) => { } }, [messageList, loading]); - useEffect(() => { - const defaultModel = selectModel || modelList[0]?.value || ''; - handleSelectModel(defaultModel); - }, [modelList, selectModel]); - return (
= forwardRef((props, ref) => {
- diff --git a/src/pages/playground/speech/tts.tsx b/src/pages/playground/speech/tts.tsx index 1cd9f61f..a1484c66 100644 --- a/src/pages/playground/speech/tts.tsx +++ b/src/pages/playground/speech/tts.tsx @@ -1,49 +1,29 @@ import { setRouteCache } from '@/atoms/route-cache'; import AlertInfo from '@/components/alert-info'; import IconFont from '@/components/icon-font'; -import AutoComplete from '@/components/seal-form/auto-complete'; -import FieldComponent from '@/components/seal-form/field-component'; -import SealSelect from '@/components/seal-form/seal-select'; import SpeechContent from '@/components/speech-content'; import routeCachekey from '@/config/route-cachekey'; -import useOverlayScroller from '@/hooks/use-overlay-scroller'; -import CollapsePanel from '@/pages/_components/collapse-panel'; -import { getLocale, useIntl, useSearchParams } from '@umijs/max'; -import { Form, Spin } from 'antd'; +import { useIntl } from '@umijs/max'; +import { Spin } from 'antd'; import _ from 'lodash'; import 'overlayscrollbars/overlayscrollbars.css'; import React, { forwardRef, - useCallback, - useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { AUDIO_TEXT_TO_SPEECH_API, CHAT_API, textToSpeech } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import MessageInput from '../components/message-input'; import RightContainer from '../components/right-container'; import ViewCommonCode from '../components/view-common-code'; import { extractErrorMessage } from '../config'; -import { MessageItem, ParamsSchema } from '../config/types'; +import { MessageItem } from '../config/types'; import '../style/ground-llm.less'; import '../style/system-message-wrap.less'; import { TextToSpeechCode } from '../view-code/audio'; -import { RefAudioFormItem } from './form'; -import { - TTSParamsConfig as paramsConfig, - TTSAdvancedParamsConfig -} from './params-config'; - -const MetaFields = [ - 'task_type', - 'language', - 'instructions', - 'max_new_tokens', - 'ref_audio' -]; +import TTSDataForm from './forms/tts-form'; interface MessageProps { modelList: Global.BaseOption[]; @@ -65,15 +45,9 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { audioUrl: string; }[] >([]); - const locale = getLocale(); const intl = useIntl(); - const [searchParams] = useSearchParams(); - const modelType = searchParams.get('type') || ''; - const selectModel = searchParams.get('model') - ? modelType === 'tts' && searchParams.get('model') - : ''; const [parameters, setParams] = useState({ - model: selectModel, + model: '', voice: '', response_format: 'mp3' }); @@ -82,20 +56,10 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { const [tokenResult, setTokenResult] = useState(null); const [collapse, setCollapse] = useState(false); const controllerRef = useRef(null); - const scroller = useRef(null); const checkvalueRef = useRef(true); const [currentPrompt, setCurrentPrompt] = useState(''); - const [voiceDataList, setVoiceList] = useState[]>( - [] - ); - const [modelMeta, setModelMeta] = useState({}); const formRef = useRef(null); - const { initialize } = useOverlayScroller(); - const [activeKey, setActiveKey] = useState( - 'advanced_config' - ); - useImperativeHandle(ref, () => { return { viewCode() { @@ -108,10 +72,6 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { }; }); - const defaultModel = useMemo(() => { - return selectModel || modelList[0]?.value || ''; - }, [modelList]); - const dropEmptyFields = (parameters: Record) => { const fields = [ 'task_type', @@ -139,37 +99,6 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { }); }, [parameters, currentPrompt]); - const sortVoiceList = useCallback( - (locale: string, voiceDataList: Global.BaseOption[]) => { - const lang = locale === 'en-US' ? 'english' : 'chinese'; - - const list = voiceDataList.sort((a, b) => { - const aContains = a.value.toLowerCase().includes(lang) ? 1 : 0; - const bContains = b.value.toLowerCase().includes(lang) ? 1 : 0; - return bContains - aContains; - }); - return list; - }, - [] - ); - - const voiceList = useMemo(() => { - if (!voiceDataList.length) return []; - const newList = sortVoiceList(locale, voiceDataList); - return newList; - }, [locale, voiceDataList, sortVoiceList]); - - useEffect(() => { - const newList = sortVoiceList(locale, voiceDataList); - setParams((pre: any) => { - return { - ...pre, - voice: newList[0]?.value - }; - }); - formRef.current?.form.setFieldValue('voice', newList[0]?.value); - }, [locale, voiceDataList, sortVoiceList]); - const setMessageId = () => { messageId.current = messageId.current + 1; }; @@ -261,146 +190,19 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { setShow(false); }; - const handleSelectModel = async (value: string) => { - if (!value) { - return; - } - const model = modelList.find((item) => item.value === value); - const list = _.map(model?.meta?.voices || [], (item: any) => { - return { - label: item, - value: item - }; - }); - - const newList = sortVoiceList(locale, list); - setVoiceList(newList); - setModelMeta(model?.meta || {}); + const updatateParams = (values: Record) => { setParams((pre: any) => { return { ...pre, - ..._.pick(model?.meta || {}, MetaFields), - task_type: model?.meta?.task_type, - model: value, - language: model?.meta?.languages?.[0] || '', - voice: newList[0]?.value + ...values }; }); }; - const handleOnValuesChange = useCallback( - (changeValues: Record, allValues: Record) => { - if (changeValues.model) { - handleSelectModel(changeValues.model); - } else { - setParams(allValues); - } - }, - [handleSelectModel] - ); - const handleOnCheckChange = (e: any) => { checkvalueRef.current = e.target.checked; }; - const handleOnCollapse = (keys: string | string[]) => { - setActiveKey(keys); - }; - - const renderAdvancedFields = () => { - const formItems = TTSAdvancedParamsConfig.map((item: ParamsSchema) => { - const comProps = { - ...item.attrs, - label: item.label.isLocalized - ? intl.formatMessage({ id: item.label.text }) - : item.label.text - }; - return ( - <> - - - - - ); - }); - - return ( - - {formItems} - - - ) - } - ]} - > - ); - }; - - const renderExtra = () => { - return paramsConfig.map((item: ParamsSchema) => { - const comProps = { - ...item.attrs, - options: item.name === 'voice' ? voiceList : item.options, - label: item.label.isLocalized - ? intl.formatMessage({ id: item.label.text }) - : item.label.text - }; - return ( - <> - - {item.type === 'AutoComplete' ? ( - - ) : ( - - )} - - - ); - }); - }; - - useEffect(() => { - if (defaultModel && modelList.length) { - handleSelectModel(defaultModel); - } - }, [defaultModel, modelList.length]); - - useEffect(() => { - if (scroller.current) { - initialize(scroller.current); - } - }, [initialize]); - return (
@@ -474,18 +276,10 @@ const GroundTTS: React.FC = forwardRef((props, ref) => {
- - {renderExtra()} - {renderAdvancedFields()} - - ]} + updatateParams={updatateParams} /> []; + onValuesChange?: (changeValues: any, value: Record) => void; + onModelChange?: (model: string) => void; + onFinish?: (values: any) => void; + onFinishFailed?: (errorInfo: any) => void; + initialValues?: Record; // for initial values when switch model, aviod update values from setParams + meta?: Record; + paramsConfig?: ParamsSchema[]; +}; + +const ParamsSettings: React.FC = forwardRef( + ( + { + onValuesChange, + onModelChange, + onFinish, + onFinishFailed, + parametersTitle, + initialValues, + modelList, + showModelSelector = true, + meta, + paramsConfig + }, + ref + ) => { + const [form] = Form.useForm(); + + useImperativeHandle(ref, () => ({ + form, + getFieldsValue: form.getFieldsValue, + setFieldsValue: form.setFieldsValue + })); + + const handleOnFinish = (values: any) => { + onFinish?.(values); + }; + + const handleOnFinishFailed = (errorInfo: any) => { + onFinishFailed?.(errorInfo); + }; + + useEffect(() => { + form.setFieldsValue(initialValues); + }, [initialValues]); + + return ( + +
+ + +
+
+ ); + } +); + +export default ParamsSettings; diff --git a/src/pages/playground/video/page.tsx b/src/pages/playground/video/page.tsx index a62b11eb..82e994db 100644 --- a/src/pages/playground/video/page.tsx +++ b/src/pages/playground/video/page.tsx @@ -15,7 +15,6 @@ import React, { useState } from 'react'; import { CREATE_VIDEO_API } from '../apis'; -import DynamicParams from '../components/dynamic-params'; import MessageInput from '../components/message-input'; import RightContainer from '../components/right-container'; import ViewCommonCode from '../components/view-common-code'; @@ -24,6 +23,7 @@ import useTextVideo from '../hooks/use-text-video'; import '../style/ground-llm.less'; import '../style/system-message-wrap.less'; import { generateCode } from '../view-code/video'; +import DataForm from './forms'; interface MessageProps { modelList: Global.BaseOption[]; @@ -241,7 +241,7 @@ const GroundVideo: React.FC = forwardRef((props, ref) => { -