File size: 4,658 Bytes
4e31db8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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()