egpivo commited on
Commit
b639e7c
·
verified ·
1 Parent(s): e7c2f0d

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +177 -218
app.py CHANGED
@@ -1,7 +1,7 @@
1
  #!/usr/bin/env python3
2
  """
3
- Hangman AI Demo for Hugging Face Spaces
4
- A Gradio interface for the hangman game demo.
5
  """
6
 
7
  import gradio as gr
@@ -16,9 +16,8 @@ sys.path.append('.')
16
 
17
  from hangman.hangman_core import ModelBackedHangman
18
 
19
-
20
- class HuggingFaceHangmanDemo:
21
- """Hangman demo adapted for Hugging Face Spaces"""
22
 
23
  def __init__(self):
24
  self.agent = None
@@ -26,6 +25,16 @@ class HuggingFaceHangmanDemo:
26
  self.demo_results = []
27
  self.demo_running = False
28
 
 
 
 
 
 
 
 
 
 
 
29
  # Initialize the agent
30
  self.init_agent()
31
 
@@ -35,8 +44,8 @@ class HuggingFaceHangmanDemo:
35
  # Try to load from the data directory
36
  dictionary_path = "data/words_250000_train.txt"
37
  if not Path(dictionary_path).exists():
38
- # Fallback to a simple word list
39
  dictionary_path = None
 
40
 
41
  self.agent = ModelBackedHangman(dictionary_path=dictionary_path)
42
  print("Hangman agent initialized successfully")
@@ -44,259 +53,209 @@ class HuggingFaceHangmanDemo:
44
  print(f"Error initializing agent: {e}")
45
  self.agent = None
46
 
47
- def run_single_game(self, word_length=None, max_tries=10):
48
- """Run a single hangman game"""
 
 
 
 
 
 
49
  if not self.agent:
50
- return "Error: Agent not initialized", []
51
 
52
- # Simple word list for demo
53
- word_list = [
54
- "python", "hangman", "computer", "algorithm", "machine",
55
- "learning", "artificial", "intelligence", "neural", "network",
56
- "transformer", "attention", "embedding", "optimization",
57
- "gradient", "descent", "backpropagation", "activation",
58
- "function", "regularization", "overfitting", "validation",
59
- "training", "testing", "dataset", "feature", "prediction",
60
- "classification", "regression", "clustering", "dimensionality",
61
- "reduction", "principal", "component", "analysis", "support",
62
- "vector", "machine", "random", "forest", "decision", "tree",
63
- "naive", "bayes", "kmeans", "hierarchical", "clustering",
64
- "feature", "transformer", "attention", "embedding", "optimization"
65
- ]
66
 
67
- # Filter by word length if specified
68
- if word_length and word_length != "Any":
69
- word_list = [w for w in word_list if len(w) == int(word_length)]
70
 
71
- if not word_list:
72
- return "No words available for the specified length", []
 
 
 
 
 
73
 
74
- import random
75
- word = random.choice(word_list).lower()
76
- pattern = "_" * len(word)
77
- guessed_letters = []
78
- tries_remaining = max_tries
79
- game_log = []
80
 
81
- # Reset agent state
82
- self.agent.guessed_letters = []
83
 
84
- turn = 0
85
- while tries_remaining > 0 and "_" in pattern:
86
- turn += 1
87
-
88
- # Get agent's guess
89
- guess = self.agent.guess(
90
- pattern,
91
- debug=False,
92
- tries_remaining=tries_remaining
93
- )
94
-
95
- # Update pattern
96
- if guess in word:
97
- new_pattern = ""
98
- for i, char in enumerate(word):
99
- if char == guess or char in guessed_letters + [guess]:
100
- new_pattern += char
101
- else:
102
- new_pattern += "_"
103
- pattern = new_pattern
104
- feedback = f"Correct! '{guess}' is in the word."
105
  else:
106
- tries_remaining -= 1
107
- feedback = f"Wrong! '{guess}' is not in the word."
108
-
109
- guessed_letters.append(guess)
110
 
111
- # Update agent's guessed letters to keep them in sync
112
- self.agent.guessed_letters = guessed_letters.copy()
113
 
