fix(style): playground image incomplete

This commit is contained in:
jialin
2024-11-28 17:13:51 +08:00
parent af789ee886
commit bd418b23dc
23 changed files with 704 additions and 255 deletions
+4 -4
View File
@@ -450,7 +450,7 @@ const Models: React.FC<ModelsProps> = ({
}}
color="geekblue"
>
Embedding Only
Embedding
</Tag>
);
}
@@ -464,7 +464,7 @@ const Models: React.FC<ModelsProps> = ({
}}
color="geekblue"
>
{intl.formatMessage({ id: 'playground.audio.texttospeech' })}
Text-To-Speech
</Tag>
);
}
@@ -478,7 +478,7 @@ const Models: React.FC<ModelsProps> = ({
}}
color="geekblue"
>
{intl.formatMessage({ id: 'playground.audio.speechtotext' })}
Speech-To-Text
</Tag>
);
}
@@ -492,7 +492,7 @@ const Models: React.FC<ModelsProps> = ({
}}
color="geekblue"
>
Image Only
Image
</Tag>
);
}
+5 -13
View File
@@ -99,25 +99,17 @@ export const textToSpeech = async (params: any, options?: any) => {
const audioBlob = await res.blob();
const audioUrl = URL.createObjectURL(audioBlob);
return audioUrl;
return {
url: audioUrl,
type: audioBlob.type
};
};
// export const speechToText = async (params: any, options?: any) => {
// const res = await fetch(AUDIO_SPEECH_TO_TEXT_API, {
// method: 'POST',
// body: JSON.stringify(params.data),
// signal: params.signal
// });
// if (!res.ok) {
// throw new Error('Network response was not ok');
// }
// return res.json();
// };
export const speechToText = async (params: any, options?: any) => {
return request(AUDIO_SPEECH_TO_TEXT_API, {
method: 'POST',
data: params.data,
cancelToken: options?.cancelToken,
headers: {
'Content-Type': 'multipart/form-data'
}
+40 -10
View File
@@ -1,7 +1,13 @@
import { AudioOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Space, Tooltip } from 'antd';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState
} from 'react';
// import '../style/audio-input.less';
interface AudioInputProps {
@@ -9,6 +15,7 @@ interface AudioInputProps {
chunks: any[];
url: string;
name: string;
type: string;
duration: number;
}) => void;
onAnalyse?: (analyseData: any, frequencyBinCount: any) => void;
@@ -19,6 +26,11 @@ interface AudioInputProps {
type?: 'text' | 'primary' | 'default';
}
const recordingFormat = {
type: 'audio/wav',
suffix: '.wav'
};
const AudioInput: React.FC<AudioInputProps> = (props) => {
const intl = useIntl();
const [audioOn, setAudioOn] = useState(false);
@@ -155,6 +167,8 @@ const AudioInput: React.FC<AudioInputProps> = (props) => {
try {
await EnableAudio();
console.log('audioStream:', audioStream.current);
audioRecorder.current = new MediaRecorder(audioStream.current);
const audioChunks: any[] = [];
@@ -170,14 +184,14 @@ const AudioInput: React.FC<AudioInputProps> = (props) => {
// stop recording
audioRecorder.current.onstop = () => {
const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
const audioBlob = new Blob(audioChunks, { type: recordingFormat.type });
const audioUrl = URL.createObjectURL(audioBlob);
handleAudioData({
chunks: audioBlob,
size: audioBlob.size,
type: audioBlob.type,
url: audioUrl,
name: `recording-${new Date().toISOString()}.wav`,
name: `recording-${new Date().toISOString()}${recordingFormat.suffix}`,
duration: Math.ceil((Date.now() - startTime.current) / 1000)
});
@@ -195,6 +209,25 @@ const AudioInput: React.FC<AudioInputProps> = (props) => {
}
};
const renderRecordButtonTips = useMemo(() => {
if (!audioPermission) {
return intl.formatMessage({ id: 'playground.audio.enablemic' });
}
return isRecording
? intl.formatMessage({ id: 'playground.audio.stoprecord' })
: intl.formatMessage({ id: 'playground.audio.startrecord' });
}, [audioPermission, isRecording, intl]);
const noAudioPermissionButtonStyle = useMemo(() => {
if (!audioPermission) {
return {
backgroundColor: 'var(--ant-color-error-bg-filled-hover)',
color: 'var(--ant-color-error-border-hover)',
border: 'none'
};
}
}, [audioPermission]);
useEffect(() => {
return () => {
handleStopRecording();
@@ -210,13 +243,7 @@ const AudioInput: React.FC<AudioInputProps> = (props) => {
<div className="audio-input">
<Space size={40} className="btns">
{
<Tooltip
title={
isRecording
? intl.formatMessage({ id: 'playground.audio.stoprecord' })
: intl.formatMessage({ id: 'playground.audio.startrecord' })
}
>
<Tooltip title={renderRecordButtonTips}>
<div
style={{
display: 'flex',
@@ -231,6 +258,9 @@ const AudioInput: React.FC<AudioInputProps> = (props) => {
icon={<AudioOutlined />}
size="middle"
type={props.type ?? 'text'}
style={{
...noAudioPermissionButtonStyle
}}
danger={isRecording}
onClick={StartRecording}
></Button>
@@ -12,7 +12,7 @@ import {
SendOutlined
} from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Checkbox, Segmented, Tabs, Tooltip } from 'antd';
import { Button, Segmented, Tabs, Tooltip } from 'antd';
import classNames from 'classnames';
import { PCA } from 'ml-pca';
import 'overlayscrollbars/overlayscrollbars.css';
@@ -81,7 +81,7 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
copyValue: ''
});
const [lessTwoInput, setLessTwoInput] = useState<boolean>(false);
const multiplePasteEnable = useRef<boolean>(true);
const [multiplePasteEnable, setMultiplePasteEnable] = useState<boolean>(true);
const [textList, setTextList] = useState<
{ text: string; uid: number | string; name: string }[]
@@ -279,7 +279,7 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
const handleOnPaste = useCallback(
(e: any, index: number) => {
if (!multiplePasteEnable.current) return;
if (!multiplePasteEnable) return;
const text = e.clipboardData.getData('text');
if (text) {
const dataLlist = text.split('\n').map((item: string) => {
@@ -402,18 +402,26 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
</div>
</h3>
<div className="flex-center gap-10">
<Button className="flex-center" size="middle">
<Checkbox
defaultChecked={multiplePasteEnable.current}
onChange={(e: any) => {
multiplePasteEnable.current = e.target.checked;
<Tooltip
title={intl.formatMessage({
id: 'playground.input.multiplePaste.tips'
})}
>
<Button
className="flex-center"
variant="filled"
size="middle"
color={multiplePasteEnable ? 'primary' : 'default'}
onClick={() => {
setMultiplePasteEnable(!multiplePasteEnable);
}}
>
{intl.formatMessage({
id: 'playground.input.multiplePaste'
})}
</Checkbox>
</Button>
</Button>
</Tooltip>
<Button size="middle" onClick={handleAddText}>
<PlusOutlined />
{intl.formatMessage({ id: 'playground.embedding.addtext' })}
@@ -47,14 +47,17 @@ interface MessageProps {
const initialValues = {
n: 1,
size: '512x512',
quality: 'standard',
style: null
seed: null,
sampler: 'euler_a',
cfg_scale: 4.5,
sample_steps: 10,
negative_prompt: null
};
const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const { modelList } = props;
const messageId = useRef<number>(0);
const [isOpenaiCompatible, setIsOpenaiCompatible] = useState<boolean>(true);
const [isOpenaiCompatible, setIsOpenaiCompatible] = useState<boolean>(false);
const [imageList, setImageList] = useState<
{
dataUrl: string;
@@ -223,7 +226,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const params = {
stream: true,
stream_options: {
chunk_result: true
// chunk_result: false
},
prompt: current?.content || currentPrompt || '',
..._.omitBy(finalParameters, (value: string) => !value)
@@ -251,8 +254,6 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const imgItem = newImageList[item.index];
if (item.b64_json) {
imgItem.dataUrl += item.b64_json;
// imgItem.cache.push(item.b64_json);
console.log('imgItem.dataUrl:', imgItem.dataUrl);
}
const progress = _.round(item.progress, 0);
newImageList[item.index] = {
@@ -303,7 +303,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
clearAll={handleClear}
setModelSelections={handleSelectModel}
presetPrompt={handlePresetPrompt}
modelList={modelList}
/>
</div>
</div>
@@ -2,7 +2,7 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller';
import useRequestToken from '@/hooks/use-request-token';
import { ClearOutlined, PlusOutlined, SendOutlined } from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Checkbox, Input, Spin, Tag } from 'antd';
import { Button, Input, Spin, Tag, Tooltip } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import 'overlayscrollbars/overlayscrollbars.css';
@@ -77,7 +77,7 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
const messageListLengthCache = useRef<number>(0);
const requestToken = useRef<any>(null);
const formRef = useRef<any>(null);
const multiplePasteEnable = useRef<boolean>(true);
const [multiplePasteEnable, setMultiplePasteEnable] = useState<boolean>(true);
const [fileList, setFileList] = useState<
{
text: string;
@@ -346,7 +346,7 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
const handleOnPaste = useCallback(
(e: any, index: number) => {
if (!multiplePasteEnable.current) return;
if (!multiplePasteEnable) return;
const text = e.clipboardData.getData('text');
if (text) {
console.log('text:', text);
@@ -465,18 +465,25 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
)}
</span>
<div className="flex-center gap-10">
<Button className="flex-center" size="middle">
<Checkbox
defaultChecked={multiplePasteEnable.current}
onChange={(e: any) => {
multiplePasteEnable.current = e.target.checked;
<Tooltip
title={intl.formatMessage({
id: 'playground.input.multiplePaste.tips'
})}
>
<Button
className="flex-center"
variant="filled"
size="middle"
color={multiplePasteEnable ? 'primary' : 'default'}
onClick={() => {
setMultiplePasteEnable(!multiplePasteEnable);
}}
>
{intl.formatMessage({
id: 'playground.input.multiplePaste'
})}
</Checkbox>
</Button>
</Button>
</Tooltip>
<Button size="middle" onClick={handleAddText}>
<PlusOutlined />
{intl.formatMessage({ id: 'playground.embedding.addtext' })}
+16 -72
View File
@@ -4,9 +4,9 @@ import IconFont from '@/components/icon-font';
import UploadAudio from '@/components/upload-audio';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { readAudioFile } from '@/utils/load-audio-file';
import { AudioOutlined, SendOutlined } from '@ant-design/icons';
import { SendOutlined } from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Spin, Tag, Tooltip } from 'antd';
import { Button, Spin, Tooltip } from 'antd';
import classNames from 'classnames';
import 'overlayscrollbars/overlayscrollbars.css';
import {
@@ -20,7 +20,6 @@ import {
} from 'react';
import { speechToText } from '../apis';
import { RealtimeParamsConfig as paramsConfig } from '../config/params-config';
import { MessageItem } from '../config/types';
import '../style/ground-left.less';
import '../style/speech-to-text.less';
import '../style/system-message-wrap.less';
@@ -42,14 +41,9 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
const intl = useIntl();
const { modelList } = props;
const messageId = useRef<number>(0);
const [messageList, setMessageList] = useState<MessageItem[]>([
{
content: '',
title: '',
role: '',
uid: messageId.current
}
]);
const [messageList, setMessageList] = useState<
{ uid: number; content: string }[]
>([]);
const [searchParams] = useSearchParams();
const selectModel = searchParams.get('model') || '';
const [parameters, setParams] = useState<any>({});
@@ -68,7 +62,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
analyser: null
});
const [isRecording, setIsRecording] = useState(false);
const [recordEnd, setRecordEnd] = useState(false);
const formRef = useRef<any>(null);
const { initialize, updateScrollerPosition } = useOverlayScroller();
@@ -127,8 +120,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
setMessageList([
{
content: result.text,
title: '',
role: '',
uid: messageId.current
}
]);
@@ -136,7 +127,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
console.log('error:', error);
} finally {
setLoading(false);
setRecordEnd(false);
setIsRecording(false);
}
};
@@ -170,9 +160,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
duration: data.duration
};
});
setTimeout(() => {
setRecordEnd(true);
}, 200);
},
[]
);
@@ -183,9 +170,8 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
const handleUploadChange = useCallback(
async (data: { file: any; fileList: any }) => {
const res = await readAudioFile(data.file.originFileObj);
const res = await readAudioFile(data.file);
setAudioData(res);
setRecordEnd(true);
},
[]
);
@@ -208,15 +194,16 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
submitMessage();
};
const handleOnDiscard = useCallback(() => {
setRecordEnd(false);
setAudioData(null);
setIsRecording(false);
}, []);
const renderAniamtion = () => {
if (!audioPermissionOn) {
return null;
return (
<div className="tips-text">
<IconFont type={'icon-audio'} style={{ fontSize: 20 }}></IconFont>
<span>
{intl.formatMessage({ id: 'playground.audio.enablemic' })}
</span>
</div>
);
}
if (isRecording) {
return (
@@ -240,7 +227,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
useEffect(() => {
console.log('parameters:', parameters);
}, [parameters]);
useEffect(() => {}, [messageList]);
useEffect(() => {
if (scroller.current) {
initialize(scroller.current);
@@ -259,13 +246,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
}
}, [messageList, loading]);
useEffect(() => {
if (messageList.length > messageListLengthCache.current) {
updateScrollerPosition();
}
messageListLengthCache.current = messageList.length;
}, [messageList.length]);
return (
<div className="ground-left-wrapper">
<div className="ground-left">
@@ -303,42 +283,6 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
renderAniamtion()
)}
</div>
{!audioPermissionOn && (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100%'
}}
>
<span>
<Tag
style={{
width: 36,
height: 36,
lineHeight: '36px',
textAlign: 'center'
}}
bordered={false}
color="error"
icon={
<AudioOutlined className="font-size-16"></AudioOutlined>
}
></Tag>
</span>
<span
style={{
marginTop: 10,
fontSize: 14,
fontWeight: 500
}}
>
{intl.formatMessage({ id: 'playground.audio.enablemic' })}
</span>
</div>
)}
</div>
<div
style={{
@@ -365,7 +309,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
justifyContent: 'center'
}}
>
{audioData ? (
{messageList.length ? (
messageList[0]?.content
) : (
<span className="text-tertiary">
@@ -36,8 +36,7 @@ interface MessageProps {
const initialValues = {
voice: '',
response_format: 'mp3',
speed: 1
response_format: 'mp3'
};
const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
@@ -113,13 +112,13 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
...parameters,
input: current?.content || currentPrompt
};
const audioUrl: any = await textToSpeech({
const res: any = await textToSpeech({
data: params,
url: CHAT_API,
signal
});
console.log('result:', parameters, audioUrl);
console.log('result:', res);
setMessageList([
{
@@ -129,7 +128,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
speed: parameters.speed,
uid: messageId.current,
autoplay: checkvalueRef.current,
audioUrl: audioUrl
audioUrl: res.url
}
]);
} catch (error) {
@@ -229,8 +229,8 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
variant="borderless"
>
<Slider
defaultValue={1024}
max={2048}
defaultValue={2048}
max={16 * 1024}
step={1}
style={{ marginBottom: 0, marginTop: 16, marginInline: 0 }}
tooltip={{ open: false }}
+25 -25
View File
@@ -28,11 +28,11 @@ export const TTSParamsConfig: ParamsSchema[] = [
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: 'opus', value: 'opus' },
// { label: 'aac', value: 'aac' },
// { label: 'flac', value: 'flac' },
{ label: 'wav', value: 'wav' }
// { label: 'pcm', value: 'pcm' }
],
label: {
text: 'playground.params.format',
@@ -43,27 +43,27 @@ export const TTSParamsConfig: ParamsSchema[] = [
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
}
]
}
// {
// 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
// }
// ]
// }
];
export const RealtimeParamsConfig: ParamsSchema[] = [