likki1715 commited on
Commit
086299f
·
verified ·
1 Parent(s): 52ee7b2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -247
app.py CHANGED
@@ -2,7 +2,6 @@ import os
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
5
- import anthropic
6
  import re
7
  from duckduckgo_search import DDGS
8
 
@@ -12,7 +11,6 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
12
  # --- Tool Implementations ---
13
 
14
  def web_search(query: str) -> str:
15
- """Search the web using DuckDuckGo."""
16
  try:
17
  with DDGS() as ddgs:
18
  results = list(ddgs.text(query, max_results=5))
@@ -20,298 +18,187 @@ def web_search(query: str) -> str:
20
  return "No results found."
21
  output = []
22
  for r in results:
23
- output.append(f"Title: {r.get('title', '')}\nURL: {r.get('href', '')}\nSnippet: {r.get('body', '')}\n")
24
  return "\n---\n".join(output)
25
  except Exception as e:
26
  return f"Search error: {e}"
27
 
28
 
29
- def fetch_page(url: str) -> str:
30
- """Fetch content from a URL."""
31
- try:
32
- headers = {"User-Agent": "Mozilla/5.0"}
33
- response = requests.get(url, headers=headers, timeout=10)
34
- response.raise_for_status()
35
- # Basic text extraction
36
- text = response.text
37
- # Remove HTML tags crudely
38
- text = re.sub(r'<[^>]+>', ' ', text)
39
- text = re.sub(r'\s+', ' ', text).strip()
40
- return text[:3000]
41
- except Exception as e:
42
- return f"Error fetching page: {e}"
43
-
44
-
45
- def run_python(code: str) -> str:
46
- """Execute Python code and return the output."""
47
- import sys
48
- from io import StringIO
49
- old_stdout = sys.stdout
50
- sys.stdout = StringIO()
51
- try:
52
- exec_globals = {}
53
- exec(code, exec_globals)
54
- output = sys.stdout.getvalue()
55
- return output if output else "Code executed successfully (no output)."
56
- except Exception as e:
57
- return f"Error executing code: {e}"
58
- finally:
59
- sys.stdout = old_stdout
60
-
61
-
62
  def wikipedia_search(query: str) -> str:
63
- """Search Wikipedia for a topic."""
64
  try:
65
  search_url = "https://en.wikipedia.org/w/api.php"
66
- params = {
67
- "action": "query",
68
- "list": "search",
69
- "srsearch": query,
70
- "format": "json",
71
- "srlimit": 3,
72
- }
73
  response = requests.get(search_url, params=params, timeout=10)
74
  data = response.json()
75
  results = data.get("query", {}).get("search", [])
76
  if not results:
77
  return "No Wikipedia results found."
78
-
79
- # Fetch first result's summary
80
  title = results[0]["title"]
81
- summary_params = {
82
- "action": "query",
83
- "titles": title,
84
- "prop": "extracts",
85
- "exintro": True,
86
- "explaintext": True,
87
- "format": "json",
88
- }
89
  summary_response = requests.get(search_url, params=summary_params, timeout=10)
90
  summary_data = summary_response.json()
91
  pages = summary_data.get("query", {}).get("pages", {})
92
  for page_id, page in pages.items():
93
  extract = page.get("extract", "No content available.")
94
- return f"Wikipedia: {title}\n\n{extract[:2000]}"
95
  return "No content found."
96
  except Exception as e:
97
  return f"Wikipedia error: {e}"
98
 
99
 
