Aranwer commited on
Commit
a374aef
·
verified ·
1 Parent(s): f7a3e32

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -85
app.py CHANGED
@@ -1,41 +1,46 @@
1
- import streamlit as st
 
 
 
2
  import speech_recognition as sr
3
  import tempfile
4
  import scipy.io.wavfile
5
  import os
6
- import requests
7
  import numpy as np
8
 
9
- # API Keys
10
- os.environ["MISTRAL_API_KEY"] = "your-mistral-key"
11
- os.environ["GROQ_API_KEY"] = "your-groq-key"
12
 
13
- # Game State
14
- if "state" not in st.session_state:
15
- st.session_state.state = {
16
- "active": False,
17
- "questions_asked": 0,
18
- "answers": [],
19
- "current_question": None,
20
- "consult_mode": False
21
- }
22
 
23
- # Functions
24
- def transcribe_audio(uploaded_file, language):
25
- if uploaded_file is None:
26
  return ""
27
  try:
28
- with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file:
29
- tmp_file.write(uploaded_file.read())
 
 
 
 
30
  tmp_file_path = tmp_file.name
31
 
32
  recognizer = sr.Recognizer()
33
  with sr.AudioFile(tmp_file_path) as source:
34
- audio = recognizer.record(source)
35
- lang_code = "en-US" if language == "English" else "ur-PK"
36
- return recognizer.recognize_google(audio, language=lang_code).lower()
 
37
  except Exception as e:
38
- return f"Transcription error: {e}"
 
39
 
40
  def query_llm(api, messages, model=None):
41
  headers = {
@@ -46,90 +51,127 @@ def query_llm(api, messages, model=None):
46
  "messages": messages,
47
  "model": model or ("llama3-70b-8192" if api == "GROQ" else "mistral-medium")
48
  }
49
- url = "https://api.groq.com/openai/v1/chat/completions" if api == "GROQ" else "https://api.mistral.ai/v1/chat/completions"
50
- response = requests.post(url, headers=headers, json=payload)
51
- if response.ok:
52
- return response.json()["choices"][0]["message"]["content"]
53
- return "API Error"
54
 
55
- def normalize_answer(ans):
56
- ans = ans.strip().lower()
57
- return "yes" if ans in ["yes", "y", "ہاں", "haan"] else "no" if ans in ["no", "n", "نہیں", "nahi"] else None
 
 
 
58
 
59
  def generate_question(answers):
60
- prompt = "You are playing Kasoti. Ask the next best yes/no question.\n\n"
61
  for i, (q, a) in enumerate(answers, 1):
62
  prompt += f"{i}. Q: {q}\n A: {a}\n"
63
- return query_llm("GROQ", [{"role": "user", "content": prompt}])
 
 
64
 
65
  def make_guess(answers):
66
- prompt = "Based on this history, make a best guess:\n\n"
67
  for i, (q, a) in enumerate(answers, 1):
68
  prompt += f"{i}. Q: {q}\n A: {a}\n"
69
- return query_llm("GROQ", [{"role": "user", "content": prompt}])
 
70
 
71
  def get_hint(question, answers):
72
- prompt = f"The player is unsure about: {question}\n\nHistory:\n"
73
  for q, a in answers:
74
  prompt += f"- Q: {q}\n A: {a}\n"
75
- return query_llm("MISTRAL", [{"role": "user", "content": prompt}])
 
76
 
77
- # Streamlit UI
78
- st.set_page_config(page_title="🎮 Kasoti 20Q", layout="centered")
79
-
80
- st.title("🎮 Kasoti - 20 Questions Game")
81
- st.info("Think of a famous person, place, or object. Answer with **yes/no** or **ہاں/نہیں** only.")
82
 
83
- if st.button("🔄 Start Game"):
84
- st.session_state.state.update({
85
  "active": True,
86
  "questions_asked": 1,
87
  "answers": [],
88
  "current_question": "Is it a living thing?",
89
  "consult_mode": False
90
  })
 
 
91
 
92
- if st.session_state.state["active"]:
93
- st.success(f"🤔 Question {st.session_state.state['questions_asked']}: {st.session_state.state['current_question']}")
 
94
 
95
- with st.form(key="answer_form"):
96
- audio_file = st.file_uploader("🎙️ Upload your answer (WAV only)", type=["wav"])
97
- language = st.selectbox("🗣️ Language", ["English", "Urdu"])
98
- manual_input = st.text_input("💬 Or type your answer:")
99
- submit = st.form_submit_button("➡️ Submit")
100
 
101
- if submit:
102
- answer = manual_input or transcribe_audio(audio_file, language)
103
- normalized = normalize_answer(answer)
104
- if not normalized:
105
- st.warning("⚠️ Please reply with 'yes' or 'no' (or 'ہاں/نہیں').")
106
  else:
