""" 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("""

🧩 Context Window Tetris

Stack tokens before you run out of context!

""") 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)