Spaces:
Running
Running
| <html> | |
| <head> | |
| <title>React API Request Form</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> | |
| <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> | |
| <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> | |
| </head> | |
| <body> | |
| <div id="app"></div> | |
| <script type="text/babel"> | |
| function App() { | |
| const [apiEndpoint, setApiEndpoint] = React.useState('https://cvs65it9x6ibiiep.us-east-1.aws.endpoints.huggingface.cloud'); | |
| const [huggingFaceToken, setHuggingFaceToken] = React.useState(''); | |
| const [prompt, setPrompt] = React.useState(''); | |
| const [desiredOutputWidth, setDesiredOutputWidth] = React.useState('512'); | |
| const [text2ImgInferenceSteps, setText2ImgInferenceSteps] = React.useState('50'); | |
| const [img2imgInferenceSteps, setImg2imgInferenceSteps] = React.useState('50'); | |
| const [Text2ImgGuidanceScale, setText2ImgGuidanceScale] = React.useState('7.14'); | |
| const [img2ImgStrength, setImg2ImgStrength] = React.useState('0.6'); | |
| const [error, setError] = React.useState(''); | |
| const [loading, setLoading] = React.useState(false); | |
| const [imageSrc, setImageSrc] = React.useState(null); | |
| const [loadingText, setLoadingText] = React.useState("Loading"); | |
| const [previewMode, setPreviewMode] = React.useState("Half-Drop"); | |
| React.useEffect(() => { | |
| let interval; | |
| if (loading) { | |
| interval = setInterval(() => { | |
| setLoadingText(prev => prev.length < 10 ? prev + "." : "Loading"); | |
| }, 500); // Update every 500 milliseconds | |
| } | |
| return () => clearInterval(interval); | |
| }, [loading]); | |
| const sendRequest = (event) => { | |
| event.preventDefault(); | |
| setError(''); | |
| setLoading(true); | |
| fetch(apiEndpoint, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| Authorization: `Bearer ${huggingFaceToken}` | |
| }, | |
| body: JSON.stringify({ | |
| inputs: prompt, | |
| desired_output_width: desiredOutputWidth, | |
| text2img_inference_steps: text2ImgInferenceSteps, | |
| img2img_inference_steps: img2imgInferenceSteps, | |
| text2img_guidance_scale: Text2ImgGuidanceScale, | |
| img2img_strength: img2ImgStrength | |
| }) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.error) { | |
| setError(data.error) | |
| } else { | |
| setImageSrc('data:image/jpeg;base64,' + data.image); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| }).finally(() => { | |
| setLoading(false); | |
| }); | |
| }; | |
| return ( | |
| <div className="grid grid-cols-2 h-screen"> | |
| <form onSubmit={sendRequest} className="grid cols-1 max-w-6xl bg-gray-100 h-full p-10 overflow-scroll"> | |
| <img src="./pipeline.png"/> | |
| {error ? <div className="bg-red-200 py-2 px-3 rounded-md mb-4"> | |
| <strong className="text-bold">Error: </strong> | |
| {error} | |
| </div> : null} | |
| <label className="block text-sm font-medium text-gray-700 cols-1">Inference Endpoint URL:</label> | |
| <input | |
| type="text" | |
| value={apiEndpoint} | |
| onChange={(e) => setApiEndpoint(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700 cols-1">Hugging Face Token:</label> | |
| <p className="text-xs">Without "Bearer " prefix, e.g. | |
| "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":</p> | |
| <input | |
| type="text" | |
| value={huggingFaceToken} | |
| onChange={(e) => setHuggingFaceToken(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Prompt:</label> | |
| <input | |
| type="text" | |
| value={prompt} | |
| onChange={(e) => setPrompt(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Desired Output Width:</label> | |
| <p className="text-xs">The desired width of the final half-drop. Because of rounding during the | |
| process, | |
| the generator will try to get as close to this as possible, but may be off by a few pixels.</p> | |
| <input | |
| type="number" | |
| value={desiredOutputWidth} | |
| onChange={(e) => setDesiredOutputWidth(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Text2Img Inference Steps:</label> | |
| <p className="text-xs">The number of steps to take when generating the original image.</p> | |
| <input | |
| type="number" | |
| value={text2ImgInferenceSteps} | |
| onChange={(e) => setText2ImgInferenceSteps(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Img2Img Inference Steps:</label> | |
| <p className="text-xs">The number of steps to take when converting the extracted diamond into a | |
| tile.</p> | |
| <input | |
| type="number" | |
| value={img2imgInferenceSteps} | |
| onChange={(e) => setImg2imgInferenceSteps(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Text2Img Guidance Scale:</label> | |
| <p className="text-xs">Guidance scale for the original image generation. The pipeline default is | |
| 5.</p> | |
| <input | |
| type="number" | |
| value={Text2ImgGuidanceScale} | |
| onChange={(e) => setText2ImgGuidanceScale(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <label className="block text-sm font-medium text-gray-700">Img2Img Strength:</label> | |
| <p className="text-xs">Strength to use when converting the diamond into a repeatable tile, i.e. how | |
| much | |
| it can vary from the original generation. Pipeline default is</p> | |
| <input | |
| type="number" | |
| value={img2ImgStrength} | |
| onChange={(e) => setImg2ImgStrength(e.target.value)} | |
| className="mb-6 p-2 border border-gray-300 rounded" | |
| /> | |
| <input | |
| type="submit" | |
| value="Generate" | |
| className="mt-2 p-2 bg-blue-500 text-white rounded hover:bg-blue-700" | |
| /> | |
| </form> | |
| <div className="p-10 overflow-scroll"> | |
| {loading && <p className="mb-8">{loadingText}</p>} | |
| {imageSrc && ( | |
| <> | |
| <label htmlFor="pattern-dropdown" className="mr-2">Pattern:</label> | |
| <select | |
| id="pattern-dropdown" | |
| value={previewMode} | |
| onChange={(e) => setPreviewMode(e.target.value)} | |
| className="border border-gray-300 rounded mb-10" | |
| > | |
| <option value="Half Drop">Half-Drop</option> | |
| <option value="Half Drop Tiled">Half-Drop Tiled</option> | |
| </select> | |
| {previewMode !== "Half Drop Tiled" && <img src={imageSrc} alt="Response"/>} | |
| {previewMode === "Half Drop Tiled" && <div className="grid grid-cols-3 h-full"> | |
| <div className="flex items-center justify-center"> | |
| <img src={imageSrc} alt="Response"/> | |
| </div> | |
| <div className="flex flex-col items-center justify-center"> | |
| <img src={imageSrc} alt="Response"/> | |
| <img src={imageSrc} alt="Response"/> | |
| </div> | |
| <div className="flex items-center justify-center"> | |
| <img src={imageSrc} alt="Response"/> | |
| </div> | |
| </div>} | |
| </> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| ReactDOM.render(<App/>, document.getElementById('app')); | |
| </script> | |
| </body> | |
| </html> | |