100
- # --- Tool Definitions for Claude API ---
101
- TOOLS = [
102
- {
103
- "name": "web_search",
104
- "description": "Search the web for current information. Use this for facts, recent events, or anything that requires looking up.",
105
- "input_schema": {
106
- "type": "object",
107
- "properties": {
108
- "query": {
109
- "type": "string",
110
- "description": "The search query"
111
- }
112
- },
113
- "required": ["query"]
114
- }
115
- },
116
- {
117
- "name": "wikipedia_search",
118
- "description": "Search Wikipedia for factual information about people, places, events, concepts, etc.",
119
- "input_schema": {
120
- "type": "object",
121
- "properties": {
122
- "query": {
123
- "type": "string",
124
- "description": "The topic to search on Wikipedia"
125
- }
126
- },
127
- "required": ["query"]
128
- }
129
- },
130
- {
131
- "name": "fetch_page",
132
- "description": "Fetch and read the content of a specific URL/webpage.",
133
- "input_schema": {
134
- "type": "object",
135
- "properties": {
136
- "url": {
137
- "type": "string",
138
- "description": "The URL to fetch"
139
- }
140
- },
141
- "required": ["url"]
142
- }
143
- },
144
- {
145
- "name": "run_python",
146
- "description": "Execute Python code for calculations, data processing, or logic. Returns stdout output.",
147
- "input_schema": {
148
- "type": "object",
149
- "properties": {
150
- "code": {
151
- "type": "string",
152
- "description": "Python code to execute"
153
- }
154
- },
155
- "required": ["code"]
156
- }
157
- }
158
- ]
159
-
160
- TOOL_FUNCTIONS = {
161
- "web_search": web_search,
162
- "wikipedia_search": wikipedia_search,
163
- "fetch_page": fetch_page,
164
- "run_python": run_python,
165
- }
166
-
167
- SYSTEM_PROMPT = """You are a general AI assistant solving benchmark questions.
168
-
169
- For each question:
170
- 1. Think carefully about what information you need
171
- 2. Use tools to search for facts, do calculations, or fetch web pages
172
- 3. Reason step by step
173
- 4. Give ONLY the final answer - no explanation, no "FINAL ANSWER:" prefix
174
-
175
- Your answer should be:
176
- - A number (no units unless specified, no commas in numbers)
177
- - A short phrase (no articles like "the" or "a", no abbreviations for proper nouns)
178
- - A comma-separated list of numbers/strings
179
-
180
- Be precise. The answer is checked by exact match."""
181
 
182
 
183
  class SmartAgent:
184
  def __init__(self):
185
- api_key = os.getenv("ANTHROPIC_API_KEY")
186
- if not api_key:
187
- raise ValueError("ANTHROPIC_API_KEY environment variable not set!")
188
- self.client = anthropic.Anthropic(api_key=api_key)
189
- self.model = "claude-opus-4-5"
190
- print("SmartAgent (Claude-powered) initialized.")
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  def __call__(self, question: str) -> str:
193
  print(f"\nQuestion: {question[:100]}...")
194
- messages = [{"role": "user", "content": question}]
195
-
196
- max_iterations = 10
197
- for iteration in range(max_iterations):
198
- response = self.client.messages.create(
199
- model=self.model,
200
- max_tokens=4096,
201
- system=SYSTEM_PROMPT,
202
- tools=TOOLS,
203
- messages=messages,
204
- )
205
-
206
- # Check if we're done
207
- if response.stop_reason == "end_turn":
208
- # Extract text answer
209
- for block in response.content:
210
- if hasattr(block, "text"):
211
- answer = block.text.strip()
212
- # Clean up any "FINAL ANSWER:" prefix if model adds it
213
- answer = re.sub(r'^FINAL ANSWER:\s*', '', answer, flags=re.IGNORECASE).strip()
214
- print(f"Answer: {answer}")
215
- return answer
216
- return "No answer"
217
-
218
- # Process tool calls
219
- if response.stop_reason == "tool_use":
220
- # Add assistant's response to messages
221
- messages.append({"role": "assistant", "content": response.content})
222
-
223
- # Execute all tool calls
224
- tool_results = []
225
- for block in response.content:
226
- if block.type == "tool_use":
227
- tool_name = block.name
228
- tool_input = block.input
229
- print(f" Tool: {tool_name}({list(tool_input.values())[0] if tool_input else ''})")
230
-
231
- try:
232
- func = TOOL_FUNCTIONS.get(tool_name)
233
- if func:
234
- result = func(**tool_input)
235
- else:
236
- result = f"Unknown tool: {tool_name}"
237
- except Exception as e:
238
- result = f"Tool error: {e}"
239
-
240
- tool_results.append({
241
- "type": "tool_result",
242
- "tool_use_id": block.id,
243
- "content": str(result)[:5000],
244
- })
245
-
246
- messages.append({"role": "user", "content": tool_results})
 
 
247
  else:
248
- # Unexpected stop reason
249
- break
250
-
251
- return "Unable to determine answer"
 
 
 
 
252
 
253
 
254
  def run_and_submit_all(profile: gr.OAuthProfile | None):
255
- """Fetches all questions, runs the SmartAgent, submits answers, and displays results."""
256
  space_id = os.getenv("SPACE_ID")
257
 
258
  if profile:
259
  username = f"{profile.username}"
260
  print(f"User logged in: {username}")
261
  else:
262
- print("User not logged in.")
263
  return "Please Login to Hugging Face with the button.", None
264
 
265
  api_url = DEFAULT_API_URL
266
  questions_url = f"{api_url}/questions"
267
  submit_url = f"{api_url}/submit"
268
 
269
- # 1. Instantiate Agent
270
  try:
271
  agent = SmartAgent()
272
  except Exception as e:
