feat: add tts params

This commit is contained in:
jialin
2026-01-30 22:58:11 +08:00
parent f0cdefad90
commit b3e186fea4
8 changed files with 259 additions and 40 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js'; // import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_3892962_hd8klbsk0yg.js' scriptUrl: '//at.alicdn.com/t/c/font_4613488_mis8x88kojd.js'
}); });
export default IconFont; export default IconFont;
+5 -1
View File
@@ -163,5 +163,9 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL', 'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL', 'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)', 'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution' 'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
}; };
+5 -1
View File
@@ -166,7 +166,11 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL', 'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL', 'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)', 'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution' 'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
+5 -1
View File
@@ -160,7 +160,11 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL', 'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL', 'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)', 'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution' 'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
+5 -1
View File
@@ -156,5 +156,9 @@ export default {
'playground.uploadImage.url.holder': '请输入图片链接', 'playground.uploadImage.url.holder': '请输入图片链接',
'playground.uploadImage.url.button': '从链接添加图片', 'playground.uploadImage.url.button': '从链接添加图片',
'playground.params.duration': '时长 (秒)', 'playground.params.duration': '时长 (秒)',
'playground.params.resolution': '分辨率' 'playground.params.resolution': '分辨率',
'playground.params.taskType': '任务类型',
'playground.params.voiceStyle': '语音风格',
'playground.params.maxTokens': '最大生成长度',
'playground.params.refAudio': '参考音频 URL'
}; };
+118 -35
View File
@@ -2,10 +2,12 @@ import { setRouteCache } from '@/atoms/route-cache';
import AlertInfo from '@/components/alert-info'; import AlertInfo from '@/components/alert-info';
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import AutoComplete from '@/components/seal-form/auto-complete'; 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 SealSelect from '@/components/seal-form/seal-select';
import SpeechContent from '@/components/speech-content'; import SpeechContent from '@/components/speech-content';
import routeCachekey from '@/config/route-cachekey'; import routeCachekey from '@/config/route-cachekey';
import useOverlayScroller from '@/hooks/use-overlay-scroller'; import useOverlayScroller from '@/hooks/use-overlay-scroller';
import CollapsePanel from '@/pages/_components/collapse-panel';
import { getLocale, useIntl, useSearchParams } from '@umijs/max'; import { getLocale, useIntl, useSearchParams } from '@umijs/max';
import { Form, Spin } from 'antd'; import { Form, Spin } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
@@ -22,7 +24,10 @@ import React, {
} from 'react'; } from 'react';
import { AUDIO_TEXT_TO_SPEECH_API, CHAT_API, textToSpeech } from '../apis'; import { AUDIO_TEXT_TO_SPEECH_API, CHAT_API, textToSpeech } from '../apis';
import { extractErrorMessage } from '../config'; import { extractErrorMessage } from '../config';
import { TTSParamsConfig as paramsConfig } from '../config/params-config'; import {
TTSParamsConfig as paramsConfig,
TTSAdvancedParamsConfig
} from '../config/params-config';
import { MessageItem, ParamsSchema } from '../config/types'; import { MessageItem, ParamsSchema } from '../config/types';
import '../style/ground-llm.less'; import '../style/ground-llm.less';
import '../style/system-message-wrap.less'; import '../style/system-message-wrap.less';
@@ -31,6 +36,14 @@ import DynamicParams from './dynamic-params';
import MessageInput from './message-input'; import MessageInput from './message-input';
import ViewCommonCode from './view-common-code'; import ViewCommonCode from './view-common-code';
const MetaFields = [
'task_type',
'language',
'instructions',
'max_new_tokens',
'ref_audio'
];
interface MessageProps { interface MessageProps {
modelList: Global.BaseOption<string>[]; modelList: Global.BaseOption<string>[];
loaded?: boolean; loaded?: boolean;
@@ -75,10 +88,14 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
const [voiceDataList, setVoiceList] = useState<Global.BaseOption<string>[]>( const [voiceDataList, setVoiceList] = useState<Global.BaseOption<string>[]>(
[] []
); );
const [modelMeta, setModelMeta] = useState<any>({});
const formRef = useRef<any>(null); const formRef = useRef<any>(null);
const { initialize } = useOverlayScroller(); const { initialize } = useOverlayScroller();
const { initialize: innitializeParams } = useOverlayScroller(); const { initialize: innitializeParams } = useOverlayScroller();
const [activeKey, setActiveKey] = useState<string | string[]>(
'advanced_config'
);
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
@@ -226,31 +243,32 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
setShow(false); setShow(false);
}; };
const handleSelectModel = useCallback( const handleSelectModel = async (value: string) => {
async (value: string) => { if (!value) {
if (!value) { return;
return; }
} const model = modelList.find((item) => item.value === value);
const model = modelList.find((item) => item.value === value); const list = _.map(model?.meta?.voices || [], (item: any) => {
const list = _.map(model?.meta?.voices || [], (item: any) => { return {
return { label: item,
label: item, value: item
value: item };
}; });
});
const newList = sortVoiceList(locale, list); const newList = sortVoiceList(locale, list);
setVoiceList(newList); setVoiceList(newList);
setParams((pre: any) => { setModelMeta(model?.meta || {});
return { setParams((pre: any) => {
...pre, return {
model: value, ...pre,
voice: newList[0]?.value ..._.pick(model?.meta || {}, MetaFields),
}; task_type: model?.meta?.default_task_type,
}); max_new_tokens: model?.meta?.max_model_len || null,
}, model: value,
[modelList] voice: newList[0]?.value
); };
});
};
const handleOnValuesChange = useCallback( const handleOnValuesChange = useCallback(
(changeValues: Record<string, any>, allValues: Record<string, any>) => { (changeValues: Record<string, any>, allValues: Record<string, any>) => {
@@ -273,7 +291,65 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
checkvalueRef.current = e.target.checked; checkvalueRef.current = e.target.checked;
}; };
const renderExtra = useMemo(() => { 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 (
<>
<Form.Item
name={item.name}
rules={item.rules}
key={item.name}
{...item.formItemAttrs}
>
<FieldComponent
{...comProps}
description={
item.description?.isLocalized
? intl.formatMessage({ id: item.description.text })
: item.description?.text
}
onChange={null}
{..._.omit(item, [
'name',
'rules',
'disabledConfig',
'description'
])}
{...item.initAttrs?.(modelMeta)}
></FieldComponent>
</Form.Item>
</>
);
});
return (
<CollapsePanel
activeKey={activeKey}
onChange={handleOnCollapse}
accordion={false}
items={[
{
key: 'advanced_config',
label: intl.formatMessage({ id: 'resources.form.advanced' }),
forceRender: true,
children: formItems
}
]}
></CollapsePanel>
);
};
const renderExtra = () => {
return paramsConfig.map((item: ParamsSchema) => { return paramsConfig.map((item: ParamsSchema) => {
const comProps = { const comProps = {
...item.attrs, ...item.attrs,
@@ -283,16 +359,18 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
: item.label.text : item.label.text
}; };
return ( return (
<Form.Item name={item.name} rules={item.rules} key={item.name}> <>
{item.type === 'AutoComplete' ? ( <Form.Item name={item.name} rules={item.rules} key={item.name}>
<AutoComplete {...comProps} /> {item.type === 'AutoComplete' ? (
) : ( <AutoComplete {...comProps} />
<SealSelect {...comProps}></SealSelect> ) : (
)} <SealSelect {...comProps}></SealSelect>
</Form.Item> )}
</Form.Item>
</>
); );
}); });
}, [paramsConfig, intl, voiceList]); };
useEffect(() => { useEffect(() => {
if (defaultModel && modelList.length) { if (defaultModel && modelList.length) {
@@ -396,7 +474,12 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
onValuesChange={handleOnValuesChange} onValuesChange={handleOnValuesChange}
initialValues={parameters} initialValues={parameters}
modelList={modelList} modelList={modelList}
extra={[renderExtra]} extra={[
<>
{renderExtra()}
{renderAdvancedFields()}
</>
]}
/> />
</div> </div>
</div> </div>
@@ -1,3 +1,4 @@
import _ from 'lodash';
import { ParamsSchema } from './types'; import { ParamsSchema } from './types';
export interface SizeOption { export interface SizeOption {
@@ -89,6 +90,124 @@ export const TTSParamsConfig: ParamsSchema[] = [
// } // }
]; ];
export const TTSAdvancedParamsConfig: ParamsSchema[] = [
{
type: 'Select',
name: 'task_type',
options: [],
attrs: {
allowClear: true
},
label: {
text: 'playground.params.taskType',
isLocalized: true
},
initAttrs: (meta: any) => {
return {
options: _.map(meta?.task_types || [], (item: string) => ({
label: item,
value: item
}))
};
},
rules: [
{
required: false
}
]
},
{
type: 'Select',
name: 'language',
options: [],
initAttrs: (meta: any) => {
return {
options: _.map(meta?.languages || [], (item: string) => ({
label: item,
value: item
}))
};
},
attrs: {
allowClear: true
},
label: {
text: 'playground.params.language',
isLocalized: true
},
rules: [
{
required: false
}
]
},
{
type: 'Select',
name: 'instructions',
label: {
text: 'playground.params.voiceStyle',
isLocalized: true
},
attrs: {
allowClear: true
},
initAttrs: (meta: any) => {
return {
options: _.map(meta?.voices || [], (item: string) => ({
label: item,
value: item
}))
};
},
rules: [
{
required: false
}
]
},
{
type: 'InputNumber',
name: 'max_new_tokens',
label: {
text: 'playground.params.maxTokens',
isLocalized: true
},
attrs: {
allowClear: true,
min: 0
},
formItemAttrs: {
hidden: true,
getValueProps: (value: number) => {
return {
value: value || null
};
}
},
rules: [
{
required: false
}
]
},
{
type: 'Input',
name: 'ref_audio',
label: {
text: 'playground.params.refAudio',
isLocalized: true
},
attrs: {
allowClear: true
},
rules: [
{
required: false
}
]
}
];
export const RealtimeParamsConfig: ParamsSchema[] = [ export const RealtimeParamsConfig: ParamsSchema[] = [
{ {
type: 'Select', type: 'Select',
+1
View File
@@ -53,6 +53,7 @@ export interface ParamsSchema {
text: string; text: string;
isLocalized?: boolean; isLocalized?: boolean;
}; };
initAttrs?: (meta: any) => Record<string, any>;
dependencies?: string[]; dependencies?: string[];
style?: React.CSSProperties; style?: React.CSSProperties;
options?: Global.BaseOption<string | number | null>[]; options?: Global.BaseOption<string | number | null>[];