File size: 8,218 Bytes
3e2907a
f44fa75
4ad659a
3e2907a
 
 
 
a5070e7
109ed81
0615413
 
3e2907a
 
0615413
 
 
 
 
 
f44fa75
 
0615413
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59bc377
 
0615413
 
 
 
59bc377
0615413
 
 
59bc377
0615413
 
 
 
 
 
 
59bc377
0615413
 
 
 
 
59bc377
0615413
 
 
59bc377
 
 
 
 
 
 
 
0615413
 
 
 
59bc377
 
 
 
 
0615413
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59bc377
 
c099445
 
d600c78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75b2548
 
d600c78
 
8309cc8
75b2548
 
8309cc8
 
 
 
c099445
 
 
 
 
75b2548
8309cc8
 
c099445
75b2548
 
 
 
c099445
226dde4
 
 
 
 
c099445
 
 
226dde4
 
 
 
 
8309cc8
59bc377
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import os
import gradio as gr
import speech_recognition as sr
import numpy as np
import tempfile
import scipy.io.wavfile
import requests

# Set your API keys
os.environ["MISTRAL_API_KEY"] = "R1ISnVkHrj7fSd5Dh6ZSZHqCJhhct0ZR"
os.environ["GROQ_API_KEY"] = "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"

state = {
    "started": False,
    "history": [],
    "current_q": "",
    "question_num": 0,
    "hint_mode": False,
    "final_answer": ""
}

def convert_audio_to_text(audio, lang_choices):
    if audio is None:
        return ""
    try:
        sr_rate, audio_data = audio
        with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as fp:
            scipy.io.wavfile.write(fp.name, sr_rate, audio_data)
            recog = sr.Recognizer()
            with sr.AudioFile(fp.name) as src:
                recorded = recog.record(src)
                lang = "en-US" if "English" in lang_choices else "ur-PK" if "Urdu" in lang_choices else "en-US"
                return recog.recognize_google(recorded, language=lang).lower()
    except Exception as e:
        return f"[Error] Couldn't transcribe: {str(e)}"

def query_llm(api, messages, model=None):
    headers = {
        "Authorization": f"Bearer {os.environ[f'{api}_API_KEY']}",
        "Content-Type": "application/json"
    }
    payload = {
        "messages": messages,
        "model": model or ("llama3-70b-8192" if api == "GROQ" else "mistral-medium")
    }
    endpoint = {
        "MISTRAL": "https://api.mistral.ai/v1/chat/completions",
        "GROQ": "https://api.groq.com/openai/v1/chat/completions"
    }[api]

    response = requests.post(endpoint, headers=headers, json=payload)
    if response.status_code == 200:
        return response.json()["choices"][0]["message"]["content"].strip()
    else:
        return f"[{api} Error] {response.status_code} - {response.text}"

def begin_game():
    state["started"] = True
    state["history"] = []
    state["question_num"] = 1
    state["hint_mode"] = False
    state["final_answer"] = ""
    state["current_q"] = "Does it belong to the world of living things?"
    return (
        f"Question 1: {state['current_q']}",
        "",
        gr.update(visible=False),
        gr.update(visible=True),
        gr.update(visible=False),
        state["question_num"]
    )

def interpret_answer(user_answer):
    if not state["started"]:
        return "⛔ Please start a new game.", "", gr.update(visible=False), "", gr.update(visible=False), state["question_num"]

    normalized = user_answer.strip().lower()
    if normalized not in ["yes", "no", "ہاں", "نہیں"]:
        return "⚠️ Respond with 'yes' or 'no' (or ہاں/نہیں).", user_answer, gr.update(visible=False), "", gr.update(visible=False), state["question_num"]

    state["history"].append((state["current_q"], normalized))

    if state["question_num"] >= 20:
        state["started"] = False
        guess = generate_final_guess()
        state["final_answer"] = guess
        return "Game Over!", user_answer, gr.update(visible=True), "", gr.update(value=guess, visible=True), state["question_num"]

    if state["question_num"] % 5 == 0:
        guess = generate_final_guess()
        if "i think" in guess.lower() or "maybe" in guess.lower():
            state["current_q"] = f"{guess} Am I right?"
            return state["current_q"], user_answer, gr.update(visible=False), "", gr.update(visible=False), state["question_num"]

    state["question_num"] += 1
    state["current_q"] = get_next_question()
    return (
        f"Question {state['question_num']}: {state['current_q']}",
        user_answer,
        gr.update(visible=False),
        "",
        gr.update(visible=False),
        state["question_num"]
    )

