Vjay15 commited on
Commit
78331be
·
verified ·
1 Parent(s): c2ae850

Upload 3 files

Browse files
Files changed (2) hide show
  1. main.py +1 -76
  2. solver.py +39 -4
main.py CHANGED
@@ -6,7 +6,7 @@ from solver import solve_quiz
6
  import logging
7
 
8
  # Configure logging
9
- logging.basicConfig(level=logging.INFO)
10
  logger = logging.getLogger(__name__)
11
 
12
  load_dotenv()
@@ -20,81 +20,6 @@ class QuizRequest(BaseModel):
20
  class Config:
21
  extra = "allow"
22
 
23
- from fastapi.responses import HTMLResponse
24
-
25
- @app.get("/", response_class=HTMLResponse)
26
- async def home():
27
- return """
28
- <!DOCTYPE html>
29
- <html>
30
- <head>
31
- <title>Quiz Solver</title>
32
- <style>
33
- body { font-family: sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; }
34
- .form-group { margin-bottom: 15px; }
35
- label { display: block; margin-bottom: 5px; }
36
- input { width: 100%; padding: 8px; box-sizing: border-box; }
37
- button { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }
38
- button:hover { background: #0056b3; }
39
- #status { margin-top: 20px; padding: 10px; display: none; }
40
- .success { background: #d4edda; color: #155724; }
41
- .error { background: #f8d7da; color: #721c24; }
42
- </style>
43
- </head>
44
- <body>
45
- <h1>Quiz Solver Agent</h1>
46
- <div class="form-group">
47
- <label>Email:</label>
48
- <input type="email" id="email" value="22f3000730@ds.iitm.ac.in">
49
- </div>
50
- <div class="form-group">
51
- <label>Secret:</label>
52
- <input type="password" id="secret" placeholder="Enter your secret">
53
- </div>
54
- <div class="form-group">
55
- <label>Start URL:</label>
56
- <input type="text" id="url" value="https://tds-llm-analysis.s-anand.net/project2">
57
- </div>
58
- <button onclick="startSolver()">Start Solving</button>
59
- <div id="status"></div>
60
-
61
- <script>
62
- async function startSolver() {
63
- const email = document.getElementById('email').value;
64
- const secret = document.getElementById('secret').value;
65
- const url = document.getElementById('url').value;
66
- const statusDiv = document.getElementById('status');
67
-
68
- statusDiv.style.display = 'block';
69
- statusDiv.className = '';
70
- statusDiv.textContent = 'Sending request...';
71
-
72
- try {
73
- const response = await fetch('/', {
74
- method: 'POST',
75
- headers: { 'Content-Type': 'application/json' },
76
- body: JSON.stringify({ email, secret, url })
77
- });
78
-
79
- const data = await response.json();
80
-
81
- if (response.ok) {
82
- statusDiv.className = 'success';
83
- statusDiv.textContent = 'Success: ' + data.message;
84
- } else {
85
- statusDiv.className = 'error';
86
- statusDiv.textContent = 'Error: ' + (data.detail || 'Unknown error');
87
- }
88
- } catch (e) {
89
- statusDiv.className = 'error';
90
- statusDiv.textContent = 'Network Error: ' + e.message;
91
- }
92
- }
93
- </script>
94
- </body>
95
- </html>
96
- """
97
-
98
  @app.post("/", status_code=200)
99
  async def solve_quiz_endpoint(request: QuizRequest, background_tasks: BackgroundTasks):
100
  logger.info(f"Received quiz request for URL: {request.url}")
 
6
  import logging
7
 
8
  # Configure logging
9
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
10
  logger = logging.getLogger(__name__)
11
 
12
  load_dotenv()
 
20
  class Config:
21
  extra = "allow"
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  @app.post("/", status_code=200)
24
  async def solve_quiz_endpoint(request: QuizRequest, background_tasks: BackgroundTasks):
25
  logger.info(f"Received quiz request for URL: {request.url}")
solver.py CHANGED
@@ -10,9 +10,14 @@ from agent import get_agent
10
  logger = logging.getLogger(__name__)
11
 
12
  async def solve_quiz(initial_url: str, email: str, secret: str):
13
- logger.info(f"Starting quiz solver workflow for {email}")
 
 
14
 
15
  current_url = initial_url
 
 
 
16
 
17
 
18
  async with async_playwright() as p:
@@ -22,10 +27,24 @@ async def solve_quiz(initial_url: str, email: str, secret: str):
22
 
23
  try:
24
  while current_url:
 
 
25
  # Generate a NEW session ID for each task/URL to keep memory clean
26
  import uuid
27
  session_id = str(uuid.uuid4())
28
- logger.info(f"Started new agent session for {current_url}: {session_id}")
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  logger.info(f"Navigating to {current_url}")
31
  await page.goto(current_url)
