Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -4,20 +4,19 @@ import requests
|
|
4 |
import pandas as pd
|
5 |
import json
|
6 |
import time
|
7 |
-
import asyncio
|
8 |
-
from concurrent.futures import ThreadPoolExecutor
|
9 |
from pathlib import Path
|
10 |
from langchain_core.messages import HumanMessage
|
11 |
from requests.adapters import HTTPAdapter
|
12 |
from urllib3.util.retry import Retry
|
13 |
-
from
|
|
|
14 |
|
15 |
# --- Constants ---
|
16 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
17 |
CACHE_FILE = "questions_cache.json"
|
18 |
-
|
19 |
-
MAX_RETRIES =
|
20 |
-
INITIAL_BACKOFF =
|
21 |
|
22 |
def create_retry_session():
|
23 |
"""Create a requests session with retry logic for handling 429 errors."""
|
@@ -39,15 +38,15 @@ def load_cached_questions():
|
|
39 |
if cache_path.exists():
|
40 |
try:
|
41 |
with cache_path.open('r') as f:
|
42 |
-
|
43 |
-
|
44 |
-
if
|
45 |
questions = [
|
46 |
{
|
47 |
"task_id": item["task_id"],
|
48 |
"question": HumanMessage(content=item["question"])
|
49 |
}
|
50 |
-
for item in
|
51 |
]
|
52 |
print(f"Loaded {len(questions)} questions from cache.")
|
53 |
return questions
|
@@ -62,7 +61,7 @@ def cache_questions(questions_data):
|
|
62 |
cache_path = Path(CACHE_FILE)
|
63 |
try:
|
64 |
cache_data = {
|
65 |
-
"timestamp":
|
66 |
"questions": [
|
67 |
{
|
68 |
"task_id": item["task_id"],
|
@@ -77,27 +76,46 @@ def cache_questions(questions_data):
|
|
77 |
except Exception as e:
|
78 |
print(f"Error caching questions: {e}")
|
79 |
|
80 |
-
|
81 |
-
"""
|
82 |
-
|
83 |
-
question = item["question"]
|
84 |
try:
|
85 |
-
|
86 |
-
|
87 |
-
return
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
-
|
101 |
"""
|
102 |
Fetches all questions, runs the AdvancedAgent on them, submits all answers,
|
103 |
and displays the results.
|
@@ -113,7 +131,6 @@ async def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
113 |
return "Please Login to Hugging Face with the button.", None
|
114 |
|
115 |
api_url = DEFAULT_API_URL
|
116 |
-
questions_url = f"{api_url}/questions"
|
117 |
submit_url = f"{api_url}/submit"
|
118 |
|
119 |
# 1. Instantiate Agent
|
@@ -126,64 +143,35 @@ async def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
126 |
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
127 |
print(agent_code)
|
128 |
|
129 |
-
# 2.
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
response = session.get(questions_url, timeout=15)
|
136 |
-
response.raise_for_status()
|
137 |
-
raw_questions = response.json()
|
138 |
-
if not raw_questions:
|
139 |
-
print("Fetched questions list is empty.")
|
140 |
-
return "Fetched questions list is empty or invalid format.", None
|
141 |
-
questions_data = [
|
142 |
-
{
|
143 |
-
"task_id": item["task_id"],
|
144 |
-
"question": HumanMessage(content=item["question"])
|
145 |
-
}
|
146 |
-
for item in raw_questions
|
147 |
-
]
|
148 |
-
print(f"Fetched {len(questions_data)} questions.")
|
149 |
-
cache_questions(questions_data)
|
150 |
-
except requests.exceptions.RequestException as e:
|
151 |
-
print(f"Error fetching questions: {e}")
|
152 |
-
# Fallback to cache even if expired
|
153 |
-
questions_data = load_cached_questions()
|
154 |
-
if questions_data:
|
155 |
-
print("Using expired cache due to API failure.")
|
156 |
-
else:
|
157 |
-
return f"Error fetching questions and no valid cache: {e}", None
|
158 |
-
except requests.exceptions.JSONDecodeError as e:
|
159 |
-
print(f"Error decoding JSON response: {e}")
|
160 |
-
return f"Error decoding server response: {e}", None
|
161 |
-
except Exception as e:
|
162 |
-
print(f"An unexpected error occurred fetching questions: {e}")
|
163 |
-
return f"An unexpected error occurred: {e}", None
|
164 |
|
165 |
-
# 3. Run Agent
|
166 |
results_log = []
|
167 |
answers_payload = []
|
168 |
-
print(f"Running agent on {len(questions_data)} questions
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
for response in responses:
|
175 |
-
if isinstance(response, Exception):
|
176 |
-
print(f"Unexpected error in async processing: {response}")
|
177 |
-
continue
|
178 |
-
task_id = response["task_id"]
|
179 |
-
submitted_answer = response["submitted_answer"]
|
180 |
-
question_text = response["question_text"]
|
181 |
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
|
182 |
results_log.append({
|
183 |
"Task ID": task_id,
|
184 |
-
"Question":
|
185 |
"Submitted Answer": submitted_answer
|
186 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
if not answers_payload:
|
189 |
print("Agent did not produce any answers to submit.")
|
@@ -194,7 +182,7 @@ async def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
194 |
status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
|
195 |
print(status_update)
|
196 |
|
197 |
-
# 5. Submit
|
198 |
print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
|
199 |
try:
|
200 |
session = create_retry_session()
|
|
|
4 |
import pandas as pd
|
5 |
import json
|
6 |
import time
|
|
|
|
|
7 |
from pathlib import Path
|
8 |
from langchain_core.messages import HumanMessage
|
9 |
from requests.adapters import HTTPAdapter
|
10 |
from urllib3.util.retry import Retry
|
11 |
+
from datetime import datetime, timedelta
|
12 |
+
from agent import AdvancedAgent # Assuming you have an AdvancedAgent class in agent.py
|
13 |
|
14 |
# --- Constants ---
|
15 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
16 |
CACHE_FILE = "questions_cache.json"
|
17 |
+
CACHE_EXPIRATION = timedelta(days=1) # Cache expires after 1 day
|
18 |
+
MAX_RETRIES = 5
|
19 |
+
INITIAL_BACKOFF = 5 # Initial backoff time in seconds for retries
|
20 |
|
21 |
def create_retry_session():
|
22 |
"""Create a requests session with retry logic for handling 429 errors."""
|
|
|
38 |
if cache_path.exists():
|
39 |
try:
|
40 |
with cache_path.open('r') as f:
|
41 |
+
cache_data = json.load(f)
|
42 |
+
timestamp = datetime.fromisoformat(cache_data['timestamp'])
|
43 |
+
if datetime.now() - timestamp < CACHE_EXPIRATION:
|
44 |
questions = [
|
45 |
{
|
46 |
"task_id": item["task_id"],
|
47 |
"question": HumanMessage(content=item["question"])
|
48 |
}
|
49 |
+
for item in cache_data['questions']
|
50 |
]
|
51 |
print(f"Loaded {len(questions)} questions from cache.")
|
52 |
return questions
|
|
|
61 |
cache_path = Path(CACHE_FILE)
|
62 |
try:
|
63 |
cache_data = {
|
64 |
+
"timestamp": datetime.now().isoformat(),
|
65 |
"questions": [
|
66 |
{
|
67 |
"task_id": item["task_id"],
|
|
|
76 |
except Exception as e:
|
77 |
print(f"Error caching questions: {e}")
|
78 |
|
79 |
+
def fetch_questions_with_retry(url):
|
80 |
+
"""Fetch questions with retry logic for 429 errors."""
|
81 |
+
session = create_retry_session()
|
|
|
82 |
try:
|
83 |
+
response = session.get(url, timeout=15)
|
84 |
+
response.raise_for_status()
|
85 |
+
return response.json()
|
86 |
+
except requests.exceptions.RequestException as e:
|
87 |
+
print(f"Error fetching questions: {e}")
|
88 |
+
raise e
|
89 |
+
|
90 |
+
def load_questions():
|
91 |
+
"""Load questions from cache or fetch from server with retries."""
|
92 |
+
questions_data = load_cached_questions()
|
93 |
+
if questions_data is None:
|
94 |
+
print(f"Fetching questions from: {DEFAULT_API_URL}/questions")
|
95 |
+
try:
|
96 |
+
raw_questions = fetch_questions_with_retry(f"{DEFAULT_API_URL}/questions")
|
97 |
+
if not raw_questions:
|
98 |
+
raise ValueError("Fetched questions list is empty.")
|
99 |
+
questions_data = [
|
100 |
+
{
|
101 |
+
"task_id": item["task_id"],
|
102 |
+
"question": HumanMessage(content=item["question"])
|
103 |
+
}
|
104 |
+
for item in raw_questions
|
105 |
+
]
|
106 |
+
cache_questions(questions_data)
|
107 |
+
except Exception as e:
|
108 |
+
print(f"Error fetching questions: {e}")
|
109 |
+
# Try to load expired cache as fallback
|
110 |
+
cache_data = load_cached_questions()
|
111 |
+
if cache_data:
|
112 |
+
print("Using expired cache due to API failure.")
|
113 |
+
questions_data = cache_data
|
114 |
+
else:
|
115 |
+
raise e
|
116 |
+
return questions_data
|
117 |
|
118 |
+
def run_and_submit_all(profile: gr.OAuthProfile | None):
|
119 |
"""
|
120 |
Fetches all questions, runs the AdvancedAgent on them, submits all answers,
|
121 |
and displays the results.
|
|
|
131 |
return "Please Login to Hugging Face with the button.", None
|
132 |
|
133 |
api_url = DEFAULT_API_URL
|
|
|
134 |
submit_url = f"{api_url}/submit"
|
135 |
|
136 |
# 1. Instantiate Agent
|
|
|
143 |
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
144 |
print(agent_code)
|
145 |
|
146 |
+
# 2. Load Questions (from cache or server)
|
147 |
+
try:
|
148 |
+
questions_data = load_questions()
|
149 |
+
except Exception as e:
|
150 |
+
print(f"Failed to load questions: {e}")
|
151 |
+
return f"Failed to load questions: {e}", None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
|
153 |
+
# 3. Run Agent (simplified for this example)
|
154 |
results_log = []
|
155 |
answers_payload = []
|
156 |
+
print(f"Running agent on {len(questions_data)} questions...")
|
157 |
+
for item in questions_data:
|
158 |
+
task_id = item["task_id"]
|
159 |
+
question = item["question"]
|
160 |
+
try:
|
161 |
+
submitted_answer = agent(question.content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
|
163 |
results_log.append({
|
164 |
"Task ID": task_id,
|
165 |
+
"Question": question.content,
|
166 |
"Submitted Answer": submitted_answer
|
167 |
})
|
168 |
+
except Exception as e:
|
169 |
+
print(f"Error running agent on task {task_id}: {e}")
|
170 |
+
results_log.append({
|
171 |
+
"Task ID": task_id,
|
172 |
+
"Question": question.content,
|
173 |
+
"Submitted Answer": f"AGENT ERROR: {e}"
|
174 |
+
})
|
175 |
|
176 |
if not answers_payload:
|
177 |
print("Agent did not produce any answers to submit.")
|
|
|
182 |
status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
|
183 |
print(status_update)
|
184 |
|
185 |
+
# 5. Submit (with retry logic)
|
186 |
print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
|
187 |
try:
|
188 |
session = create_retry_session()
|