fix: audio view code

This commit is contained in:
jialin
2024-12-05 17:54:20 +08:00
parent c8d585889b
commit 899862dc57
7 changed files with 434 additions and 31 deletions
@@ -279,6 +279,10 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
setTokenResult(null);
};
const handleInputChange = (e: any) => {
setCurrentPrompt(e.target.value);
};
const handleSendMessage = (message: Omit<MessageItem, 'uid'>) => {
const currentMessage = message.content ? message : undefined;
submitMessage(currentMessage);
@@ -527,6 +531,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
isEmpty={!imageList.length}
handleSubmit={handleSendMessage}
handleAbortFetch={handleStopConversation}
onInputChange={handleInputChange}
shouldResetMessage={false}
clearAll={handleClear}
tools={
@@ -79,7 +79,6 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
const [loading, setLoading] = useState(false);
const [tokenResult, setTokenResult] = useState<any>(null);
const [collapse, setCollapse] = useState(false);
const contentRef = useRef<any>('');
const scroller = useRef<any>(null);
const inputListRef = useRef<any>(null);
const paramsRef = useRef<any>(null);
@@ -198,7 +197,7 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
setLoading(false);
};
const submitMessage = async (current?: { content: string }) => {
const submitMessage = async () => {
await formRef.current?.form.validateFields();
if (!parameters.model) return;
try {
@@ -219,13 +218,11 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
requestToken.current?.cancel?.();
requestToken.current = requestSource();
contentRef.current = current?.content || '';
const result: any = await rerankerQuery(
{
model: parameters.model,
top_n: parameters.top_n,
query: contentRef.current,
query: queryValueRef.current,
documents: [
...textList.map((item) => item.text),
...fileList.map((item) => item.text)
@@ -309,24 +306,9 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
setLoading(false);
}
};
const handleClear = () => {
if (!messageList.length) {
return;
}
setMessageId();
setMessageList([]);
setTokenResult(null);
};
const handleSendMessage = (message: Omit<MessageItem, 'uid'>) => {
submitMessage(message);
};
const handleSearch = (val: string) => {
if (!val) {
return;
}
submitMessage({ content: val });
submitMessage();
};
const handleQueryChange = (e: any) => {
@@ -630,7 +612,7 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
}}
parameters={{
...parameters,
query: contentRef.current
query: queryValueRef.current
}}
onCancel={handleCloseViewCode}
title={intl.formatMessage({ id: 'playground.viewcode' })}
@@ -28,7 +28,7 @@ import '../style/speech-to-text.less';
import '../style/system-message-wrap.less';
import AudioInput from './audio-input';
import DynamicParams from './dynamic-params';
import ViewCodeModal from './view-code-modal';
import ViewSTTCode from './view-stt-code';
interface MessageProps {
modelList: Global.BaseOption<string>[];
@@ -450,15 +450,15 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
</div>
</div>
<ViewCodeModal
<ViewSTTCode
open={show}
payload={{}}
api="audio/transcriptions"
clientType="audio.transcriptions"
clientType="audio.transcriptions.create"
parameters={parameters}
onCancel={handleCloseViewCode}
title={intl.formatMessage({ id: 'playground.viewcode' })}
></ViewCodeModal>
></ViewSTTCode>
</div>
);
});
@@ -26,7 +26,7 @@ import '../style/ground-left.less';
import '../style/system-message-wrap.less';
import DynamicParams from './dynamic-params';
import MessageInput from './message-input';
import ViewCodeModal from './view-code-modal';
import ViewTTSCode from './view-tts-code';
interface MessageProps {
modelList: Global.BaseOption<string>[];
@@ -132,6 +132,10 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
setLoading(false);
};
const handleInputChange = (e: any) => {
setCurrentPrompt(e.target.value);
};
const submitMessage = async (current?: { role: string; content: string }) => {
await formRef.current?.form.validateFields();
if (!parameters.model) return;
@@ -420,6 +424,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
isEmpty={true}
handleSubmit={handleSendMessage}
handleAbortFetch={handleStopConversation}
onInputChange={handleInputChange}
clearAll={handleClear}
shouldResetMessage={false}
submitIcon={<SendOutlined></SendOutlined>}
@@ -445,17 +450,17 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
</div>
</div>
<ViewCodeModal
<ViewTTSCode
open={show}
payload={{
input: currentPrompt
}}
api="audio/speech"
clientType="audio.speech"
clientType="audio.speech.create"
parameters={parameters}
onCancel={handleCloseViewCode}
title={intl.formatMessage({ id: 'playground.viewcode' })}
></ViewCodeModal>
></ViewTTSCode>
</div>
);
});
@@ -85,6 +85,7 @@ interface MessageInputProps {
submitIcon?: React.ReactNode;
presetPrompt?: (list: CurrentMessage[]) => void;
addMessage?: (message: CurrentMessage) => void;
onInputChange?: (e: any) => void;
title?: React.ReactNode;
tools?: React.ReactNode;
loading: boolean;
@@ -108,6 +109,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
updateLayout,
addMessage,
onCheck,
onInputChange,
title,
loading,
disabled,
@@ -150,7 +152,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
};
const handleInputChange = (e: any) => {
console.log('input change:', e.target?.value);
onInputChange?.(e);
setMessage({
...message,
content: e.target?.value
@@ -179,6 +181,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
const handleClearAll = (e: any) => {
e.stopPropagation();
clearAll();
handleInputChange({ target: { value: '' } });
setMessage({
role: Roles.User,
content: '',
@@ -0,0 +1,201 @@
import EditorWrap from '@/components/editor-wrap';
import HighlightCode from '@/components/highlight-code';
import { BulbOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Modal } from 'antd';
import _ from 'lodash';
import React, { useMemo, useState } from 'react';
type ViewModalProps = {
systemMessage?: string;
messageList?: any[];
payload: Record<string, any>;
parameters: any;
title: string;
api: string;
clientType: string;
logcommand?: string;
open: boolean;
onCancel: () => void;
};
const langMap = {
shell: 'bash',
python: 'python',
javascript: 'javascript'
};
const langOptions = [
{ label: 'Curl', value: langMap.shell },
{ label: 'Python', value: langMap.python },
{ label: 'Nodejs', value: langMap.javascript }
];
const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
const {
title,
open,
api,
clientType,
logcommand,
onCancel,
payload,
parameters = {}
} = props || {};
const intl = useIntl();
const [lang, setLang] = useState(langMap.shell);
const BaseURL = `${window.location.origin}/v1-openai`;
const formatPyParams = (params: any) => {
return _.keys(params).reduce((acc: string, key: string) => {
if (params[key] === null) {
return acc;
}
const value =
typeof params[key] === 'object'
? JSON.stringify(params[key], null, 2)
: `"${params[key]}"`;
return acc + ` ${key}=${value},\n`;
}, ' file=audio_file\n');
};
const codeValue = useMemo(() => {
const consoleLog = `console.log(response.text);\n`;
const printLog = logcommand ? `print(response.${logcommand})` : '';
if (lang === langMap.shell) {
const code = `curl ${window.location.origin}/v1-openai/${api} \\\n-H "Content-Type: multipart/form-data" \\\n-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\\n-F file="@/path/to/file/audio.mp3;type=audio/mpeg" \\\n-F model="${parameters.model}" \\\n-F language="${parameters.language}"`;
return code;
}
if (lang === langMap.javascript) {
const paramStr = JSON.stringify(
{
...parameters,
...payload,
file: `fs.createReadStream(audio.mp3)`
},
null,
4
);
const params = paramStr.replace(
/"fs.createReadStream\(audio.mp3\)"/g,
'fs.createReadStream("audio.mp3")'
);
const code = `const fs = require("fs")\nconst OpenAI = require("openai");\n\nconst openai = new OpenAI({\n "apiKey": "YOUR_GPUSTACK_API_KEY",\n "baseURL": "${BaseURL}"\n});\n\nasync function main(){\n const params = ${params};\nconst response = await openai.${clientType}(params);\n ${consoleLog}}\nmain();`;
return code;
}
if (lang === langMap.python) {
const formattedParams = _.keys(parameters).reduce(
(acc: string, key: string) => {
if (parameters[key] === null) {
return acc;
}
const value =
typeof parameters[key] === 'string'
? `"${parameters[key]}"`
: parameters[key];
return acc + ` ${key}=${value},\n`;
},
''
);
const params = formatPyParams(payload);
const code = `from openai import OpenAI\n\naudio_file = open("audio.mp3", "rb")\nclient = OpenAI(\n base_url="${BaseURL}", \n api_key="YOUR_GPUSTACK_API_KEY"\n)\n\nresponse = client.${clientType}(\n${formattedParams}${params})\nprint('response:', response.text)`;
return code;
}
return '';
}, [lang, payload, parameters, api, clientType, logcommand]);
const handleOnChangeLang = (value: string) => {
setLang(value);
};
const handleClose = () => {
setLang(langMap.shell);
onCancel();
};
return (
<>
<Modal
title={title}
open={open}
centered={true}
onCancel={handleClose}
destroyOnClose={true}
closeIcon={true}
maskClosable={false}
keyboard={false}
width={600}
footer={null}
>
<div style={{ marginBottom: '10px' }}>
{intl.formatMessage({ id: 'playground.viewcode.info' })}
</div>
<div>
<EditorWrap
copyText={codeValue}
langOptions={langOptions}
defaultValue={langMap.shell}
showHeader={true}
onChangeLang={handleOnChangeLang}
styles={{
wrapper: {
backgroundColor: 'var(--color-editor-dark)'
}
}}
>
<div
style={{
paddingRight: 2,
paddingBottom: 2
}}
>
<HighlightCode
height={380}
theme="dark"
code={codeValue}
lang={lang}
copyable={false}
></HighlightCode>
</div>
</EditorWrap>
<div
style={{ marginTop: 10, display: 'flex', alignItems: 'baseline' }}
>
<BulbOutlined className="m-r-8" />
<span>
{intl.formatMessage(
{ id: 'playground.viewcode.tips' },
{
here: (
<Button
type="link"
size="small"
href="#/api-keys"
target="_blank"
style={{ paddingInline: 2 }}
>
<span>
{' '}
{intl.formatMessage({
id: 'playground.viewcode.here'
})}
</span>
</Button>
)
}
)}
</span>
</div>
</div>
</Modal>
</>
);
};
export default React.memo(ViewCodeModal);
@@ -0,0 +1,207 @@
import EditorWrap from '@/components/editor-wrap';
import HighlightCode from '@/components/highlight-code';
import { BulbOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Modal } from 'antd';
import _ from 'lodash';
import React, { useMemo, useState } from 'react';
type ViewModalProps = {
systemMessage?: string;
messageList?: any[];
payload: Record<string, any>;
parameters: any;
title: string;
api: string;
clientType: string;
logcommand?: string;
open: boolean;
onCancel: () => void;
};
const langMap = {
shell: 'bash',
python: 'python',
javascript: 'javascript'
};
const langOptions = [
{ label: 'Curl', value: langMap.shell },
{ label: 'Python', value: langMap.python },
{ label: 'Nodejs', value: langMap.javascript }
];
const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
const {
title,
open,
api,
clientType,
logcommand,
onCancel,
payload,
parameters = {}
} = props || {};
const intl = useIntl();
const [lang, setLang] = useState(langMap.shell);
const BaseURL = `${window.location.origin}/v1-openai`;
const formatPyParams = (params: any) => {
return _.keys(params).reduce((acc: string, key: string) => {
if (params[key] === null) {
return acc;
}
const value =
typeof params[key] === 'object'
? JSON.stringify(params[key], null, 2)
: `"${params[key]}"`;
return acc + ` ${key}=${value},\n`;
}, '');
};
const codeValue = useMemo(() => {
const consoleLog = logcommand
? `console.log(response.${logcommand});`
: `console.log(ouptFile);\n const buffer = Buffer.from(await response.arrayBuffer());\n await fs.promises.writeFile(ouptFile, buffer);\n`;
const printLog = logcommand ? `print(response.${logcommand})` : '';
if (lang === langMap.shell) {
const code = `curl ${window.location.origin}/v1-openai/${api} \\\n-H "Content-Type: application/json" \\\n-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\\n-d '${JSON.stringify(
{
...parameters,
...payload
},
null,
2
)}' \\\n--output output.${parameters.response_format}`;
return code;
}
if (lang === langMap.javascript) {
const code = `const fs = require("fs");\nconst path = require("path");\nconst OpenAI = require("openai");\n\nconst ouptFile = path.resolve("./output.${parameters.response_format}");\n\nconst openai = new OpenAI({\n "apiKey": "YOUR_GPUSTACK_API_KEY",\n "baseURL": "${BaseURL}"\n});\n\nasync function main(){\n const params = ${JSON.stringify(
{
...parameters,
...payload
},
null,
4
)};\nconst response = await openai.${clientType}(params);\n ${consoleLog}}\nmain();`;
return code;
}
if (lang === langMap.python) {
const formattedParams = _.keys(parameters).reduce(
(acc: string, key: string) => {
if (parameters[key] === null) {
return acc;
}
const value =
typeof parameters[key] === 'string'
? `"${parameters[key]}"`
: parameters[key];
return acc + ` ${key}=${value},\n`;
},
''
);
const params = formatPyParams(payload);
const code = `from pathlib import Path\nfrom openai import OpenAI\n\nclient = OpenAI(\n base_url="${BaseURL}", \n api_key="YOUR_GPUSTACK_API_KEY"\n)\n\nouput_file_path = Path(__file__).parent\nresponse = client.${clientType}(\n${formattedParams}${params})\n${printLog}\nwith open(output_file_path, "wb") as f:
for chunk in response.iter_bytes():
f.write(chunk)
print(f"Audio saved to {output_file_path}")`;
return code;
}
return '';
}, [lang, payload, parameters, api, clientType, logcommand]);
const handleOnChangeLang = (value: string) => {
setLang(value);
};
const handleClose = () => {
setLang(langMap.shell);
onCancel();
};
return (
<>
<Modal
title={title}
open={open}
centered={true}
onCancel={handleClose}
destroyOnClose={true}
closeIcon={true}
maskClosable={false}
keyboard={false}
width={600}
footer={null}
>
<div style={{ marginBottom: '10px' }}>
{intl.formatMessage({ id: 'playground.viewcode.info' })}
</div>
<div>
<EditorWrap
copyText={codeValue}
langOptions={langOptions}
defaultValue={langMap.shell}
showHeader={true}
onChangeLang={handleOnChangeLang}
styles={{
wrapper: {
backgroundColor: 'var(--color-editor-dark)'
}
}}
>
<div
style={{
paddingRight: 2,
paddingBottom: 2
}}
>
<HighlightCode
height={380}
theme="dark"
code={codeValue}
lang={lang}
copyable={false}
></HighlightCode>
</div>
</EditorWrap>
<div
style={{ marginTop: 10, display: 'flex', alignItems: 'baseline' }}
>
<BulbOutlined className="m-r-8" />
<span>
{intl.formatMessage(
{ id: 'playground.viewcode.tips' },
{
here: (
<Button
type="link"
size="small"
href="#/api-keys"
target="_blank"
style={{ paddingInline: 2 }}
>
<span>
{' '}
{intl.formatMessage({
id: 'playground.viewcode.here'
})}
</span>
</Button>
)
}
)}
</span>
</div>
</div>
</Modal>
</>
);
};
export default React.memo(ViewCodeModal);