273
- print(f"Error instantiating agent: {e}")
274
  return f"Error initializing agent: {e}", None
275
 
276
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
277
- print(agent_code)
278
 
279
- # 2. Fetch Questions
280
- print(f"Fetching questions from: {questions_url}")
281
  try:
282
  response = requests.get(questions_url, timeout=15)
283
  response.raise_for_status()
284
  questions_data = response.json()
285
  if not questions_data:
286
- return "Fetched questions list is empty or invalid format.", None
287
  print(f"Fetched {len(questions_data)} questions.")
288
  except Exception as e:
289
  return f"Error fetching questions: {e}", None
290
 
291
- # 3. Run Agent on all questions
292
  results_log = []
293
  answers_payload = []
294
- print(f"Running agent on {len(questions_data)} questions...")
295
  for item in questions_data:
296
  task_id = item.get("task_id")
297
  question_text = item.get("question")
298
  if not task_id or question_text is None:
299
- print(f"Skipping item with missing task_id or question: {item}")
300
  continue
301
  try:
302
  submitted_answer = agent(question_text)
303
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
304
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
305
  except Exception as e:
306
- print(f"Error running agent on task {task_id}: {e}")
307
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
308
 
309
  if not answers_payload:
310
- return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
311
 
312
- # 4. Submit
313
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
314
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
315
  try:
316
  response = requests.post(submit_url, json=submission_data, timeout=120)
317
  response.raise_for_status()
@@ -323,7 +210,6 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
323
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
324
  f"Message: {result_data.get('message', 'No message received.')}"
325
  )
326
- print("Submission successful.")
327
  return final_status, pd.DataFrame(results_log)
328
  except requests.exceptions.HTTPError as e:
329
  error_detail = f"Server responded with status {e.response.status_code}."
@@ -334,52 +220,30 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
334
  error_detail += f" Response: {e.response.text[:500]}"
335
  return f"Submission Failed: {error_detail}", pd.DataFrame(results_log)
336
  except Exception as e:
337
- return f"An unexpected error occurred during submission: {e}", pd.DataFrame(results_log)
338
 
339
 
340
- # --- Gradio Interface ---
341
  with gr.Blocks() as demo:
342
  gr.Markdown("# 🤖 Smart Agent — GAIA Benchmark Runner")
343
  gr.Markdown(
344
  """
345
- **Powered by Claude with Web Search, Wikipedia, and Python tools**
346
-
347
  **Instructions:**
348
- 1. Make sure `ANTHROPIC_API_KEY` is set in your Space secrets
349
  2. Log in with your Hugging Face account below
350
  3. Click **Run Evaluation & Submit All Answers**
351
-
352
- The agent will fetch all 20 GAIA questions, reason through each one using tools, and submit your answers.
353
  """
354
  )
355
-
356
  gr.LoginButton()
357
-
358
  run_button = gr.Button("🚀 Run Evaluation & Submit All Answers", variant="primary")
359
-
360
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
361
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
362
-
363
- run_button.click(
364
- fn=run_and_submit_all,
365
- outputs=[status_output, results_table]
366
- )
367
 
368
  if __name__ == "__main__":
369
- print("\n" + "-" * 30 + " App Starting " + "-" * 30)
370
- space_host_startup = os.getenv("SPACE_HOST")
371
- space_id_startup = os.getenv("SPACE_ID")
372
-
373
- if space_host_startup:
374
- print(f"✅ SPACE_HOST found: {space_host_startup}")
375
- else:
376
- print("ℹ️ SPACE_HOST not found (running locally?)")
377
-
378
- if space_id_startup:
379
- print(f"✅ SPACE_ID found: {space_id_startup}")
380
- else:
381
- print("ℹ️ SPACE_ID not found (running locally?)")
382
-
383
- print("-" * 74 + "\n")
384
- print("Launching Gradio Interface...")
385
  demo.launch(debug=True, share=False)
 
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
 
5
  import re
6
  from duckduckgo_search import DDGS
7
 
 
11
  # --- Tool Implementations ---
12
 
13
  def web_search(query: str) -> str:
 
14
  try:
15
  with DDGS() as ddgs:
16
  results = list(ddgs.text(query, max_results=5))
 
18
  return "No results found."
19
  output = []
20
  for r in results:
21
+ output.append(f"Title: {r.get('title', '')}\nSnippet: {r.get('body', '')}")
22
  return "\n---\n".join(output)
23
  except Exception as e:
24
  return f"Search error: {e}"
25
 
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  def wikipedia_search(query: str) -> str:
 
28
  try:
29
  search_url = "https://en.wikipedia.org/w/api.php"
