HAMMALE commited on
Commit
e2ae385
Β·
verified Β·
1 Parent(s): 6b5b0cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +161 -125
app.py CHANGED
@@ -111,69 +111,28 @@ def download_and_load_model(progress=gr.Progress()):
111
 
112
  try:
113
  progress(0, desc="Downloading model...")
114
- progress(0.5, desc="Loading model (this may take several minutes)...")
115
 
116
  pipe = pipeline(
117
  "text-generation",
118
  model=MODEL_NAME,
119
- torch_dtype="auto",
120
  device_map="auto",
121
  )
122
 
123
  progress(0.95, desc="Finalizing...")
124
  model_loaded = True
125
  progress(1.0, desc="Model loaded!")
126
- return f"Model '{MODEL_NAME}' loaded successfully!"
127
  except Exception as e:
128
  return f"Error: {str(e)}"
129
 
130
  def get_tool_descriptions() -> str:
131
  return "\n".join([f"- {tool.name}: {tool.description}" for tool in TOOLS])
132
 
133
- THINK_ONLY_PROMPT = """You are a helpful AI assistant. Solve problems step-by-step.
134
-
135
- Format:
136
- Thought: your reasoning
137
- Answer: your final answer
138
-
139
- Question: {question}
140
-
141
- Think step by step:"""
142
-
143
- ACT_ONLY_PROMPT = """You are a helpful AI assistant with tools.
144
-
145
- Available tools:
146
- {tools}
147
-
148
- Format:
149
- Action: tool_name
150
- Action Input: input
151
-
152
- Question: {question}
153
-
154
- Action:"""
155
-
156
- REACT_PROMPT = """You are a helpful AI assistant with tools.
157
-
158
- Available tools:
159
- {tools}
160
-
161
- Pattern:
162
- Thought: what to do next
163
- Action: tool_name
164
- Action Input: input
165
- Observation: [result]
166
- ... repeat as needed
167
- Thought: I know the answer
168
- Answer: final answer
169
-
170
- Question: {question}
171
-
172
- Thought:"""
173
-
174
  def parse_action(text: str) -> tuple:
175
  action_match = re.search(r'Action:\s*(\w+)', text, re.IGNORECASE)
176
- input_match = re.search(r'Action Input:\s*(.+?)(?=\n(?:Thought:|Action:|Answer:|$))', text, re.IGNORECASE | re.DOTALL)
177
  return (action_match.group(1).strip(), input_match.group(1).strip()) if action_match and input_match else (None, None)
178
 
179
  def call_tool(tool_name: str, tool_input: str) -> str:
@@ -182,134 +141,211 @@ def call_tool(tool_name: str, tool_input: str) -> str:
182
  return tool(tool_input)
183
  return f"Error: Tool '{tool_name}' not found."
184
 
185
- def call_llm(prompt: str, max_tokens: int = 500) -> str:
186
  if not model_loaded:
187
- return "Error: Model not loaded."
188
 
189
  try:
190
- messages = [{"role": "user", "content": prompt}]
191
- outputs = pipe(messages, max_new_tokens=max_tokens)
192
  return outputs[0]["generated_text"][-1]["content"]
193
  except Exception as e:
194
  return f"Error: {str(e)}"
195
 
196
- def think_only_mode(question: str) -> str:
197
- if not model_loaded:
198
- return "Error: Model not loaded."
 
 
 
 
 
 
 
 
199
 
200
- output = "**Mode: Think-Only**\n\n"
201
- response = call_llm(THINK_ONLY_PROMPT.format(question=question), max_tokens=800)
 
202
 
203
- for line in response.split('\n'):
204
- if line.strip():
205
- output += f"**{line.strip()}**\n\n" if line.strip().startswith(('Thought:', 'Answer:')) else f"{line}\n\n"
206
 
207
- return output + "\n---\n"
 
208
 
209
- def act_only_mode(question: str, max_iterations: int = 5) -> str:
 
 
210
  if not model_loaded:
211
  return "Error: Model not loaded."
212
 
213
- output = "**Mode: Act-Only**\n\n"
214
- conversation = ACT_ONLY_PROMPT.format(question=question, tools=get_tool_descriptions())
 
 
 
 
 
 
 
 
215
 
216
- for _ in range(max_iterations):
217
- response = call_llm(conversation, max_tokens=300)
218
-
219
- if 'Answer:' in response:
220
- match = re.search(r'Answer:\s*(.+)', response, re.IGNORECASE | re.DOTALL)
221
- if match:
222
- output += f"**Answer:** {match.group(1).strip()}\n\n"
223
- break
 
 
 
 
 
224
 
225
  action_name, action_input = parse_action(response)
 
226
  if action_name and action_input:
