czrrr commited on
Commit
3fd5127
·
verified ·
1 Parent(s): 963ed46

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -42
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import os
2
  import re
3
  import base64
4
- import json
5
  from io import BytesIO
6
  from pathlib import Path
7
  from zipfile import ZipFile
@@ -65,6 +64,65 @@ def filename_from_response(response: requests.Response, task_id: str) -> str:
65
  return f"{clean_filename(task_id)}{extension}"
66
 
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  def extract_attachment_text(data: bytes, filename: str) -> str:
69
  """Extrai conteúdo legível dos formatos mais comuns do GAIA."""
70
  suffix = Path(filename).suffix.lower()
@@ -180,14 +238,9 @@ class InspectGaiaAttachmentTool(Tool):
180
  if not task_id:
181
  return "No task_id was supplied."
182
 
183
- url = f"{DEFAULT_API_URL}/files/{task_id}"
184
  try:
185
- response = requests.get(url, timeout=HTTP_TIMEOUT)
186
- if response.status_code == 404:
187
- return f"No attachment exists for task {task_id}."
188
- response.raise_for_status()
189
- filename = filename_from_response(response, task_id)
190
- extracted = extract_attachment_text(response.content, filename)
191
  return f"Attachment filename: {filename}\n\n{extracted}"
192
  except Exception as exc:
193
  return f"Could not inspect attachment for task {task_id}: {exc}"
@@ -262,13 +315,16 @@ class AnalyzeGaiaImageTool(Tool):
262
  return "Image analysis failed: HF_TOKEN is not configured."
263
 
264
  try:
265
- response = requests.get(
266
- f"{DEFAULT_API_URL}/files/{str(task_id).strip()}",
267
- timeout=HTTP_TIMEOUT,
268
- )
269
- response.raise_for_status()
270
- mime = response.headers.get("content-type", "image/png").split(";")[0]
271
- encoded = base64.b64encode(response.content).decode("ascii")
 
 
 
272
 
