Spaces:
Sleeping
Sleeping
| """ | |
| 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) | |