114
- # Log the turn
115
- game_log.append(f"🎮 Turn {turn}: Guessed '{guess}' - {feedback}")
116
- game_log.append(f"🔤 Pattern: {pattern}")
117
- game_log.append(f"⏳ Tries remaining: {tries_remaining}")
118
- game_log.append(f"🔤 Guessed letters: {', '.join(guessed_letters)}")
119
- game_log.append("---")
120
-
121
- # Game result
122
- if "_" not in pattern:
123
- result = f"🎉 Agent won! The word was '{word}' in {turn} turns."
124
- else:
125
- result = f"💀 Agent lost! The word was '{word}'."
126
-
127
- return result, game_log
128
-
129
- def run_demo(self, num_trials, word_length, max_tries):
130
- """Run multiple games and return results"""
131
- if not self.agent:
132
- return "Error: Agent not initialized", []
133
 
134
- results = []
135
- game_logs = []
 
 
136
 
137
- for trial in range(num_trials):
138
- result, game_log = self.run_single_game(word_length, max_tries)
139
- results.append(f"Game {trial + 1}: {result}")
140
- game_logs.extend([f"=== GAME {trial + 1} ==="] + game_log)
141
 
142
- # Calculate statistics
143
- wins = sum(1 for r in results if "won" in r.lower())
144
- win_rate = (wins / num_trials) * 100 if num_trials > 0 else 0
 
 
145
 
146
- summary = f"""
147
- DEMO SUMMARY
148
- ============
149
- Games played: {num_trials}
150
- Wins: {wins}
151
- Losses: {num_trials - wins}
152
- Win rate: {win_rate:.1f}%
153
- """.strip()
154
 
155
- return summary, game_logs
156
-
157
-
158
- # Initialize the demo
159
- demo_app = HuggingFaceHangmanDemo()
160
-
161
-
162
- def run_hangman_demo(num_trials, word_length, max_tries):
163
- """Gradio interface function"""
164
- try:
165
- summary, game_logs = demo_app.run_demo(num_trials, word_length, max_tries)
166
- return summary, "\n".join(game_logs)
167
- except Exception as e:
168
- return f"Error running demo: {str(e)}", ""
169
-
170
-
171
- def run_single_game(word_length, max_tries):
172
- """Run a single game"""
173
- try:
174
- result, game_log = demo_app.run_single_game(word_length, max_tries)
175
- return result, "\n".join(game_log)
176
- except Exception as e:
177
- return f"Error running game: {str(e)}", ""
178
 
 
 
179
 
180
  # Create Gradio interface
181
- with gr.Blocks(title="Hangman AI Demo", theme=gr.themes.Soft()) as interface:
182
- gr.Markdown("""
183
- # Hangman AI Demo
184
-
185
- Watch an AI agent play hangman using a trained transformer model. The agent uses intelligent strategies
186
- to guess letters and solve the word puzzle.
187
- """)
188
 
189
  with gr.Tab("Single Game"):
190
- gr.Markdown("### Play a single hangman game")
191
-
192
  with gr.Row():
193
- single_word_length = gr.Dropdown(
194
- choices=["Any", "4", "5", "6", "7", "8", "9", "10"],
195
- value="Any",
196
- label="Word Length"
197
- )
198
- single_max_tries = gr.Number(
199
- value=10,
200
- minimum=1,
201
- maximum=26,
202
- label="Max Wrong Guesses"
203
- )
204
-
205
- single_play_btn = gr.Button("Play Single Game", variant="primary")
206
-
207
- single_result = gr.Textbox(
208
- label="Game Result",
209
- lines=2,
210
- interactive=False
211
- )
212
- single_log = gr.Textbox(
213
- label="Game Log",
214
- lines=15,
215
- interactive=False
216
- )
217
 
218
- single_play_btn.click(
219
- fn=run_single_game,
220
- inputs=[single_word_length, single_max_tries],
221
- outputs=[single_result, single_log]
222
  )
223
 
224
  with gr.Tab("Multi-Game Demo"):
225
- gr.Markdown("### Run multiple games and see statistics")
226
-
227
  with gr.Row():
