cgoncalves commited on
Commit
a23cb5a
·
verified ·
1 Parent(s): 81917a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -15
app.py CHANGED
@@ -1,8 +1,15 @@
 
 
 
1
  import os
 
 
2
  import gradio as gr
3
- import requests
4
- import inspect
5
  import pandas as pd
 
 
 
 
6
 
7
  # (Keep Constants as is)
8
  # --- Constants ---
@@ -10,14 +17,98 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
11
  # --- Basic Agent Definition ---
12
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
13
- class BasicAgent:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  def __init__(self):
15
- print("BasicAgent initialized.")
16
- def __call__(self, question: str) -> str:
 
17
  print(f"Agent received question (first 50 chars): {question[:50]}...")
18
- fixed_answer = "This is a default answer."
19
- print(f"Agent returning fixed answer: {fixed_answer}")
20
- return fixed_answer
 
 
 
 
 
 
 
 
 
 
21
 
22
  def run_and_submit_all( profile: gr.OAuthProfile | None):
23
  """
@@ -40,7 +131,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
40
 
41
  # 1. Instantiate Agent ( modify this part to create your agent)
42
  try:
43
- agent = BasicAgent()
44
  except Exception as e:
45
  print(f"Error instantiating agent: {e}")
46
  return f"Error initializing agent: {e}", None
@@ -76,16 +167,17 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
76
  for item in questions_data:
77
  task_id = item.get("task_id")
78
  question_text = item.get("question")
 
79
  if not task_id or question_text is None:
80
  print(f"Skipping item with missing task_id or question: {item}")
81
  continue
82
  try:
83
- submitted_answer = agent(question_text)
84
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
85
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
86
  except Exception as e:
87
- print(f"Error running agent on task {task_id}: {e}")
88
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
89
 
90
  if not answers_payload:
91
  print("Agent did not produce any answers to submit.")
@@ -149,17 +241,38 @@ with gr.Blocks() as demo:
149
 
150
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
151
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
152
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
 
153
 
154
  ---
155
  **Disclaimers:**
156
- Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
157
- This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
158
  """
159
  )
160
 
161
  gr.LoginButton()
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  run_button = gr.Button("Run Evaluation & Submit All Answers")
164
 
165
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
1
+ import base64
2
+ import inspect
3
+ import mimetypes
4
  import os
5
+ import tempfile
6
+
7
  import gradio as gr
 
 
8
  import pandas as pd
9
+ import requests
10
+ from langchain_community.document_loaders import UnstructuredExcelLoader
11
+
12
+ from agents import supervisor_agent
13
 
14
  # (Keep Constants as is)
15
  # --- Constants ---
 
17
 
18
  # --- Basic Agent Definition ---
19
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
20
+ def fetch_file(task_id):
21
+ if not task_id:
22
+ return None
23
+ url = f"https://agents-course-unit4-scoring.hf.space/files/{task_id}"
24
+ response = requests.get(url)
25
+ if response.status_code == 200:
26
+ return response.content # Return raw bytes
27
+ else:
28
+ print(f"Failed to fetch file for task_id {task_id}: {response.status_code}")
29
+ return None
30
+
31
+ def build_multimodal_message(question, file_bytes=None, file_name=None):
32
+ """
33
+ Build a multimodal message with correct content blocks for text, image, audio, or file.
34
+ For .xlsx files, extract the text and append it to the question, since LLMs do not natively support .xlsx.
35
+ Follows: https://python.langchain.com/docs/how_to/multimodal_inputs/
36
+ """
37
+ content = []
38
+ # Special handling for .xlsx files
39
+ if file_bytes and file_name and file_name.lower().endswith('.xlsx'):
40
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.xlsx') as tmp:
41
+ tmp.write(file_bytes)
42
+ tmp_path = tmp.name
43
+ loader = UnstructuredExcelLoader(tmp_path, mode="elements")
44
+ docs = loader.load()
45
+ excel_text = "\n".join(doc.page_content for doc in docs)
46
+ question = f"{question}\n\n[Excel file content follows:]\n{excel_text}"
47
+ content.append({"type": "text", "text": question})
48
+ if file_bytes and file_name and not file_name.lower().endswith('.xlsx'):
49
+ ext = file_name.lower().split('.')[-1]
50
+ b64_data = base64.b64encode(file_bytes).decode("utf-8")
51
+ mime_type, _ = mimetypes.guess_type(file_name)
52
+ # Handle common audio/image types explicitly
53
+ if ext in ["png"]:
54
+ mime_type = "image/png"
55
+ block_type = "image"
56
+ elif ext in ["jpg", "jpeg"]:
57
+ mime_type = "image/jpeg"
58
+ block_type = "image"
59
+ elif ext == "mp3":
60
+ mime_type = "audio/mpeg"
61
+ block_type = "audio"
62
+ elif ext == "wav":
63
+ mime_type = "audio/wav"
64
+ block_type = "audio"
65
+ elif ext == "m4a":
66
+ mime_type = "audio/mp4"
67
+ block_type = "audio"
68
+ else:
69
+ block_type = "file"
70
+ if not mime_type:
71
+ mime_type = "application/octet-stream"
72
+ block = {
73
+ "type": block_type,
74
+ "source_type": "base64",
75
+ "data": b64_data,
76
+ "mime_type": mime_type,
77
+ "filename": file_name,
78
+ }
79
+ content.append(block)
80
+ return [{"role": "user", "content": content}]
81
+
82
+ def filter_supported_content_blocks(messages):
83
+ allowed_types = {"text", "image_url", "input_audio", "refusal", "audio", "file", "image"}
84
+ filtered = []
85
+ for msg in messages:
86
+ if "content" in msg and isinstance(msg["content"], list):
87
+ filtered_content = [block for block in msg["content"] if block.get("type") in allowed_types]
88
+ msg = dict(msg)
89
+ msg["content"] = filtered_content
90
+ filtered.append(msg)
91
+ return filtered
92
+
93
+ class Agent:
94
  def __init__(self):
