Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

my commits #11

Open
wants to merge 1 commit into
base: starter
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions pages/api/generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const bufferToBase64 = (buffer) => {
let arr = new Uint8Array(buffer);
const base64 = btoa(
arr.reduce((data, byte) => data + String.fromCharCode(byte), '')
)
return `data:image/png;base64,${base64}`;
};

const generateAction = async (req, res) => {
console.log('Received request');

const input = JSON.parse(req.body).input;

// Add fetch request to Hugging Face
const response = await fetch(
`https://api-inference.huggingface.co/models/Medicypo/sd-1-5-stephanemed`,
{
headers: {
Authorization: `Bearer ${process.env.HF_AUTH_KEY}`,
'Content-Type': 'application/json',
'x-use-cache': 'false'
},
method: 'POST',
body: JSON.stringify({
inputs: input,
}),
}
);
// Check for different statuses to send proper payload
if (response.ok) {
const buffer = await response.arrayBuffer();
// Convert to base64
const base64 = bufferToBase64(buffer);
// Make sure to change to base64
res.status(200).json({ image: base64 });
} else if (response.status === 503) {
const json = await response.json();
res.status(503).json(json);
} else {
const json = await response.json();
res.status(response.status).json({ error: response.statusText });
}
};

export default generateAction;
162 changes: 144 additions & 18 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,162 @@
import { useState, useEffect } from 'react';
import Head from 'next/head';
import Image from 'next/image';
import buildspaceLogo from '../assets/buildspace-logo.png';

const Home = () => {
const maxRetries = 20;
const [input, setInput] = useState("");
const [img, setImg] = useState("");
// Numbers of retries
const [retry, setRetry] = useState(0);
// Number of retries left
const [retryCount, setRetryCount] = useState(maxRetries);
// Add isGenerating state
const [isGenerating, setIsGenerating] = useState(false);
// Add new state here
const [finalPrompt, setFinalPrompt] = useState('');

const sleep = (ms) => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
};

useEffect(() => {
const runRetry = async () => {
if (retryCount === 0) {
console.log(`Model still loading after ${maxRetries} retries. Try request again in 5 minutes.`);
setRetryCount(maxRetries);
return;
}

console.log(`Trying again in ${retry} seconds.`);

await sleep(retry * 1000);

await generateAction();
};

if (retry === 0) {
return;
}

runRetry();
}, [retry]);

const onChange = (event) => {
setInput(event.target.value);
};
// Add generateAction
const generateAction = async () => {
console.log("Generating...");
// Add this check to make sure there is no double click
if (isGenerating && retry === 0) return;

// Set loading has started
setIsGenerating(true);

// If this is a retry request, take away retryCount
if (retry > 0) {
setRetryCount((prevState) => {
if (prevState === 0) {
return 0;
} else {
return prevState - 1;
}
});

setRetry(0);
}

// const finalInput = input.replace(/raza/gi, 'abraza');

// Add the fetch request
const response = await fetch("/api/generate", {
method: "POST",
headers: {
"Content-Type": "image/jpeg",
},
// body: JSON.stringify({ finalInput }),
body: JSON.stringify({ input }),
});

const data = await response.json();
if (response.status === 503) {
setRetry(data.estimated_time);

return;
}

// If another error, drop error
if (!response.ok) {
console.log(`Error: ${data.error}`);
// Stop loading
setIsGenerating(false);
return;
}
// Set final prompt here
setFinalPrompt(input);
// Remove content from input box
setInput('');
setImg(data.image);
setIsGenerating(false);
};

return (
<div className="root">
<Head>
<title>AI Avatar Generator | buildspace</title>
<title>AI Avatar Generator</title>
</Head>
<div className="container">
<div className="header">
<div className="header-title">
<h1>your generator one-liner</h1>
<h1>FFS Generator</h1>
</div>
<div className="header-subtitle">
<h2>description of your generator</h2>
<h2>Write the name of the FFS member and a prompt of your choice. Available FFS members so far: "stephane"</h2>
</div>
</div>
</div>
<div className="badge-container grow">
<a
href="https://buildspace.so/builds/ai-avatar"
target="_blank"
rel="noreferrer"
>
<div className="badge">
<Image src={buildspaceLogo} alt="buildspace logo" />
<p>build with buildspace</p>
{/* Add prompt container here */}
<div className="prompt-container">
<input className="prompt-box" value={input} onChange={onChange} />
<div className="prompt-buttons">
{/* Tweak classNames to change classes */}
<a
className={
isGenerating ? 'generate-button loading' : 'generate-button'
}
onClick={generateAction}
>
{/* Tweak to show a loading indicator */}
<div className="generate">
{isGenerating ? (
<span className="loader"></span>
) : (
<p>Generate pictures</p>
)}
</div>
</a>
</div>
</div>
</div>
{/* Add output container */}
{img && (
<div className="output-content">
<Image src={img} width={512} height={512} alt={finalPrompt} />
{/* Add prompt here */}
<p>{finalPrompt}</p>
</div>
)}
</div>
</a>
</div>
</div>
<div className="badge-container grow">
<a
href="https://buildspace.so/builds/ai-avatar"
target="_blank"
rel="noreferrer"
>

</a>
</div>
</div>
);
};

Expand Down