227
- output += f"**Action:** {action_name}\n**Input:** {action_input}\n\n"
228
  observation = call_tool(action_name, action_input)
229
- output += f"**Observation:** {observation}\n\n"
230
- conversation += f"\n{response}\nObservation: {observation}\n\n"
 
 
231
  else:
232
- output += f"Could not parse action.\n\n"
233
  break
234
 
235
- return output + "\n---\n"
236
 
237
- def react_mode(question: str, max_iterations: int = 5) -> str:
 
 
238
  if not model_loaded:
239
  return "Error: Model not loaded."
240
 
241
- output = "**Mode: ReAct**\n\n"
242
- conversation = REACT_PROMPT.format(question=question, tools=get_tool_descriptions())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
- for _ in range(max_iterations):
245
- response = call_llm(conversation, max_tokens=400)
246
-
247
- for thought in re.findall(r'Thought:\s*(.+?)(?=\n(?:Action:|Answer:|$))', response, re.IGNORECASE | re.DOTALL):
248
- output += f"**Thought:** {thought.strip()}\n\n"
 
 
 
 
 
 
249
 
250
- if 'Answer:' in response:
251
- match = re.search(r'Answer:\s*(.+)', response, re.IGNORECASE | re.DOTALL)
252
- if match:
253
- output += f"**Answer:** {match.group(1).strip()}\n\n"
254
- break
255
 
256
  action_name, action_input = parse_action(response)
 
257
  if action_name and action_input:
258
- output += f"**Action:** {action_name}\n**Input:** {action_input}\n\n"
259
  observation = call_tool(action_name, action_input)
260
- output += f"**Observation:** {observation}\n\n"
261
- conversation += f"\n{response}\nObservation: {observation}\n\nThought:"
 
 
262
  else:
263
- if 'Answer:' not in response:
264
- output += "No action found.\n\n"
265
  break
266
 
267
- return output + "\n---\n"
268
 
269
- EXAMPLES = [
270
- "What is the capital of France and its weather?",
271
- "Who wrote 'To Kill a Mockingbird'?",
272
- "Calculate: 1000 * (1.05 ** 3)",
273
- "What is Tokyo's population?",
274
- ]
275
-
276
- def run_comparison(question: str, mode: str):
277
  if mode == "Think-Only":
278
- return think_only_mode(question), "", ""
279
  elif mode == "Act-Only":
280
- return "", act_only_mode(question), ""
281
  elif mode == "ReAct":
282
- return "", "", react_mode(question)
283
- elif mode == "All (Compare)":
284
- return think_only_mode(question), act_only_mode(question), react_mode(question)
285
- return "Invalid mode.", "", ""
286
 
287
- with gr.Blocks(title="LLM Reasoning Modes") as demo:
288
- gr.Markdown("# LLM Reasoning Modes Comparison\n\n**Model:** openai/gpt-oss-20b\n\n**Tools:** DuckDuckGo | Wikipedia | Weather | Calculator | Python")
 
 
 
 
 
 
289
 
290
  with gr.Row():
291
- download_btn = gr.Button("Download & Load Model", variant="primary", size="lg")
292
- model_status = gr.Textbox(label="Status", value="Click to download", interactive=False)
293
 
294
  with gr.Row():
295
- with gr.Column(scale=3):
296
- question_input = gr.Textbox(label="Question", lines=3)
297
- mode_dropdown = gr.Dropdown(choices=["Think-Only", "Act-Only", "ReAct", "All (Compare)"], value="All (Compare)", label="Mode")
298
- submit_btn = gr.Button("Run", variant="primary", size="lg")
299
- with gr.Column(scale=1):
300
- gr.Markdown("**Examples**")
301
- for idx, ex in enumerate(EXAMPLES):
302
- gr.Button(f"Ex {idx+1}", size="sm").click(fn=lambda e=ex: e, outputs=question_input)
303
 
304
- gr.Markdown("---")
 
 
 
 
 
305
 
306
  with gr.Row():
307
- think_output = gr.Markdown(label="Think-Only")
308
- act_output = gr.Markdown(label="Act-Only")
309
- react_output = gr.Markdown(label="ReAct")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
- download_btn.click(fn=download_and_load_model, outputs=model_status)
312
- submit_btn.click(fn=run_comparison, inputs=[question_input, mode_dropdown], outputs=[think_output, act_output, react_output])
313
 
314
  if __name__ == "__main__":
315
  demo.launch(share=True)
 
111
 
112
  try:
113
  progress(0, desc="Downloading model...")
114
+ progress(0.5, desc="Loading model...")
115
 
116
  pipe = pipeline(
117
  "text-generation",
118
  model=MODEL_NAME,
119
+ torch_dtype=torch.bfloat16,
120
  device_map="auto",
121
  )
122
 
