Jonathan Bejarano commited on
Commit
daf7e93
·
1 Parent(s): 160f0de

refactoring to add support for US States as well

Browse files
Files changed (5) hide show
  1. .gitignore +5 -1
  2. app.py +133 -246
  3. countries.json +124 -0
  4. rag.py +48 -0
  5. us_states.json +52 -0
.gitignore CHANGED
@@ -1,2 +1,6 @@
1
  .env
2
- *.DS_Store
 
 
 
 
 
1
  .env
2
+ *.DS_Store
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+ .pytest_cache/
app.py CHANGED
@@ -1,12 +1,13 @@
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
3
- import re
4
  import random
5
  import os
6
- import requests
7
- from bs4 import BeautifulSoup
8
  from dotenv import load_dotenv
9
 
 
 
10
  # Load environment variables from .env file if it exists
11
  load_dotenv()
12
 
@@ -17,209 +18,84 @@ LOCAL_MODE = bool(BASE_URL and LOCAL_TOKEN)
17
  MODEL_NAME = os.getenv('MODEL_NAME', 'openai/gpt-oss-20b')
18
 
19
 
20
- # List of countries for the game with URLs
21
- COUNTRIES = [
22
- {"name": "Algeria", "url": "/algeria-facts-for-kids.html"},
23
- {"name": "Angola", "url": "/facts-about-angola.html"},
24
- {"name": "Argentina", "url": "/argentina-facts.html"},
25
- {"name": "Australia", "url": "/australia-facts.html"},
26
- {"name": "Austria", "url": "/austria-facts.html"},
27
- {"name": "Bahamas", "url": "/facts-about-the-bahamas.html"},
28
- {"name": "Barbados", "url": "/barbados-facts.html"},
29
- {"name": "Belgium", "url": "/belgium-facts.html"},
30
- {"name": "Belize", "url": "/facts-about-belize.html"},
31
- {"name": "Bhutan", "url": "/bhutan-facts.html"},
32
- {"name": "Bolivia", "url": "/bolivia-facts.html"},
33
- {"name": "Botswana", "url": "/facts-about-botswana.html"},
34
- {"name": "Brazil", "url": "/brazil-facts.html"},
35
- {"name": "Bulgaria", "url": "/facts-about-bulgaria.html"},
36
- {"name": "Canada", "url": "/canada-facts-for-kids.html"},
37
- {"name": "Chile", "url": "/chile-facts.html"},
38
- {"name": "China", "url": "/china-facts.html"},
39
- {"name": "Colombia", "url": "/colombia-facts.html"},
40
- {"name": "Comoros", "url": "/comoros-facts.html"},
41
- {"name": "Costa Rica", "url": "/costa-rica-facts.html"},
42
- {"name": "Croatia", "url": "/croatia-facts.html"},
43
- {"name": "Cuba", "url": "/cuba-facts.html"},
44
- {"name": "Cyprus", "url": "/cyprus-facts-for-kids.html"},
45
- {"name": "Denmark", "url": "/denmark-facts.html"},
46
- {"name": "Dominican Republic", "url": "/dominican-republic-facts.html"},
47
- {"name": "Ecuador", "url": "/ecuador-facts.html"},
48
- {"name": "Egypt", "url": "/egypt-facts.html"},
49
- {"name": "Estonia", "url": "/estonia-facts-for-kids.html"},
50
- {"name": "Eswatini", "url": "/eswatini-facts.html"},
51
- {"name": "Ethiopia", "url": "/ethiopia-facts.html"},
52
- {"name": "Fiji", "url": "/facts-about-fiji.html"},
53
- {"name": "Finland", "url": "/finland-facts.html"},
54
- {"name": "France", "url": "/france-facts.html"},
55
- {"name": "Georgia", "url": "/georgia-facts.html"},
56
- {"name": "Germany", "url": "/germany-facts.html"},
57
- {"name": "Ghana", "url": "/ghana-facts.html"},
58
- {"name": "Greece", "url": "/greece-facts.html"},
59
- {"name": "Greenland", "url": "/facts-about-greenland.html"},
60
- {"name": "Guatemala", "url": "/guatemala-facts.html"},
61
- {"name": "Guyana", "url": "/guyana-facts.html"},
62
- {"name": "Honduras", "url": "/honduras-facts-for-kids.html"},
63
- {"name": "Hong Kong", "url": "/facts-about-hong-kong.html"},
64
- {"name": "Hungary", "url": "/hungary-facts.html"},
65
- {"name": "Iceland", "url": "/iceland-facts.html"},
66
- {"name": "India", "url": "/india-for-kids.html"},
67
- {"name": "Indonesia", "url": "/indonesia-facts.html"},
68
- {"name": "Iran", "url": "/iran-facts-for-kids.html"},
69
- {"name": "Ireland", "url": "/ireland-for-kids.html"},
70
- {"name": "Israel", "url": "/israel-facts.html"},
71
- {"name": "Italy", "url": "/italy-facts.html"},
72
- {"name": "Jamaica", "url": "/jamaica-facts.html"},
73
- {"name": "Japan", "url": "/japan-facts.html"},
74
- {"name": "Kenya", "url": "/facts-about-kenya.html"},
75
- {"name": "Kiribati", "url": "/facts-about-kiribati.html"},
76
- {"name": "Latvia", "url": "/latvia-facts-for-kids.html"},
77
- {"name": "Lesotho", "url": "/lesotho-facts.html"},
78
- {"name": "Liberia", "url": "/facts-about-liberia.html"},
79
- {"name": "Lithuania", "url": "/lithuania-facts-for-kids.html"},
80
- {"name": "Luxembourg", "url": "/luxembourg-facts.html"},
81
- {"name": "Macao", "url": "/facts-about-macao.html"},
82
- {"name": "Madagascar", "url": "/facts-about-madagascar.html"},
83
- {"name": "Malaysia", "url": "/malaysia-facts.html"},
84
- {"name": "Maldives", "url": "/maldives-facts.html"},
85
- {"name": "Malta", "url": "/malta-for-kids.html"},
86
- {"name": "Mauritius", "url": "/mauritius-facts.html"},
87
- {"name": "Mexico", "url": "/mexico-facts.html"},
88
- {"name": "Micronesia", "url": "/facts-about-micronesia.html"},
89
- {"name": "Moldova", "url": "/moldova-facts-for-kids.html"},
90
- {"name": "Monaco", "url": "/facts-about-monaco.html"},
91
- {"name": "Morocco", "url": "/morocco-facts.html"},
92
- {"name": "Mozambique", "url": "/mozambique-facts.html"},
93
- {"name": "Myanmar", "url": "/myanmar-facts.html"},
94
- {"name": "Namibia", "url": "/namibia-facts.html"},
95
- {"name": "Nauru", "url": "/facts-about-nauru.html"},
96
- {"name": "Nepal", "url": "/nepal-facts.html"},
97
- {"name": "Netherlands", "url": "/facts-about-the-netherlands.html"},
98
- {"name": "New Zealand", "url": "/new-zealand-facts.html"},
99
- {"name": "Nicaragua", "url": "/nicaragua-facts.html"},
100
- {"name": "Nigeria", "url": "/nigeria-facts.html"},
101
- {"name": "Norway", "url": "/norway-facts.html"},
102
- {"name": "Pakistan", "url": "/pakistan-facts.html"},
103
- {"name": "Panama", "url": "/panama-facts.html"},
104
- {"name": "Papua New Guinea", "url": "/papua-new-guinea.html"},
105
- {"name": "Peru", "url": "/peru-facts.html"},
106
- {"name": "Philippines", "url": "/philippines-facts.html"},
107
- {"name": "Poland", "url": "/poland-facts.html"},
108
- {"name": "Portugal", "url": "/portugal-facts.html"},
109
- {"name": "Puerto Rico", "url": "/facts-about-puerto-rico.html"},
110
- {"name": "Qatar", "url": "/qatar-facts.html"},
111
- {"name": "Romania", "url": "/romania-facts-for-kids.html"},
112
- {"name": "Russia", "url": "/russia-facts.html"},
113
- {"name": "Samoa", "url": "/facts-about-samoa.html"},
114
- {"name": "San Marino", "url": "/facts-about-san-marino.html"},
115
- {"name": "Serbia", "url": "/facts-about-serbia.html"},
116
- {"name": "Seychelles", "url": "/seychelles-facts.html"},
117
- {"name": "Singapore", "url": "/singapore-facts.html"},
118
- {"name": "Solomon Islands", "url": "/solomon-islands-facts.html"},
119
- {"name": "South Africa", "url": "/south-africa-for-kids.html"},
120
- {"name": "South Korea", "url": "/south-korea-facts.html"},
121
- {"name": "Spain", "url": "/spain-facts.html"},
122
- {"name": "Sri Lanka", "url": "/sri-lanka-facts.html"},
123
- {"name": "Suriname", "url": "/suriname-facts.html"},
124
- {"name": "Sweden", "url": "/Sweden-facts.html"},
125
- {"name": "Switzerland", "url": "/switzerland-facts.html"},
126
- {"name": "Taiwan", "url": "/taiwan-facts.html"},
127
- {"name": "Tanzania", "url": "/tanzania-facts.html"},
128
- {"name": "Thailand", "url": "/thailand-facts.html"},
129
- {"name": "Togo", "url": "/togo-facts-for-kids.html"},
130
- {"name": "Tonga", "url": "/facts-about-tonga.html"},
131
- {"name": "Tunisia", "url": "/tunisia-facts.html"},
132
- {"name": "Türkiye", "url": "/turkey-facts.html"},
133
- {"name": "Tuvalu", "url": "/facts-about-tuvalu.html"},
134
- {"name": "Uganda", "url": "/facts-about-uganda.html"},
135
- {"name": "Ukraine", "url": "/ukraine-for-kids.html"},
136
- {"name": "United Arab Emirates", "url": "/uae-facts.html"},
137
- {"name": "United Kingdom", "url": "/uk-facts.html"},
138
- {"name": "United States of America", "url": "/usa-facts.html"},
139
- {"name": "Uruguay", "url": "/uruguay-facts.html"},
140
- {"name": "Vanuatu", "url": "/facts-about-vanuatu.html"},
141
- {"name": "Venezuela", "url": "/venezuela-for-kids.html"},
142
- {"name": "Vietnam", "url": "/vietnam-facts.html"},
143
- {"name": "Zambia", "url": "/zambia-facts.html"}
144
- ]
145
 