95
+ self.main_agent = supervisor_agent
96
+ print("Agent initialized.")
97
+ def __call__(self, question: str, file_name: str = "", task_id: str = "") -> str:
98
  print(f"Agent received question (first 50 chars): {question[:50]}...")
99
+ file_bytes = fetch_file(task_id) if file_name else None
100
+ message = build_multimodal_message(question, file_bytes, file_name)
101
+ # Filter out unsupported content block types
102
+ message = filter_supported_content_blocks(message)
103
+ result = self.main_agent.invoke({"messages": message})
104
+ answer = result["messages"][-1]
105
+ content = answer.content
106
+ if isinstance(content, list) and content and isinstance(content[0], dict) and "text" in content[0]:
107
+ return content[0]["text"]
108
+ elif isinstance(content, str):
109
+ return content
110
+ else:
111
+ return str(content)
112
 
113
  def run_and_submit_all( profile: gr.OAuthProfile | None):
114
  """
 
131
 
132
  # 1. Instantiate Agent ( modify this part to create your agent)
133
  try:
134
+ agent = Agent()
135
  except Exception as e:
136
  print(f"Error instantiating agent: {e}")
137
  return f"Error initializing agent: {e}", None
 
167
  for item in questions_data:
168
  task_id = item.get("task_id")
169
  question_text = item.get("question")
170
+ file_name = item.get("file_name", "")
171
  if not task_id or question_text is None:
172
  print(f"Skipping item with missing task_id or question: {item}")
173
  continue
174
  try:
175
+ submitted_answer = agent(question_text, file_name, task_id)
176
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
177
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
178
  except Exception as e:
179
+ print(f"Error running agent on task {task_id}: {e}")
180
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
181
 
182
  if not answers_payload:
183
  print("Agent did not produce any answers to submit.")
 
241
 
242
  1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
243
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
244
+ 3. Enter your OpenAI and Google API keys below (these are required for the agent to work).
245
+ 4. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
246
 
247
  ---
248
  **Disclaimers:**
249
+ Once clicking on the "submit" button, it can take quite some time (this is the time for the agent to go through all the questions).
250
+ This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a separate action or even to answer the questions in async.
251
  """
252
  )
253
 
254
  gr.LoginButton()
255
 
256
+ openai_key_box = gr.Textbox(label="OpenAI API Key", type="password", placeholder="sk-...", lines=1)
257
+ google_key_box = gr.Textbox(label="Google API Key", type="password", placeholder="AIza...", lines=1)
258
+ set_keys_btn = gr.Button("Set API Keys")
259
+ status_api_keys = gr.Textbox(label="API Key Status", lines=1, interactive=False)
260
+
261
+ def set_api_keys(openai_key, google_key):
262
+ if openai_key:
263
+ os.environ["OPENAI_API_KEY"] = openai_key
264
+ if google_key:
265
+ os.environ["GOOGLE_API_KEY"] = google_key
266
+ if openai_key or google_key:
267
+ return "API keys set for this session."
268
+ return "No API keys provided."
269
+
270
+ set_keys_btn.click(
271
+ fn=set_api_keys,
272
+ inputs=[openai_key_box, google_key_box],
273
+ outputs=status_api_keys
274
+ )
275
+
276
  run_button = gr.Button("Run Evaluation & Submit All Answers")
277
 
278
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)