yoshizen commited on
Commit
0d32a9e
·
verified ·
1 Parent(s): b8312c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +164 -146
app.py CHANGED
@@ -22,7 +22,7 @@ logger = logging.getLogger("GAIA-Mastermind")
22
 
23
  # Конфигурация
24
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
25
- MODEL_NAME = "google/flan-t5-xxl"
26
  API_RETRIES = 3
27
  API_TIMEOUT = 45
28
 
@@ -32,25 +32,29 @@ class GAIAThoughtProcessor:
32
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
33
  logger.info(f"⚡ Инициализация GAIAThoughtProcessor на {self.device.upper()}")
34
 
35
- # Оптимизированная загрузка модели
36
- self.tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
37
- self.model = AutoModelForSeq2SeqLM.from_pretrained(
38
- MODEL_NAME,
39
- device_map="auto",
40
- torch_dtype=torch.float16 if "cuda" in self.device else torch.float32,
41
- low_cpu_mem_usage=True
42
- ).eval()
43
-
44
- # Создаем пайплайн для генерации текста
45
- self.text_generator = pipeline(
46
- "text2text-generation",
47
- model=self.model,
48
- tokenizer=self.tokenizer,
49
- device=self.device,
50
- max_new_tokens=512
51
- )
52
-
53
- logger.info("✅ GAIAThoughtProcessor готов")
 
 
 
 
54
 
55
  def _math_solver(self, expression: str) -> str:
56
  """Безопасное вычисление математических выражений"""
@@ -138,7 +142,7 @@ class GAIAThoughtProcessor:
138
  # Базовый анализ изображения
139
  description = (
140
  f"Format: {img.format}, Size: {img.size}, "
141
- f"Mode: {img.mode}, Colors: {len(set(img.getdata()))}"
142
  )
143
  return description
144
  except (UnidentifiedImageError, requests.exceptions.RequestException) as e:
@@ -189,53 +193,15 @@ class GAIAThoughtProcessor:
189
  def process_question(self, question: str, task_id: str) -> str:
190
  """Обработка вопроса с декомпозицией на шаги"""
191
  try:
192
- # Шаг 1: Декомпозиция задачи
193
- decomposition_prompt = (
194
- f"Декомпозируй задачу GAIA ({task_id}) на шаги. "
195
- f"Используй инструменты: math_solver, table_analyzer, text_processor, image_processor.\n\n"
196
- f"Задача: {question}\n\n"
197
- "Шаги (формат: [tool_name] arguments):"
198
- )
199
-
200
- steps_response = self._generate_response(decomposition_prompt)
201
- steps = [s.strip() for s in steps_response.split("\n") if s.strip()]
202
-
203
- # Шаг 2: Выполнение шагов
204
- results = []
205
- for step in steps:
206
- if step:
207
- try:
208
- # Извлечение инструмента и аргументов
209
- match = re.match(r"\[(\w+)\]\s*(.+)", step)
210
- if match:
211
- tool_name = match.group(1)
212
- arguments = match.group(2)
213
- result = self._call_tool(tool_name, arguments)
214
- results.append(f"{step} -> {result}")
215
- else:
216
- results.append(f"{step} -> ERROR: Invalid format")
217
- except Exception as e:
218
- results.append(f"{step} -> ERROR: {str(e)}")
219
-
220
- # Шаг 3: Синтез финального ответа
221
- synthesis_prompt = (
222
- f"Задача GAIA {task_id}:\n{question}\n\n"
223
- "Выполненные шаги:\n" + "\n".join(results) +
224
- "\n\nФинальный ответ в формате JSON (только п��ле final_answer):"
225
- )
226
-
227
- final_response = self._generate_response(synthesis_prompt)
228
 
229
  # Извлечение чистого ответа
230
- if "final_answer" in final_response:
231
- return json.dumps({"final_answer": final_response})
232
  else:
233
- # Попробуем извлечь ответ из текста
234
- answer_match = re.search(r'\{.*\}', final_response, re.DOTALL)
235
- if answer_match:
236
- return answer_match.group(0)
237
- else:
238
- return json.dumps({"final_answer": final_response.strip()})
239
  except Exception as e:
240
  logger.exception("Processing failed")
