Commit
·
9c2aaab
1
Parent(s):
40e6934
:sparkles: Adding image modality
Browse files- .gitignore +3 -1
- app.py +175 -39
- pyproject.toml +1 -0
- uv.lock +23 -0
.gitignore
CHANGED
|
@@ -1,2 +1,4 @@
|
|
| 1 |
.venv
|
| 2 |
-
.env
|
|
|
|
|
|
|
|
|
| 1 |
.venv
|
| 2 |
+
.env
|
| 3 |
+
|
| 4 |
+
test*
|
app.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
| 1 |
import os
|
|
|
|
|
|
|
| 2 |
import base64
|
| 3 |
import gradio as gr
|
| 4 |
import requests
|
|
@@ -17,6 +19,7 @@ load_dotenv()
|
|
| 17 |
# --- Constants ---
|
| 18 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 19 |
|
|
|
|
| 20 |
# --- Basic Agent Definition ---
|
| 21 |
# ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
|
| 22 |
class BasicAgent:
|
|
@@ -35,60 +38,166 @@ class BasicAgent:
|
|
| 35 |
tools=[DuckDuckGoSearchTool()],
|
| 36 |
model=OpenAIServerModel(model_id=OPENAI_MODEL_ID, api_key=OPENAI_API_KEY),
|
| 37 |
additional_authorized_imports=["BeautifulSoup"],
|
| 38 |
-
max_steps=
|
| 39 |
)
|
| 40 |
-
|
|
|
|
| 41 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 42 |
try:
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
print(f"Agent returned answer: {result}")
|
| 46 |
return result
|
| 47 |
except Exception as e:
|
| 48 |
print(f"Error during CodeAgent.run: {e}")
|
| 49 |
return f"Error from CodeAgent: {e}"
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
def load_pil_image(image_path: str) -> Image.Image:
|
| 52 |
"""Loads an image from disk for processing by GPT-4O."""
|
| 53 |
return Image.open(image_path)
|
| 54 |
|
|
|
|
| 55 |
def load_image(image_path: str) -> str:
|
| 56 |
"""Loads image and encodes it as base64 string for GPT-4o."""
|
| 57 |
with open(image_path, "rb") as f:
|
| 58 |
encoded = base64.b64encode(f.read()).decode("utf-8")
|
| 59 |
return f"data:image/jpeg;base64,{encoded}"
|
| 60 |
|
|
|
|
| 61 |
def load_audio(audio_path: str) -> str:
|
| 62 |
"""Encodes audio as base64 for GPT-4o (if needed)."""
|
| 63 |
with open(audio_path, "rb") as f:
|
| 64 |
encoded = base64.b64encode(f.read()).decode("utf-8")
|
| 65 |
return f"data:audio/wav;base64,{encoded}"
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
def describe_image(image_path: str) -> str:
|
| 68 |
"""Sends image directly to GPT-4o to describe it."""
|
| 69 |
image_base64 = load_image(image_path)
|
| 70 |
messages = [
|
| 71 |
-
{
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
]
|
| 76 |
-
response = openai.ChatCompletion.create(
|
| 77 |
-
model="gpt-4o",
|
| 78 |
-
messages=messages
|
| 79 |
-
)
|
| 80 |
return response.choices[0].message["content"]
|
| 81 |
|
| 82 |
-
|
|
|
|
| 83 |
"""
|
| 84 |
Fetches all questions, runs the BasicAgent on them, submits all answers,
|
| 85 |
and displays the results.
|
| 86 |
"""
|
| 87 |
# --- Determine HF Space Runtime URL and Repo URL ---
|
| 88 |
-
space_id = os.getenv("SPACE_ID")
|
| 89 |
|
| 90 |
if profile:
|
| 91 |
-
username= f"{profile.username}"
|
| 92 |
print(f"User logged in: {username}")
|
| 93 |
else:
|
| 94 |
print("User not logged in.")
|
|
@@ -97,6 +206,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 97 |
api_url = DEFAULT_API_URL
|
| 98 |
questions_url = f"{api_url}/questions"
|
| 99 |
submit_url = f"{api_url}/submit"
|
|
|
|
| 100 |
|
| 101 |
# 1. Instantiate Agent ( modify this part to create your agent)
|
| 102 |
try:
|
|
@@ -115,16 +225,16 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 115 |
response.raise_for_status()
|
| 116 |
questions_data = response.json()
|
| 117 |
if not questions_data:
|
| 118 |
-
|
| 119 |
-
|
| 120 |
print(f"Fetched {len(questions_data)} questions.")
|
| 121 |
except requests.exceptions.RequestException as e:
|
| 122 |
print(f"Error fetching questions: {e}")
|
| 123 |
return f"Error fetching questions: {e}", None
|
| 124 |
except requests.exceptions.JSONDecodeError as e:
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
except Exception as e:
|
| 129 |
print(f"An unexpected error occurred fetching questions: {e}")
|
| 130 |
return f"An unexpected error occurred fetching questions: {e}", None
|
|
@@ -139,20 +249,43 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 139 |
if not task_id or question_text is None:
|
| 140 |
print(f"Skipping item with missing task_id or question: {item}")
|
| 141 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
try:
|
| 143 |
-
submitted_answer = agent(question_text)
|
| 144 |
-
answers_payload.append(
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
except Exception as e:
|
| 147 |
-
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
if not answers_payload:
|
| 151 |
print("Agent did not produce any answers to submit.")
|
| 152 |
return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
|
| 153 |
|
| 154 |
-
# 4. Prepare Submission
|
| 155 |
-
submission_data = {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
|
| 157 |
print(status_update)
|
| 158 |
|
|
@@ -222,20 +355,19 @@ with gr.Blocks() as demo:
|
|
| 222 |
|
| 223 |
run_button = gr.Button("Run Evaluation & Submit All Answers")
|
| 224 |
|
| 225 |
-
status_output = gr.Textbox(
|
|
|
|
|
|
|
| 226 |
# Removed max_rows=10 from DataFrame constructor
|
| 227 |
results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
|
| 228 |
|
| 229 |
-
run_button.click(
|
| 230 |
-
fn=run_and_submit_all,
|
| 231 |
-
outputs=[status_output, results_table]
|
| 232 |
-
)
|
| 233 |
|
| 234 |
if __name__ == "__main__":
|
| 235 |
-
print("\n" + "-"*30 + " App Starting " + "-"*30)
|
| 236 |
# Check for SPACE_HOST and SPACE_ID at startup for information
|
| 237 |
space_host_startup = os.getenv("SPACE_HOST")
|
| 238 |
-
space_id_startup = os.getenv("SPACE_ID")
|
| 239 |
|
| 240 |
if space_host_startup:
|
| 241 |
print(f"✅ SPACE_HOST found: {space_host_startup}")
|
|
@@ -243,14 +375,18 @@ if __name__ == "__main__":
|
|
| 243 |
else:
|
| 244 |
print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
|
| 245 |
|
| 246 |
-
if space_id_startup:
|
| 247 |
print(f"✅ SPACE_ID found: {space_id_startup}")
|
| 248 |
print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
|
| 249 |
-
print(
|
|
|
|
|
|
|
| 250 |
else:
|
| 251 |
-
print(
|
|
|
|
|
|
|
| 252 |
|
| 253 |
-
print("-"*(60 + len(" App Starting ")) + "\n")
|
| 254 |
|
| 255 |
print("Launching Gradio Interface for Basic Agent Evaluation...")
|
| 256 |
-
demo.launch(debug=True, share=False)
|
|
|
|
| 1 |
import os
|
| 2 |
+
import io
|
| 3 |
+
import json
|
| 4 |
import base64
|
| 5 |
import gradio as gr
|
| 6 |
import requests
|
|
|
|
| 19 |
# --- Constants ---
|
| 20 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 21 |
|
| 22 |
+
|
| 23 |
# --- Basic Agent Definition ---
|
| 24 |
# ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
|
| 25 |
class BasicAgent:
|
|
|
|
| 38 |
tools=[DuckDuckGoSearchTool()],
|
| 39 |
model=OpenAIServerModel(model_id=OPENAI_MODEL_ID, api_key=OPENAI_API_KEY),
|
| 40 |
additional_authorized_imports=["BeautifulSoup"],
|
| 41 |
+
max_steps=10,
|
| 42 |
)
|
| 43 |
+
|
| 44 |
+
def __call__(self, question: str, file_data: dict = None) -> str:
|
| 45 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 46 |
try:
|
| 47 |
+
images = None
|
| 48 |
+
if file_data is not None:
|
| 49 |
+
file_data = self.handle_file_data(file_data)
|
| 50 |
+
if file_data is not None:
|
| 51 |
+
images = file_data["images"]
|
| 52 |
+
if file_data["text"] is not None:
|
| 53 |
+
question += "\n\n" + file_data["text"]
|
| 54 |
+
|
| 55 |
+
result = self.agent.run(question, images=images)
|
| 56 |
+
|
| 57 |
print(f"Agent returned answer: {result}")
|
| 58 |
return result
|
| 59 |
except Exception as e:
|
| 60 |
print(f"Error during CodeAgent.run: {e}")
|
| 61 |
return f"Error from CodeAgent: {e}"
|
| 62 |
|
| 63 |
+
def handle_file_data(self, file_data: dict) -> dict:
|
| 64 |
+
if file_data["type"] in ["excel", "csv"]:
|
| 65 |
+
return {"images": None, "text": file_data["data"]}
|
| 66 |
+
elif file_data["type"] == "image":
|
| 67 |
+
return {"images": [file_data["data"]], "text": None}
|
| 68 |
+
elif file_data["type"] == "text":
|
| 69 |
+
return {"images": None, "text": file_data["data"]}
|
| 70 |
+
elif file_data["type"] == "audio":
|
| 71 |
+
return None
|
| 72 |
+
else:
|
| 73 |
+
return None
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def load_file_from_response(response):
|
| 77 |
+
"""
|
| 78 |
+
Loads and identifies file content from an HTTP response based on its content-type.
|
| 79 |
+
Returns a dictionary with 'type' and 'data' keys.
|
| 80 |
+
"""
|
| 81 |
+
content_type = response.headers.get("content-type", "").lower()
|
| 82 |
+
content_bytes = response.content
|
| 83 |
+
|
| 84 |
+
try:
|
| 85 |
+
if "application/json" in content_type:
|
| 86 |
+
if "No file path" in response.json()["detail"]:
|
| 87 |
+
return None
|
| 88 |
+
return {"type": "json", "data": response.json()}
|
| 89 |
+
|
| 90 |
+
elif "text/csv" in content_type:
|
| 91 |
+
return {"type": "csv", "data": pd.read_csv(io.StringIO(response.text))}
|
| 92 |
+
|
| 93 |
+
elif "text/plain" in content_type or "text/x-python" in content_type:
|
| 94 |
+
return {"type": "text", "data": response.text}
|
| 95 |
+
|
| 96 |
+
elif "image/" in content_type:
|
| 97 |
+
return {"type": "image", "data": Image.open(io.BytesIO(content_bytes))}
|
| 98 |
+
|
| 99 |
+
elif "audio/" in content_type:
|
| 100 |
+
audio_data, sample_rate = sf.read(io.BytesIO(content_bytes))
|
| 101 |
+
return {
|
| 102 |
+
"type": "audio",
|
| 103 |
+
"data": {"array": audio_data, "sample_rate": sample_rate},
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
elif "application/octet-stream" in content_type:
|
| 107 |
+
# Try Excel
|
| 108 |
+
try:
|
| 109 |
+
excel_data = pd.read_excel(io.BytesIO(content_bytes))
|
| 110 |
+
return {"type": "excel", "data": excel_data}
|
| 111 |
+
except Exception:
|
| 112 |
+
pass
|
| 113 |
+
|
| 114 |
+
# Try image
|
| 115 |
+
try:
|
| 116 |
+
img = Image.open(io.BytesIO(content_bytes))
|
| 117 |
+
return {"type": "image", "data": img}
|
| 118 |
+
except UnidentifiedImageError:
|
| 119 |
+
pass
|
| 120 |
+
|
| 121 |
+
# Try audio
|
| 122 |
+
try:
|
| 123 |
+
audio_data, sample_rate = sf.read(io.BytesIO(content_bytes))
|
| 124 |
+
return {
|
| 125 |
+
"type": "audio",
|
| 126 |
+
"data": {"array": audio_data, "sample_rate": sample_rate},
|
| 127 |
+
}
|
| 128 |
+
except RuntimeError:
|
| 129 |
+
pass
|
| 130 |
+
|
| 131 |
+
# Try UTF-8 text
|
| 132 |
+
try:
|
| 133 |
+
text = content_bytes.decode("utf-8")
|
| 134 |
+
return {"type": "text", "data": text}
|
| 135 |
+
except UnicodeDecodeError:
|
| 136 |
+
pass
|
| 137 |
+
|
| 138 |
+
return {"type": "binary", "data": content_bytes}
|
| 139 |
+
|
| 140 |
+
else:
|
| 141 |
+
print(f"⚠️ Unhandled content type: {content_type}")
|
| 142 |
+
return {"type": "unknown", "data": content_bytes}
|
| 143 |
+
|
| 144 |
+
except Exception as e:
|
| 145 |
+
print(f"❌ Failed to process content: {e}")
|
| 146 |
+
return {"type": "error", "data": str(e)}
|
| 147 |
+
|
| 148 |
+
|
| 149 |
def load_pil_image(image_path: str) -> Image.Image:
|
| 150 |
"""Loads an image from disk for processing by GPT-4O."""
|
| 151 |
return Image.open(image_path)
|
| 152 |
|
| 153 |
+
|
| 154 |
def load_image(image_path: str) -> str:
|
| 155 |
"""Loads image and encodes it as base64 string for GPT-4o."""
|
| 156 |
with open(image_path, "rb") as f:
|
| 157 |
encoded = base64.b64encode(f.read()).decode("utf-8")
|
| 158 |
return f"data:image/jpeg;base64,{encoded}"
|
| 159 |
|
| 160 |
+
|
| 161 |
def load_audio(audio_path: str) -> str:
|
| 162 |
"""Encodes audio as base64 for GPT-4o (if needed)."""
|
| 163 |
with open(audio_path, "rb") as f:
|
| 164 |
encoded = base64.b64encode(f.read()).decode("utf-8")
|
| 165 |
return f"data:audio/wav;base64,{encoded}"
|
| 166 |
|
| 167 |
+
|
| 168 |
+
def transcribe_audio(audio_path: str) -> str:
|
| 169 |
+
"""Transcribes audio file using OpenAI Whisper model (whisper-1)."""
|
| 170 |
+
with open(audio_path, "rb") as f:
|
| 171 |
+
transcript = openai.Audio.transcribe("whisper-1", f)
|
| 172 |
+
return transcript.get("text", "")
|
| 173 |
+
|
| 174 |
+
|
| 175 |
def describe_image(image_path: str) -> str:
|
| 176 |
"""Sends image directly to GPT-4o to describe it."""
|
| 177 |
image_base64 = load_image(image_path)
|
| 178 |
messages = [
|
| 179 |
+
{
|
| 180 |
+
"role": "user",
|
| 181 |
+
"content": [
|
| 182 |
+
{"type": "text", "text": "Describe this image."},
|
| 183 |
+
{"type": "image_url", "image_url": {"url": image_base64}},
|
| 184 |
+
],
|
| 185 |
+
}
|
| 186 |
]
|
| 187 |
+
response = openai.ChatCompletion.create(model="gpt-4o", messages=messages)
|
|
|
|
|
|
|
|
|
|
| 188 |
return response.choices[0].message["content"]
|
| 189 |
|
| 190 |
+
|
| 191 |
+
def run_and_submit_all(profile: gr.OAuthProfile | None):
|
| 192 |
"""
|
| 193 |
Fetches all questions, runs the BasicAgent on them, submits all answers,
|
| 194 |
and displays the results.
|
| 195 |
"""
|
| 196 |
# --- Determine HF Space Runtime URL and Repo URL ---
|
| 197 |
+
space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
|
| 198 |
|
| 199 |
if profile:
|
| 200 |
+
username = f"{profile.username}"
|
| 201 |
print(f"User logged in: {username}")
|
| 202 |
else:
|
| 203 |
print("User not logged in.")
|
|
|
|
| 206 |
api_url = DEFAULT_API_URL
|
| 207 |
questions_url = f"{api_url}/questions"
|
| 208 |
submit_url = f"{api_url}/submit"
|
| 209 |
+
files_url = f"{api_url}/files" # /files/{task_id}
|
| 210 |
|
| 211 |
# 1. Instantiate Agent ( modify this part to create your agent)
|
| 212 |
try:
|
|
|
|
| 225 |
response.raise_for_status()
|
| 226 |
questions_data = response.json()
|
| 227 |
if not questions_data:
|
| 228 |
+
print("Fetched questions list is empty.")
|
| 229 |
+
return "Fetched questions list is empty or invalid format.", None
|
| 230 |
print(f"Fetched {len(questions_data)} questions.")
|
| 231 |
except requests.exceptions.RequestException as e:
|
| 232 |
print(f"Error fetching questions: {e}")
|
| 233 |
return f"Error fetching questions: {e}", None
|
| 234 |
except requests.exceptions.JSONDecodeError as e:
|
| 235 |
+
print(f"Error decoding JSON response from questions endpoint: {e}")
|
| 236 |
+
print(f"Response text: {response.text[:500]}")
|
| 237 |
+
return f"Error decoding server response for questions: {e}", None
|
| 238 |
except Exception as e:
|
| 239 |
print(f"An unexpected error occurred fetching questions: {e}")
|
| 240 |
return f"An unexpected error occurred fetching questions: {e}", None
|
|
|
|
| 249 |
if not task_id or question_text is None:
|
| 250 |
print(f"Skipping item with missing task_id or question: {item}")
|
| 251 |
continue
|
| 252 |
+
|
| 253 |
+
file_data = load_file_from_response(
|
| 254 |
+
requests.get(f"{files_url}/{task_id}", timeout=15)
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
try:
|
| 258 |
+
submitted_answer = agent(question_text, file_data)
|
| 259 |
+
answers_payload.append(
|
| 260 |
+
{"task_id": task_id, "submitted_answer": submitted_answer}
|
| 261 |
+
)
|
| 262 |
+
results_log.append(
|
| 263 |
+
{
|
| 264 |
+
"Task ID": task_id,
|
| 265 |
+
"Question": question_text,
|
| 266 |
+
"Submitted Answer": submitted_answer,
|
| 267 |
+
}
|
| 268 |
+
)
|
| 269 |
except Exception as e:
|
| 270 |
+
print(f"Error running agent on task {task_id}: {e}")
|
| 271 |
+
results_log.append(
|
| 272 |
+
{
|
| 273 |
+
"Task ID": task_id,
|
| 274 |
+
"Question": question_text,
|
| 275 |
+
"Submitted Answer": f"AGENT ERROR: {e}",
|
| 276 |
+
}
|
| 277 |
+
)
|
| 278 |
|
| 279 |
if not answers_payload:
|
| 280 |
print("Agent did not produce any answers to submit.")
|
| 281 |
return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
|
| 282 |
|
| 283 |
+
# 4. Prepare Submission
|
| 284 |
+
submission_data = {
|
| 285 |
+
"username": username.strip(),
|
| 286 |
+
"agent_code": agent_code,
|
| 287 |
+
"answers": answers_payload,
|
| 288 |
+
}
|
| 289 |
status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
|
| 290 |
print(status_update)
|
| 291 |
|
|
|
|
| 355 |
|
| 356 |
run_button = gr.Button("Run Evaluation & Submit All Answers")
|
| 357 |
|
| 358 |
+
status_output = gr.Textbox(
|
| 359 |
+
label="Run Status / Submission Result", lines=5, interactive=False
|
| 360 |
+
)
|
| 361 |
# Removed max_rows=10 from DataFrame constructor
|
| 362 |
results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
|
| 363 |
|
| 364 |
+
run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])
|
|
|
|
|
|
|
|
|
|
| 365 |
|
| 366 |
if __name__ == "__main__":
|
| 367 |
+
print("\n" + "-" * 30 + " App Starting " + "-" * 30)
|
| 368 |
# Check for SPACE_HOST and SPACE_ID at startup for information
|
| 369 |
space_host_startup = os.getenv("SPACE_HOST")
|
| 370 |
+
space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
|
| 371 |
|
| 372 |
if space_host_startup:
|
| 373 |
print(f"✅ SPACE_HOST found: {space_host_startup}")
|
|
|
|
| 375 |
else:
|
| 376 |
print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
|
| 377 |
|
| 378 |
+
if space_id_startup: # Print repo URLs if SPACE_ID is found
|
| 379 |
print(f"✅ SPACE_ID found: {space_id_startup}")
|
| 380 |
print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
|
| 381 |
+
print(
|
| 382 |
+
f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main"
|
| 383 |
+
)
|
| 384 |
else:
|
| 385 |
+
print(
|
| 386 |
+
"ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined."
|
| 387 |
+
)
|
| 388 |
|
| 389 |
+
print("-" * (60 + len(" App Starting ")) + "\n")
|
| 390 |
|
| 391 |
print("Launching Gradio Interface for Basic Agent Evaluation...")
|
| 392 |
+
demo.launch(debug=True, share=False)
|
pyproject.toml
CHANGED
|
@@ -8,6 +8,7 @@ dependencies = [
|
|
| 8 |
"beautifulsoup4>=4.13.4",
|
| 9 |
"dotenv>=0.9.9",
|
| 10 |
"gradio[oauth]>=5.26.0",
|
|
|
|
| 11 |
"requests>=2.32.3",
|
| 12 |
"smolagents[openai]>=1.14.0",
|
| 13 |
"soundfile>=0.13.1",
|
|
|
|
| 8 |
"beautifulsoup4>=4.13.4",
|
| 9 |
"dotenv>=0.9.9",
|
| 10 |
"gradio[oauth]>=5.26.0",
|
| 11 |
+
"openpyxl>=3.1.5",
|
| 12 |
"requests>=2.32.3",
|
| 13 |
"smolagents[openai]>=1.14.0",
|
| 14 |
"soundfile>=0.13.1",
|
uv.lock
CHANGED
|
@@ -14,6 +14,7 @@ dependencies = [
|
|
| 14 |
{ name = "beautifulsoup4" },
|
| 15 |
{ name = "dotenv" },
|
| 16 |
{ name = "gradio", extra = ["oauth"] },
|
|
|
|
| 17 |
{ name = "requests" },
|
| 18 |
{ name = "smolagents", extra = ["openai"] },
|
| 19 |
{ name = "soundfile" },
|
|
@@ -24,6 +25,7 @@ requires-dist = [
|
|
| 24 |
{ name = "beautifulsoup4", specifier = ">=4.13.4" },
|
| 25 |
{ name = "dotenv", specifier = ">=0.9.9" },
|
| 26 |
{ name = "gradio", extras = ["oauth"], specifier = ">=5.26.0" },
|
|
|
|
| 27 |
{ name = "requests", specifier = ">=2.32.3" },
|
| 28 |
{ name = "smolagents", extras = ["openai"], specifier = ">=1.14.0" },
|
| 29 |
{ name = "soundfile", specifier = ">=0.13.1" },
|
|
@@ -293,6 +295,15 @@ wheels = [
|
|
| 293 |
{ url = "https://files.pythonhosted.org/packages/83/a2/66adca41164860dee6d2d47b506fef3262c8879aab727b687c798d67313f/duckduckgo_search-8.0.1-py3-none-any.whl", hash = "sha256:87ea18d9abb1cd5dc8f63fc70ac867996acce2cb5e0129d191b9491c202420be", size = 18125 },
|
| 294 |
]
|
| 295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
[[package]]
|
| 297 |
name = "fastapi"
|
| 298 |
version = "0.115.12"
|
|
@@ -697,6 +708,18 @@ wheels = [
|
|
| 697 |
{ url = "https://files.pythonhosted.org/packages/59/aa/84e02ab500ca871eb8f62784426963a1c7c17a72fea3c7f268af4bbaafa5/openai-1.76.0-py3-none-any.whl", hash = "sha256:a712b50e78cf78e6d7b2a8f69c4978243517c2c36999756673e07a14ce37dc0a", size = 661201 },
|
| 698 |
]
|
| 699 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 700 |
[[package]]
|
| 701 |
name = "orjson"
|
| 702 |
version = "3.10.16"
|
|
|
|
| 14 |
{ name = "beautifulsoup4" },
|
| 15 |
{ name = "dotenv" },
|
| 16 |
{ name = "gradio", extra = ["oauth"] },
|
| 17 |
+
{ name = "openpyxl" },
|
| 18 |
{ name = "requests" },
|
| 19 |
{ name = "smolagents", extra = ["openai"] },
|
| 20 |
{ name = "soundfile" },
|
|
|
|
| 25 |
{ name = "beautifulsoup4", specifier = ">=4.13.4" },
|
| 26 |
{ name = "dotenv", specifier = ">=0.9.9" },
|
| 27 |
{ name = "gradio", extras = ["oauth"], specifier = ">=5.26.0" },
|
| 28 |
+
{ name = "openpyxl", specifier = ">=3.1.5" },
|
| 29 |
{ name = "requests", specifier = ">=2.32.3" },
|
| 30 |
{ name = "smolagents", extras = ["openai"], specifier = ">=1.14.0" },
|
| 31 |
{ name = "soundfile", specifier = ">=0.13.1" },
|
|
|
|
| 295 |
{ url = "https://files.pythonhosted.org/packages/83/a2/66adca41164860dee6d2d47b506fef3262c8879aab727b687c798d67313f/duckduckgo_search-8.0.1-py3-none-any.whl", hash = "sha256:87ea18d9abb1cd5dc8f63fc70ac867996acce2cb5e0129d191b9491c202420be", size = 18125 },
|
| 296 |
]
|
| 297 |
|
| 298 |
+
[[package]]
|
| 299 |
+
name = "et-xmlfile"
|
| 300 |
+
version = "2.0.0"
|
| 301 |
+
source = { registry = "https://pypi.org/simple" }
|
| 302 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234 }
|
| 303 |
+
wheels = [
|
| 304 |
+
{ url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059 },
|
| 305 |
+
]
|
| 306 |
+
|
| 307 |
[[package]]
|
| 308 |
name = "fastapi"
|
| 309 |
version = "0.115.12"
|
|
|
|
| 708 |
{ url = "https://files.pythonhosted.org/packages/59/aa/84e02ab500ca871eb8f62784426963a1c7c17a72fea3c7f268af4bbaafa5/openai-1.76.0-py3-none-any.whl", hash = "sha256:a712b50e78cf78e6d7b2a8f69c4978243517c2c36999756673e07a14ce37dc0a", size = 661201 },
|
| 709 |
]
|
| 710 |
|
| 711 |
+
[[package]]
|
| 712 |
+
name = "openpyxl"
|
| 713 |
+
version = "3.1.5"
|
| 714 |
+
source = { registry = "https://pypi.org/simple" }
|
| 715 |
+
dependencies = [
|
| 716 |
+
{ name = "et-xmlfile" },
|
| 717 |
+
]
|
| 718 |
+
sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464 }
|
| 719 |
+
wheels = [
|
| 720 |
+
{ url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910 },
|
| 721 |
+
]
|
| 722 |
+
|
| 723 |
[[package]]
|
| 724 |
name = "orjson"
|
| 725 |
version = "3.10.16"
|