Adding css and adding prompt chainging
This commit is contained in:
1 parent
1f096cb1a7
commit
57054f8654
6 files changed
+242
-159
No files matched your search
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -9,7 +9,6 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.4.1",
|
|
||||||
"@emotion/react": "^11.10.5",
|
"@emotion/react": "^11.10.5",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
"eslint": "8.27.0",
|
"eslint": "8.27.0",
|
||||||
|
|||||||
+2
-7
@@ -1,11 +1,6 @@
|
|||||||
import { ChakraProvider } from '@chakra-ui/react';
|
import './styles.css';
|
||||||
|
|
||||||
const App = ({ Component, pageProps }) => {
|
const App = ({ Component, pageProps }) => {
|
||||||
return (
|
return <Component {...pageProps} />;
|
||||||
<ChakraProvider>
|
|
||||||
<Component {...pageProps} />
|
|
||||||
</ChakraProvider>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
+24
-4
@@ -6,15 +6,35 @@ const configuration = new Configuration({
|
|||||||
|
|
||||||
const openai = new OpenAIApi(configuration);
|
const openai = new OpenAIApi(configuration);
|
||||||
|
|
||||||
|
const basePromptPrefix =
|
||||||
|
'Help me write lyrics in the style of Drake, Canadian Rapper\n';
|
||||||
|
const finalPromptPrefix = 'Take the lyrics below and generate 5 song titles:\n';
|
||||||
|
|
||||||
const generateAction = async (req, res) => {
|
const generateAction = async (req, res) => {
|
||||||
const completion = await openai.createCompletion({
|
// Run first prompt
|
||||||
|
const baseCompletion = await openai.createCompletion({
|
||||||
model: 'text-davinci-002',
|
model: 'text-davinci-002',
|
||||||
prompt: req.body.input,
|
prompt: `${basePromptPrefix}${req.body.input}`,
|
||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
|
max_tokens: 2048,
|
||||||
});
|
});
|
||||||
|
|
||||||
const choice = completion.data.choices.pop();
|
const baseChoice = baseCompletion.data.choices.pop();
|
||||||
res.status(200).json({ choice });
|
|
||||||
|
// Run second prompt with prefix
|
||||||
|
const finalPrompt = `${finalPromptPrefix}${req.body.input}${baseChoice.text}`;
|
||||||
|
console.log(finalPrompt);
|
||||||
|
|
||||||
|
const prefixCompletion = await openai.createCompletion({
|
||||||
|
model: 'text-davinci-002',
|
||||||
|
prompt: finalPrompt,
|
||||||
|
temperature: 0.7,
|
||||||
|
max_tokens: 2048,
|
||||||
|
});
|
||||||
|
|
||||||
|
const finalChoice = prefixCompletion.data.choices.pop();
|
||||||
|
|
||||||
|
res.status(200).json({ baseChoice, finalChoice });
|
||||||
};
|
};
|
||||||
|
|
||||||
export default generateAction;
|
export default generateAction;
|
||||||
+55
-147
@@ -1,21 +1,10 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Text,
|
|
||||||
Flex,
|
|
||||||
VStack,
|
|
||||||
Textarea,
|
|
||||||
Link,
|
|
||||||
Kbd,
|
|
||||||
Spinner,
|
|
||||||
HStack,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import buildspaceLogo from '../assets/buildspace-logo.png';
|
import buildspaceLogo from '../assets/buildspace-logo.png';
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const [input, setInput] = useState('');
|
const [input, setInput] = useState('');
|
||||||
const [finishReason, setFinishReason] = useState('');
|
const [output, setOutput] = useState('');
|
||||||
const [isGenerating, setIsGenerating] = useState(false);
|
const [isGenerating, setIsGenerating] = useState(false);
|
||||||
|
|
||||||
const onChange = (event) => {
|
const onChange = (event) => {
|
||||||
@@ -33,150 +22,69 @@ const Home = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const { choice } = data;
|
const { baseChoice, finalChoice } = data;
|
||||||
|
|
||||||
|
setOutput(
|
||||||
|
`Song Titles:${finalChoice.text}\n\nLyrics:\n${input}${baseChoice.text}`
|
||||||
|
);
|
||||||
|
|
||||||
setIsGenerating(false);
|
setIsGenerating(false);
|
||||||
|
|
||||||
setFinishReason(choice.finish_reason);
|
|
||||||
|
|
||||||
if (choice.finish_reason === 'stop') {
|
|
||||||
console.log('end of the completion!');
|
|
||||||
}
|
|
||||||
|
|
||||||
setInput((prevState) => {
|
|
||||||
return prevState + choice.text;
|
|
||||||
});
|
|
||||||
}, [input]);
|
}, [input]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const scratchPadText = localStorage.getItem('scratchpad');
|
|
||||||
setInput(scratchPadText);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const keydownHandler = async (event) => {
|
|
||||||
if ((event.metaKey || event.ctrlKey) && event.code === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
await generateAction();
|
|
||||||
}
|
|
||||||
localStorage.setItem('scratchpad', input);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('keydown', keydownHandler);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('keydown', keydownHandler);
|
|
||||||
};
|
|
||||||
}, [input, generateAction]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex position="relative" minHeight="100vh">
|
<div className="root">
|
||||||
<Flex
|
<div className="container">
|
||||||
position="absolute"
|
<div className="content">
|
||||||
h="100%"
|
<div className="header">
|
||||||
w="100%"
|
<p className="header-title">Scratchpad</p>
|
||||||
bgColor="black"
|
<p className="header-subtitle">
|
||||||
flexDirection="column"
|
Write your first song in the style of your favorite artist.
|
||||||
letterSpacing="-0.08em"
|
</p>
|
||||||
>
|
</div>
|
||||||
<VStack
|
<div className="text-container">
|
||||||
w="100%"
|
<textarea
|
||||||
height="100%"
|
className="text-area"
|
||||||
spacing={5}
|
placeholder="write some lyrics here to get started"
|
||||||
color="white"
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<VStack padding={3}>
|
|
||||||
<Text color="white" fontWeight="bold" fontSize="5xl" pl={3} pt={1}>
|
|
||||||
Scratchpad
|
|
||||||
</Text>
|
|
||||||
<Text color="white" fontSize="2xl" textAlign="center">
|
|
||||||
Write your own song, movie script, or anime in 2 minutes.
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
<Box
|
|
||||||
h={{ base: '250px', md: '350px', lg: '400px' }}
|
|
||||||
w={{ base: '80%', md: '60%', lg: '50%' }}
|
|
||||||
position="relative"
|
|
||||||
>
|
|
||||||
{isGenerating && (
|
|
||||||
<Flex
|
|
||||||
position="absolute"
|
|
||||||
zIndex="1"
|
|
||||||
w="100%"
|
|
||||||
h="100%"
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
>
|
|
||||||
<Spinner size="lg" />
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
{!isGenerating && finishReason === 'stop' && (
|
|
||||||
<Flex
|
|
||||||
position="absolute"
|
|
||||||
zIndex="1"
|
|
||||||
bottom={0}
|
|
||||||
right={0}
|
|
||||||
bgColor="white"
|
|
||||||
padding={2}
|
|
||||||
mb={3}
|
|
||||||
mr={2}
|
|
||||||
borderRadius={5}
|
|
||||||
>
|
|
||||||
<Text color="black" fontWeight="bold" letterSpacing="-0.01em">
|
|
||||||
Keep writing to generate more!
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
<Textarea
|
|
||||||
w="100%"
|
|
||||||
h="100%"
|
|
||||||
fontSize="18px"
|
|
||||||
variant="outline"
|
|
||||||
placeholder="type here to get started"
|
|
||||||
value={input}
|
value={input}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
isDisabled={isGenerating}
|
|
||||||
bgColor="gray.900"
|
|
||||||
/>
|
/>
|
||||||
<Flex>
|
<textarea
|
||||||
<Text
|
className="text-area"
|
||||||
pt={2}
|
placeholder="your lyrics and song titles will go here"
|
||||||
fontSize="lg"
|
value={output}
|
||||||
fontWeight="bold"
|
disabled
|
||||||
letterSpacing="-0.01em"
|
/>
|
||||||
>
|
</div>
|
||||||
Press <Kbd color="gray.700">ctrl</Kbd> or{' '}
|
<button
|
||||||
<Kbd color="gray.700">cmd</Kbd> +{' '}
|
className="generate-button"
|
||||||
<Kbd color="gray.700">enter</Kbd> to have your AI writer to help
|
onClick={generateAction}
|
||||||
you generate the rest!
|
disabled={isGenerating}
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<HStack
|
|
||||||
w="100%"
|
|
||||||
position="absolute"
|
|
||||||
bottom={0}
|
|
||||||
justifyContent="center"
|
|
||||||
pb={5}
|
|
||||||
>
|
>
|
||||||
<Image src={buildspaceLogo} width={25} alt="buildspace logo" />
|
{isGenerating ? (
|
||||||
<Text fontSize="lg">
|
<div class="lds-ring">
|
||||||
build on{' '}
|
<div></div>
|
||||||
<Link
|
<div></div>
|
||||||
color="blue.300"
|
<div></div>
|
||||||
href="https://buildspace.so/builds/ai-writer"
|
<div></div>
|
||||||
isExternal
|
</div>
|
||||||
>
|
) : (
|
||||||
buildspace
|
<p>Generate</p>
|
||||||
</Link>
|
)}
|
||||||
</Text>
|
</button>
|
||||||
</HStack>
|
</div>
|
||||||
</VStack>
|
<div className="footer">
|
||||||
</Flex>
|
<Image src={buildspaceLogo} width={25} alt="buildspace logo" />
|
||||||
</Flex>
|
<p>build on</p>
|
||||||
|
<a
|
||||||
|
href="https://buildspace.so/builds/ai-writer"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
buildspace
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: SF Pro Display, Inter, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: SF Pro Display,
|
||||||
|
serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
color: #000;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin: 0;
|
||||||
|
padding-top: 1em;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-subtitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area {
|
||||||
|
font-family: SF Pro Display,
|
||||||
|
serif;
|
||||||
|
color: #000;
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #EDF2F7;
|
||||||
|
border-color: rgba(118, 118, 118, 0.3);
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-area-output {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button {
|
||||||
|
width: 40%;
|
||||||
|
font-family: Inter,
|
||||||
|
sans-serif;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
border-style: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-button:disabled {
|
||||||
|
background-color: #d2d2d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer p {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
color:#63b3ed;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading ring animation */
|
||||||
|
.lds-ring {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-ring div {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
margin: 4px;
|
||||||
|
border: 2px solid #000;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||||
|
border-color: #000 transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-ring div:nth-child(1) {
|
||||||
|
animation-delay: -0.45s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-ring div:nth-child(2) {
|
||||||
|
animation-delay: -0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lds-ring div:nth-child(3) {
|
||||||
|
animation-delay: -0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes lds-ring {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user