ATK20 commited on
Commit
3f38818
·
verified ·
1 Parent(s): c4ac215

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +195 -28
app.py CHANGED
@@ -1,41 +1,191 @@
1
  import os
2
- #os.environ["TRANSFORMERS_NO_TF"] = "1"
3
-
4
  import gradio as gr
5
  import requests
6
- import inspect
 
 
 
 
 
 
7
  import pandas as pd
8
- import time
9
- #from transformers import pipeline
10
- from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
11
  # (Keep Constants as is)
12
  # --- Constants ---
13
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  # --- Basic Agent Definition ---
17
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
18
  class BasicAgent:
19
- def __init__(self, HF_API_KEY):
20
- print("BasicAgent initialized.")
21
- # Initialize a small local model instead of API model
22
- self.model = HfApiModel("text-generation", model="mistralai/Mistral-7B-v0.1")
23
- self.HF_API_KEY = HF_API_KEY
24
- # Initialize the search tool (you can keep DuckDuckGoSearchTool)
25
- search_tool = DuckDuckGoSearchTool()
26
-
27
- # Initialize Agent
28
  self.agent = CodeAgent(
29
- model=self.model,
30
- api_key = self.HF_API_KEY,
31
- tools=[search_tool]
 
32
  )
33
 
 
 
34
  def __call__(self, question: str) -> str:
35
  print(f"Agent received question (first 50 chars): {question[:50]}...")
36
- generated_text = self.model(question, max_length=200, num_return_sequences=1)[0]['generated_text']
37
- print(f"Agent returning fixed answer: {generated_text}")
38
- return generated_text
39
 
40
  def run_and_submit_all( profile: gr.OAuthProfile | None):
41
  """
@@ -43,7 +193,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
43
  and displays the results.
44
  """
45
  # --- Determine HF Space Runtime URL and Repo URL ---
46
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
47
 
48
  if profile:
49
  username= f"{profile.username}"
@@ -94,14 +244,33 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
94
  for item in questions_data:
95
  task_id = item.get("task_id")
96
  question_text = item.get("question")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  if not task_id or question_text is None:
98
  print(f"Skipping item with missing task_id or question: {item}")
99
  continue
100
  try:
101
- submitted_answer = agent(question_text)
102
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
103
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
104
- time.sleep(2)
105
  except Exception as e:
106
  print(f"Error running agent on task {task_id}: {e}")
107
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
@@ -176,7 +345,7 @@ with gr.Blocks() as demo:
176
  )
177
 
178
  gr.LoginButton()
179
-
180
  run_button = gr.Button("Run Evaluation & Submit All Answers")
181
 
182
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
@@ -185,8 +354,6 @@ with gr.Blocks() as demo:
185
 
186
  run_button.click(
187
  fn=run_and_submit_all,
188
-
189
-
190
  outputs=[status_output, results_table]
191
  )
192
 
@@ -194,7 +361,7 @@ if __name__ == "__main__":
194
  print("\n" + "-"*30 + " App Starting " + "-"*30)
195
  # Check for SPACE_HOST and SPACE_ID at startup for information
196
  space_host_startup = os.getenv("SPACE_HOST")
197
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
198
 
199
  if space_host_startup:
200
  print(f"✅ SPACE_HOST found: {space_host_startup}")
 
1
  import os
 
 
2
  import gradio as gr
3
  import requests
4
+ import openai
5
+ from smolagents import OpenAIServerModel, DuckDuckGoSearchTool, CodeAgent, WikipediaSearchTool
6
+ from pathlib import Path
7
+ import tempfile
8
+ from smolagents.tools import PipelineTool, Tool
9
+ import pathlib
10
+ from typing import Union, Optional
11
  import pandas as pd
12
+ from tabulate import tabulate # pragma: no cover – fallback path
13
+ import re
14
+
15
  # (Keep Constants as is)
16
  # --- Constants ---
17
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
18
 
