Jonathan Bejarano commited on
Commit
036d0fc
·
1 Parent(s): e45c325

Enhance README and implement local/cloud mode support in the geography game

Browse files
Files changed (5) hide show
  1. .gitignore +1 -0
  2. README.md +54 -1
  3. app.py +95 -57
  4. requirements.txt +2 -1
  5. sample.env +3 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .env
README.md CHANGED
@@ -14,4 +14,57 @@ license: apache-2.0
14
  short_description: Learning Country Names, locations, flags, principal location
15
  ---
16
 
17
- An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  short_description: Learning Country Names, locations, flags, principal location
15
  ---
16
 
17
+ # World Geography Game 🌍
18
+
19
+ An interactive geography game where you try to guess the country I'm thinking of using 20 yes/no questions.
20
+
21
+ Built with [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
22
+
23
+ ## Features
24
+
25
+ - 🎯 20 Questions gameplay format
26
+ - 🌍 Covers countries from around the world
27
+ - 🤖 AI-powered responses using Llama models
28
+ - 🏠 Local model support for development
29
+ - ☁️ Cloud deployment with HuggingFace OAuth
30
+
31
+ ## Running Locally
32
+
33
+ To run this application with a local inference server (like LM Studio, Ollama, etc.):
34
+
35
+ 1. **Create a `.env` file** from the sample:
36
+ ```bash
37
+ cp sample.env .env
38
+ ```
39
+
40
+ 2. **Configure your local model settings** in `.env`:
41
+ ```env
42
+ MODEL_NAME=llama-3.2-3b-instruct
43
+ BASE_URL=http://127.0.0.1:1234/v1
44
+ TOKEN=abc123
45
+ ```
46
+
47
+ 3. **Install dependencies**:
48
+ ```bash
49
+ pip install -r requirements.txt
50
+ ```
51
+
52
+ 4. **Run the application**:
53
+ ```bash
54
+ python app.py
55
+ ```
56
+
57
+ When running locally, the app will automatically detect the environment variables and use your local model instead of requiring HuggingFace OAuth login.
58
+
59
+ ## Cloud Deployment
60
+
61
+ When deployed to HuggingFace Spaces or running without local environment variables, the app will use HuggingFace's Inference API and require users to log in with their HuggingFace account.
62
+
63
+ ## How to Play
64
+
65
+ 1. Think of questions that can be answered with "Yes" or "No"
66
+ 2. Try to narrow down the location, language, geography, or other characteristics
67
+ 3. You have 20 questions to guess the correct country
68
+ 4. The AI will keep track of your question count and let you know when you've won or used all your questions
69
+
70
+ Good luck! 🎮
app.py CHANGED
@@ -2,6 +2,17 @@ import gradio as gr
2
  from huggingface_hub import InferenceClient
3
  import re
4
  import random
 
 
 
 
 
 
 
 
 
 
 
5
 
6
 
7
  # List of countries for the game
@@ -69,90 +80,117 @@ def respond(
69
  max_tokens,
70
  temperature,
71
  top_p,
72
- hf_token: gr.OAuthToken,
73
  ):
74
  """
75
  For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
76
  """
77
- # Check if user is logged in
78
- if not hf_token or not hf_token.token:
79
- yield "Please log in with your HuggingFace account to play the geography game!"
80
- return
81
-
82
- client = InferenceClient(token=hf_token.token, model="meta-llama/Llama-3.2-3B-Instruct")
83
-
84
  # Generate a new system message with random country for new conversations
85
  if not history:
86
  system_message = get_system_message_with_country()
87
 
88
  messages = [{"role": "system", "content": system_message}]
89
-
90
  messages.extend(history)
91
-
92
  messages.append({"role": "user", "content": message})
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  response = ""
95
 
96
- for message in client.chat_completion(
97
- messages,
98
- max_tokens=max_tokens,
99
- stream=True,
100
- temperature=temperature,
101
- top_p=top_p,
102
- ):
103
- choices = message.choices
104
- token = ""
105
- if len(choices) and choices[0].delta.content:
106
- token = choices[0].delta.content
107
-
108
- response += token
109
-
 
 
110
  # Check if this is a game end response and format it nicely
111
  if "<<" in response and ">>" in response:
112
- formatted_response = format_game_result(response)
113
- yield formatted_response
114
  else:
115
- yield response
 
 
116
 
117
 
118
  """
119
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
120
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  chatbot = gr.ChatInterface(
122
- respond,
123
  type="messages",
124
- 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",
125
- examples=[
126
- ["Is the country located in Europe?"],
127
- ["Is it in the Northern Hemisphere?"],
128
- ["Is the official language Spanish?"],
129
- ["Is the capital city Rome?"],
130
- ["Is this country bordered by an ocean?"],
131
- ["Does this country have more than 100 million people?"],
132
- ["Is this country known for producing coffee?"],
133
- ["Was this country ever a colony of the United Kingdom?"],
134
- ["Is this country located on an island?"],
135
- ["Is the currency the Euro?"],
136
- ],
137
- cache_examples=False, # Disable caching to prevent login errors during deployment
138
- additional_inputs=[
139
- gr.Textbox(visible=False, value="Geography game placeholder - will be replaced with random country", label="System message"),
140
- gr.Slider(visible=False, minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
141
- gr.Slider(visible=False, minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
142
- gr.Slider(
143
- visible=False,
144
- minimum=0.1,
145
- maximum=1.0,
146
- value=0.95,
147
- step=0.05,
148
- label="Top-p (nucleus sampling)",
149
- ),
150
- ],
151
  )
152
 
153
  with gr.Blocks() as demo:
154
- with gr.Sidebar():
155
- gr.LoginButton()
 
 
156
  chatbot.render()
157
 
158
 
 
2
  from huggingface_hub import InferenceClient
3
  import re
4
  import random
5
+ import os
6
+ from dotenv import load_dotenv
7
+
8
+ # Load environment variables from .env file if it exists
9
+ load_dotenv()
10
+
11
+ # Check if we're running locally with custom model settings
12
+ BASE_URL = os.getenv('BASE_URL')
13
+ LOCAL_TOKEN = os.getenv('TOKEN')
14
+ LOCAL_MODE = bool(BASE_URL and LOCAL_TOKEN)
15
+ MODEL_NAME = os.getenv('MODEL_NAME', 'meta-llama/Llama-3.2-3B-Instruct')
16
 
17
 
18
  # List of countries for the game
 
80
  max_tokens,
81
  temperature,
82
  top_p,
83
+ hf_token: gr.OAuthToken | None = None,
84
  ):
85
  """
86
  For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
87
  """
 
 
 
 
 
 
 
88
  # Generate a new system message with random country for new conversations
89
  if not history:
90
  system_message = get_system_message_with_country()
91
 
92
  messages = [{"role": "system", "content": system_message}]
 
93
  messages.extend(history)
 
94
  messages.append({"role": "user", "content": message})
95
 
96
+ # Choose client based on whether we're running locally or in the cloud
97
+ if LOCAL_MODE:
98
+ # Running locally with custom model settings
99
+ try:
100
+ # Use local inference server
101
+ client = InferenceClient(model=BASE_URL, token=LOCAL_TOKEN)
102
+ except Exception as e:
103
+ return f"Error connecting to local model: {str(e)}"
104
+ else:
105
+ # Running in cloud mode with HuggingFace
106
+ if not hf_token or not hf_token.token:
107
+ return "Please log in with your HuggingFace account to play the geography game!"
108
+
109
+ client = InferenceClient(token=hf_token.token, model=MODEL_NAME)
110
+
111
  response = ""
112
 
113
+ try:
114
+ for message_chunk in client.chat_completion(
115
+ messages,
116
+ model=MODEL_NAME,
117
+ max_tokens=max_tokens,
118
+ stream=True,
119
+ temperature=temperature,
120
+ top_p=top_p,
121
+ ):
122
+ choices = message_chunk.choices
123
+ token = ""
124
+ if len(choices) and choices[0].delta.content:
125
+ token = choices[0].delta.content
126
+
127
+ response += token
128
+
129
  # Check if this is a game end response and format it nicely
130
  if "<<" in response and ">>" in response:
131
+ return format_game_result(response)
 
132
  else:
133
+ return response
134
+ except Exception as e:
135
+ return f"Error during inference: {str(e)}"
136
 
137
 
138
  """
139
  For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
140
  """
141
+
142
+ # Create description based on mode
143
+ if LOCAL_MODE:
144
+ 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"
145
+ else:
146
+ 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"
147
+
148
+ # Common examples and settings
149
+ examples = [
150
+ ["Is the country located in Europe?"],
151
+ ["Is it in the Northern Hemisphere?"],
152
+ ["Is the official language Spanish?"],
153
+ ["Is the capital city Rome?"],
154
+ ["Is this country bordered by an ocean?"],
155
+ ["Does this country have more than 100 million people?"],
156
+ ["Is this country known for producing coffee?"],
157
+ ["Was this country ever a colony of the United Kingdom?"],
158
+ ["Is this country located on an island?"],
159
+ ["Is the currency the Euro?"],
160
+ ]
161
+
162
+ additional_inputs = [
163
+ gr.Textbox(visible=False, value="Geography game placeholder - will be replaced with random country", label="System message"),
164
+ gr.Slider(visible=False, minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
165
+ gr.Slider(visible=False, minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
166
+ gr.Slider(
167
+ visible=False,
168
+ minimum=0.1,
169
+ maximum=1.0,
170
+ value=0.95,
171
+ step=0.05,
172
+ label="Top-p (nucleus sampling)",
173
+ ),
174
+ ]
175
+
176
+ # Create wrapper function for local mode that doesn't expect OAuth token
177
+ def respond_local(message, history, system_message, max_tokens, temperature, top_p):
178
+ return respond(message, history, system_message, max_tokens, temperature, top_p, None)
179
+
180
  chatbot = gr.ChatInterface(
181
+ (respond_local if LOCAL_MODE else respond),
182
  type="messages",
183
+ description=description,
184
+ examples=examples,
185
+ cache_examples=False,
186
+ additional_inputs=additional_inputs,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  )
188
 
189
  with gr.Blocks() as demo:
190
+ if not LOCAL_MODE:
191
+ # Only show login button when running in cloud mode
192
+ with gr.Sidebar():
193
+ gr.LoginButton()
194
  chatbot.render()
195
 
196
 
requirements.txt CHANGED
@@ -1,2 +1,3 @@
1
  gradio
2
- gradio[oauth]
 
 
1
  gradio
2
+ gradio[oauth]
3
+ python-dotenv
sample.env ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ MODEL_NAME=llama-3.2-3b-instruct
2
+ BASE_URL=http://127.0.0.1:1234/v1
3
+ TOKEN=abc123