fix: image chunk data broken

This commit is contained in:
jialin
2024-11-27 21:13:31 +08:00
parent 146bcdcf1c
commit 324bd57e3d
6 changed files with 86 additions and 12 deletions
@@ -28,6 +28,18 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
setCollapsed(!collapsed); setCollapsed(!collapsed);
}; };
const onDownload = () => {
const url = props.audioUrl || '';
const filename = Date.now() + '';
const link = document.createElement('a');
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
};
return ( return (
<div> <div>
<div className="speech-item"> <div className="speech-item">
@@ -60,6 +72,7 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
</Tooltip> </Tooltip>
<Tooltip title="Download"> <Tooltip title="Download">
<Button <Button
onClick={onDownload}
icon={<DownloadOutlined />} icon={<DownloadOutlined />}
type="text" type="text"
size="small" size="small"
@@ -282,7 +282,7 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
.split('\n') .split('\n')
.map((item: string) => { .map((item: string) => {
return { return {
text: item, text: item?.trim(),
uid: inputListRef.current?.setMessageId(), uid: inputListRef.current?.setMessageId(),
name: '' name: ''
}; };
@@ -4,7 +4,10 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select'; import SealSelect from '@/components/seal-form/seal-select';
import useOverlayScroller from '@/hooks/use-overlay-scroller'; import useOverlayScroller from '@/hooks/use-overlay-scroller';
import ThumbImg from '@/pages/playground/components/thumb-img'; import ThumbImg from '@/pages/playground/components/thumb-img';
import { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data'; import {
fetchChunkedData,
readLargeStreamData as readStreamData
} from '@/utils/fetch-chunk-data';
import { FileImageOutlined, SwapOutlined } from '@ant-design/icons'; import { FileImageOutlined, SwapOutlined } from '@ant-design/icons';
import { useIntl, useSearchParams } from '@umijs/max'; import { useIntl, useSearchParams } from '@umijs/max';
import { Button, Form, Tooltip } from 'antd'; import { Button, Form, Tooltip } from 'antd';
@@ -138,18 +141,28 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const setImageSize = useCallback(() => { const setImageSize = useCallback(() => {
let size: Record<string, string | number> = { let size: Record<string, string | number> = {
with: 256,
height: 256,
span: 12 span: 12
}; };
if (parameters.n === 1) { if (parameters.n === 1) {
size.width = '100%';
size.height = '100%';
size.span = 24; size.span = 24;
} }
if (parameters.n === 2) { if (parameters.n === 2) {
size.width = '50%';
size.height = 256;
size.span = 12; size.span = 12;
} }
if (parameters.n === 3) { if (parameters.n === 3) {
size.width = '33%';
size.height = 256;
size.span = 12; size.span = 12;
} }
if (parameters.n === 4) { if (parameters.n === 4) {
size.width = '25%';
size.height = 256;
size.span = 12; size.span = 12;
} }
return size; return size;
@@ -210,8 +223,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const params = { const params = {
stream: true, stream: true,
stream_options: { stream_options: {
chunk_result: true, chunk_result: true
chunk_size: 16 * 1024
}, },
prompt: current?.content || currentPrompt || '', prompt: current?.content || currentPrompt || '',
..._.omitBy(finalParameters, (value: string) => !value) ..._.omitBy(finalParameters, (value: string) => !value)
@@ -220,7 +232,6 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
const result: any = await fetchChunkedData({ const result: any = await fetchChunkedData({
data: params, data: params,
url: CREAT_IMAGE_API, url: CREAT_IMAGE_API,
// url: 'http://192.168.50.27:9090/v1/images/generations',
signal: requestToken.current.signal signal: requestToken.current.signal
}); });
@@ -235,12 +246,13 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}); });
return; return;
} }
console.log('imgItem.dataUrl:', chunk.data);
chunk?.data?.forEach((item: any) => { chunk?.data?.forEach((item: any) => {
const imgItem = newImageList[item.index]; const imgItem = newImageList[item.index];
if (item.b64_json) { if (item.b64_json) {
imgItem.dataUrl += item.b64_json; imgItem.dataUrl += item.b64_json;
// imgItem.cache.push(item.b64_json); // imgItem.cache.push(item.b64_json);
console.log('imgItem.dataUrl:', imgItem.dataUrl);
} }
const progress = _.round(item.progress, 0); const progress = _.round(item.progress, 0);
newImageList[item.index] = { newImageList[item.index] = {
@@ -295,7 +307,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}); });
setParams((pre: object) => { setParams((pre: object) => {
return { return {
...pre, ..._.omit(pre, ['quality', 'style']),
seed: null, seed: null,
sampler: 'euler_a', sampler: 'euler_a',
cfg_scale: 1, cfg_scale: 1,
@@ -306,6 +318,8 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
} else { } else {
setParams((pre: object) => { setParams((pre: object) => {
return { return {
quality: 'standard',
style: null,
..._.omit(pre, [ ..._.omit(pre, [
'seed', 'seed',
'sampler', 'sampler',
@@ -320,6 +334,9 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
}; };
const renderExtra = useMemo(() => { const renderExtra = useMemo(() => {
if (!isOpenaiCompatible) {
return [];
}
return ImageconstExtraConfig.map((item: ParamsSchema) => { return ImageconstExtraConfig.map((item: ParamsSchema) => {
return ( return (
<Form.Item name={item.name} rules={item.rules} key={item.name}> <Form.Item name={item.name} rules={item.rules} key={item.name}>
@@ -335,7 +352,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
</Form.Item> </Form.Item>
); );
}); });
}, [ImageconstExtraConfig, intl]); }, [ImageconstExtraConfig, isOpenaiCompatible, intl]);
const renderAdvanced = useMemo(() => { const renderAdvanced = useMemo(() => {
if (isOpenaiCompatible) { if (isOpenaiCompatible) {
@@ -354,7 +354,7 @@ const GroundReranker: React.FC<MessageProps> = forwardRef((props, ref) => {
.split('\n') .split('\n')
.map((item: string) => { .map((item: string) => {
return { return {
text: item, text: item?.trim(),
uid: inputListRef.current?.setMessageId(), uid: inputListRef.current?.setMessageId(),
name: '' name: ''
}; };
+2 -2
View File
@@ -112,12 +112,12 @@ export const ImageParamsConfig: ParamsSchema[] = [
type: 'Select', type: 'Select',
name: 'size', name: 'size',
options: [ options: [
{ label: 'playground.params.custom', value: 'custom', locale: true },
{ label: '256x256', value: '256x256' }, { label: '256x256', value: '256x256' },
{ label: '512x512', value: '512x512' }, { label: '512x512', value: '512x512' },
{ label: '1024x1024', value: '1024x1024' }, { label: '1024x1024', value: '1024x1024' },
{ label: '1792x1024', value: '1792x1024' }, { label: '1792x1024', value: '1792x1024' },
{ label: '1024x1792', value: '1024x1792' }, { label: '1024x1792', value: '1024x1792' }
{ label: 'playground.params.custom', value: 'custom', locale: true }
], ],
label: { label: {
text: 'playground.params.size', text: 'playground.params.size',
+45 -1
View File
@@ -59,7 +59,9 @@ export const fetchChunkedData = async (params: {
}; };
} }
const reader = response?.body?.getReader(); const reader = response?.body?.getReader();
const decoder = new TextDecoder('utf-8'); const decoder = new TextDecoder('utf-8', {
fatal: true
});
return { return {
reader, reader,
decoder decoder
@@ -77,12 +79,54 @@ export const readStreamData = async (
} }
let chunk = decoder.decode(value, { stream: true }); let chunk = decoder.decode(value, { stream: true });
extractJSON(chunk).forEach((data) => { extractJSON(chunk).forEach((data) => {
callback?.(data); callback?.(data);
}); });
await readStreamData(reader, decoder, callback); await readStreamData(reader, decoder, callback);
}; };
export const readLargeStreamData = async (
reader: any,
decoder: TextDecoder,
callback: (data: any) => void
) => {
let buffer = '';
const processStream = async () => {
const { done, value } = await reader.read();
if (done) {
if (buffer) {
try {
extractJSON(buffer).forEach((data) => {
callback?.(data);
});
} catch (e) {
console.error('parse buffer failed:', buffer);
}
}
return;
}
// cache each chunk
buffer += decoder.decode(value, { stream: true });
const extractedData = extractJSON(buffer);
extractedData.forEach((data) => {
callback?.(data);
});
const lastIndex = buffer.lastIndexOf('}');
buffer = lastIndex !== -1 ? buffer.slice(lastIndex + 1) : buffer;
// next chunk
await processStream();
};
await processStream();
};
export const readTextEventStreamData = async ( export const readTextEventStreamData = async (
reader: any, reader: any,
decoder: TextDecoder, decoder: TextDecoder,