228
- demo_trials = gr.Number(
229
- value=5,
230
- minimum=1,
231
- maximum=20,
232
- label="Number of Games"
233
- )
234
- demo_word_length = gr.Dropdown(
235
- choices=["Any", "4", "5", "6", "7", "8", "9", "10"],
236
- value="Any",
237
- label="Word Length"
238
- )
239
- demo_max_tries = gr.Number(
240
- value=10,
241
- minimum=1,
242
- maximum=26,
243
- label="Max Wrong Guesses"
244
- )
245
-
246
- demo_play_btn = gr.Button("Run Demo", variant="primary")
 
247
 
248
- demo_summary = gr.Textbox(
249
- label="Demo Summary",
250
- lines=8,
251
- interactive=False
252
- )
253
- demo_log = gr.Textbox(
254
- label="Game Logs",
255
- lines=20,
256
- interactive=False
257
  )
258
 
259
- demo_play_btn.click(
260
- fn=run_hangman_demo,
261
- inputs=[demo_trials, demo_word_length, demo_max_tries],
262
- outputs=[demo_summary, demo_log]
263
  )
264
 
265
- with gr.Tab("About"):
 
266
  gr.Markdown("""
267
- ## About This Demo
 
 
 
268
 
269
- This hangman AI demo showcases an intelligent agent that plays hangman using:
 
 
 
 
 
 
 
270
 
271
- - **Transformer Model**: A character-level transformer trained on hangman games
272
- - **Dictionary Filtering**: Filters possible words based on current pattern
273
- - **Information Theory**: Uses information gain to make optimal guesses
274
- - **Baseline Strategy**: Falls back to frequency-based guessing when needed
 
 
 
 
 
 
275
 
276
- ### How It Works
277
 
278
- 1. **Pattern Analysis**: The agent analyzes the current word pattern
279
- 2. **Candidate Filtering**: Filters possible words from the dictionary
280
- 3. **Information Gain**: Calculates which letter provides the most information
281
- 4. **Smart Guessing**: Makes the most informative guess based on multiple strategies
282
 
283
- ### Features
284
 
285
- - Configurable game parameters (word length, max tries)
286
- - Real-time game logging
287
- - Win/loss statistics
288
- - Multiple game modes (single game vs. demo)
 
289
 
290
- ### Technical Details
291
 
292
- The agent combines multiple strategies:
293
- - Length priors for initial guesses
294
- - Pattern matching and dictionary filtering
295
- - Information gain calculations
296
- - Frequency analysis of remaining candidates
297
- - Context-aware letter selection
298
  """)
299
 
300
-
301
  if __name__ == "__main__":
302
  interface.launch()
 
1
  #!/usr/bin/env python3
2
  """
3
+ Enhanced Hangman AI Demo for Hugging Face Spaces
4
+ Now includes simulator playground and performance monitoring
5
  """
6
 
7
  import gradio as gr
 
16
 
17
  from hangman.hangman_core import ModelBackedHangman
18
 
19
+ class EnhancedHangmanDemo:
20
+ """Enhanced hangman demo with performance monitoring"""
 
21
 
22
  def __init__(self):
23
  self.agent = None
 
25
  self.demo_results = []
26
  self.demo_running = False
27
 
28
+ # Performance tracking
29
+ self.performance_history = []
30
+ self.baseline_performance = {
31
+ 'cand': 0.866,
32
+ 'igx': 0.127,
33
+ 'pos': 0.160,
34
+ 'len': 0.112,
35
+ 'ig': 0.100
36
+ }
37
+
38
  # Initialize the agent
39
  self.init_agent()
40
 
 
44
  # Try to load from the data directory
45
  dictionary_path = "data/words_250000_train.txt"
46
  if not Path(dictionary_path).exists():
 
47
  dictionary_path = None
48
+ print("Warning: Dictionary file not found, using fallback word list")
49
 
50
  self.agent = ModelBackedHangman(dictionary_path=dictionary_path)
51
  print("Hangman agent initialized successfully")
 
53
  print(f"Error initializing agent: {e}")
54
  self.agent = None
55
 
