import os import json import time import enum import uuid import base64 import requests import structlog import gradio as gr import random import functools logger = structlog.getLogger() replicate_api_key = os.environ.get('REPLICATE_KEY') # Everyone gets the same order of words random.seed(42) with open('five_letter_words.txt') as f: words = f.read().splitlines() random.shuffle(words) random.seed() class Image: @classmethod def create(cls, prompt, n=1, response_format="url", model="fofr", size="256x256"): logger.info(f'requesting Image with prompt={prompt}, n={n}, response_format={response_format}, model={model}, size={size}...') width, height = size.split('x') width, height = int(width), int(height) resp = requests.post( "https://api.replicate.com/v1/predictions", headers={"Content-Type": "application/json", "Authorization": f"Token {replicate_api_key}"}, json={"version": "a83d4056c205f4f62ae2d19f73b04881db59ce8b81154d314dd34ab7babaa0f1", "input": { "prompt": prompt, "width": width, "height": height, "num_images": n, }}, ) resp = resp.json() sleeps = 0 while resp.get("status", "fail").lower() not in {"fail", "succeeded"}: if sleeps >= 10: raise Exception('Error generating image', resp) logger.info(f"Sleeping 1...") time.sleep(1) sleeps += 1 resp = requests.get(f"https://api.replicate.com/v1/predictions/{resp['id']}", headers={"Content-Type": "application/json", "Authorization": f"Token {replicate_api_key}"}) resp = resp.json() logger.info('received Image...') url = resp['output'][0] # Get the MIME type of the image (e.g., 'image/jpeg', 'image/png') mime_type = f"image/{url.rsplit('.', 1)[-1]}" # Encode to base64 and format as a data URI return f"data:{mime_type};base64," + base64.b64encode(requests.get(url).content).decode() @functools.cache def get_image(word_num, guess_num): prompt = words[word_num] return Image.create(prompt) def display_images_base64(image_strings): # Start of the HTML string html = '
' # Template for an individual image img_template = '' # Loop through the list of image strings and append each to the HTML string for img_str in image_strings: html += img_template.format(img_str) # Close the div and body tags html += '
' return html def guess_word(word_num, guess, history=None): word_num = abs(word_num) % len(words) target = words[word_num] guess = guess.lower() feedback = [] if history is None: history = {} if word_num not in history: history[word_num] = { 'guess': [], 'image': [], } if len(guess) != len(target): feedback_str = "Guess must be {} letters long".format(len(target)) else: for i, char in enumerate(guess): if char == target[i]: feedback.append('🟩') # Green for correct position elif char in target: feedback.append('🟨') # Yellow for correct letter, wrong position else: feedback.append('⬛') # Black for incorrect letter feedback_str = "".join(feedback) # Update and return the history with the current guess feedback history[word_num]['guess'].append(f"{guess}: {feedback_str}") # Get and update the image history new_image = get_image(word_num, len(history[word_num]['guess']) + 1) history[word_num]['image'].append(new_image) return feedback_str, '\n'.join(history[word_num]['guess']), display_images_base64(history[word_num]['image']), history interface = gr.Interface(fn=guess_word, inputs=[ gr.Number(value=random.randint(0, 100_000), label='Word number (Cannot be empty)'), gr.Textbox(lines=1, label="Enter your guess (Cannot be empty)"), gr.State()], outputs=["text", gr.Textbox(label="Guess History", interactive=False, lines=10), gr.HTML(label="Guess Images"), gr.State()], title="Wordle with Gradio", description="A simple Wordle clone with guess history. Try to guess the word 'python'!", allow_flagging="never") interface.launch()