AIWordleImage / app.py
jonathang's picture
app.py
4e31db8 verified
raw
history blame
4.66 kB
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 = '<html><body><div style="display: flex; flex-wrap: wrap;">'
# Template for an individual image
img_template = '<img src="{}" style="width: 30%; margin: 1%;" />'
# 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 += '</div></body></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()