56
+ def get_word_list(self):
57
+ """Get available words for the demo"""
58
+ if self.agent and hasattr(self.agent, 'words'):
59
+ return self.agent.words[:100] # Return first 100 words
60
+ return ["example", "hangman", "python", "gradio", "huggingface"]
61
+
62
+ def play_single_game(self, word_length, max_tries):
63
+ """Play a single hangman game"""
64
  if not self.agent:
65
+ return "Error: Agent not initialized", ""
66
 
67
+ # Select a word
68
+ if word_length == "Any":
69
+ word = self.agent.select_word()
70
+ else:
71
+ word = self.agent.select_word(length=int(word_length))
72
+
73
+ if not word:
74
+ return "Error: No word available", ""
 
 
 
 
 
 
75
 
76
+ # Play the game
77
+ result = self.agent.play_game(word, max_tries)
 
78
 
79
+ # Format the result
80
+ game_log = f"Word: {word}\n"
81
+ game_log += f"Length: {len(word)}\n"
82
+ game_log += f"Max Tries: {max_tries}\n"
83
+ game_log += f"Result: {'WON' if result['won'] else 'LOST'}\n"
84
+ game_log += f"Turns: {result['turns']}\n"
85
+ game_log += f"Guesses: {', '.join(result['guesses'])}"
86
 
87
+ return game_log, result
88
+
89
+ def run_demo(self, num_games, word_length, max_tries):
90
+ """Run multiple games demo"""
91
+ if not self.agent:
92
+ return "Error: Agent not initialized", ""
93
 
94
+ self.demo_running = True
95
+ self.demo_results = []
96
 
97
+ # Run games
98
+ for i in range(num_games):
99
+ if not self.demo_running:
100
+ break
101
+
102
+ # Select word
103
+ if word_length == "Any":
104
+ word = self.agent.select_word()
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  else:
106
+ word = self.agent.select_word(length=int(word_length))
 
 
 
107
 
108
+ if not word:
109
+ continue
110
 
