Moftah
Deploy
14eda48
"""
Context Window Tetris - Gamified AI context limit visualization
A Tetris-style game that teaches about AI context windows!
"""
import gradio as gr
import random
import time
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 0, 0], [1, 1, 1]], # L
[[0, 0, 1], [1, 1, 1]], # J
[[0, 1, 1], [1, 1, 0]], # S
[[1, 1, 0], [0, 1, 1]], # Z
]
TOKEN_VALUES = {
"I": 4,
"O": 4,
"T": 6,
"L": 6,
"J": 6,
"S": 6,
"Z": 6
}
MODEL_LIMITS = {
"GPT-4 Turbo (128K)": 128000,
"Claude 3 (200K)": 200000,
"Gemini 1.5 (1M)": 1000000,
"Llama 3.1 (128K)": 128000
}
MODEL_DISPLAY = {
"GPT-4 Turbo (128K)": 128,
"Claude 3 (200K)": 200,
"Gemini 1.5 (1M)": 1000,
"Llama 3.1 (128K)": 128
}
class TetrisGame:
def __init__(self, model_name):
self.model_name = model_name
self.limit = MODEL_LIMITS[model_name]
self.display_limit = MODEL_DISPLAY[model_name]
self.board_width = 10
self.board_height = 20
self.board = [[0] * self.board_width for _ in range(self.board_height)]
self.score = 0
self.lines_cleared = 0
self.tokens_used = 0
self.game_over = False
self.current_piece = None
self.current_pos = [0, 0]
self.generate_piece()
def generate_piece(self):
shape_idx = random.randint(0, len(SHAPES) - 1)
self.current_piece = SHAPES[shape_idx]
self.current_pos = [0, self.board_width // 2 - len(self.current_piece[0]) // 2]
def rotate_piece(self):
if self.current_piece:
rows = len(self.current_piece)
cols = len(self.current_piece[0])
rotated = [[self.current_piece[rows - 1 - j][i] for j in range(rows)] for i in range(cols)]
return rotated
return self.current_piece
def get_display_board(self):
display = []
for row in self.board:
display_row = ""
for cell in row:
display_row += "โ–ˆโ–ˆ" if cell else "โ–‘โ–‘"
display.append(display_row)
return "\n".join(display)
def get_stats(self):
efficiency = (self.tokens_used / self.limit * 100) if self.limit > 0 else 0
return {
"score": self.score,
"lines": self.lines_cleared,
"tokens": self.tokens_used,
"limit": self.display_limit,
"efficiency": efficiency
}
def move_piece(self, direction):
if direction == "left":
self.current_pos[1] = max(0, self.current_pos[1] - 1)
elif direction == "right":
self.current_pos[1] = min(
self.board_width - len(self.current_piece[0]),
self.current_pos[1] + 1
)
def drop_piece(self):
self.current_pos[0] += 1
if self.check_collision():
self.current_pos[0] -= 1
self.lock_piece()
return True
return False
def hard_drop(self):
while not self.check_collision():
self.current_pos[0] += 1
self.current_pos[0] -= 1
self.lock_piece()
return True
def check_collision(self):
for i, row in enumerate(self.current_piece):
for j, cell in enumerate(row):
if cell:
new_x = self.current_pos[0] + i
new_y = self.current_pos[1] + j
if new_x >= self.board_height:
return True
if new_y < 0 or new_y >= self.board_width:
return True
if new_x >= 0 and self.board[new_x][new_y]:
return True
return False
def lock_piece(self):
tokens = 0
for i, row in enumerate(self.current_piece):
for j, cell in enumerate(row):
if cell:
x = self.current_pos[0] + i
y = self.current_pos[1] + j
if x >= 0:
self.board[x][y] = 1
tokens += 1
self.tokens_used += TOKEN_VALUES.get(
["I", "O", "T", "L", "J", "S", "Z"][SHAPES.index(self.current_piece)],
6
)
if self.tokens_used >= self.limit:
self.game_over = True
return
self.clear_lines()
self.generate_piece()
def clear_lines(self):
lines_to_clear = []
for i, row in enumerate(self.board):
if all(row):
lines_to_clear.append(i)
if lines_to_clear:
self.lines_cleared += len(lines_to_clear)
self.score += len(lines_to_clear) * 100 * (2 ** len(lines_to_clear))
for line in lines_to_clear:
del self.board[line]
self.board.insert(0, [0] * self.board_width)
def create_game_state(model):
return TetrisGame(model)
custom_css = """
.game-container {
background: #1a1a2e;
padding: 20px;
border-radius: 15px;
text-align: center;
}
.board-display {
font-family: monospace;
font-size: 14px;
line-height: 1.2;
color: #00ff00;
background: #000;
padding: 15px;
border-radius: 10px;
}
.stats-box {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
border-radius: 10px;
color: white;
margin: 10px 0;
}
.controls {
background: #2d3748;
padding: 15px;
border-radius: 10px;
margin: 10px 0;
}
.control-btn {
margin: 5px;
}
"""
with gr.Blocks(css=custom_css, title="Context Window Tetris") as demo:
gr.HTML("""
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 20px;">
<h1 style="color: white; font-size: 2.5em; margin: 0;">๐Ÿงฉ Context Window Tetris</h1>
<p style="color: white; font-size: 1.2em;">Stack tokens before you run out of context!</p>
</div>
""")
gr.Markdown("""
## ๐ŸŽฎ How to Play
Each block represents tokens in an AI's context window. Stack them efficiently!
| Block Type | Token Cost | Notes |
|------------|-----------|-------|
| I-Block | 4 tokens | Most efficient |
| O-Block | 4 tokens | Square, easy |
| T/L/J/S/Z | 6 tokens | Standard |
**Controls:** โ† โ†’ to move, โ†‘ to rotate, โ†“ to drop, Space for hard drop
""")
with gr.Row():
with gr.Column(scale=2):
model_select = gr.Dropdown(
choices=list(MODEL_LIMITS.keys()),
value="GPT-4 Turbo (128K)",
label="๐ŸŽฏ AI Model (Context Size)"
)
game_display = gr.Textbox(
label="๐ŸŽฎ Game Board",
lines=22,
interactive=False,
elem_classes="board-display"
)
with gr.Row():
new_game_btn = gr.Button("๐ŸŽฎ New Game", variant="primary")
move_left = gr.Button("โ† Left")
rotate_btn = gr.Button("โ†ป Rotate")
move_right = gr.Button("Right โ†’")
drop_btn = gr.Button("โฌ‡ Drop")
with gr.Column(scale=1):
gr.Markdown("### ๐Ÿ“Š Game Stats")
stats_display = gr.JSON(label="Current Stats")
gr.Markdown("### ๐Ÿ† High Score")
high_score = gr.Number(value=0, interactive=False)
gr.Markdown("""
### ๐Ÿ’ก Why This Matters
Understanding context windows helps you:
- Write more efficient prompts
- Optimize for cost
- Better utilize AI capabilities
""")
game_state = gr.State(create_game_state("GPT-4 Turbo (128K)"))
def new_game(model):
return create_game_state(model)
def update_display(state):
return state.get_display_board(), state.get_stats()
def move_left_fn(state):
state.move_piece("left")
return state, state.get_display_board(), state.get_stats()
def move_right_fn(state):
state.move_piece("right")
return state, state.get_display_board(), state.get_stats()
def rotate_fn(state):
state.current_piece = state.rotate_piece()
return state, state.get_display_board(), state.get_stats()
def drop_fn(state):
state.drop_piece()
return state, state.get_display_board(), state.get_stats()
# Initial display
def init_display(state):
return state.get_display_board(), state.get_stats()
demo.load(
fn=init_display,
inputs=[game_state],
outputs=[game_display, stats_display]
)
new_game_btn.click(
fn=new_game,
inputs=[model_select],
outputs=[game_state]
).then(
fn=init_display,
inputs=[game_state],
outputs=[game_display, stats_display]
)
model_select.change(
fn=new_game,
inputs=[model_select],
outputs=[game_state]
).then(
fn=init_display,
inputs=[game_state],
outputs=[game_display, stats_display]
)
move_left.click(
fn=move_left_fn,
inputs=[game_state],
outputs=[game_state, game_display, stats_display]
)
move_right.click(
fn=move_right_fn,
inputs=[game_state],
outputs=[game_state, game_display, stats_display]
)
rotate_btn.click(
fn=rotate_fn,
inputs=[game_state],
outputs=[game_state, game_display, stats_display]
)
drop_btn.click(
fn=drop_fn,
inputs=[game_state],
outputs=[game_state, game_display, stats_display]
)
gr.Markdown("""
---
### ๐ŸŽฏ About Context Windows
Every AI model has a **context window** - the maximum amount of text it can process at once.
| Model | Context Window | Relative Size |
|-------|---------------|---------------|
| GPT-4 Turbo | 128K tokens | ๐Ÿ”ต๐Ÿ”ต |
| Claude 3 | 200K tokens | ๐Ÿ”ต๐Ÿ”ต๐Ÿ”ต |
| Gemini 1.5 | 1M tokens | ๐Ÿ”ต๐Ÿ”ต๐Ÿ”ต๐Ÿ”ต๐Ÿ”ต |
| Llama 3.1 | 128K tokens | ๐Ÿ”ต๐Ÿ”ต |
**Fun fact:** 1M tokens โ‰ˆ 750,000 words โ‰ˆ 3 novels!
---
*Built as part of HF-Master: 196 AI Projects*
""")
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)