241
  return json.dumps({
@@ -262,7 +228,14 @@ class GAIAEvaluationRunner:
262
  # Получение вопросов
263
  questions, status = self._fetch_questions()
264
  if status != "success":
265
- return status, 0, 0, pd.DataFrame()
 
 
 
 
 
 
 
266
 
267
  # Обработка вопросов
268
  results = []
@@ -290,8 +263,8 @@ class GAIAEvaluationRunner:
290
  # Запись результатов
291
  results.append({
292
  "Task ID": task_id,
293
- "Question": q["question"][:150] + "..." if len(q["question"]) > 150 else q["question"],
294
- "Answer": final_answer[:200],
295
  "Status": "Processed"
296
  })
297
  except Exception as e:
@@ -308,12 +281,22 @@ class GAIAEvaluationRunner:
308
  })
309
 
310
  # Отправка ответов
311
- submission_result, score = self._submit_answers(username, agent_code, answers)
312
- return submission_result, score, len(questions), pd.DataFrame(results)
 
 
 
 
 
 
 
 
 
 
313
 
314
  def _fetch_questions(self) -> Tuple[list, str]:
315
  """Получение вопросов с API"""
316
- for _ in range(API_RETRIES):
317
  try:
318
  response = self.session.get(
319
  self.questions_url,
@@ -323,7 +306,7 @@ class GAIAEvaluationRunner:
323
  if response.status_code == 200:
324
  questions = response.json()
325
  if not isinstance(questions, list):
326
- return [], "Invalid response format: expected list"
327
 
328
  # Добавление task_id если отсутствует
329
  for q in questions:
@@ -331,18 +314,22 @@ class GAIAEvaluationRunner:
331
  return questions, "success"
332
 
333
  elif response.status_code == 429:
334
- logger.warning("Rate limited, retrying...")
335
- time.sleep(5)
 
336
  continue
337
 
338
  else:
339
- return [], f"API error: HTTP {response.status_code}"
340
 
 
 
 
341
  except Exception as e:
342
- logger.error(f"Fetch error: {e}")
343
- return [], f"Connection error: {str(e)}"
344
 
345
- return [], "API unavailable after retries"
346
 
347
  def _submit_answers(self, username: str, agent_code: str, answers: list) -> Tuple[str, int]:
348
  """Отправка ответов на сервер"""
@@ -363,89 +350,120 @@ class GAIAEvaluationRunner:
363
  if response.status_code == 200:
364
  result = response.json()
365
  score = result.get("score", 0)
366
- return result.get("message", "Answers submitted"), score
367
 
368
  elif response.status_code == 400:
369
- error = response.json().get("error", "Invalid request")
370
- logger.error(f"Validation error: {error}")
371
- return f"Validation Error: {error}", 0
372
 
373
  elif response.status_code == 429:
374
- logger.warning("Rate limited, retrying...")
375
- time.sleep(10)
 
376
  continue
377
 
378
  else:
379
- return f"HTTP Error {response.status_code}", 0
380
 
 
 
 
381
  except Exception as e:
382
- logger.error(f"Submit error: {e}")
383
- return f"Connection Error: {str(e)}", 0
384
 
385
- return "Submission failed after retries", 0
386
 
387
  # === ИНТЕРФЕЙС GRADIO ===
388
  def run_evaluation(username: str, agent_code: str, progress=gr.Progress()):
389
- progress(0, desc="⚡ Инициализация GAIA Mastermind...")
390
  try:
 
391
  agent = GAIAThoughtProcessor()
392
- except Exception as e:
393
- logger.exception("Agent initialization failed")
394
- return f"Agent Error: {str(e)}", 0, 0, pd.DataFrame()
395
-
396
- progress(0.1, desc="🌐 Подключение к GAIA API...")
397
- runner = GAIAEvaluationRunner()
398
-
399
- # Получение вопросов
400
- questions, status = runner._fetch_questions()
401
- if status != "success":
402
- return status, 0, 0, pd.DataFrame()
403
-
404
- # Обработка вопросов с прогрессом
405
- results = []
406
- answers = []
407
- total = len(questions)
408
-
409
- for i, q in enumerate(questions):
410
- progress(i / total, desc=f"🧠 Обработка задач ({i+1}/{total})")
411
- try:
412
- task_id = q.get("task_id", f"unknown_{i}")
413
- json_response = agent.process_question(q["question"], task_id)
414
-
415
- # Парсинг ответа
416
- try:
417
- response_obj = json.loads(json_response)
418
- final_answer = response_obj.get("final_answer", "")
419
- except:
420
- final_answer = json_response
421
-
422
- answers.append({
423
- "task_id": task_id,
424
- "answer": str(final_answer)[:500]
425
- })
426
-
427
- results.append({
428
- "Task ID": task_id,
429
- "Question": q["question"][:150] + "..." if len(q["question"]) > 150 else q["question"],
430
- "Answer": str(final_answer)[:200],
431
- "Status": "Processed"
432
- })
433
- except Exception as e:
434
- logger.error(f"Task {task_id} failed: {e}")
435
- answers.append({
436
- "task_id": task_id,
437
- "answer": f"ERROR: {str(e)}"
438
- })
439
- results.append({
440
- "Task ID": task_id,
441
- "Question": "Error",
442
- "Answer": f"ERROR: {str(e)}",
443
  "Status": "Failed"
444
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
446
- # Отправка ответов
447
- submission_result, score = runner._submit_answers(username, agent_code, answers)
448
- return submission_result, score, total, pd.DataFrame(results)
 
 
 
 
 
 
 
449
 
450
  # Создание интерфейса
451
  with gr.Blocks(
@@ -500,7 +518,7 @@ with gr.Blocks(
500
  interactive=False
501
  )
502
 
503
- # Упрощенный Dataframe без параметров, вызывающих ошибки
504
  results_table = gr.Dataframe(
505
  label="🔍 Детализация ответов",
506
  headers=["Task ID", "Question", "Answer", "Status"],
@@ -528,5 +546,5 @@ if __name__ == "__main__":
528
  server_port=7860,
529
  share=False,
530
  show_error=True,
531
- debug=False
532
  )
 
22
 
23
  # Конфигурация
24
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
25
+ MODEL_NAME = "google/flan-t5-large" # Упрощенная модель для CPU
26
  API_RETRIES = 3
27
  API_TIMEOUT = 45
28
 
 
32
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
33
  logger.info(f"⚡ Инициализация GAIAThoughtProcessor на {self.device.upper()}")
34
 
35
+ try:
36
+ # Оптимизированная загрузка модели
37
+ self.tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
38
+ self.model = AutoModelForSeq2SeqLM.from_pretrained(
39
+ MODEL_NAME,
40
+ device_map="auto" if torch.cuda.is_available() else None,
41
+ torch_dtype=torch.float16 if "cuda" in self.device else torch.float32,
42
+ low_cpu_mem_usage=True
43
+ ).eval()
44
+
45
+ # Создаем пайплайн для генерации текста
46
+ self.text_generator = pipeline(
47
+ "text2text-generation",
48
+ model=self.model,
49
+ tokenizer=self.tokenizer,
50
+ device=self.device,
51
+ max_new_tokens=256
52
+ )
53
+
54
+ logger.info("✅ GAIAThoughtProcessor готов")
55
+ except Exception as e:
56
+ logger.exception("Ошибка инициализации модели")
57
+ raise RuntimeError(f"Ошибка инициализации: {str(e)}")
58
 
59
  def _math_solver(self, expression: str) -> str:
60
  """Безопасное вычисление математических выражений"""
 
142
  # Базовый анализ изображения
143
  description = (
144
  f"Format: {img.format}, Size: {img.size}, "
145
+ f"Mode: {img.mode}"
146
  )
147
  return description
148
  except (UnidentifiedImageError, requests.exceptions.RequestException) as e:
 
193
  def process_question(self, question: str, task_id: str) -> str:
194
  """Обработка вопроса с декомпозицией на шаги"""
195
  try:
196
+ # Упрощенный промпт для CPU
197
+ prompt = f"Реши задачу шаг за шагом: {question}\n\nФинальный ответ:"
198
+ response = self._generate_response(prompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  # Извлечение чистого ответа
201
+ if "final_answer" in response:
202
+ return json.dumps({"final_answer": response})
203
  else:
204
+ return json.dumps({"final_answer": response.strip()})
 
 
 
 
 
205
  except Exception as e:
206
  logger.exception("Processing failed")
207
  return json.dumps({
 
228
  # Получение вопросов
229
  questions, status = self._fetch_questions()
230
  if status != "success":
231
+ # Возвращаем ошибку в понятном формате
232
+ error_df = pd.DataFrame([{
233
+ "Task ID": "ERROR",
234
+ "Question": status,
235
+ "Answer": "Не удалось получить вопросы",
236
+ "Status": "Failed"
237
+ }])
238
+ return status, 0, 0, error_df
239
 
240
  # Обработка вопросов
241
  results = []
 
263
  # Запись результатов
264
  results.append({
265
  "Task ID": task_id,
266
+ "Question": q["question"][:100] + "..." if len(q["question"]) > 100 else q["question"],
267
+ "Answer": final_answer[:100] + "..." if len(final_answer) > 100 else final_answer,
268
  "Status": "Processed"
269
  })
270
  except Exception as e:
 
281
  })
282
 
283
  # Отправка ответов
284
+ try:
285
+ submission_result, score = self._submit_answers(username, agent_code, answers)
286
+ return submission_result, score, len(questions), pd.DataFrame(results)
287
+ except Exception as e:
288
+ error_message = f"Ошибка отправки: {str(e)}"
289
+ results.append({
290
+ "Task ID": "SUBMIT_ERROR",
291
+ "Question": error_message,
292
+ "Answer": "",
293
+ "Status": "Failed"
294
+ })
295
+ return error_message, 0, len(questions), pd.DataFrame(results)
296
 
297
  def _fetch_questions(self) -> Tuple[list, str]:
298
  """Получение вопросов с API"""
299
+ for attempt in range(API_RETRIES):
300
  try:
301
  response = self.session.get(
302
  self.questions_url,
 
306
  if response.status_code == 200:
307
  questions = response.json()
308
  if not isinstance(questions, list):
309
+ return [], f"Неверный формат ответа: ожидался список, получен {type(questions)}"
310
 
311
  # Добавление task_id если отсутствует
312
  for q in questions:
 
314
  return questions, "success"
315
 
316
  elif response.status_code == 429:
317
+ wait_time = 2 ** attempt # Экспоненциальная задержка
318
+ logger.warning(f"Rate limited, retrying in {wait_time}s...")
319
+ time.sleep(wait_time)
320
  continue
321
 
322
  else:
323
+ return [], f"Ошибка API: HTTP {response.status_code} - {response.text}"
324
 
325
+ except requests.exceptions.RequestException as e:
326
+ logger.error(f"Ошибка соединения: {e}")
327
+ return [], f"Ошибка сети: {str(e)}"
328
  except Exception as e:
329
+ logger.error(f"Неожиданная ошибка: {e}")
330
+ return [], f"Неожиданная ошибка: {str(e)}"
331
 
332
+ return [], "API недоступен после попыток"
333
 
334
  def _submit_answers(self, username: str, agent_code: str, answers: list) -> Tuple[str, int]:
335
  """Отправка ответов на сервер"""
 
350
  if response.status_code == 200:
351
  result = response.json()
352
  score = result.get("score", 0)
353
+ return result.get("message", "Ответы успешно отправлены"), score
354
 
355
  elif response.status_code == 400:
356
+ error = response.json().get("error", "Неверный запрос")
357
+ logger.error(f"Ошибка валидации: {error}")
358
+ return f"Ошибка валидации: {error}", 0
359
 
360
  elif response.status_code == 429:
361
+ wait_time = 5 * (attempt + 1)
362
+ logger.warning(f"Rate limited, retrying in {wait_time}s...")
363
+ time.sleep(wait_time)
364
  continue
365
 
366
  else:
367
+ return f"HTTP Ошибка {response.status_code} - {response.text}", 0
368
 
369
+ except requests.exceptions.RequestException as e:
370
+ logger.error(f"Ошибка отправки: {e}")
371
+ return f"Ошибка сети: {str(e)}", 0
372
  except Exception as e:
373
+ logger.error(f"Неожиданная ошибка отправки: {e}")
374
+ return f"Неожиданная ошибка: {str(e)}", 0
375
 
376
+ return "Сбой отправки после попыток", 0
377
 
378
  # === ИНТЕРФЕЙС GRADIO ===
379
  def run_evaluation(username: str, agent_code: str, progress=gr.Progress()):
 
380
  try:
381
+ progress(0, desc="⚡ Инициализация GAIA Mastermind...")
382
  agent = GAIAThoughtProcessor()
383
+
384
+ progress(0.1, desc="🌐 Подключение к GAIA API...")
385
+ runner = GAIAEvaluationRunner()
386
+
387
+ # Получение вопросов
388
+ progress(0.2, desc="📡 Получение вопросов...")
389
+ questions, status = runner._fetch_questions()
390
+ if status != "success":
391
+ error_message = f"Ошибка: {status}"
392
+ error_df = pd.DataFrame([{
393
+ "Task ID": "ERROR",
394
+ "Question": error_message,
395
+ "Answer": "Не удалось получить вопросы",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  "Status": "Failed"
397
+ }])
398
+ return error_message, 0, 0, error_df
399
+
400
+ total = len(questions)
401
+ if total == 0:
402
+ error_message = "Получено 0 вопросов"
403
+ error_df = pd.DataFrame([{
404
+ "Task ID": "ERROR",
405
+ "Question": error_message,
406
+ "Answer": "Нет данных",
407
+ "Status": "Failed"
408
+ }])
409
+ return error_message, 0, 0, error_df
410
+
411
+ # Обработка вопросов с прогрессом
412
+ results = []
413
+ answers = []
414
+
415
+ for i, q in enumerate(questions):
416
+ progress(i / total, desc=f"🧠 Обработка задачи {i+1}/{total}")
417
+ try:
418
+ task_id = q.get("task_id", f"unknown_{i}")
419
+ json_response = agent.process_question(q["question"], task_id)
420
+
421
+ # Парсинг ответа
422
+ try:
423
+ response_obj = json.loads(json_response)
424
+ final_answer = response_obj.get("final_answer", "")
425
+ except:
426
+ final_answer = json_response
427
+
428
+ answers.append({
429
+ "task_id": task_id,
430
+ "answer": str(final_answer)[:500]
431
+ })
432
+
433
+ results.append({
434
+ "Task ID": task_id,
435
+ "Question": q["question"][:100] + "..." if len(q["question"]) > 100 else q["question"],
436
+ "Answer": str(final_answer)[:100] + "..." if len(str(final_answer)) > 100 else str(final_answer),
437
+ "Status": "Processed"
438
+ })
439
+ except Exception as e:
440
+ logger.error(f"Task {task_id} failed: {e}")
441
+ answers.append({
442
+ "task_id": task_id,
443
+ "answer": f"ERROR: {str(e)}"
444
+ })
445
+ results.append({
446
+ "Task ID": task_id,
447
+ "Question": "Error",
448
+ "Answer": f"ERROR: {str(e)}",
449
+ "Status": "Failed"
450
+ })
451
+
452
+ # Отправка ответов
453
+ progress(0.9, desc="📤 Отправка результатов...")
454
+ submission_result, score = runner._submit_answers(username, agent_code, answers)
455
+ return submission_result, score, total, pd.DataFrame(results)
456
 
457
+ except Exception as e:
458
+ logger.exception("Critical error in run_evaluation")
459
+ error_message = f"Критическая ошибка: {str(e)}"
460
+ error_df = pd.DataFrame([{
461
+ "Task ID": "CRITICAL",
462
+ "Question": error_message,
463
+ "Answer": "См. логи",
464
+ "Status": "Failed"
465
+ }])
466
+ return error_message, 0, 0, error_df
467
 
468
  # Создание интерфейса
469
  with gr.Blocks(
 
518
  interactive=False
519
  )
520
 
521
+ # Упрощенный Dataframe
522
  results_table = gr.Dataframe(
523
  label="🔍 Детализация ответов",
524
  headers=["Task ID", "Question", "Answer", "Status"],
 
546
  server_port=7860,
547
  share=False,
548
  show_error=True,
549
+ debug=True # Включение детального лога
550
  )