19
+ class SpeechToTextTool(PipelineTool):
20
+ """
21
+ Transcribes an audio file to text using the OpenAI Whisper API.
22
+ Only local file paths are supported.
23
+ """
24
+ default_checkpoint = "openai/whisper-1" # purely informational here
25
+ description = (
26
+ "This tool sends an audio file to OpenAI Whisper and returns the "
27
+ "transcribed text."
28
+ )
29
+ name = "transcriber"
30
+ inputs = {
31
+ "audio": {
32
+ "type": "string",
33
+ "description": "Absolute or relative path to a local audio file.",
34
+ }
35
+ }
36
+ output_type = "string"
37
+
38
+ # ──────────────────────────────────────────────────────────────────────────
39
+ # Public interface
40
+ # ──────────────────────────────────────────────────────────────────────────
41
+ def __call__(self, audio: str) -> str:
42
+ """
43
+ Convenience wrapper so the tool can be used like a regular function:
44
+ text = SpeechToTextTool()(path_to_audio)
45
+ """
46
+ return self._transcribe(audio)
47
+
48
+ # ──────────────────────────────────────────────────────────────────────────
49
+ # Internal helpers
50
+ # ──────────────────────────────────────────────────────────────────────────
51
+ @staticmethod
52
+ def _transcribe(audio_path: str) -> str:
53
+ # ----- validation ----------------------------------------------------
54
+ if not isinstance(audio_path, str):
55
+ raise TypeError(
56
+ "Parameter 'audio' must be a string containing the file path."
57
+ )
58
+ path = Path(audio_path).expanduser().resolve()
59
+ if not path.is_file():
60
+ raise FileNotFoundError(f"No such audio file: {path}")
61
+
62
+ # ----- API call ------------------------------------------------------
63
+ with path.open("rb") as fp:
64
+ response = openai.audio.transcriptions.create(
65
+ file=fp,
66
+ model="whisper-1", # currently the only Whisper model
67
+ response_format="text" # returns plain text instead of JSON
68
+ )
69
+
70
+ # For response_format="text", `response` is already the raw transcript
71
+ return response
72
+
73
+ class ExcelToTextTool(Tool):
74
+ """Render an Excel worksheet as Markdown text."""
75
+
76
+ # ------------------------------------------------------------------
77
+ # Required smol‑agents metadata
78
+ # ------------------------------------------------------------------
79
+ name = "excel_to_text"
80
+ description = (
81
+ "Read an Excel file and return a Markdown table of the requested sheet. "
82
+ "Accepts either the sheet name or the zero-based index."
83
+ )
84
+
85
+ inputs = {
86
+ "excel_path": {
87
+ "type": "string",
88
+ "description": "Path to the Excel file (.xlsx / .xls).",
89
+ },
90
+ "sheet_name": {
91
+ "type": "string",
92
+ "description": (
93
+ "Worksheet name or zero‑based index *as a string* (optional; default first sheet)."
94
+ ),
95
+ "nullable": True,
96
+ },
97
+ }
98
+
99
+ output_type = "string"
100
+
101
+ # ------------------------------------------------------------------
102
+ # Core logic
103
+ # ------------------------------------------------------------------
104
+ def forward(
105
+ self,
106
+ excel_path: str,
107
+ sheet_name: Optional[str] = None,
108
+ ) -> str:
109
+ """Load *excel_path* and return the sheet as a Markdown table."""
110
+
111
+ path = pathlib.Path(excel_path).expanduser().resolve()
112
+ if not path.exists():
113
+ return f"Error: Excel file not found at {path}"
114
+
115
+ try:
116
+ # Interpret sheet identifier -----------------------------------
117
+ sheet: Union[str, int]
118
+ if sheet_name is None or sheet_name == "":
119
+ sheet = 0 # first sheet
120
+ else:
121
+ # If the user passed a numeric string (e.g. "1"), cast to int
122
+ sheet = int(sheet_name) if sheet_name.isdigit() else sheet_name
123
+
124
+ # Load worksheet ----------------------------------------------
125
+ df = pd.read_excel(path, sheet_name=sheet)
126
+
127
+ # Render to Markdown; fall back to tabulate if needed ---------
128
+ if hasattr(pd.DataFrame, "to_markdown"):
129
+ return df.to_markdown(index=False)
130
+ from tabulate import tabulate # pragma: no cover – fallback path
131
+
132
+ return tabulate(df, headers="keys", tablefmt="github", showindex=False)
133
+
134
+ except Exception as exc: # broad catch keeps the agent chat‑friendly
135
+ return f"Error reading Excel file: {exc}"
136
+
137
+
138
+ def download_file_if_any(base_api_url: str, task_id: str) -> str | None:
139
+ """
140
+ Try GET /files/{task_id}.
141
+ • On HTTP 200 → save to a temp dir and return local path.
142
+ • On 404 → return None.
143
+ • On other errors → raise so caller can log / handle.
144
+ """
145
+ url = f"{base_api_url}/files/{task_id}"
146
+ try:
147
+ resp = requests.get(url, timeout=30)
148
+ if resp.status_code == 404:
149
+ return None # no file
150
+ resp.raise_for_status() # raise on 4xx/5xx ≠ 404
151
+ except requests.exceptions.HTTPError as e:
152
+ # propagate non-404 errors (403, 500, …)
153
+ raise e
154
+
155
+ # ▸ Save bytes to a named file inside the system temp dir
156
+ # Try to keep original extension from Content-Disposition if present.
157
+ cdisp = resp.headers.get("content-disposition", "")
158
+ filename = task_id # default base name
159
+ if "filename=" in cdisp:
160
+ m = re.search(r'filename="([^"]+)"', cdisp)
161
+ if m:
162
+ filename = m.group(1) # keep provided name
163
+
164
+ tmp_dir = Path(tempfile.gettempdir()) / "gaia_files"
165
+ tmp_dir.mkdir(exist_ok=True)
166
+ file_path = tmp_dir / filename
167
+ with open(file_path, "wb") as f:
168
+ f.write(resp.content)
169
+ return str(file_path)
170
 
