ngxson's picture
ngxson HF Staff
first working version
8e0957b
raw
history blame
4.05 kB
import { useEffect, useState } from 'react';
import { CONFIG } from '../config';
import { getPromptGeneratePodcastScript } from '../utils/prompts';
import { getSSEStreamAsync } from '../utils/utils';
interface SplitContent {
thought: string;
codeBlock: string;
}
const getFromTo = (content: string, from: string, to: string): string => {
const firstSplit = content.split(from, 2);
if (firstSplit[1] !== undefined) {
const secondSplit = firstSplit[1].split(to, 1);
return secondSplit[0];
} else {
return '';
}
};
const splitContent = (content: string): SplitContent => {
return {
thought: getFromTo(content, '<think>', '</think>').trim(),
codeBlock: getFromTo(content, '```yaml', '```').trim(),
};
};
export const ScriptMaker = ({
setScript,
setBusy,
busy,
}: {
setScript: (script: string) => void;
setBusy: (busy: boolean) => void;
busy: boolean;
}) => {
const [input, setInput] = useState<string>('');
const [note, setNote] = useState<string>('');
const [thought, setThought] = useState<string>('');
const [isGenerating, setIsGenerating] = useState<boolean>(false);
useEffect(() => {
setBusy(isGenerating);
}, [isGenerating]);
const generate = async () => {
setIsGenerating(true);
setThought('');
try {
let responseContent = '';
const fetchResponse = await fetch(CONFIG.llmEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
messages: [
{
role: 'user',
content: getPromptGeneratePodcastScript(input, note),
},
],
temperature: 0.3,
stream: true,
}),
});
if (fetchResponse.status !== 200) {
const body = await fetchResponse.json();
throw new Error(body?.error?.message || 'Unknown error');
}
const chunks = getSSEStreamAsync(fetchResponse);
for await (const chunk of chunks) {
// const stop = chunk.stop;
if (chunk.error) {
throw new Error(chunk.error?.message || 'Unknown error');
}
const addedContent = chunk.choices[0].delta.content;
responseContent += addedContent;
const { thought, codeBlock } = splitContent(responseContent);
setThought(thought);
if (codeBlock.length > 0) {
setScript(codeBlock);
}
}
} catch (error) {
console.error(error);
alert('Failed to generate the script. Please try again.');
}
setIsGenerating(false);
};
return (
<div className="card bg-base-100 w-full shadow-xl">
<div className="card-body">
<h2 className="card-title">Step 1: Input information</h2>
<textarea
className="textarea textarea-bordered w-full h-72 p-2"
placeholder="Type your input information here (an article, a document, etc)..."
value={input}
onChange={(e) => setInput(e.target.value)}
disabled={isGenerating || busy}
></textarea>
<textarea
className="textarea textarea-bordered w-full h-24 p-2"
placeholder="Optional note (the theme, tone, etc)..."
value={note}
onChange={(e) => setNote(e.target.value)}
disabled={isGenerating || busy}
></textarea>
{thought.length > 0 && (
<>
<p>Thought process:</p>
<textarea
className="textarea textarea-bordered w-full h-24 p-2"
value={thought}
readOnly
></textarea>
</>
)}
<button
className="btn btn-primary mt-2"
onClick={generate}
disabled={isGenerating || busy}
>
{isGenerating ? (
<>
<span className="loading loading-spinner loading-sm"></span>
Generating...
</>
) : (
'Generate script'
)}
</button>
</div>
</div>
);
};