123
  progress(0.95, desc="Finalizing...")
124
  model_loaded = True
125
  progress(1.0, desc="Model loaded!")
126
+ return f"Model loaded successfully!"
127
  except Exception as e:
128
  return f"Error: {str(e)}"
129
 
130
  def get_tool_descriptions() -> str:
131
  return "\n".join([f"- {tool.name}: {tool.description}" for tool in TOOLS])
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  def parse_action(text: str) -> tuple:
134
  action_match = re.search(r'Action:\s*(\w+)', text, re.IGNORECASE)
135
+ input_match = re.search(r'Action Input:\s*(.+?)(?=\n|$)', text, re.IGNORECASE | re.DOTALL)
136
  return (action_match.group(1).strip(), input_match.group(1).strip()) if action_match and input_match else (None, None)
137
 
138
  def call_tool(tool_name: str, tool_input: str) -> str:
 
141
  return tool(tool_input)
142
  return f"Error: Tool '{tool_name}' not found."
143
 
144
+ def call_llm(messages: List[Dict], max_tokens: int = 500) -> str:
145
  if not model_loaded:
146
+ return "Error: Model not loaded. Please click 'Load Model' button first."
147
 
148
  try:
149
+ outputs = pipe(messages, max_new_tokens=max_tokens, do_sample=True, temperature=0.7)
 
150
  return outputs[0]["generated_text"][-1]["content"]
151
  except Exception as e:
152
  return f"Error: {str(e)}"
153
 
154
+ def chat_think_only(message, history, mode):
155
+ """Think-Only mode: Pure reasoning without tools"""
156
+
157
+ system_prompt = """You are a helpful AI assistant that thinks step-by-step. For each question:
158
+ 1. Think through the problem carefully
159
+ 2. Show your reasoning process
160
+ 3. Provide a clear answer
161
+
162
+ Always respond conversationally and naturally."""
163
+
164
+ messages = [{"role": "system", "content": system_prompt}]
165
 
166
+ for user_msg, assistant_msg in history:
167
+ messages.append({"role": "user", "content": user_msg})
168
+ messages.append({"role": "assistant", "content": assistant_msg})
169
 
170
+ messages.append({"role": "user", "content": message})
 
 
171
 
172
+ response = call_llm(messages, max_tokens=800)
173
+ return response
174
 
175
+ def chat_act_only(message, history, mode):
176
+ """Act-Only mode: Use tools to answer"""
177
+
178
  if not model_loaded:
179
  return "Error: Model not loaded."
180
 
181
+ system_prompt = f"""You are a helpful AI assistant with access to tools. Use tools to find accurate information.
182
+
183
+ Available tools:
184
+ {get_tool_descriptions()}
185
+
186
+ When you need to use a tool, respond with:
187
+ Action: tool_name
188
+ Action Input: your input
189
+
190
+ After getting results, provide a natural answer to the user."""
191
 
192
+ messages = [{"role": "system", "content": system_prompt}]
193
+
194
+ for user_msg, assistant_msg in history:
195
+ messages.append({"role": "user", "content": user_msg})
196
+ messages.append({"role": "assistant", "content": assistant_msg})
197
+
198
+ messages.append({"role": "user", "content": message})
199
+
200
+ max_iterations = 3
201
+ response_parts = []
202
+
203
+ for iteration in range(max_iterations):
204
+ response = call_llm(messages, max_tokens=400)
205
 
206
  action_name, action_input = parse_action(response)
207
+
208
  if action_name and action_input:
209
+ response_parts.append(f"πŸ”§ Using tool: **{action_name}**")
210
  observation = call_tool(action_name, action_input)
211
+ response_parts.append(f"πŸ“Š Result: {observation}\n")
212
+
213
+ messages.append({"role": "assistant", "content": response})
214
+ messages.append({"role": "user", "content": f"Tool result: {observation}\n\nNow provide a natural answer to the user based on this information."})
215
  else:
216
+ response_parts.append(response)
217
  break
218
 
219
+ return "\n\n".join(response_parts)
220
 
221
+ def chat_react(message, history, mode):
222
+ """ReAct mode: Interleaved thinking and tool use"""
223
+
224
  if not model_loaded:
225
  return "Error: Model not loaded."
226
 
227
+ system_prompt = f"""You are a helpful AI assistant that thinks and uses tools.
228
+
229
+ Available tools:
230
+ {get_tool_descriptions()}
231
+
232
+ For each question:
233
+ 1. Think about what you need to do
234
+ 2. Use tools when you need information
235
+ 3. Think about the results
236
+ 4. Provide a clear answer
237
+
238
+ Format for tool use:
239
+ Thought: [your reasoning]
240
+ Action: tool_name
241
+ Action Input: input
242
+
243
+ After tool results, think again and either use another tool or provide the final answer."""
244
+
245
+ messages = [{"role": "system", "content": system_prompt}]
246
 
