chthees commited on
Commit
d44df79
·
verified ·
1 Parent(s): d4704a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -84
app.py CHANGED
@@ -1,139 +1,151 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
 
4
- # --- CONFIGURATION ---
5
- # We use the Instruct version of the 1B model as it follows rules best
6
- MODEL_ID = "meta-llama/Llama-3.2-1B-Instruct"
7
 
8
- # --- THE RIDDLES (DATABASE) ---
9
- # Each riddle has a public 'scenario' and a hidden 'solution'.
 
 
 
 
 
 
 
 
10
  RIDDLES = {
11
- "The Dead Man": {
12
- "scenario": "A man lies dead in a field. Next to him is an unopened package. There are no footprints around him. How did he die?",
13
- "solution": "The man jumped from a plane. The package was his parachute, which failed to open."
14
  },
15
- "The Barman": {
16
- "scenario": "A man walks into a bar and asks for a glass of water. The barman pulls out a gun and points it at him. The man says 'Thank you' and walks out. Why?",
17
- "solution": "The man had the hiccups. The barman used the gun to scare him, curing the hiccups. The man was thankful."
18
  },
19
- "The Cabin": {
20
- "scenario": "Two men are in a cabin in the woods. One is dead. The cabin did not burn down, but the dead man is charred. How happened?",
21
- "solution": "The cabin is the cabin of a crashed airplane. The man died in the crash/fire."
22
  },
23
- "The Suitcase": {
24
- "scenario": "A woman opens her suitcase and finds a dead man inside. She is not arrested or afraid. Why?",
25
- "solution": "The 'suitcase' is actually a coffin. The woman is attending a funeral."
26
  }
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  def respond(
30
  message,
31
  history: list[dict[str, str]],
32
- system_message, # We will ignore the user input for this and build our own
33
  max_tokens,
34
  temperature,
35
  top_p,
36
- hf_token: gr.OAuthToken,
37
- selected_riddle, # The dropdown input
38
  ):
39
- """
40
- This function handles the game logic. It injects the hidden solution
41
- into the system prompt based on the user's selection.
42
- """
43
- client = InferenceClient(token=hf_token.token, model=MODEL_ID)
44
-
45
- # 1. Get the current riddle data
46
  current_game = RIDDLES[selected_riddle]
47
 
48
- # 2. Construct the Strict Game Master Prompt
49
- # This is where the "Context Learning" happens. We teach the model the rules in-context.
50
  game_master_prompt = (
51
- f"You are the Game Master of a lateral thinking puzzle. "
52
- f"CURRENT PUZZLE SCENARIO: '{current_game['scenario']}' "
53
- f"HIDDEN SOLUTION (User does not know this!): '{current_game['solution']}' "
54
- f"\n\n"
55
- f"RULES FOR YOU:"
56
- f"1. The user will ask questions to figure out the solution."
57
- f"2. You must analyze their question against the HIDDEN SOLUTION."
58
- f"3. Answer ONLY with 'Yes', 'No', or 'Irrelevant'. "
59
- f"4. If the user guesses the solution correctly, say 'CORRECT! You solved it: [Explain solution]'."
60
- f"5. Do NOT give hints. Do NOT explain your 'Yes/No' answers."
61
  )
62
 
63
- # 3. Build message history
64
- messages = [{"role": "system", "content": game_master_prompt}]
65
- messages.extend(history)
66
- messages.append({"role": "user", "content": message})
67
 
68
- response = ""
 
 
 
 
 
 
 
 
69
 
70
- # 4. Stream the response
71
- for message in client.chat_completion(
72
- messages,
73
- max_tokens=max_tokens,
74
- stream=True,
75
- temperature=temperature, # Low temp = more strict adherence to Yes/No
76
- top_p=top_p,
77
- ):
78
- choices = message.choices
79
- token = ""
80
- if len(choices) and choices[0].delta.content:
81
- token = choices[0].delta.content
82
 
83
- response += token
84
- yield response
85
 
 
86
 
87
- # --- UI SETUP ---
88
- # We use Blocks to add the Dropdown menu cleanly above the chat
89
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
90
-
91
- # Header
92
- gr.Markdown("# 🕵️ The Yes/No Detective")
93
  gr.Markdown(
94
- "**Instructions:** I am thinking of a strange situation. "
95
- "Ask me questions to figure out the truth! I can only answer **Yes**, **No**, or **Irrelevant**."
96
  )
97
 
 
98
  with gr.Row():
99
- # The Dropdown to select the "Level"
100
  riddle_select = gr.Dropdown(
101
  choices=list(RIDDLES.keys()),
102
- value="The Dead Man",
103
- label="Select a Mystery Case",
104
  interactive=True
105
  )
106
 
107
- # Display the current scenario description dynamically
108
  scenario_display = gr.Textbox(
109
- label="The Scenario (Clue)",
110
- value=RIDDLES["The Dead Man"]["scenario"],
111
  interactive=False
112
  )
113
 
114
- # Function to update the text box when dropdown changes
115
  def update_scenario(choice):
116
  return RIDDLES[choice]["scenario"]
117
 
118
  riddle_select.change(fn=update_scenario, inputs=riddle_select, outputs=scenario_display)
119
 
120
- # The Chat Interface
121
- # Note: We hide the system message input because we hardcode it in the function
122
  chatbot = gr.ChatInterface(
123
  respond,
124
  type="messages",
125
  additional_inputs=[
126
- gr.Textbox(value="Game Master", visible=False), # Hidden system prompt placeholder
127
- gr.Slider(minimum=1, maximum=512, value=100, step=1, label="Max tokens", visible=False),
128
- gr.Slider(minimum=0.1, maximum=2.0, value=0.2, step=0.1, label="Temperature"), # Low temp for precision
129
- gr.Slider(minimum=0.1, maximum=1.0, value=0.9, step=0.05, label="Top-p"),
130
- riddle_select # Pass the selected riddle to the function
131
  ],
132
  )
133
-
134
- # Sidebar for login
135
- with gr.Sidebar():
136
- gr.LoginButton()
137
 
138
  if __name__ == "__main__":
139
  demo.launch()
 
1
  import gradio as gr
2
+ from llama_cpp import Llama
3
 
4
+ # --- 1. SETUP & DATEN ---
 
 
5
 
6
+ # Das lokale Modell laden (dein angegebener Pfad)
7
+ llm = Llama.from_pretrained(
8
+ repo_id="simonper/Llama-3.2-1B-bnb-4bit_finetome-100k_gguf_4bit",
9
+ filename="Llama-3.2-1B.Q4_K_M.gguf",
10
+ n_ctx=4096, # Context window
11
+ n_threads=8, # CPU threads (anpassbar)
12
+ n_gpu_layers=0, # 0 für CPU, höher setzen wenn du GPU hast
13
+ )
14
+
15
+ # Die Datenbank der Rätsel (Szenario = Öffentlich, Lösung = Versteckt)
16
  RIDDLES = {
17
+ "Der tote Mann": {
18
+ "scenario": "Ein Mann liegt tot auf einer Wiese. Neben ihm liegt ein ungeöffnetes Paket. Es sind keine Fußspuren zu sehen. Wie ist er gestorben?",
19
+ "solution": "Der Mann ist aus einem Flugzeug gesprungen. Das Paket war sein Fallschirm, der sich nicht geöffnet hat."
20
  },
21
+ "Der Barman": {
22
+ "scenario": "Ein Mann geht in eine Bar und bestellt ein Glas Wasser. Der Barkeeper zieht eine Waffe und richtet sie auf ihn. Der Mann sagt 'Danke' und geht. Warum?",
23
+ "solution": "Der Mann hatte Schluckauf. Der Schreck durch die Waffe hat ihn geheilt, weshalb er dankbar war."
24
  },
25
+ "Die Hütte": {
26
+ "scenario": "Zwei Männer sind in einer Hütte im Wald. Einer ist tot. Die Hütte ist nicht abgebrannt, aber der tote Mann ist verkohlt. Was ist passiert?",
27
+ "solution": "Die Hütte ist die Kabine eines abgestürzten Flugzeugs. Der Mann starb beim Absturzfeuer."
28
  },
29
+ "Der Koffer": {
30
+ "scenario": "Eine Frau öffnet ihren Koffer und findet einen toten Mann darin. Sie wird nicht verhaftet und hat keine Angst. Warum?",
31
+ "solution": "Der 'Koffer' ist eigentlich ein Sarg. Die Frau ist auf einer Beerdigung."
32
  }
33
  }
34
 
35
+ # --- 2. HELPER FUNCTIONS ---
36
+
37
+ def build_prompt(system_message: str, history: list[dict], user_message: str) -> str:
38
+ """
39
+ Konstruiert den Prompt für das Llama Modell.
40
+ Da wir Llama-3 nutzen, ist ein Format wichtig, das System-Instruktionen klar trennt.
41
+ """
42
+ lines = []
43
+
44
+ # System Prompt Injection
45
+ if system_message:
46
+ lines.append(f"System: {system_message}\n")
47
+
48
+ # History aufbauen
49
+ for turn in history:
50
+ role = turn["role"]
51
+ content = turn["content"]
52
+ if role == "user":
53
+ lines.append(f"User: {content}")
54
+ elif role == "assistant":
55
+ lines.append(f"Assistant: {content}")
56
+
57
+ # Aktuelle Nachricht
58
+ lines.append(f"User: {user_message}")
59
+ lines.append("Assistant:")
60
+
61
+ return "\n".join(lines)
62
+
63
+
64
  def respond(
65
  message,
66
  history: list[dict[str, str]],
67
+ system_message_dummy, # Wir ignorieren den Input vom Slider und bauen unseren eigenen
68
  max_tokens,
69
  temperature,
70
  top_p,
71
+ selected_riddle, # Das kommt vom Dropdown
 
72
  ):
73
+ # 1. Das aktuelle Rätsel laden
 
 
 
 
 
 
74
  current_game = RIDDLES[selected_riddle]
75
 
76
+ # 2. Den "Game Master" System Prompt bauen (Hier passiert das Context Learning)
77
+ # Wir injizieren die Lösung direkt in den Kontext des Modells
78
  game_master_prompt = (
79
+ f"Du bist der Spielleiter eines Laterale-Denk-Rätsels (Black Stories). "
80
+ f"AKTUELLES SZENARIO: '{current_game['scenario']}' "
81
+ f"VERSTECKTE LÖSUNG (Der User kennt diese NICHT!): '{current_game['solution']}' "
82
+ f"\nREGELN FÜR DICH:\n"
83
+ f"1. Analysiere die Frage des Users logisch in Bezug auf die versteckte Lösung.\n"
84
+ f"2. Antworte AUSSCHLIESSLICH mit: 'Ja', 'Nein', oder 'Irrelevant'.\n"
85
+ f"3. Wenn der User die Lösung errät, sage: 'KORREKT! Du hast es gelöst: [Erklärung]'.\n"
86
+ f"4. Gib KEINE Hinweise."
 
 
87
  )
88
 
89
+ # 3. Prompt zusammenbauen
90
+ prompt = build_prompt(game_master_prompt, history, message)
 
 
91
 
92
+ # 4. Llama.cpp aufrufen
93
+ output = llm(
94
+ prompt,
95
+ max_tokens=int(max_tokens),
96
+ temperature=float(temperature),
97
+ top_p=float(top_p),
98
+ stop=["User:", "System:"],
99
+ echo=False # Wichtig: Den Prompt nicht wiederholen
100
+ )
101
 
102
+ reply = output["choices"][0]["text"].strip()
103
+ return reply
 
 
 
 
 
 
 
 
 
 
104
 
 
 
105
 
106
+ # --- 3. UI AUFBAU (GRADIO BLOCKS) ---
107
 
 
 
108
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
109
+ gr.Markdown("# 🕵️ Der Ja/Nein Detektiv (Llama GGUF Edition)")
 
 
110
  gr.Markdown(
111
+ "**Anleitung:** Ich denke an eine seltsame Situation. "
112
+ "Stelle mir Ja/Nein-Fragen, um herauszufinden, was passiert ist!"
113
  )
114
 
115
+ # Das Dropdown Menü für die Rätsel-Auswahl
116
  with gr.Row():
 
117
  riddle_select = gr.Dropdown(
118
  choices=list(RIDDLES.keys()),
119
+ value="Der tote Mann",
120
+ label="Wähle einen Fall",
121
  interactive=True
122
  )
123
 
124
+ # Textfeld, das das Szenario anzeigt
125
  scenario_display = gr.Textbox(
126
+ label="Das Szenario (Dein Hinweis)",
127
+ value=RIDDLES["Der tote Mann"]["scenario"],
128
  interactive=False
129
  )
130
 
131
+ # Logik: Wenn Dropdown geändert wird, Textbox aktualisieren
132
  def update_scenario(choice):
133
  return RIDDLES[choice]["scenario"]
134
 
135
  riddle_select.change(fn=update_scenario, inputs=riddle_select, outputs=scenario_display)
136
 
137
+ # Chat Interface
 
138
  chatbot = gr.ChatInterface(
139
  respond,
140
  type="messages",
141
  additional_inputs=[
142
+ gr.Textbox(value="", visible=False), # Dummy für System Message (wir nutzen den generierten)
143
+ gr.Slider(minimum=1, maximum=512, value=100, step=1, label="Max new tokens"),
144
+ gr.Slider(minimum=0.1, maximum=2.0, value=0.2, step=0.1, label="Temperature (Niedrig für Logik)"),
145
+ gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p"),
146
+ riddle_select # Das ausgewählte Rätsel wird an die respond-Funktion übergeben
147
  ],
148
  )
 
 
 
 
149
 
150
  if __name__ == "__main__":
151
  demo.launch()