146
- def fetch_country_facts(country_url):
147
- """Fetch facts about a country from the Kids World Travel Guide website"""
148
- base_url = "https://www.kids-world-travel-guide.com"
149
- full_url = base_url + country_url
150
-
151
- try:
152
- response = requests.get(full_url, timeout=10)
153
- response.raise_for_status()
154
-
155
- # Parse the HTML content
156
- soup = BeautifulSoup(response.content, 'html.parser')
157
-
158
- # Extract relevant facts - looking for common patterns in the website
159
- facts = []
160
-
161
- # Look for fact sections, lists, and key information
162
- # This is a basic parser - you might need to adjust based on the actual HTML structure
163
-
164
- # Try to find paragraphs with factual content
165
- paragraphs = soup.find_all('p')
166
- for p in paragraphs[:10]: # Limit to first 10 paragraphs to avoid too much content
167
- text = p.get_text().strip()
168
- if len(text) > 50 and not text.startswith('Related'): # Filter out short texts and navigation
169
- facts.append(text)
170
-
171
- # Look for list items that might contain facts
172
- list_items = soup.find_all('li')
173
- for li in list_items[:15]: # Limit to avoid too much content
174
- text = li.get_text().strip()
175
- if len(text) > 20 and len(text) < 200: # Filter for reasonable fact lengths
176
- facts.append(text)
177
-
178
- # Join facts with newlines, limit total length
179
- facts_text = '\n'.join(facts[:10]) # Limit to 10 facts
180
-
181
- # Truncate if too long to avoid token limits
182
- if len(facts_text) > 2000:
183
- facts_text = facts_text[:2000] + "..."
184
-
185
- return facts_text
186
-
187
- except Exception as e:
188
- print(f"Error fetching facts for {country_url}: {str(e)}")
189
- return "Unable to fetch additional facts about this country."
190
 