247
+ for user_msg, assistant_msg in history:
248
+ messages.append({"role": "user", "content": user_msg})
249
+ messages.append({"role": "assistant", "content": assistant_msg})
250
+
251
+ messages.append({"role": "user", "content": message})
252
+
253
+ max_iterations = 3
254
+ response_parts = []
255
+
256
+ for iteration in range(max_iterations):
257
+ response = call_llm(messages, max_tokens=400)
258
 
259
+ thoughts = re.findall(r'Thought:\s*(.+?)(?=\n|Action:|$)', response, re.IGNORECASE | re.DOTALL)
260
+ for thought in thoughts:
261
+ response_parts.append(f"πŸ’­ **Thought:** {thought.strip()}")
 
 
262
 
263
  action_name, action_input = parse_action(response)
264
+
265
  if action_name and action_input:
266
+ response_parts.append(f"πŸ”§ **Action:** {action_name} with input: {action_input}")
267
  observation = call_tool(action_name, action_input)
268
+ response_parts.append(f"πŸ“Š **Result:** {observation}\n")
269
+
270
+ messages.append({"role": "assistant", "content": response})
271
+ messages.append({"role": "user", "content": f"Observation: {observation}\n\nContinue thinking or provide final answer."})
272
  else:
273
+ if not thoughts:
274
+ response_parts.append(response)
275
  break
276
 
277
+ return "\n\n".join(response_parts)
278
 
279
+ def chat_response(message, history, mode):
280
+ """Route to appropriate mode"""
 
 
 
 
 
 
281
  if mode == "Think-Only":
282
+ return chat_think_only(message, history, mode)
283
  elif mode == "Act-Only":
284
+ return chat_act_only(message, history, mode)
285
  elif mode == "ReAct":
286
+ return chat_react(message, history, mode)
287
+ else:
288
+ return "Please select a reasoning mode."
 
289
 
290
+ with gr.Blocks(title="LLM Reasoning Chat", theme=gr.themes.Soft()) as demo:
291
+ gr.Markdown("""
292
+ # πŸ€– LLM Reasoning Chat
293
+
294
+ **Model:** openai/gpt-oss-20b | **Tools:** DuckDuckGo, Wikipedia, Weather, Calculator, Python
295
+
296
+ Select a reasoning mode and start chatting!
297
+ """)
298
 
299
  with gr.Row():
300
+ load_btn = gr.Button("πŸš€ Load Model", variant="primary", size="lg")
301
+ status = gr.Textbox(label="Status", value="Click 'Load Model' to start", interactive=False, scale=2)
302
 
303
  with gr.Row():
304
+ mode_selector = gr.Radio(
305
+ choices=["Think-Only", "Act-Only", "ReAct"],
306
+ value="ReAct",
307
+ label="Reasoning Mode",
308
+ info="Think-Only: Pure reasoning | Act-Only: Tools only | ReAct: Think + Tools"
309
+ )
 
 
310
 
311
+ chatbot = gr.Chatbot(
312
+ label="Chat",
313
+ height=500,
314
+ show_label=True,
315
+ avatar_images=(None, "https://huggingface.co/datasets/huggingface/brand-assets/resolve/main/hf-logo.png")
316
+ )
317
 
318
  with gr.Row():
319
+ msg = gr.Textbox(
320
+ label="Message",
321
+ placeholder="Ask me anything...",
322
+ scale=4
323
+ )
324
+ submit = gr.Button("Send", variant="primary", scale=1)
325
+
326
+ gr.Examples(
327
+ examples=[
328
+ "What is the capital of France and what's the weather there?",
329
+ "Who wrote 'To Kill a Mockingbird' and when was it published?",
330
+ "Calculate the compound interest on $1000 at 5% for 3 years",
331
+ "What is the population of Tokyo?",
332
+ "Explain quantum mechanics in simple terms",
333
+ ],
334
+ inputs=msg,
335
+ label="Example Questions"
336
+ )
337
+
338
+ clear = gr.Button("πŸ—‘οΈ Clear Chat")
339
+
340
+ load_btn.click(fn=download_and_load_model, outputs=status)
341
+
342
+ msg.submit(fn=chat_response, inputs=[msg, chatbot, mode_selector], outputs=chatbot)
343
+ submit.click(fn=chat_response, inputs=[msg, chatbot, mode_selector], outputs=chatbot)
344
+
345
+ msg.submit(lambda: "", None, msg)
346
+ submit.click(lambda: "", None, msg)
347
 
348
+ clear.click(lambda: None, None, chatbot)
 
349
 
350
  if __name__ == "__main__":
351
  demo.launch(share=True)