diff --git a/config/routes.ts b/config/routes.ts
index 8a50de9d..5885a09a 100644
--- a/config/routes.ts
+++ b/config/routes.ts
@@ -25,6 +25,14 @@ export default [
icon: 'Comment',
component: './playground/index'
},
+ {
+ name: 'speech',
+ title: 'Speech',
+ path: '/playground/speech',
+ key: 'speech',
+ icon: 'Comment',
+ component: './playground/speech'
+ },
{
name: 'embedding',
title: 'embedding',
diff --git a/src/locales/en-US/menu.ts b/src/locales/en-US/menu.ts
index c9ee5112..4e48291f 100644
--- a/src/locales/en-US/menu.ts
+++ b/src/locales/en-US/menu.ts
@@ -2,7 +2,9 @@ export default {
'menu.dashboard': 'Dashboard',
'menu.playground': 'Playground',
'menu.playground.rerank': 'Rerank',
+ 'menu.playground.embedding': 'Embedding',
'menu.playground.chat': 'Chat',
+ 'menu.playground.speech': 'Speech',
'menu.compare': 'Compare',
'menu.models': 'Models',
'menu.resources': 'Resources',
diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts
index ef313f7a..a9141b61 100644
--- a/src/locales/zh-CN/menu.ts
+++ b/src/locales/zh-CN/menu.ts
@@ -4,6 +4,7 @@ export default {
'menu.playground.rerank': '重排',
'menu.playground.embedding': '文本嵌入',
'menu.playground.chat': '对话',
+ 'menu.playground.speech': '语音',
'menu.compare': '多模型对比',
'menu.models': '模型',
'menu.resources': '资源',
diff --git a/src/pages/llmodels/config/llama-config.ts b/src/pages/llmodels/config/llama-config.ts
index 2af59f07..f4497545 100644
--- a/src/pages/llmodels/config/llama-config.ts
+++ b/src/pages/llmodels/config/llama-config.ts
@@ -23,6 +23,10 @@ const options = [
{
label: '--ubatch-size',
value: '--ubatch-size'
+ },
+ {
+ label: '--images',
+ value: '--images'
}
];
diff --git a/src/pages/playground/components/ground-stt.tsx b/src/pages/playground/components/ground-stt.tsx
new file mode 100644
index 00000000..9a120a61
--- /dev/null
+++ b/src/pages/playground/components/ground-stt.tsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+const GroundStt = () => {
+ return
STT
;
+};
+
+export default React.memo(GroundStt);
diff --git a/src/pages/playground/components/ground-tts.tsx b/src/pages/playground/components/ground-tts.tsx
new file mode 100644
index 00000000..bce84aa1
--- /dev/null
+++ b/src/pages/playground/components/ground-tts.tsx
@@ -0,0 +1,353 @@
+import useOverlayScroller from '@/hooks/use-overlay-scroller';
+import { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data';
+import { useIntl, useSearchParams } from '@umijs/max';
+import { Spin } from 'antd';
+import classNames from 'classnames';
+import _ from 'lodash';
+import 'overlayscrollbars/overlayscrollbars.css';
+import {
+ forwardRef,
+ memo,
+ useEffect,
+ useImperativeHandle,
+ useMemo,
+ useRef,
+ useState
+} from 'react';
+import { CHAT_API } from '../apis';
+import { Roles, generateMessages } from '../config';
+import { TTSParamsConfig as paramsConfig } from '../config/params-config';
+import { MessageItem } from '../config/types';
+import '../style/ground-left.less';
+import '../style/system-message-wrap.less';
+import MessageInput from './message-input';
+import MessageContent from './multiple-chat/message-content';
+import SystemMessage from './multiple-chat/system-message';
+import ReferenceParams from './reference-params';
+import RerankerParams from './reranker-params';
+import ViewCodeModal from './view-code-modal';
+
+interface MessageProps {
+ modelList: Global.BaseOption[];
+ loaded?: boolean;
+ ref?: any;
+}
+
+const GroundLeft: React.FC = forwardRef((props, ref) => {
+ const { modelList } = props;
+ const messageId = useRef(0);
+ const [messageList, setMessageList] = useState([]);
+
+ const intl = useIntl();
+ const [searchParams] = useSearchParams();
+ const selectModel = searchParams.get('model') || '';
+ const [parameters, setParams] = useState({});
+ const [systemMessage, setSystemMessage] = useState('');
+ const [show, setShow] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [tokenResult, setTokenResult] = useState(null);
+ const [collapse, setCollapse] = useState(false);
+ const contentRef = useRef('');
+ const controllerRef = useRef(null);
+ const scroller = useRef(null);
+ const currentMessageRef = useRef(null);
+ const paramsRef = useRef(null);
+ const messageListLengthCache = useRef(0);
+
+ const { initialize, updateScrollerPosition } = useOverlayScroller();
+ const { initialize: innitializeParams } = useOverlayScroller();
+
+ const initialValues = {
+ voice: 'Alloy',
+ response_format: 'mp3',
+ speed: 1
+ };
+
+ useImperativeHandle(ref, () => {
+ return {
+ viewCode() {
+ setShow(true);
+ },
+ setCollapse() {
+ setCollapse(!collapse);
+ },
+ collapse: collapse
+ };
+ });
+
+ const viewCodeMessage = useMemo(() => {
+ return generateMessages([
+ { role: Roles.System, content: systemMessage },
+ ...messageList
+ ]);
+ }, [messageList, systemMessage]);
+
+ const setMessageId = () => {
+ messageId.current = messageId.current + 1;
+ };
+
+ const handleNewMessage = (message?: { role: string; content: string }) => {
+ const newMessage = message || {
+ role:
+ _.last(messageList)?.role === Roles.User ? Roles.Assistant : Roles.User,
+ content: ''
+ };
+ messageList.push({
+ ...newMessage,
+ uid: messageId.current + 1
+ });
+ setMessageId();
+ setMessageList([...messageList]);
+ };
+
+ const joinMessage = (chunk: any) => {
+ setTokenResult({
+ ...(chunk?.usage ?? {})
+ });
+
+ if (!chunk || !_.get(chunk, 'choices', []).length) {
+ return;
+ }
+ contentRef.current =
+ contentRef.current + _.get(chunk, 'choices.0.delta.content', '');
+ setMessageList([
+ ...messageList,
+ ...currentMessageRef.current,
+ {
+ role: Roles.Assistant,
+ content: contentRef.current,
+ uid: messageId.current
+ }
+ ]);
+ };
+ const handleStopConversation = () => {
+ controllerRef.current?.abort?.();
+ setLoading(false);
+ };
+
+ const submitMessage = async (current?: { role: string; content: string }) => {
+ if (!parameters.model) return;
+ try {
+ setLoading(true);
+ setMessageId();
+ setTokenResult(null);
+
+ controllerRef.current?.abort?.();
+ controllerRef.current = new AbortController();
+ const signal = controllerRef.current.signal;
+ currentMessageRef.current = current
+ ? [
+ {
+ ...current,
+ uid: messageId.current
+ }
+ ]
+ : [];
+
+ contentRef.current = '';
+ setMessageList((pre) => {
+ return [...pre, ...currentMessageRef.current];
+ });
+
+ const messageParams = [
+ { role: Roles.System, content: systemMessage },
+ ...messageList,
+ ...currentMessageRef.current
+ ];
+
+ const messages = generateMessages(messageParams);
+
+ const chatParams = {
+ messages: messages,
+ ...parameters,
+ stream: true,
+ stream_options: {
+ include_usage: true
+ }
+ };
+ const result: any = await fetchChunkedData({
+ data: chatParams,
+ url: CHAT_API,
+ signal
+ });
+
+ if (result?.error) {
+ setTokenResult({
+ error: true,
+ errorMessage:
+ result?.data?.error?.message || result?.data?.message || ''
+ });
+ return;
+ }
+ setMessageId();
+ const { reader, decoder } = result;
+ await readStreamData(reader, decoder, (chunk: any) => {
+ if (chunk?.error) {
+ setTokenResult({
+ error: true,
+ errorMessage: chunk?.error?.message || chunk?.message || ''
+ });
+ return;
+ }
+ joinMessage(chunk);
+ });
+ } catch (error) {
+ // console.log('error:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+ const handleClear = () => {
+ if (!messageList.length) {
+ return;
+ }
+ setMessageId();
+ setMessageList([]);
+ setTokenResult(null);
+ };
+
+ const handleSendMessage = (message: Omit) => {
+ console.log('message:', message);
+ const currentMessage =
+ message.content || message.imgs?.length ? message : undefined;
+ submitMessage(currentMessage);
+ };
+
+ const handleCloseViewCode = () => {
+ setShow(false);
+ };
+
+ const handleSelectModel = () => {};
+
+ const handlePresetPrompt = (list: { role: string; content: string }[]) => {
+ const sysMsg = list.filter((item) => item.role === 'system');
+ const userMsg = list
+ .filter((item) => item.role === 'user')
+ .map((item) => {
+ setMessageId();
+ return {
+ ...item,
+ uid: messageId.current
+ };
+ });
+ setSystemMessage(sysMsg[0]?.content || '');
+ setMessageList(userMsg);
+ };
+
+ useEffect(() => {
+ if (scroller.current) {
+ initialize(scroller.current);
+ }
+ }, [scroller.current, initialize]);
+
+ useEffect(() => {
+ if (paramsRef.current) {
+ innitializeParams(paramsRef.current);
+ }
+ }, [paramsRef.current, innitializeParams]);
+
+ useEffect(() => {
+ if (loading) {
+ updateScrollerPosition();
+ }
+ }, [messageList, loading]);
+
+ useEffect(() => {
+ if (messageList.length > messageListLengthCache.current) {
+ updateScrollerPosition();
+ }
+ messageListLengthCache.current = messageList.length;
+ }, [messageList.length]);
+
+ return (
+
+
+
+ <>
+
+
+
+
+
+
+ {loading && (
+
+
+
+ )}
+
+ >
+
+ {tokenResult && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+ );
+});
+
+export default memo(GroundLeft);
diff --git a/src/pages/playground/components/reranker-params.tsx b/src/pages/playground/components/reranker-params.tsx
index c06e53f0..5ec7ff4f 100644
--- a/src/pages/playground/components/reranker-params.tsx
+++ b/src/pages/playground/components/reranker-params.tsx
@@ -1,9 +1,10 @@
+import FieldWrapper from '@/components/seal-form/field-wrapper';
import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { INPUT_WIDTH } from '@/constants';
import { InfoCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
-import { Form, InputNumber, Tooltip } from 'antd';
+import { Form, InputNumber, Slider, Tooltip } from 'antd';
import _ from 'lodash';
import { memo, useCallback, useEffect, useId } from 'react';
import { ParamsSchema } from '../config/types';
@@ -104,45 +105,6 @@ const ParamsSettings: React.FC = ({
form.setFieldsValue(globalParams);
}, [globalParams]);
- const renderFields = useCallback(() => {
- console.log('paramsConfig:', paramsConfig);
- if (!paramsConfig?.length) {
- return null;
- }
- return paramsConfig.map((item: ParamsSchema) => {
- if (item.type === 'InputNumber') {
- return (
-
-
-
- );
- }
- if (item.type === 'Select') {
- return (
-
-
-
- );
- }
- return null;
- });
- }, [paramsConfig]);
-
const renderLabel = (args: {
field: string;
label: string;
@@ -178,6 +140,73 @@ const ParamsSettings: React.FC = ({
);
};
+ const renderFields = useCallback(() => {
+ console.log('paramsConfig:', paramsConfig);
+ if (!paramsConfig?.length) {
+ return null;
+ }
+ return paramsConfig.map((item: ParamsSchema) => {
+ if (item.type === 'InputNumber') {
+ return (
+
+
+
+ );
+ }
+ if (item.type === 'Select') {
+ return (
+
+
+
+ );
+ }
+ if (item.type === 'Slider') {
+ return (
+
+
+ handleFieldValueChange(val, item.name)}
+ >
+
+
+ );
+ }
+ return null;
+ });
+ }, [paramsConfig]);
+
return (