191
- def get_system_message_with_country():
192
- """Generate a system message with a randomly selected country"""
193
- global selected_country, selected_country_dict
194
- selected_country_dict = random.choice(COUNTRIES)
195
- selected_country = selected_country_dict["name"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- # Fetch facts about the selected country
198
- print(f"Selected country for this session: {selected_country}")
 
 
199
  print(f"Fetching facts from: {selected_country_dict['url']}")
200
 
201
- country_facts = fetch_country_facts(selected_country_dict["url"])
202
- print(country_facts)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
- return f"""You are a friendly geography game host playing 20 questions with students. You are thinking of the country: {selected_country}
205
 
206
- COUNTRY FACTS (use these to answer questions accurately - DO NOT reveal the country name):
207
- {country_facts}
208
 
209
  RULES:
210
- 1. NEVER reveal the country name ({selected_country}) in your responses
211
  2. Answer only 'Yes' or 'No' to their questions
212
  3. Keep track of how many questions they've asked
213
- 4. When they correctly guess or ask if it is {selected_country}, respond with: 'Congratulations! The country was <<{selected_country}>>'
214
- 5. If they reach 20 questions without guessing correctly, respond with: 'Game over! The country was <<{selected_country}>>'
215
  6. Be encouraging and give helpful hints through your yes/no answers
216
  7. If they want to play again tell them they need to reload the page.
217
- 8. IMPORTANT: Only accept the country name "{selected_country}" as correct, but Spelling is not important and they can ask a question like it is? Do NOT accept neighboring countries, similar countries, or regions that contain this country.
218
- 9. If they guess a neighboring country or similar country, respond with "No" and continue the game.
219
- 10. Be very strict about the exact country match - only "{selected_country}" is the correct answer.
220
- 11. Use the COUNTRY FACTS above to provide accurate yes/no answers - do not make up information."""
221
 
222
- current_system = get_system_message_with_country()
223
 
224
  def clean_response(response):
225
  """Clean up the response by removing unwanted metadata and formatting artifacts"""
@@ -259,15 +135,18 @@ def clean_response(response):
259
 
260
  def format_game_result(response):
261
  """Format the game result with proper styling"""
262
- if "The country was" in response:
263
- print(f"🔍 DEBUG - Game end detected! Country extracted: {selected_country}")
 
 
 
264
  else:
265
  print("🔍 DEBUG - Regular response (no game end)")
266
 
267
  if "Congratulations" in response:
268
  return f"🎉 **Congratulations!** You correctly guessed **{selected_country}**! Well done! 🎉\n\nTo play another round, please start a new conversation or reload the page."
269
  elif "Game over" in response:
270
- return f"😔 **Game Over!** You've used all 20 questions. The country I was thinking of was **{selected_country}**. 😔\n\nTo try again, please start a new conversation or reload the page."
271
 
272
  return response
273
 
@@ -279,6 +158,7 @@ def respond(
279
  max_tokens,
280
  temperature,
281
  top_p,
 
282
  hf_token: gr.OAuthToken | None = None,
283
  ):
284
  """
@@ -286,10 +166,14 @@ def respond(
286
  """
287
  global current_system
288
 
289
- # If this is the start of a new conversation (empty history), generate a new country
290
  if not history:
291
- current_system = get_system_message_with_country()
292
- print(f"🔍 DEBUG - New session started, selected country: {selected_country}")
 
 
 
 
293
 
294
  messages = [{"role": "system", "content": current_system}]
295
  messages.extend(history)
@@ -362,8 +246,8 @@ def respond(
362
  print(f"🔍 DEBUG - Cleaned response: {response}")
363
 
364
  # Check if this is a game end response and format it nicely
365
- if "The country was" in response:
366
- print(f"🔍 DEBUG - Game end detected! Country extracted: {selected_country}")
367
  return format_game_result(response)
368
  else:
369
  print("🔍 DEBUG - Regular response (no game end)")
@@ -378,64 +262,67 @@ For information on how to customize the ChatInterface, peruse the gradio docs: h
378
 
379
  # Create description based on mode
380
  if LOCAL_MODE:
381
- description = f"🏠 Running locally with {MODEL_NAME}. I am thinking of a country, you have 20 yes or no questions to ask me to help you figure out what the country is"
382
  else:
383
- description = "I am thinking of a country, you have 20 yes or no questions to ask me to help you figure out what the country is"
384
 
385
- # Common examples and settings
386
  examples = [
387
- ["Is the country located in Europe?"],
388
  ["Is it in the Northern Hemisphere?"],
389
- ["Is the official language Spanish?"],
390
- ["Is the capital city Rome?"],
391
- ["Is this country bordered by an ocean?"],
392
- ["Does this country have more than 100 million people?"],
393
- ["Is this country known for producing coffee?"],
394
- ["Was this country ever a colony of the United Kingdom?"],
395
- ["Is this country located on an island?"],
396
- ["Is the currency the Euro?"],
397
  ]
398
 
399
  # Create wrapper function that handles both local and cloud modes
400
- if LOCAL_MODE:
401
- # Local mode - no OAuth needed
402
- def custom_respond(message, history):
403
- system_message = ""
404
- max_tokens = 4000
405
- temperature = 0.3
406
- top_p = 0.6
407
- return respond(message, history, system_message, max_tokens, temperature, top_p, None)
408
-
409
- chatbot = gr.ChatInterface(
410
- custom_respond,
411
- type="messages",
412
- description=description,
413
- examples=examples,
414
- cache_examples=False,
415
- )
416
- else:
417
- # Cloud mode - use OAuth
418
- chatbot = gr.ChatInterface(
419
- respond,
420
- type="messages",
421
- description=description,
422
- examples=examples,
423
- cache_examples=False,
424
- additional_inputs=[
425
- gr.Textbox(value="", visible=False), # system_message (hidden)
426
- gr.Slider(minimum=1, maximum=4096, value=4000, visible=False), # max_tokens (hidden)
427
- gr.Slider(minimum=0.1, maximum=2.0, value=0.3, visible=False), # temperature (hidden)
428
- gr.Slider(minimum=0.1, maximum=1.0, value=0.6, visible=False), # top_p (hidden)
429
- ],
430
- )
431
 
432
  with gr.Blocks() as demo:
433
  if not LOCAL_MODE:
434
- # Only show login button when running in cloud mode
435
  with gr.Sidebar():
436
  gr.LoginButton()
437
- chatbot.render()
438
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
 
440
  if __name__ == "__main__":
441
  demo.launch()
 
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
3
+
4
  import random
5
  import os
6
+ import re
 
7
  from dotenv import load_dotenv
8
 
9
+ from rag import fetch_facts
10
+
11
  # Load environment variables from .env file if it exists
12
  load_dotenv()
13
 
 
18
  MODEL_NAME = os.getenv('MODEL_NAME', 'openai/gpt-oss-20b')
19
 
20
 
21
+ import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # Load country list from countries.json
24
+ COUNTRIES_JSON_PATH = os.path.join(os.path.dirname(__file__), "countries.json")
25
+ with open(COUNTRIES_JSON_PATH, "r", encoding="utf-8") as f:
26
+ GEOGRAPHY_GUESS_LIST = json.load(f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ STATES_JSON_PATH = os.path.join(os.path.dirname(__file__), "us_states.json")
29
+ with open(STATES_JSON_PATH, "r", encoding="utf-8") as f:
30
+ US_STATES_GUESS_LIST = json.load(f)
31
+
32
+ # Game mode constants
33
+ GAME_MODE_COUNTRIES = "Countries of the World"
34
+ GAME_MODE_STATES = "US States"
35
+
36
+ # Global variables for current game state
37
+ current_system = ""
38
+ selected_country = ""
39
+ selected_country_dict = {}
40
+ game_mode = GAME_MODE_COUNTRIES
41
+
42
+
43
+
44
+ def get_system_message(mode):
45
+ """Generate a system message with a randomly selected location based on game mode"""
46
+ global selected_country, selected_country_dict, game_mode
47
+
48
+ if mode == GAME_MODE_STATES:
49
+ selected_country_dict = random.choice(US_STATES_GUESS_LIST)
50
+ location_type = "state"
51
+ location_type_upper = "US state"
52
+ else:
53
+ selected_country_dict = random.choice(GEOGRAPHY_GUESS_LIST)
54
+ location_type = "country"
55
+ location_type_upper = "country"
56
 
57
+ selected_country = selected_country_dict["name"]
58
+ game_mode = mode
59
+
60
+ print(f"Selected {location_type} for this session: {selected_country}")
61
  print(f"Fetching facts from: {selected_country_dict['url']}")
62
 
63
+ facts = fetch_facts(game_mode, selected_country_dict["url"])
64
+ print(facts)
65
+
66
+ if mode == GAME_MODE_STATES:
67
+ location_info = f"""
68
+ State: {selected_country_dict['name']}
69
+ Capital: {selected_country_dict['capital']}
70
+ Nickname: {selected_country_dict['nickname']}
71
+ Facts: {facts}
72
+ """
73
+ info_label = "STATE INFORMATION"
74
+ reveal_text = "Do NOT reveal the state name"
75
+ else:
76
+ location_info = facts
77
+ info_label = "COUNTRY FACTS"
78
+ reveal_text = "Do NOT reveal the country name"
79
 
80
+ return f"""You are a friendly geography game host playing 20 questions with students. You are thinking of the {location_type_upper}: {selected_country}
81
 
82
+ {info_label} (use these to answer questions accurately - {reveal_text}):
83
+ {location_info}
84
 
85
  RULES:
86
+ 1. NEVER reveal the {location_type} name ({selected_country}) in your responses
87
  2. Answer only 'Yes' or 'No' to their questions
88
  3. Keep track of how many questions they've asked
89
+ 4. When they correctly guess or ask if it is {selected_country}, respond with: 'Congratulations! The {location_type} was <<{selected_country}>>'
90
+ 5. If they reach 20 questions without guessing correctly, respond with: 'Game over! The {location_type} was <<{selected_country}>>'
91
  6. Be encouraging and give helpful hints through your yes/no answers
92
  7. If they want to play again tell them they need to reload the page.
93
+ 8. IMPORTANT: Only accept the {location_type} name "{selected_country}" as correct, but Spelling is not important and they can ask a question like it is? Do NOT accept neighboring {location_type}s, similar {location_type}s, or regions that contain this {location_type}.
94
+ 9. If they guess a neighboring {location_type} or similar {location_type}, respond with "No" and continue the game.
95
+ 10. Be very strict about the exact {location_type} match - only "{selected_country}" is the correct answer.
96
+ 11. Use the {info_label} above to provide accurate yes/no answers - do not make up information."""
97
 
98
+ current_system = ""
99
 
100
  def clean_response(response):
101
  """Clean up the response by removing unwanted metadata and formatting artifacts"""
 
135
 
136
  def format_game_result(response):
137
  """Format the game result with proper styling"""
138
+ global game_mode
139
+ location_type = "state" if game_mode == GAME_MODE_STATES else "country"
140
+
141
+ if f"The {location_type} was" in response:
142
+ print(f"🔍 DEBUG - Game end detected! {location_type.capitalize()} extracted: {selected_country}")
143
  else:
144
  print("🔍 DEBUG - Regular response (no game end)")
145
 
146
  if "Congratulations" in response:
147
  return f"🎉 **Congratulations!** You correctly guessed **{selected_country}**! Well done! 🎉\n\nTo play another round, please start a new conversation or reload the page."
148
  elif "Game over" in response:
149
+ return f"😔 **Game Over!** You've used all 20 questions. The {location_type} I was thinking of was **{selected_country}**. 😔\n\nTo try again, please start a new conversation or reload the page."
150
 
151
  return response
152
 
 
158
  max_tokens,
159
  temperature,
160
  top_p,
161
+ game_mode_selection,
162
  hf_token: gr.OAuthToken | None = None,
163
  ):
164
  """
 
166
  """
167
  global current_system
168
 
169
+ # If this is the start of a new conversation (empty history), generate a new country/state
170
  if not history:
171
+ if game_mode_selection == GAME_MODE_STATES:
172
+ current_system = get_system_message(GAME_MODE_STATES)
173
+ print(f"🔍 DEBUG - New session started, selected state: {selected_country}")
174
+ else:
175
+ current_system = get_system_message(GAME_MODE_COUNTRIES)
176
+ print(f"🔍 DEBUG - New session started, selected country: {selected_country}")
177
 
178
  messages = [{"role": "system", "content": current_system}]
179
  messages.extend(history)
 
246
  print(f"🔍 DEBUG - Cleaned response: {response}")
247
 
248
  # Check if this is a game end response and format it nicely
249
+ if "The country was" in response or "The state was" in response:
250
+ print(f"🔍 DEBUG - Game end detected! Location extracted: {selected_country}")
251
  return format_game_result(response)
252
  else:
253
  print("🔍 DEBUG - Regular response (no game end)")
 
262
 
263
  # Create description based on mode
264
  if LOCAL_MODE:
265
+ description = f"🏠 Running locally with {MODEL_NAME}. Choose your game mode and I'll think of a location for you to guess with 20 yes or no questions!"
266
  else:
267
+ description = "Choose your game mode and I'll think of a location for you to guess with 20 yes or no questions!"
268
 
269
+ # Common examples and settings - updated to be more generic
270
  examples = [
271
+ ["Is it located in North America?"],
272
  ["Is it in the Northern Hemisphere?"],
273
+ ["Does it border an ocean?"],
274
+ ["Is the official language English?"],
275
+ ["Does it have more than 10 million people?"],
276
+ ["Is it known for producing oil?"],
277
+ ["Was it ever a British colony?"],
278
+ ["Is it located on an island?"],
279
+ ["Does it use the US Dollar as currency?"],
280
+ ["Is it a landlocked location?"],
281
  ]
282
 
283
  # Create wrapper function that handles both local and cloud modes
284
+ # Local mode wrapper function
285
+ def custom_respond(message, history, game_mode_selection):
286
+ return respond(message, history, "", 4000, 0.3, 0.6, game_mode_selection, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
 
288
  with gr.Blocks() as demo:
289
  if not LOCAL_MODE:
 
290
  with gr.Sidebar():
291
  gr.LoginButton()
292
+
293
+ gr.Markdown("# 20 Questions Geography Game")
294
+ gr.Markdown(description)
295
+
296
+ # Game mode selection at the top
297
+ game_mode_dropdown = gr.Dropdown(
298
+ choices=[GAME_MODE_STATES, GAME_MODE_COUNTRIES],
299
+ value=GAME_MODE_STATES,
300
+ label="Game Mode",
301
+ info="Choose what type of location to guess"
302
+ )
303
+
304
+ if LOCAL_MODE:
305
+ chatbot = gr.ChatInterface(
306
+ custom_respond,
307
+ type="messages",
308
+ examples=examples,
309
+ cache_examples=False,
310
+ additional_inputs=[game_mode_dropdown],
311
+ )
312
+ else:
313
+ chatbot = gr.ChatInterface(
314
+ respond,
315
+ type="messages",
316
+ examples=examples,
317
+ cache_examples=False,
318
+ additional_inputs=[
319
+ gr.Textbox(value="", visible=False), # system_message (hidden)
320
+ gr.Slider(minimum=1, maximum=4096, value=4000, visible=False), # max_tokens (hidden)
321
+ gr.Slider(minimum=0.1, maximum=2.0, value=0.3, visible=False), # temperature (hidden)
322
+ gr.Slider(minimum=0.1, maximum=1.0, value=0.6, visible=False), # top_p (hidden)
323
+ game_mode_dropdown,
324
+ ],
325
+ )
326
 
327
  if __name__ == "__main__":
328
  demo.launch()
countries.json ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {"name": "Algeria", "url": "/algeria-facts-for-kids.html"},
3
+ {"name": "Angola", "url": "/facts-about-angola.html"},
4
+ {"name": "Argentina", "url": "/argentina-facts.html"},
5
+ {"name": "Australia", "url": "/australia-facts.html"},
6
+ {"name": "Austria", "url": "/austria-facts.html"},
7
+ {"name": "Bahamas", "url": "/facts-about-the-bahamas.html"},
8
+ {"name": "Barbados", "url": "/barbados-facts.html"},
9
+ {"name": "Belgium", "url": "/belgium-facts.html"},
10
+ {"name": "Belize", "url": "/facts-about-belize.html"},
11
+ {"name": "Bhutan", "url": "/bhutan-facts.html"},
12
+ {"name": "Bolivia", "url": "/bolivia-facts.html"},
13
+ {"name": "Botswana", "url": "/facts-about-botswana.html"},
14
+ {"name": "Brazil", "url": "/brazil-facts.html"},
15
+ {"name": "Bulgaria", "url": "/facts-about-bulgaria.html"},
16
+ {"name": "Canada", "url": "/canada-facts-for-kids.html"},
17
+ {"name": "Chile", "url": "/chile-facts.html"},
18
+ {"name": "China", "url": "/china-facts.html"},
19
+ {"name": "Colombia", "url": "/colombia-facts.html"},
20
+ {"name": "Comoros", "url": "/comoros-facts.html"},
21
+ {"name": "Costa Rica", "url": "/costa-rica-facts.html"},
22
+ {"name": "Croatia", "url": "/croatia-facts.html"},
23
+ {"name": "Cuba", "url": "/cuba-facts.html"},
24
+ {"name": "Cyprus", "url": "/cyprus-facts-for-kids.html"},
25
+ {"name": "Denmark", "url": "/denmark-facts.html"},
26
+ {"name": "Dominican Republic", "url": "/dominican-republic-facts.html"},
27
+ {"name": "Ecuador", "url": "/ecuador-facts.html"},
28
+ {"name": "Egypt", "url": "/egypt-facts.html"},
29
+ {"name": "Estonia", "url": "/estonia-facts-for-kids.html"},
30
+ {"name": "Eswatini", "url": "/eswatini-facts.html"},
31
+ {"name": "Ethiopia", "url": "/ethiopia-facts.html"},
32
+ {"name": "Fiji", "url": "/facts-about-fiji.html"},
33
+ {"name": "Finland", "url": "/finland-facts.html"},
34
+ {"name": "France", "url": "/france-facts.html"},
35
+ {"name": "Georgia", "url": "/georgia-facts.html"},
36
+ {"name": "Germany", "url": "/germany-facts.html"},
37
+ {"name": "Ghana", "url": "/ghana-facts.html"},
38
+ {"name": "Greece", "url": "/greece-facts.html"},
39
+ {"name": "Greenland", "url": "/facts-about-greenland.html"},
40
+ {"name": "Guatemala", "url": "/guatemala-facts.html"},
41
+ {"name": "Guyana", "url": "/guyana-facts.html"},
42
+ {"name": "Honduras", "url": "/honduras-facts-for-kids.html"},
43
+ {"name": "Hong Kong", "url": "/facts-about-hong-kong.html"},
44
+ {"name": "Hungary", "url": "/hungary-facts.html"},
45
+ {"name": "Iceland", "url": "/iceland-facts.html"},
46
+ {"name": "India", "url": "/india-for-kids.html"},
47
+ {"name": "Indonesia", "url": "/indonesia-facts.html"},
48
+ {"name": "Iran", "url": "/iran-facts-for-kids.html"},
49
+ {"name": "Ireland", "url": "/ireland-for-kids.html"},
50
+ {"name": "Israel", "url": "/israel-facts.html"},
51
+ {"name": "Italy", "url": "/italy-facts.html"},
52
+ {"name": "Jamaica", "url": "/jamaica-facts.html"},
53
+ {"name": "Japan", "url": "/japan-facts.html"},
54
+ {"name": "Kenya", "url": "/facts-about-kenya.html"},
55
+ {"name": "Kiribati", "url": "/facts-about-kiribati.html"},
56
+ {"name": "Latvia", "url": "/latvia-facts-for-kids.html"},
57
+ {"name": "Lesotho", "url": "/lesotho-facts.html"},
58
+ {"name": "Liberia", "url": "/facts-about-liberia.html"},
59
+ {"name": "Lithuania", "url": "/lithuania-facts-for-kids.html"},
60
+ {"name": "Luxembourg", "url": "/luxembourg-facts.html"},
61
+ {"name": "Macao", "url": "/facts-about-macao.html"},
62
+ {"name": "Madagascar", "url": "/facts-about-madagascar.html"},
63
+ {"name": "Malaysia", "url": "/malaysia-facts.html"},
64
+ {"name": "Maldives", "url": "/maldives-facts.html"},
65
+ {"name": "Malta", "url": "/malta-for-kids.html"},
66
+ {"name": "Mauritius", "url": "/mauritius-facts.html"},
67
+ {"name": "Mexico", "url": "/mexico-facts.html"},
68
+ {"name": "Micronesia", "url": "/facts-about-micronesia.html"},
69
+ {"name": "Moldova", "url": "/moldova-facts-for-kids.html"},
70
+ {"name": "Monaco", "url": "/facts-about-monaco.html"},
71
+ {"name": "Morocco", "url": "/morocco-facts.html"},
72
+ {"name": "Mozambique", "url": "/mozambique-facts.html"},
73
+ {"name": "Myanmar", "url": "/myanmar-facts.html"},
74
+ {"name": "Namibia", "url": "/namibia-facts.html"},
75
+ {"name": "Nauru", "url": "/facts-about-nauru.html"},
76
+ {"name": "Nepal", "url": "/nepal-facts.html"},
77
+ {"name": "Netherlands", "url": "/facts-about-the-netherlands.html"},
78
+ {"name": "New Zealand", "url": "/new-zealand-facts.html"},
79
+ {"name": "Nicaragua", "url": "/nicaragua-facts.html"},
80
+ {"name": "Nigeria", "url": "/nigeria-facts.html"},
81
+ {"name": "Norway", "url": "/norway-facts.html"},
82
+ {"name": "Pakistan", "url": "/pakistan-facts.html"},
83
+ {"name": "Panama", "url": "/panama-facts.html"},
84
+ {"name": "Papua New Guinea", "url": "/papua-new-guinea.html"},
85
+ {"name": "Peru", "url": "/peru-facts.html"},
86
+ {"name": "Philippines", "url": "/philippines-facts.html"},
87
+ {"name": "Poland", "url": "/poland-facts.html"},
88
+ {"name": "Portugal", "url": "/portugal-facts.html"},
89
+ {"name": "Puerto Rico", "url": "/facts-about-puerto-rico.html"},
90
+ {"name": "Qatar", "url": "/qatar-facts.html"},
91
+ {"name": "Romania", "url": "/romania-facts-for-kids.html"},
92
+ {"name": "Russia", "url": "/russia-facts.html"},
93
+ {"name": "Samoa", "url": "/facts-about-samoa.html"},
94
+ {"name": "San Marino", "url": "/facts-about-san-marino.html"},
95
+ {"name": "Serbia", "url": "/facts-about-serbia.html"},
96
+ {"name": "Seychelles", "url": "/seychelles-facts.html"},
97
+ {"name": "Singapore", "url": "/singapore-facts.html"},
98
+ {"name": "Solomon Islands", "url": "/solomon-islands-facts.html"},
99
+ {"name": "South Africa", "url": "/south-africa-for-kids.html"},
100
+ {"name": "South Korea", "url": "/south-korea-facts.html"},
101
+ {"name": "Spain", "url": "/spain-facts.html"},
102
+ {"name": "Sri Lanka", "url": "/sri-lanka-facts.html"},
103
+ {"name": "Suriname", "url": "/suriname-facts.html"},
104
+ {"name": "Sweden", "url": "/Sweden-facts.html"},
105
+ {"name": "Switzerland", "url": "/switzerland-facts.html"},
106
+ {"name": "Taiwan", "url": "/taiwan-facts.html"},
107
+ {"name": "Tanzania", "url": "/tanzania-facts.html"},
108
+ {"name": "Thailand", "url": "/thailand-facts.html"},
109
+ {"name": "Togo", "url": "/togo-facts-for-kids.html"},
110
+ {"name": "Tonga", "url": "/facts-about-tonga.html"},
111
+ {"name": "Tunisia", "url": "/tunisia-facts.html"},
112
+ {"name": "Türkiye", "url": "/turkey-facts.html"},
113
+ {"name": "Tuvalu", "url": "/facts-about-tuvalu.html"},
114
+ {"name": "Uganda", "url": "/facts-about-uganda.html"},
115
+ {"name": "Ukraine", "url": "/ukraine-for-kids.html"},
116
+ {"name": "United Arab Emirates", "url": "/uae-facts.html"},
117
+ {"name": "United Kingdom", "url": "/uk-facts.html"},
118
+ {"name": "United States of America", "url": "/usa-facts.html"},
119
+ {"name": "Uruguay", "url": "/uruguay-facts.html"},
120
+ {"name": "Vanuatu", "url": "/facts-about-vanuatu.html"},
121
+ {"name": "Venezuela", "url": "/venezuela-for-kids.html"},
122
+ {"name": "Vietnam", "url": "/vietnam-facts.html"},
123
+ {"name": "Zambia", "url": "/zambia-facts.html"}
124
+ ]
rag.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import requests
3
+ from bs4 import BeautifulSoup
4
+
5
+ def fetch_facts(game_mode, path):
6
+ """Fetch facts about a country from the Kids World Travel Guide website"""
7
+ base_url = "https://www.kids-world-travel-guide.com" if game_mode == "Countries of the World" else "https://kids.nationalgeographic.com/geography/states/article/"
8
+ full_url = base_url + path
9
+
10
+ try:
11
+ response = requests.get(full_url, timeout=10)
12
+ response.raise_for_status()
13
+
14
+ # Parse the HTML content
15
+ soup = BeautifulSoup(response.content, 'html.parser')
16
+
17
+ # Extract relevant facts - looking for common patterns in the website
18
+ facts = []
19
+
20
+ # Look for fact sections, lists, and key information
21
+ # This is a basic parser - you might need to adjust based on the actual HTML structure
22
+
23
+ # Try to find paragraphs with factual content
24
+ paragraphs = soup.find_all('p')
25
+ for p in paragraphs[:10]: # Limit to first 10 paragraphs to avoid too much content
26
+ text = p.get_text().strip()
27
+ if len(text) > 50 and not text.startswith('Related'): # Filter out short texts and navigation
28
+ facts.append(text)
29
+
30
+ # Look for list items that might contain facts
31
+ list_items = soup.find_all('li')
32
+ for li in list_items[:20]: # Limit to avoid too much content
33
+ text = li.get_text().strip()
34
+ if len(text) > 20 and len(text) < 450: # Filter for reasonable fact lengths
35
+ facts.append(text)
36
+
37
+ # Join facts with newlines, limit total length
38
+ facts_text = '\n'.join(facts[:20]) # Limit to 20 facts
39
+
40
+ # Truncate if too long to avoid token limits
41
+ if len(facts_text) > 2000:
42
+ facts_text = facts_text[:2000] + "..."
43
+
44
+ return facts_text
45
+
46
+ except Exception as e:
47
+ print(f"Error fetching facts for {path}: {str(e)}")
48
+ return "Unable to fetch additional facts about this country."
us_states.json ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {"name": "Alabama", "capital": "Montgomery", "nickname": "The Heart of Dixie", "url": "alabama"},
3
+ {"name": "Alaska", "capital": "Juneau", "nickname": "The Last Frontier", "url": "alaska"},
4
+ {"name": "Arizona", "capital": "Phoenix", "nickname": "The Grand Canyon State", "url": "arizona"},
5
+ {"name": "Arkansas", "capital": "Little Rock", "nickname": "The Natural State", "url": "arkansas"},
6
+ {"name": "California", "capital": "Sacramento", "nickname": "The Golden State", "url": "california"},
7
+ {"name": "Colorado", "capital": "Denver", "nickname": "The Centennial State", "url": "colorado"},
8
+ {"name": "Connecticut", "capital": "Hartford", "nickname": "The Constitution State", "url": "connecticut"},
9
+ {"name": "Delaware", "capital": "Dover", "nickname": "The First State", "url": "delaware"},
10
+ {"name": "Florida", "capital": "Tallahassee", "nickname": "The Sunshine State", "url": "florida"},
11
+ {"name": "Georgia", "capital": "Atlanta", "nickname": "The Peach State", "url": "georgia"},
12
+ {"name": "Hawaii", "capital": "Honolulu", "nickname": "The Aloha State", "url": "hawaii"},
13
+ {"name": "Idaho", "capital": "Boise", "nickname": "The Gem State", "url": "idaho"},
14
+ {"name": "Illinois", "capital": "Springfield", "nickname": "The Prairie State", "url": "illinois"},
15
+ {"name": "Indiana", "capital": "Indianapolis", "nickname": "The Hoosier State", "url": "indiana"},
16
+ {"name": "Iowa", "capital": "Des Moines", "nickname": "The Hawkeye State", "url": "iowa"},
17
+ {"name": "Kansas", "capital": "Topeka", "nickname": "The Sunflower State", "url": "kansas"},
18
+ {"name": "Kentucky", "capital": "Frankfort", "nickname": "The Bluegrass State", "url": "kentucky"},
19
+ {"name": "Louisiana", "capital": "Baton Rouge", "nickname": "The Pelican State", "url": "louisiana"},
20
+ {"name": "Maine", "capital": "Augusta", "nickname": "The Pine Tree State", "url": "maine"},
21
+ {"name": "Maryland", "capital": "Annapolis", "nickname": "The Old Line State", "url": "maryland"},
22
+ {"name": "Massachusetts", "capital": "Boston", "nickname": "The Bay State", "url": "massachusetts"},
23
+ {"name": "Michigan", "capital": "Lansing", "nickname": "The Great Lakes State", "url": "michigan"},
24
+ {"name": "Minnesota", "capital": "Saint Paul", "nickname": "The North Star State", "url": "minnesota"},
25
+ {"name": "Mississippi", "capital": "Jackson", "nickname": "The Magnolia State", "url": "mississippi"},
26
+ {"name": "Missouri", "capital": "Jefferson City", "nickname": "The Show-Me State", "url": "missouri"},
27
+ {"name": "Montana", "capital": "Helena", "nickname": "The Treasure State", "url": "montana"},
28
+ {"name": "Nebraska", "capital": "Lincoln", "nickname": "The Cornhusker State", "url": "nebraska"},
29
+ {"name": "Nevada", "capital": "Carson City", "nickname": "The Silver State", "url": "nevada"},
30
+ {"name": "New Hampshire", "capital": "Concord", "nickname": "The Live Free or Die State", "url": "new-hampshire"},
31
+ {"name": "New Jersey", "capital": "Trenton", "nickname": "The Garden State", "url": "new-jersey"},
32
+ {"name": "New Mexico", "capital": "Santa Fe", "nickname": "The Land of Enchantment", "url": "new-mexico"},
33
+ {"name": "New York", "capital": "Albany", "nickname": "The Empire State", "url": "new-york"},
34
+ {"name": "North Carolina", "capital": "Raleigh", "nickname": "The Tar Heel State", "url": "north-carolina"},
35
+ {"name": "North Dakota", "capital": "Bismarck", "nickname": "The Peace Garden State", "url": "north-dakota"},
36
+ {"name": "Ohio", "capital": "Columbus", "nickname": "The Buckeye State", "url": "ohio"},
37
+ {"name": "Oklahoma", "capital": "Oklahoma City", "nickname": "The Sooner State", "url": "oklahoma"},
38
+ {"name": "Oregon", "capital": "Salem", "nickname": "The Beaver State", "url": "oregon"},
39
+ {"name": "Pennsylvania", "capital": "Harrisburg", "nickname": "The Keystone State", "url": "pennsylvania"},
40
+ {"name": "Rhode Island", "capital": "Providence", "nickname": "The Ocean State", "url": "rhode-island"},
41
+ {"name": "South Carolina", "capital": "Columbia", "nickname": "The Palmetto State", "url": "south-carolina"},
42
+ {"name": "South Dakota", "capital": "Pierre", "nickname": "The Mount Rushmore State", "url": "south-dakota"},
43
+ {"name": "Tennessee", "capital": "Nashville", "nickname": "The Volunteer State", "url": "tennessee"},
44
+ {"name": "Texas", "capital": "Austin", "nickname": "The Lone Star State", "url": "texas"},
45
+ {"name": "Utah", "capital": "Salt Lake City", "nickname": "The Beehive State", "url": "utah"},
46
+ {"name": "Vermont", "capital": "Montpelier", "nickname": "The Green Mountain State", "url": "vermont"},
47
+ {"name": "Virginia", "capital": "Richmond", "nickname": "The Old Dominion", "url": "virginia"},
48
+ {"name": "Washington", "capital": "Olympia", "nickname": "The Evergreen State", "url": "washington"},
49
+ {"name": "West Virginia", "capital": "Charleston", "nickname": "The Mountain State", "url": "west-virginia"},
50
+ {"name": "Wisconsin", "capital": "Madison", "nickname": "The Badger State", "url": "wisconsin"},
51
+ {"name": "Wyoming", "capital": "Cheyenne", "nickname": "The Equality State", "url": "wyoming"}
52
+ ]