ATK20 commited on
Commit
13b9133
Β·
verified Β·
1 Parent(s): 253a3db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -194
app.py CHANGED
@@ -1,190 +1,29 @@
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):
@@ -193,7 +32,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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,31 +83,11 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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:
@@ -361,7 +180,7 @@ if __name__ == "__main__":
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}")
 
1
  import os
2
  import gradio as gr
3
  import requests
 
 
 
 
 
 
 
4
  import pandas as pd
5
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, HFApiModel
6
+ # Test comment
7
 
8
  # (Keep Constants as is)
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # --- Basic Agent Definition ---
13
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
14
  class BasicAgent:
15
  def __init__(self):
 
 
 
 
 
 
 
16
  print("BasicAgent initialized.")
17
+ token_key = os.getenv("HFAPI_KEY")
18
+ # Initialize the search tool
19
+ model = HFApiModel(model_id="Qwen/Qwen2.5-7B-Instruct", api_key=token_key)
20
+ search_tool = DuckDuckGoSearchTool()
21
+
22
+ self.agent = CodeAgent(model=model, tools=[search_tool])
23
  def __call__(self, question: str) -> str:
24
  print(f"Agent received question (first 50 chars): {question[:50]}...")
25
+ fixed_answer = "This is a default answer."
26
+ print(f"Agent returning fixed answer: {fixed_answer}")
27
  return fixed_answer
28
 
29
  def run_and_submit_all( profile: gr.OAuthProfile | None):
 
32
  and displays the results.
33
  """
34
  # --- Determine HF Space Runtime URL and Repo URL ---
35
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
36
 
37
  if profile:
38
  username= f"{profile.username}"
 
83
  for item in questions_data:
84
  task_id = item.get("task_id")
85
  question_text = item.get("question")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  if not task_id or question_text is None:
87
  print(f"Skipping item with missing task_id or question: {item}")
88
  continue
89
  try:
90
+ submitted_answer = agent(question_text)
91
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
92
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
93
  except Exception as e:
 
180
  print("\n" + "-"*30 + " App Starting " + "-"*30)
181
  # Check for SPACE_HOST and SPACE_ID at startup for information
182
  space_host_startup = os.getenv("SPACE_HOST")
183
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
184
 
185
  if space_host_startup:
186
  print(f"βœ… SPACE_HOST found: {space_host_startup}")