273
  client = OpenAI(
274
  base_url="https://router.huggingface.co/v1",
@@ -624,46 +680,66 @@ Formatting rules:
624
  ordering, capitalization, and plurality.
625
  - If asked for a quote: return only the requested spoken words.
626
  - If asked for a chess move: return only algebraic notation.
627
- - Never include labels, Markdown, citations, rationale, or "FINAL ANSWER".
628
-
629
- Return one JSON object and nothing else:
630
- {{
631
- "final_answer": "exact value to submit",
632
- "changed": true,
633
- "review_note": "brief reason, maximum 20 words"
634
- }}
635
  """.strip()
636
 
637
  last_error = None
638
- for use_json_mode in (True, False):
639
  try:
640
- kwargs = {
641
- "model": reviewer_model,
642
- "api_key": self.gemini_api_key,
643
- "messages": [{"role": "user", "content": review_prompt}],
644
- "temperature": 0,
645
- "max_tokens": 350,
646
- }
647
- if use_json_mode:
648
- kwargs["response_format"] = {"type": "json_object"}
649
- response = completion(**kwargs)
 
 
 
 
 
 
 
650
  content = str(response.choices[0].message.content).strip()
651
  content = re.sub(
652
- r"^```(?:json)?\s*|\s*```$", "", content, flags=re.I
 
 
 
 
 
653
  )
654
- start = content.find("{")
655
- end = content.rfind("}")
656
- if start >= 0 and end > start:
657
- content = content[start : end + 1]
658
- payload = json.loads(content)
 
 
 
 
659
  final_answer = self.deterministic_answer_cleanup(
660
- str(payload.get("final_answer", ""))
661
  )
662
  if not final_answer:
663
  raise ValueError("Gemini returned an empty final_answer.")
664
 
665
  changed = final_answer != candidate
666
- note = str(payload.get("review_note", "")).strip()
 
 
 
 
667
  print(f"Candidate answer: {candidate}")
668
  print(f"Gemini reviewed answer: {final_answer}")
669
  print(f"Gemini changed answer: {changed}")
 
1
  import os
2
  import re
3
  import base64
 
4
  from io import BytesIO
5
  from pathlib import Path
6
  from zipfile import ZipFile
 
64
  return f"{clean_filename(task_id)}{extension}"
65
 
66
 
67
+ def download_gaia_attachment(task_id: str) -> tuple[bytes, str]:
68
+ """Baixa um anexo pela API do curso, com fallback para o dataset oficial."""
69
+ task_id = str(task_id).strip()
70
+ course_url = f"{DEFAULT_API_URL}/files/{task_id}"
71
+ response = requests.get(course_url, timeout=HTTP_TIMEOUT)
72
+ if response.ok:
73
+ return response.content, filename_from_response(response, task_id)
74
+ if response.status_code != 404:
75
+ response.raise_for_status()
76
+
77
+ questions_response = requests.get(
78
+ f"{DEFAULT_API_URL}/questions", timeout=HTTP_TIMEOUT
79
+ )
80
+ questions_response.raise_for_status()
81
+ item = next(
82
+ (
83
+ question
84
+ for question in questions_response.json()
85
+ if str(question.get("task_id")) == task_id
86
+ ),
87
+ None,
88
+ )
89
+ filename = str((item or {}).get("file_name") or "").strip()
90
+ if not filename:
91
+ raise FileNotFoundError(f"No attachment exists for task {task_id}.")
92
+
93
+ token = os.getenv("HF_TOKEN")
94
+ if not token:
95
+ raise RuntimeError(
96
+ "The course file endpoint returned 404 and HF_TOKEN is required "
97
+ "for the official GAIA dataset fallback."
98
+ )
99
+
100
+ from huggingface_hub import hf_hub_download
101
+
102
+ errors = []
103
+ for dataset_path in (
104
+ f"2023/validation/{filename}",
105
+ filename,
106
+ ):
107
+ try:
108
+ local_path = hf_hub_download(
109
+ repo_id="gaia-benchmark/GAIA",
110
+ repo_type="dataset",
111
+ filename=dataset_path,
112
+ token=token,
113
+ )
114
+ return Path(local_path).read_bytes(), filename
115
+ except Exception as exc:
116
+ errors.append(str(exc))
117
+
118
+ raise RuntimeError(
119
+ "Could not download the attachment from the course API or official "
120
+ "GAIA dataset. Accept the dataset access conditions at "
121
+ "https://huggingface.co/datasets/gaia-benchmark/GAIA and ensure "
122
+ f"HF_TOKEN has read access. Details: {' | '.join(errors)}"
123
+ )
124
+
125
+
126
  def extract_attachment_text(data: bytes, filename: str) -> str:
127
  """Extrai conteúdo legível dos formatos mais comuns do GAIA."""
128
  suffix = Path(filename).suffix.lower()
 
238
  if not task_id:
239
  return "No task_id was supplied."
240
 
 
241
  try:
242
+ data, filename = download_gaia_attachment(task_id)
243
+ extracted = extract_attachment_text(data, filename)
 
 
 
 
244
  return f"Attachment filename: {filename}\n\n{extracted}"
245
  except Exception as exc:
246
  return f"Could not inspect attachment for task {task_id}: {exc}"
 
315
  return "Image analysis failed: HF_TOKEN is not configured."
316
 
317
  try:
318
+ data, filename = download_gaia_attachment(str(task_id).strip())
319
+ suffix = Path(filename).suffix.lower()
320
+ mime = {
321
+ ".png": "image/png",
322
+ ".jpg": "image/jpeg",
323
+ ".jpeg": "image/jpeg",
324
+ ".webp": "image/webp",
325
+ ".gif": "image/gif",
326
+ }.get(suffix, "image/png")
327
+ encoded = base64.b64encode(data).decode("ascii")
328
 
329
  client = OpenAI(
330
  base_url="https://router.huggingface.co/v1",
 
680
  ordering, capitalization, and plurality.
681
  - If asked for a quote: return only the requested spoken words.
682
  - If asked for a chess move: return only algebraic notation.
683
+ - Never include labels, Markdown, citations, rationale, or "FINAL ANSWER" inside
684
+ the final_answer value.
685
+
686
+ Return exactly these two XML-style fields:
687
+ <final_answer>exact value to submit</final_answer>
688
+ <review_note>brief reason, maximum 20 words</review_note>
689
+
690
+ Do not return JSON. Do not wrap the fields in Markdown or a code block.
691
  """.strip()
692
 
693
  last_error = None
694
+ for attempt in range(2):
695
  try:
696
+ retry_instruction = (
697
+ ""
698
+ if attempt == 0
699
+ else "\nIMPORTANT: Return both XML fields exactly as specified."
700
+ )
701
+ response = completion(
702
+ model=reviewer_model,
703
+ api_key=self.gemini_api_key,
704
+ messages=[
705
+ {
706
+ "role": "user",
707
+ "content": review_prompt + retry_instruction,
708
+ }
709
+ ],
710
+ temperature=0,
711
+ max_tokens=350,
712
+ )
713
  content = str(response.choices[0].message.content).strip()
714
  content = re.sub(
715
+ r"^```(?:xml|text)?\s*|\s*```$", "", content, flags=re.I
716
+ )
717
+ answer_match = re.search(
718
+ r"<final_answer>\s*(.*?)\s*</final_answer>",
719
+ content,
720
+ flags=re.I | re.S,
721
  )
722
+ note_match = re.search(
723
+ r"<review_note>\s*(.*?)\s*</review_note>",
724
+ content,
725
+ flags=re.I | re.S,
726
+ )
727
+ if not answer_match:
728
+ raise ValueError(
729
+ "Gemini did not return the <final_answer> field."
730
+ )
731
  final_answer = self.deterministic_answer_cleanup(
732
+ answer_match.group(1)
733
  )
734
  if not final_answer:
735
  raise ValueError("Gemini returned an empty final_answer.")
736
 
737
  changed = final_answer != candidate
738
+ note = (
739
+ note_match.group(1).strip()
740
+ if note_match
741
+ else "Review completed without a note."
742
+ )
743
  print(f"Candidate answer: {candidate}")
744
  print(f"Gemini reviewed answer: {final_answer}")
745
  print(f"Gemini changed answer: {changed}")