171
  # --- Basic Agent Definition ---
172
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
173
  class BasicAgent:
174
+ def __init__(self):
 
 
 
 
 
 
 
 
175
  self.agent = CodeAgent(
176
+ model=OpenAIServerModel(model_id="gpt-4o"),
177
+ tools=[DuckDuckGoSearchTool(), WikipediaSearchTool(), SpeechToTextTool(), ExcelToTextTool()],
178
+ add_base_tools=True,
179
+ additional_authorized_imports=['pandas','numpy','csv','subprocess']
180
  )
181
 
182
+ print("BasicAgent initialized.")
183
+
184
  def __call__(self, question: str) -> str:
185
  print(f"Agent received question (first 50 chars): {question[:50]}...")
186
+ fixed_answer = self.agent.run(question)
187
+ print(f"Agent returning answer: {fixed_answer}")
188
+ return fixed_answer
189
 
190
  def run_and_submit_all( profile: gr.OAuthProfile | None):
191
  """
 
193
  and displays the results.
194
  """
195
  # --- Determine HF Space Runtime URL and Repo URL ---
196
+ space_id = "l3xv/Final_Assignment_Template"
197
 
198
  if profile:
199
  username= f"{profile.username}"
 
244
  for item in questions_data:
245
  task_id = item.get("task_id")
246
  question_text = item.get("question")
247
+
248
+ # ----------fetch any attached file ----------
249
+ try:
250
+ file_path = download_file_if_any(api_url, task_id)
251
+ except Exception as e:
252
+ file_path = None
253
+ print(f"[file fetch error] {task_id}: {e}")
254
+
255
+ # ---------- Build the prompt sent to the agent ----------
256
+ if file_path:
257
+ q_for_agent = (
258
+ f"{question_text}\n\n"
259
+ f"---\n"
260
+ f"A file was downloaded for this task and saved locally at:\n"
261
+ f"{file_path}\n"
262
+ f"---\n\n"
263
+ )
264
+ else:
265
+ q_for_agent = question_text
266
+
267
  if not task_id or question_text is None:
268
  print(f"Skipping item with missing task_id or question: {item}")
269
  continue
270
  try:
271
+ submitted_answer = agent(q_for_agent)
272
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
273
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
 
274
  except Exception as e:
275
  print(f"Error running agent on task {task_id}: {e}")
276
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
345
  )
346
 
347
  gr.LoginButton()
348
+
349
  run_button = gr.Button("Run Evaluation & Submit All Answers")
350
 
351
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
354
 
355
  run_button.click(
356
  fn=run_and_submit_all,
 
 
357
  outputs=[status_output, results_table]
358
  )
359
 
 
361
  print("\n" + "-"*30 + " App Starting " + "-"*30)
362
  # Check for SPACE_HOST and SPACE_ID at startup for information
363
  space_host_startup = os.getenv("SPACE_HOST")
364
+ space_id_startup = "l3xv/Final_Assignment_Template"
365
 
366
  if space_host_startup:
367
  print(f"✅ SPACE_HOST found: {space_host_startup}")