107
- question = st.session_state.state["current_question"]
108
- st.session_state.state["answers"].append((question, normalized))
109
-
110
- if "is this correct?" in question.lower():
111
- if normalized == "yes":
112
- st.balloons()
113
- st.success("🎉 I guessed it right!")
114
- st.session_state.state["active"] = False
115
- else:
116
- next_q = generate_question(st.session_state.state["answers"])
117
- st.session_state.state["current_question"] = next_q
118
- st.session_state.state["questions_asked"] += 1
119
- elif st.session_state.state["questions_asked"] >= 20:
120
- st.session_state.state["active"] = False
121
- guess = make_guess(st.session_state.state["answers"])
122
- st.error(f" Game over! Final guess: {guess}")
123
- elif st.session_state.state["questions_asked"] % 5 == 0:
124
- guess = make_guess(st.session_state.state["answers"])
125
- st.session_state.state["current_question"] = guess + " Is this correct?"
126
- st.session_state.state["questions_asked"] += 1
127
- else:
128
- next_q = generate_question(st.session_state.state["answers"])
129
- st.session_state.state["current_question"] = next_q
130
- st.session_state.state["questions_asked"] += 1
131
-
132
- if st.session_state.state["active"]:
133
- if st.toggle("💡 Enable Consult Mode"):
134
- hint = get_hint(st.session_state.state["current_question"], st.session_state.state["answers"])
135
- st.info(f"💭 Hint: {hint}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
+ import gradio as gr
4
+ import requests
5
  import speech_recognition as sr
6
  import tempfile
7
  import scipy.io.wavfile
8
  import os
 
9
  import numpy as np
10
 
11
+ # Set your API keys as HF secrets or environment variables
12
+ os.environ["MISTRAL_API_KEY"] = os.getenv("MISTRAL_API_KEY", "your-mistral-key")
13
+ os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY", "your-groq-key")
14
 
15
+ game_state = {
16
+ "active": False,
17
+ "questions_asked": 0,
18
+ "answers": [],
19
+ "current_question": None,
20
+ "consult_mode": False
21
+ }
 
 
22
 
23
+ def transcribe_audio(audio, language):
24
+ if audio is None:
 
25
  return ""
26
  try:
27
+ sr_rate, audio_data = audio
28
+ if isinstance(audio_data, tuple):
29
+ audio_data = np.array(audio_data)
30
+
31
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp_file:
32
+ scipy.io.wavfile.write(tmp_file.name, sr_rate, audio_data)
33
  tmp_file_path = tmp_file.name
34
 
35
  recognizer = sr.Recognizer()
36
  with sr.AudioFile(tmp_file_path) as source:
37
+ audio_content = recognizer.record(source)
38
+ language_code = "en-US" if language == "English" else "ur-PK"
39
+ text = recognizer.recognize_google(audio_content, language=language_code)
40
+ return text.lower()
41
  except Exception as e:
42
+ print(f"Transcription error: {e}")
43
+ return ""
44
 
45
  def query_llm(api, messages, model=None):
46
  headers = {
 
51
  "messages": messages,
52
  "model": model or ("llama3-70b-8192" if api == "GROQ" else "mistral-medium")
53
  }
54
+ endpoint = {
55
+ "MISTRAL": "https://api.mistral.ai/v1/chat/completions",
56
+ "GROQ": "https://api.groq.com/openai/v1/chat/completions"
57
+ }[api]
 
58
 
59
+ response = requests.post(endpoint, headers=headers, json=payload)
60
+ if response.status_code == 200:
61
+ return response.json()["choices"][0]["message"]["content"]
62
+ else:
63
+ print(f"Error from {api} API: {response.text}")
64
+ return None
65
 
66
  def generate_question(answers):
67
+ prompt = "You are playing a game called Kasoti (20 Questions)...\n"
68
  for i, (q, a) in enumerate(answers, 1):
69
  prompt += f"{i}. Q: {q}\n A: {a}\n"
70
+ prompt += "\nAsk ONLY the next best yes/no question."
71
+ response = query_llm("GROQ", [{"role": "user", "content": prompt}])
72
+ return response.strip() if response else "Is it something you can hold?"
73
 
74
  def make_guess(answers):
75
+ prompt = "Based on the following yes/no history, make a best guess.\n\nHistory:\n"
76
  for i, (q, a) in enumerate(answers, 1):
77
  prompt += f"{i}. Q: {q}\n A: {a}\n"
78
+ response = query_llm("GROQ", [{"role": "user", "content": prompt}])
79
+ return response.strip() if response else "I need more information."
80
 
81
  def get_hint(question, answers):
82
+ prompt = f"The player is unsure about answering: '{question}'\n\nHistory:\n"
83
  for q, a in answers:
84
  prompt += f"- Q: {q}\n A: {a}\n"
85
+ prompt += "\nSuggest a helpful hint to clarify."
86
+ return query_llm("MISTRAL", [{"role": "user", "content": prompt}]) or "Consider the common meaning."
87
 
88
+ def normalize_answer(ans):
89
+ ans = ans.strip().lower()
90
+ return "yes" if ans in ["yes", "y", "ہاں", "haan"] else "no" if ans in ["no", "n", "نہیں", "nahi"] else None
 
 
91
 
92
+ def start_game():
93
+ game_state.update({
94
  "active": True,
95
  "questions_asked": 1,
96
  "answers": [],
97
  "current_question": "Is it a living thing?",
98
  "consult_mode": False
99
  })
100
+ intro = "🎯 **Kasoti Started!**\nThink of something... I'll guess in 20 questions.\n\n➡️ First Question: **Is it a living thing?**"
101
+ return intro, gr.update(interactive=True), gr.update(interactive=True), "🔕 Consult Mode: OFF", gr.update(visible=False)
102
 
103
+ def process_answer(answer_text):
104
+ if not game_state["active"]:
105
+ return "⚠️ Start the game first.", "", "", gr.update(visible=False)
106
 
107
+ normalized = normalize_answer(answer_text)
108
+ if normalized is None:
109
+ return "❌ Please reply with 'yes' or 'no' (or 'ہاں/نہیں').", "", answer_text, gr.update(visible=game_state["consult_mode"])
 
 
110
 
111
+ if "is this correct?" in (game_state["current_question"] or "").lower():
112
+ if normalized == "yes":
113
+ game_state["active"] = False
114
+ return "🎉 YAY! I guessed it!", "", answer_text, gr.update(visible=False)
 
115
  else:
116
+ next_q = generate_question(game_state["answers"])
117
+ game_state["current_question"] = next_q
118
+ game_state["questions_asked"] += 1
119
+ return next_q, "", answer_text, gr.update(visible=game_state["consult_mode"])
120
+
121
+ game_state["answers"].append((game_state["current_question"], normalized))
122
+
123
+ if game_state["questions_asked"] >= 20:
124
+ game_state["active"] = False
125
+ guess = make_guess(game_state["answers"])
126
+ return f"🕹️ Game over! My final guess: **{guess}**", "", answer_text, gr.update(visible=False)
127
+
128
+ if game_state["questions_asked"] % 5 == 0:
129
+ guess = make_guess(game_state["answers"])
130
+ if guess.startswith("I think it's"):
131
+ game_state["current_question"] = guess + " Is this correct? (yes/no)"
132
+ return game_state["current_question"], "", answer_text, gr.update(visible=game_state["consult_mode"])
133
+
134
+ next_q = generate_question(game_state["answers"])
135
+ game_state["current_question"] = next_q
136
+ game_state["questions_asked"] += 1
137
+ return next_q, "", answer_text, gr.update(visible=game_state["consult_mode"])
138
+
139
+ def toggle_consult_mode():
140
+ game_state["consult_mode"] = not game_state["consult_mode"]
141
+ return ("��� Consult Mode: ON" if game_state["consult_mode"] else "🔕 Consult Mode: OFF",
142
+ gr.update(visible=game_state["consult_mode"]))
143
+
144
+ def get_consult_hint():
145
+ if not game_state["active"] or not game_state["consult_mode"]:
146
+ return "ℹ️ Consult mode is not active or game not started."
147
+ return get_hint(game_state["current_question"], game_state["answers"])
148
+
149
+ # Colorful and polished UI
150
+ with gr.Blocks(css=".gr-button {background-color: #4CAF50; color: white} .gr-box {background: #f7f7ff; border: 1px solid #ccc; padding: 10px; border-radius: 10px;}") as demo:
151
+ gr.Markdown("## 🧠 Kasoti: 20 Questions AI Game")
152
+ gr.Markdown("Think of a person, place, or thing. I'll try to guess it in 20 questions or less! Just answer 'yes' or 'no'.")
153
+
154
+ with gr.Row():
155
+ start_btn = gr.Button("🚀 Start Game")
156
+ consult_btn = gr.Button("💬 Toggle Consult Mode")
157
+ consult_status = gr.Textbox(label="Consult Mode", interactive=False)
158
+
159
+ with gr.Row():
160
+ with gr.Column():
161
+ language = gr.Dropdown(["English", "Urdu"], label="Audio Language", value="English")
162
+ audio_input = gr.Audio(label="🎤 Answer via Microphone", type="numpy", sources=["microphone"])
163
+ transcribe_btn = gr.Button("📝 Transcribe Audio")
164
+ transcribed_text = gr.Textbox(label="✍️ Answer Text", interactive=True)
165
+ submit_btn = gr.Button("✅ Submit Answer")
166
+
167
+ with gr.Column():
168
+ game_output = gr.Textbox(label="🎲 Game Progress", interactive=False)
169
+ consult_output = gr.Textbox(label="💡 Consult Hint", visible=False)
170
+
171
+ start_btn.click(start_game, outputs=[game_output, transcribed_text, submit_btn, consult_status, consult_output])
172
+ consult_btn.click(toggle_consult_mode, outputs=[consult_status, consult_output])
173
+ consult_btn.click(get_consult_hint, outputs=[consult_output])
174
+ transcribe_btn.click(transcribe_audio, inputs=[audio_input, language], outputs=[transcribed_text])
175
+ submit_btn.click(process_answer, inputs=[transcribed_text], outputs=[game_output, transcribed_text, transcribed_text, consult_output])
176
+
177
+ demo.launch()