@@ -118,8 +137,20 @@ async def solve_quiz(initial_url: str, email: str, secret: str):
118
  # Use agent to solve (initialize here if needed, but we use get_agent() outside if we wanted persistent agent object,
119
  # but we want fresh memory per task, so we rely on session_id)
120
  agent = get_agent()
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  prompt = f"""
 
123
  You are a highly capable Quiz Solver Agent.
124
  Current Page URL: {current_url}
125
 
@@ -134,6 +165,7 @@ Solve the task on the current page.
134
  **GUIDELINES**
135
  - **Conciseness**: Plan and explain in **2-3 lines maximum**.
136
  - **Action**: Respond **IMMEDIATELY** with a tool call or the final JSON. **DO NOT** output conversational text or plans like "I need to...". Just run the code.
 
137
 
138
  **TOOL USAGE**
139
  - **Secret Codes**: Return exactly as requested (no extra spaces).
@@ -263,6 +295,7 @@ Now return the final JSON for submission:
263
  logger.info("Answer correct! Moving to next URL.")
264
 
265
  current_url = next_url
 
266
  break # Break retry loop to process new URL
267
 
268
  # No new URL provided
@@ -272,8 +305,10 @@ Now return the final JSON for submission:
272
  break # Break retry loop
273
  else:
274
  logger.warning(f"Answer incorrect: {submission_response.get('reason')}")
275
- logger.info("No new URL provided. Retrying same URL in 2 seconds...")
276
- await asyncio.sleep(2)
 
 
277
  # Break inner loop to refresh page and try again
278
  break
279
 
 
10
  logger = logging.getLogger(__name__)
11
 
12
  async def solve_quiz(initial_url: str, email: str, secret: str):
13
+ import uuid
14
+ task_id = str(uuid.uuid4())[:8]
15
+ logger.info(f"[{task_id}] Starting quiz solver workflow for {email}")
16
 
17
  current_url = initial_url
18
+ last_url = None
19
+ url_attempts = 0
20
+ failure_details = None
21
 
22
 
23
  async with async_playwright() as p:
 
27
 
28
  try:
29
  while current_url:
30
+ # Generate a NEW session ID for each task/URL to keep memory clean
31
+ import uuid
32
  # Generate a NEW session ID for each task/URL to keep memory clean
33
  import uuid
34
  session_id = str(uuid.uuid4())
35
+
36
+ # Update attempt counter
37
+ if current_url == last_url:
38
+ url_attempts += 1
39
+ else:
40
+ last_url = current_url
41
+ url_attempts = 1
42
+
43
+ if url_attempts > 60:
44
+ logger.error(f"Max attempts (60) reached for {current_url}. Stopping loop.")
45
+ break
46
+
47
+ logger.info(f"Started new agent session for {current_url} (Attempt {url_attempts}): {session_id}")
48
 
49
  logger.info(f"Navigating to {current_url}")
50
  await page.goto(current_url)
 
137
  # Use agent to solve (initialize here if needed, but we use get_agent() outside if we wanted persistent agent object,
138
  # but we want fresh memory per task, so we rely on session_id)
139
  agent = get_agent()
140
+
141
+ failure_info = ""
142
+ if failure_details:
143
+ failure_info = f"""
144
+ ***PREVIOUS FAILED SUBMISSION***
145
+ - The previous answer you submitted was INCORRECT.
146
+ - **Submitted Answer**: {json.dumps(failure_details['answer'].get('answer', 'UNKNOWN'))}
147
+ - **Error/Reason**: {failure_details['reason']}
148
+ - **GUIDANCE**: Analyze the error message carefully. Do NOT repeat the same answer. Try a different approach or format.
149
+ ***
150
+ """
151
 
152
  prompt = f"""
153
+ {failure_info}
154
  You are a highly capable Quiz Solver Agent.
155
  Current Page URL: {current_url}
156
 
 
165
  **GUIDELINES**
166
  - **Conciseness**: Plan and explain in **2-3 lines maximum**.
167
  - **Action**: Respond **IMMEDIATELY** with a tool call or the final JSON. **DO NOT** output conversational text or plans like "I need to...". Just run the code.
168
+ - Have a dummy answer for the intial request
169
 
170
  **TOOL USAGE**
171
  - **Secret Codes**: Return exactly as requested (no extra spaces).
 
295
  logger.info("Answer correct! Moving to next URL.")
296
 
297
  current_url = next_url
298
+ failure_details = None # Reset on success
299
  break # Break retry loop to process new URL
300
 
301
  # No new URL provided
 
305
  break # Break retry loop
306
  else:
307
  logger.warning(f"Answer incorrect: {submission_response.get('reason')}")
308
+ logger.info("No new URL provided. Retrying same URL in 20 seconds...")
309
+ current_url = current_url # Just to be explicit, logic loops anyway
310
+ failure_details = {"answer": answer_payload, "reason": submission_response.get("reason")}
311
+ await asyncio.sleep(20)
312
  # Break inner loop to refresh page and try again
313
  break
314