def get_next_question():
    history_prompt = "\n".join([f"Q: {q}\nA: {a}" for q, a in state["history"]])
    prompt = (
        "You're playing a guessing game. Only respond with a yes/no question, nothing else.\n"
        "Based on the following history, ask the next smart question:\n\n"
        f"{history_prompt}\n\n"
        "Next question only:"
    )
    return query_llm("MISTRAL", [{"role": "user", "content": prompt}])

def generate_final_guess():
    history = "\n".join([f"Q: {q}\nA: {a}" for q, a in state["history"]])
    prompt = f"""Guess the secret concept based on these Q&A. If you're not sure, say "I need more clues."\n\n{history}\n\nYour guess:"""
    return query_llm("MISTRAL", [{"role": "user", "content": prompt}])

def hint_response():
    if not state["hint_mode"] or not state["started"]:
        return "Hint mode is off or game not active."
    question = state["current_q"]
    history = "\n".join([f"{q} - {a}" for q, a in state["history"]])
    prompt = f"""The player seems confused by this question: "{question}". Previous Q&A were:\n{history}\n\nGive a helpful, simple hint."""
    return query_llm("MISTRAL", [{"role": "user", "content": prompt}])

def toggle_hint_mode():
    state["hint_mode"] = not state["hint_mode"]
    return (
        "Hint Mode: ON" if state["hint_mode"] else "Hint Mode: OFF",
        gr.update(visible=True)
    )

# UI
with gr.Blocks(title="Kasoti", theme=gr.themes.Soft(primary_hue="pink", secondary_hue="blue")) as demo:
    gr.Markdown(
        """
        <link href="https://fonts.googleapis.com/css2?family=Comic+Neue&display=swap" rel="stylesheet">
        <style>
            * { font-family: 'Comic Neue', cursive; }
            body {
                background: linear-gradient(120deg, #ffe0f0 0%, #e0f7ff 100%);
            }
            .gr-button {
                border-radius: 12px !important;
                font-size: 16px !important;
                padding: 10px 18px !important;
            }
            .title-text {
                text-align: center;
                font-size: 32px;
                color: #ff69b4;
                font-weight: bold;
                margin-bottom: 0;
            }
            .subtitle-text {
                text-align: center;
                font-size: 16px;
                color: #555;
                margin-top: 0;
            }
        </style>
        <div class='title-text'>🧠 Kasoti - The Mind Reading Game</div>
        <p class='subtitle-text'>Think of something and answer my yes/no questions — let's see if I can guess it in 20 tries! 🕵️‍♀️</p>
        """
    )
    with gr.Row():
        start = gr.Button("🎲 Start Game")
        hint_toggle = gr.Button("💡 Toggle Hint Mode")
        hint_status = gr.Textbox(value="Hint Mode: OFF", show_label=False, interactive=False)

    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### 🎤 Your Answer")
            lang_sel = gr.CheckboxGroup(["English", "Urdu"], label="🌐 Choose Language", value=["English"])
            mic_input = gr.Audio(sources=["microphone"], type="numpy", label="🎙️ Speak Your Answer")
            transcribe = gr.Button("📝 Transcribe Voice")
            typed_ans = gr.Textbox(label="✍️ Or Type Your Answer")
            submit = gr.Button("✅ Yep, Here You Go!")

        with gr.Column(scale=2):
            gr.Markdown("### 🎮 Game Progress")
            question_progress = gr.Slider(minimum=1, maximum=20, value=1, label="❓ Question Number", interactive=False)
            game_q_box = gr.Textbox(label="🧩 Current Question", interactive=False, lines=2)
            game_history = gr.Textbox(label="📜 Game Updates", interactive=False, lines=3)
            final_answer_box = gr.Textbox(label="🎯 Final Guess", visible=False, lines=2, interactive=False)

    # Button logic
    start.click(
        fn=begin_game,
        outputs=[game_q_box, game_history, final_answer_box, submit, final_answer_box, question_progress]
    )
    hint_toggle.click(fn=toggle_hint_mode, outputs=[hint_status, game_history])
    hint_toggle.click(fn=hint_response, outputs=[game_history])
    transcribe.click(fn=convert_audio_to_text, inputs=[mic_input, lang_sel], outputs=[typed_ans])
    submit.click(
        fn=interpret_answer,
        inputs=[typed_ans],
        outputs=[game_q_box, typed_ans, final_answer_box, game_history, final_answer_box, question_progress]
    )

demo.launch()