111
+ # Play game
112
+ result = self.agent.play_game(word, max_tries)
113
+ self.demo_results.append(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
+ # Calculate statistics
116
+ wins = sum(1 for r in self.demo_results if r['won'])
117
+ total = len(self.demo_results)
118
+ win_rate = wins / total if total > 0 else 0
119
 
120
+ # Format results
121
+ summary = f"Demo Results ({total} games):\n"
122
+ summary += f"Win Rate: {win_rate:.3f} ({wins}/{total})\n"
123
+ summary += f"Average Turns: {sum(r['turns'] for r in self.demo_results) / total:.1f}\n"
124
 
125
+ # Compare with baselines
126
+ summary += "\nBaseline Comparison:\n"
127
+ for strategy, rate in self.baseline_performance.items():
128
+ diff = win_rate - rate
129
+ summary += f"{strategy.upper()}: {rate:.3f} ({diff:+.3f})\n"
130
 
131
+ # Game log
132
+ game_log = "\n".join([
133
+ f"Game {i+1}: {r['word']} - {'WON' if r['won'] else 'LOST'} ({r['turns']} turns)"
134
+ for i, r in enumerate(self.demo_results)
135
+ ])
 
 
 
136
 
137
+ return summary, game_log
138
+
139
+ def stop_demo(self):
140
+ """Stop the running demo"""
141
+ self.demo_running = False
142
+ return "Demo stopped"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
+ # Initialize demo
145
+ demo = EnhancedHangmanDemo()
146
 
147
  # Create Gradio interface
148
+ with gr.Blocks(title="Enhanced Hangman AI Demo") as interface:
149
+ gr.Markdown("# 🤖 Enhanced Hangman AI Demo")
150
+ gr.Markdown("Now with performance monitoring and baseline comparison!")
 
 
 
 
151
 
152
  with gr.Tab("Single Game"):
 
 
153
  with gr.Row():
154
+ with gr.Column():
155
+ word_length = gr.Dropdown(
156
+ choices=["Any", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
157
+ value="Any",
158
+ label="Word Length"
159
+ )
160
+ max_tries = gr.Slider(
161
+ minimum=3, maximum=15, value=6, step=1,
162
+ label="Max Wrong Guesses"
163
+ )
164
+ play_btn = gr.Button("Play Single Game", variant="primary")
165
+
166
+ with gr.Column():
167
+ game_output = gr.Textbox(label="Game Result", lines=10)
 
 
 
 
 
 
 
 
 
 
168
 
169
+ play_btn.click(
170
+ demo.play_single_game,
171
+ inputs=[word_length, max_tries],
172
+ outputs=[game_output, gr.State()]
173
  )
174
 
175
  with gr.Tab("Multi-Game Demo"):
 
 
176
  with gr.Row():
177
+ with gr.Column():
178
+ num_games = gr.Slider(
179
+ minimum=1, maximum=50, value=10, step=1,
180
+ label="Number of Games"
181
+ )
182
+ demo_word_length = gr.Dropdown(
183
+ choices=["Any", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
184
+ value="Any",
185
+ label="Word Length"
186
+ )
187
+ demo_max_tries = gr.Slider(
188
+ minimum=3, maximum=15, value=6, step=1,
189
+ label="Max Wrong Guesses"
190
+ )
191
+ demo_btn = gr.Button("Run Demo", variant="primary")
192
+ stop_btn = gr.Button("Stop Demo", variant="stop")
193
+
194
+ with gr.Column():
195
+ demo_summary = gr.Textbox(label="Demo Summary", lines=8)
196
+ demo_log = gr.Textbox(label="Game Log", lines=15)
197
 
198
+ demo_btn.click(
199
+ demo.run_demo,
200
+ inputs=[num_games, demo_word_length, demo_max_tries],
201
+ outputs=[demo_summary, demo_log]
 
 
 
 
 
202
  )
203
 
204
+ stop_btn.click(
205
+ demo.stop_demo,
206
+ outputs=[demo_summary]
 
207
  )
208
 
209
+ with gr.Tab("Performance Analysis"):
210
+ gr.Markdown("## 📊 Performance Comparison")
211
  gr.Markdown("""
212
+ ### Current Model Performance
213
+ - **Win Rate**: 1.2% (needs improvement!)
214
+ - **Best Baseline**: CAND strategy (86.6%)
215
+ - **Performance Gap**: 85.4% behind optimal
216
 
217
+ ### Baseline Strategies
218
+ | Strategy | Win Rate | Description |
219
+ |----------|----------|-------------|
220
+ | CAND | 86.6% | Candidate filtering (optimal) |
221
+ | IGX | 12.7% | Information gain exact |
222
+ | POS | 16.0% | Positional priors |
223
+ | LEN | 11.2% | Length-based priors |
224
+ | IG | 10.0% | Information gain |
225
 
226
+ ### Next Steps
227
+ 1. **Retrain with CAND Teacher**: Use 86.6% win rate strategy
228
+ 2. **Enhanced Architecture**: Add candidate priors
229
+ 3. **More Training Data**: Increase seeding episodes
230
+ 4. **Monitor Progress**: Use simulator playground
231
+ """)
232
+
233
+ with gr.Tab("About"):
234
+ gr.Markdown("""
235
+ ## About This Enhanced Demo
236
 
237
+ This hangman AI demo now includes:
238
 
239
+ - **Performance Monitoring**: Real-time win rate tracking
240
+ - **Baseline Comparison**: Compare with optimal strategies
241
+ - **Simulator Playground**: Advanced evaluation tools
242
+ - **Training Monitor**: Track model improvements
243
 
244
+ ### Technical Details
245
 
246
+ The agent uses a **Dueling Q-Network** with:
247
+ - Transformer encoder (2 layers, 4 heads)
248
+ - 128 model dimension
249
+ - Behavior cloning training
250
+ - Multiple heuristic strategies
251
 
252
+ ### Files Included
253
 
254
+ - `simulator_playground.py`: Complete evaluation tool
255
+ - `training_monitor.py`: Training progress tracking
256
+ - `runs/bc_sbx_tiny/bc_dueling_qnet.pt`: Current model
257
+ - `simulator_results/`: Performance analysis
 
 
258
  """)
259
 
 
260
  if __name__ == "__main__":
261
  interface.launch()