30
+ params = {"action": "query", "list": "search", "srsearch": query, "format": "json", "srlimit": 1}
 
 
 
 
 
 
31
  response = requests.get(search_url, params=params, timeout=10)
32
  data = response.json()
33
  results = data.get("query", {}).get("search", [])
34
  if not results:
35
  return "No Wikipedia results found."
 
 
36
  title = results[0]["title"]
37
+ summary_params = {"action": "query", "titles": title, "prop": "extracts", "exintro": True, "explaintext": True, "format": "json"}
 
 
 
 
 
 
 
38
  summary_response = requests.get(search_url, params=summary_params, timeout=10)
39
  summary_data = summary_response.json()
40
  pages = summary_data.get("query", {}).get("pages", {})
41
  for page_id, page in pages.items():
42
  extract = page.get("extract", "No content available.")
43
+ return f"Wikipedia: {title}\n\n{extract[:3000]}"
44
  return "No content found."
45
  except Exception as e:
46
  return f"Wikipedia error: {e}"
47
 
48
 
49
+ def run_python(code: str) -> str:
50
+ import sys
51
+ from io import StringIO
52
+ old_stdout = sys.stdout
53
+ sys.stdout = StringIO()
54
+ try:
55
+ exec_globals = {}
56
+ exec(code, exec_globals)
57
+ output = sys.stdout.getvalue()
58
+ return output if output else "Code executed (no output)."
59
+ except Exception as e:
60
+ return f"Error: {e}"
61
+ finally:
62
+ sys.stdout = old_stdout
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
 
65
  class SmartAgent:
66
  def __init__(self):
67
+ self.hf_token = os.getenv("HF_TOKEN")
68
+ if not self.hf_token:
69
+ raise ValueError("HF_TOKEN environment variable not set!")
70
+ self.api_url = "https://api-inference.huggingface.co/models/Qwen/Qwen2.5-72B-Instruct/v1/chat/completions"
71
+ self.headers = {"Authorization": f"Bearer {self.hf_token}"}
72
+ print("SmartAgent initialized with Qwen2.5-72B (HF Inference API - FREE)")
73
+
74
+ def call_llm(self, messages: list) -> str:
75
+ payload = {
76
+ "model": "Qwen/Qwen2.5-72B-Instruct",
77
+ "messages": messages,
78
+ "max_tokens": 1024,
79
+ "temperature": 0.1,
80
+ }
81
+ response = requests.post(self.api_url, headers=self.headers, json=payload, timeout=60)
82
+ response.raise_for_status()
83
+ return response.json()["choices"][0]["message"]["content"]
84
 
85
  def __call__(self, question: str) -> str:
86
  print(f"\nQuestion: {question[:100]}...")
87
+
88
+ system_prompt = """You are a precise AI assistant solving benchmark questions.
89
+
90
+ You have access to these tools - call them by outputting exactly:
91
+ SEARCH: <query>
92
+ WIKIPEDIA: <query>
93
+ PYTHON: <code>
94
+
95
+ Rules:
96
+ - Use tools to look up facts you are unsure about
97
+ - After gathering info, output your final answer as: ANSWER: <your answer>
98
+ - Answer must be a number, short phrase, or comma-separated list
99
+ - No articles (a/the), no units unless asked, no explanations
100
+ - The answer is checked by exact match so be precise"""
101
+
102
+ messages = [
103
+ {"role": "system", "content": system_prompt},
104
+ {"role": "user", "content": question}
105
+ ]
106
+
107
+ for iteration in range(6):
108
+ response = self.call_llm(messages)
109
+ print(f" LLM: {response[:200]}")
110
+
111
+ answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', response, re.IGNORECASE)
112
+ if answer_match:
113
+ answer = answer_match.group(1).strip()
114
+ print(f" Final answer: {answer}")
115
+ return answer
116
+
117
+ tool_result = None
118
+
119
+ search_match = re.search(r'SEARCH:\s*(.+?)(?:\n|$)', response)
120
+ if search_match:
121
+ query = search_match.group(1).strip()
122
+ print(f" Tool: web_search({query})")
123
+ tool_result = f"Search results for '{query}':\n{web_search(query)}"
124
+
125
+ wiki_match = re.search(r'WIKIPEDIA:\s*(.+?)(?:\n|$)', response)
126
+ if wiki_match:
127
+ query = wiki_match.group(1).strip()
128
+ print(f" Tool: wikipedia({query})")
129
+ tool_result = f"Wikipedia results for '{query}':\n{wikipedia_search(query)}"
130
+
131
+ python_match = re.search(r'PYTHON:\s*```(?:python)?\n?(.*?)```', response, re.DOTALL)
132
+ if not python_match:
133
+ python_match = re.search(r'PYTHON:\s*(.+?)(?:\nSEARCH|\nWIKIPEDIA|\nANSWER|$)', response, re.DOTALL)
134
+ if python_match:
135
+ code = python_match.group(1).strip()
136
+ print(f" Tool: python({code[:50]})")
137
+ tool_result = f"Python output:\n{run_python(code)}"
138
+
139
+ if tool_result:
140
+ messages.append({"role": "assistant", "content": response})
141
+ messages.append({"role": "user", "content": tool_result})
142
  else:
143
+ messages.append({"role": "assistant", "content": response})
144
+ messages.append({"role": "user", "content": "Please provide your final answer now using: ANSWER: <your answer>"})
145
+
146
+ last_response = self.call_llm(messages)
147
+ answer_match = re.search(r'ANSWER:\s*(.+?)(?:\n|$)', last_response, re.IGNORECASE)
148
+ if answer_match:
149
+ return answer_match.group(1).strip()
150
+ return last_response.strip().split('\n')[0][:200]
151
 
152
 
153
  def run_and_submit_all(profile: gr.OAuthProfile | None):
 
154
  space_id = os.getenv("SPACE_ID")
155
 
156
  if profile:
157
  username = f"{profile.username}"
158
  print(f"User logged in: {username}")
159
  else:
 
160
  return "Please Login to Hugging Face with the button.", None
161
 
162
  api_url = DEFAULT_API_URL
163
  questions_url = f"{api_url}/questions"
164
  submit_url = f"{api_url}/submit"
165
 
 
166
  try:
167
  agent = SmartAgent()
168
  except Exception as e:
 
169
  return f"Error initializing agent: {e}", None
170
 
171
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
 
172
 
 
 
173
  try:
174
  response = requests.get(questions_url, timeout=15)
175
  response.raise_for_status()
176
  questions_data = response.json()
177
  if not questions_data:
178
+ return "Fetched questions list is empty.", None
179
  print(f"Fetched {len(questions_data)} questions.")
180
  except Exception as e:
181
  return f"Error fetching questions: {e}", None
182
 
 
183
  results_log = []
184
  answers_payload = []
 
185
  for item in questions_data:
186
  task_id = item.get("task_id")
187
  question_text = item.get("question")
188
  if not task_id or question_text is None:
 
189
  continue
190
  try:
191
  submitted_answer = agent(question_text)
192
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
193
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
194
  except Exception as e:
195
+ print(f"Error on task {task_id}: {e}")
196
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"ERROR: {e}"})
197
 
198
  if not answers_payload:
199
+ return "Agent did not produce any answers.", pd.DataFrame(results_log)
200
 
 
201
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
 
202
  try:
203
  response = requests.post(submit_url, json=submission_data, timeout=120)
204
  response.raise_for_status()
 
210
  f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
211
  f"Message: {result_data.get('message', 'No message received.')}"
212
  )
 
213
  return final_status, pd.DataFrame(results_log)
214
  except requests.exceptions.HTTPError as e:
215
  error_detail = f"Server responded with status {e.response.status_code}."
 
220
  error_detail += f" Response: {e.response.text[:500]}"
221
  return f"Submission Failed: {error_detail}", pd.DataFrame(results_log)
222
  except Exception as e:
223
+ return f"Submission error: {e}", pd.DataFrame(results_log)
224
 
225
 
 
226
  with gr.Blocks() as demo:
227
  gr.Markdown("# 🤖 Smart Agent — GAIA Benchmark Runner")
228
  gr.Markdown(
229
  """
230
+ **Powered by Qwen2.5-72B via HuggingFace Inference API (FREE)**
231
+
232
  **Instructions:**
233
+ 1. Make sure `HF_TOKEN` is set in your Space secrets (your HF access token)
234
  2. Log in with your Hugging Face account below
235
  3. Click **Run Evaluation & Submit All Answers**
 
 
236
  """
237
  )
 
238
  gr.LoginButton()
 
239
  run_button = gr.Button("🚀 Run Evaluation & Submit All Answers", variant="primary")
 
240
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
241
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
242
+ run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])
 
 
 
 
243
 
244
  if __name__ == "__main__":
245
+ print("\n" + "=" * 30 + " Application Startup " + "=" * 30)
246
+ print(f"SPACE_HOST: {os.getenv('SPACE_HOST', 'not set')}")
247
+ print(f"SPACE_ID: {os.getenv('SPACE_ID', 'not set')}")
248
+ print("=" * 81 + "\n")
 
 
 
 
 
 
 
 
 
 
 
 
249
  demo.launch(debug=True, share=False)