LamiaYT commited on
Commit
cf825e8
·
1 Parent(s): 2327ec9

Add agent and utils modules

Browse files
Files changed (6) hide show
  1. Dockerfile +1 -0
  2. agent/local_llm.py +21 -35
  3. app.py +1 -0
  4. directory_structure_and_contents.txt +1017 -0
  5. packages.txt +2 -0
  6. str.py +29 -0
Dockerfile CHANGED
@@ -1,4 +1,5 @@
1
  # Use a base Python image with better compatibility
 
2
  FROM python:3.10-slim
3
 
4
  # Set environment variables to fix permission issues (use /tmp paths)
 
1
  # Use a base Python image with better compatibility
2
+ ENV PYTHONPATH=/app
3
  FROM python:3.10-slim
4
 
5
  # Set environment variables to fix permission issues (use /tmp paths)
agent/local_llm.py CHANGED
@@ -1,41 +1,38 @@
1
- try:
2
- from transformers import AutoModelForCausalLM, AutoTokenizer
3
- from llama_index.llms.huggingface import HuggingFaceLLM
4
- import torch
5
- except ImportError as e:
6
- print(f"Import error in local_llm.py: {e}")
7
- raise
8
 
9
  class LocalLLM:
10
  def __init__(self):
11
- # Use a lightweight chat-compatible model that actually exists
12
  self.model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
13
  print(f"Initializing LocalLLM with model: {self.model_name}")
14
  self.llm = self._create_llama_index_llm()
15
 
16
  def _create_llama_index_llm(self):
17
  try:
18
- print("Loading tokenizer...")
19
  tokenizer = AutoTokenizer.from_pretrained(self.model_name)
20
 
21
- print("Loading model...")
22
  model = AutoModelForCausalLM.from_pretrained(
23
  self.model_name,
24
- torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
25
- device_map="auto" if torch.cuda.is_available() else None,
26
- low_cpu_mem_usage=True
27
  )
28
 
29
- print("Creating LlamaIndex-compatible LLM...")
30
  llm = HuggingFaceLLM(
31
  model=model,
32
  tokenizer=tokenizer,
33
  context_window=2048,
34
  generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
35
  tokenizer_kwargs={"use_fast": True},
36
- device_map="auto" if torch.cuda.is_available() else None
37
  )
38
- print("✅ LLM created successfully!")
39
  return llm
40
 
41
  except Exception as e:
@@ -43,13 +40,12 @@ class LocalLLM:
43
  return self._create_fallback_llm()
44
 
45
  def _create_fallback_llm(self):
46
- print("⚠️ Falling back to GPT2 model")
47
- model_name = "gpt2"
48
  try:
49
- tokenizer = AutoTokenizer.from_pretrained(model_name)
50
  tokenizer.pad_token = tokenizer.eos_token
51
-
52
- model = AutoModelForCausalLM.from_pretrained(model_name)
53
 
54
  return HuggingFaceLLM(
55
  model=model,
@@ -57,25 +53,15 @@ class LocalLLM:
57
  generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
58
  )
59
  except Exception as e:
60
- print(f"⚠️ Fallback model also failed: {e}")
61
  return self._create_mock_llm()
62
 
63
  def _create_mock_llm(self):
64
- print("️ Using mock LLM")
65
  class MockLLM:
66
- def chat(self, messages, **kwargs):
67
- class MockResponse:
68
- def __init__(self, text):
69
- self.message = type('obj', (object,), {'content': text})
70
- return MockResponse("Mock chat response: I would analyze this question and provide an answer.")
71
-
72
  def complete(self, prompt, **kwargs):
73
- class MockCompletion:
74
- def __init__(self, text):
75
- self.text = text
76
- return MockCompletion("Mock completion response: I would analyze this question and provide an answer.")
77
-
78
  return MockLLM()
79
 
80
  def get_llm(self):
81
- return self.llm
 
1
+ # File: agent/local_llm.py
2
+
3
+ import torch
4
+ from transformers import AutoTokenizer, AutoModelForCausalLM
5
+ from llama_index.llms.huggingface import HuggingFaceLLM
 
 
6
 
7
  class LocalLLM:
8
  def __init__(self):
 
9
  self.model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
10
  print(f"Initializing LocalLLM with model: {self.model_name}")
11
  self.llm = self._create_llama_index_llm()
12
 
13
  def _create_llama_index_llm(self):
14
  try:
15
+ print("🔄 Loading tokenizer...")
16
  tokenizer = AutoTokenizer.from_pretrained(self.model_name)
17
 
18
+ print("🧠 Loading model with 8-bit quantization...")
19
  model = AutoModelForCausalLM.from_pretrained(
20
  self.model_name,
21
+ load_in_8bit=True, # Requires bitsandbytes
22
+ device_map="auto",
23
+ torch_dtype=torch.float16
24
  )
25
 
26
+ print("🔗 Wrapping in HuggingFaceLLM...")
27
  llm = HuggingFaceLLM(
28
  model=model,
29
  tokenizer=tokenizer,
30
  context_window=2048,
31
  generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
32
  tokenizer_kwargs={"use_fast": True},
33
+ device_map="auto"
34
  )
35
+ print("✅ LLM initialized successfully!")
36
  return llm
37
 
38
  except Exception as e:
 
40
  return self._create_fallback_llm()
41
 
42
  def _create_fallback_llm(self):
43
+ print("⚠️ Falling back to GPT2...")
44
+ fallback_model = "gpt2"
45
  try:
46
+ tokenizer = AutoTokenizer.from_pretrained(fallback_model)
47
  tokenizer.pad_token = tokenizer.eos_token
48
+ model = AutoModelForCausalLM.from_pretrained(fallback_model)
 
49
 
50
  return HuggingFaceLLM(
51
  model=model,
 
53
  generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
54
  )
55
  except Exception as e:
56
+ print(f" Fallback model failed: {e}")
57
  return self._create_mock_llm()
58
 
59
  def _create_mock_llm(self):
60
+ print("🛠️ Using MockLLM fallback...")
61
  class MockLLM:
 
 
 
 
 
 
62
  def complete(self, prompt, **kwargs):
63
+ return type("Response", (), {"text": "Mock answer: I would respond here."})
 
 
 
 
64
  return MockLLM()
65
 
66
  def get_llm(self):
67
+ return self.llm
app.py CHANGED
@@ -10,6 +10,7 @@ warnings.filterwarnings("ignore", category=FutureWarning)
10
  warnings.filterwarnings("ignore", category=UserWarning)
11
 
12
  import gradio as gr
 
13
 
14
  # --- Environment variable setup to fix permission issues ---
15
  def setup_environment():
 
10
  warnings.filterwarnings("ignore", category=UserWarning)
11
 
12
  import gradio as gr
13
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
14
 
15
  # --- Environment variable setup to fix permission issues ---
16
  def setup_environment():
directory_structure_and_contents.txt ADDED
@@ -0,0 +1,1017 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- Contents of .\agent\local_llm.py ---
2
+ try:
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer
4
+ from llama_index.llms.huggingface import HuggingFaceLLM
5
+ import torch
6
+ except ImportError as e:
7
+ print(f"Import error in local_llm.py: {e}")
8
+ raise
9
+
10
+ class LocalLLM:
11
+ def __init__(self):
12
+ # Use a lightweight chat-compatible model that actually exists
13
+ self.model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
14
+ print(f"Initializing LocalLLM with model: {self.model_name}")
15
+ self.llm = self._create_llama_index_llm()
16
+
17
+ def _create_llama_index_llm(self):
18
+ try:
19
+ print("Loading tokenizer...")
20
+ tokenizer = AutoTokenizer.from_pretrained(self.model_name)
21
+
22
+ print("Loading model...")
23
+ model = AutoModelForCausalLM.from_pretrained(
24
+ self.model_name,
25
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
26
+ device_map="auto" if torch.cuda.is_available() else None,
27
+ low_cpu_mem_usage=True
28
+ )
29
+
30
+ print("Creating LlamaIndex-compatible LLM...")
31
+ llm = HuggingFaceLLM(
32
+ model=model,
33
+ tokenizer=tokenizer,
34
+ context_window=2048,
35
+ generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
36
+ tokenizer_kwargs={"use_fast": True},
37
+ device_map="auto" if torch.cuda.is_available() else None
38
+ )
39
+ print("✅ LLM created successfully!")
40
+ return llm
41
+
42
+ except Exception as e:
43
+ print(f"❌ Failed to load {self.model_name}: {e}")
44
+ return self._create_fallback_llm()
45
+
46
+ def _create_fallback_llm(self):
47
+ print("⚠️ Falling back to GPT2 model")
48
+ model_name = "gpt2"
49
+ try:
50
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
51
+ tokenizer.pad_token = tokenizer.eos_token
52
+
53
+ model = AutoModelForCausalLM.from_pretrained(model_name)
54
+
55
+ return HuggingFaceLLM(
56
+ model=model,
57
+ tokenizer=tokenizer,
58
+ generate_kwargs={"temperature": 0.7, "max_new_tokens": 256},
59
+ )
60
+ except Exception as e:
61
+ print(f"⚠️ Fallback model also failed: {e}")
62
+ return self._create_mock_llm()
63
+
64
+ def _create_mock_llm(self):
65
+ print("⚠️ Using mock LLM")
66
+ class MockLLM:
67
+ def chat(self, messages, **kwargs):
68
+ class MockResponse:
69
+ def __init__(self, text):
70
+ self.message = type('obj', (object,), {'content': text})
71
+ return MockResponse("Mock chat response: I would analyze this question and provide an answer.")
72
+
73
+ def complete(self, prompt, **kwargs):
74
+ class MockCompletion:
75
+ def __init__(self, text):
76
+ self.text = text
77
+ return MockCompletion("Mock completion response: I would analyze this question and provide an answer.")
78
+
79
+ return MockLLM()
80
+
81
+ def get_llm(self):
82
+ return self.llm tools.py
83
+
84
+ --- Contents of .\agent\tools.py ---
85
+ # File: agent/tools.py
86
+ try:
87
+ from llama_index.core.tools import FunctionTool
88
+ import sys
89
+ import os
90
+
91
+ # Add the parent directory to the path so we can import utils
92
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
93
+
94
+ from utils.gaia_api import GaiaAPI
95
+ except ImportError as e:
96
+ print(f"Import error in tools.py: {e}")
97
+ # Create a fallback GaiaAPI class if import fails
98
+ class GaiaAPI:
99
+ @classmethod
100
+ def get_questions(cls):
101
+ return [{"task_id": "fallback", "question": "What is 2+2?"}]
102
+
103
+ @classmethod
104
+ def get_random_question(cls):
105
+ return {"task_id": "fallback", "question": "What is 2+2?"}
106
+
107
+ import requests
108
+ from typing import Optional
109
+ import json
110
+
111
+ def get_gaia_questions() -> str:
112
+ """Fetch all GAIA benchmark questions for reference"""
113
+ try:
114
+ questions = GaiaAPI.get_questions()
115
+ result = "Available GAIA Questions:\n"
116
+ for q in questions[:5]: # Show first 5 questions
117
+ result += f"ID: {q['task_id']} - {q['question'][:100]}...\n"
118
+ return result
119
+ except Exception as e:
120
+ return f"Error fetching questions: {str(e)}"
121
+
122
+ def get_random_gaia_question() -> str:
123
+ """Get a single random GAIA question to work on"""
124
+ try:
125
+ question = GaiaAPI.get_random_question()
126
+ return f"Task ID: {question['task_id']}\nQuestion: {question['question']}"
127
+ except Exception as e:
128
+ return f"Error getting random question: {str(e)}"
129
+
130
+ def search_web(query: str) -> str:
131
+ """Search the web for information (mock implementation)"""
132
+ try:
133
+ # This is a simplified web search - you might want to integrate real search API
134
+ # For now, return a mock response
135
+ return f"Search results for '{query}': This is a mock search result. In a real implementation, this would search the web and return relevant information."
136
+ except Exception as e:
137
+ return f"Search failed: {str(e)}"
138
+
139
+ def calculate(expression: str) -> str:
140
+ """Safely evaluate mathematical expressions"""
141
+ try:
142
+ # Only allow safe mathematical operations
143
+ allowed_chars = set('0123456789+-*/.() ')
144
+ if not all(c in allowed_chars for c in expression):
145
+ return "Error: Invalid characters in expression"
146
+
147
+ result = eval(expression)
148
+ return str(result)
149
+ except Exception as e:
150
+ return f"Calculation error: {str(e)}"
151
+
152
+ def read_file_content(file_path: str) -> str:
153
+ """Read content from a file (for GAIA tasks that include files)"""
154
+ try:
155
+ with open(file_path, 'r', encoding='utf-8') as f:
156
+ content = f.read()
157
+ return content[:1000] # Limit content length
158
+ except Exception as e:
159
+ return f"Error reading file: {str(e)}"
160
+
161
+ def get_current_info(topic: str) -> str:
162
+ """Get current information about a topic"""
163
+ return f"Current information about '{topic}': This is a mock response. In a real implementation, this would fetch current information from reliable sources."
164
+
165
+ # Create the tools list for the agent
166
+ try:
167
+ gaia_tools = [
168
+ FunctionTool.from_defaults(
169
+ fn=get_gaia_questions,
170
+ name="get_gaia_questions",
171
+ description="Fetch all available GAIA benchmark questions"
172
+ ),
173
+ FunctionTool.from_defaults(
174
+ fn=get_random_gaia_question,
175
+ name="get_random_question",
176
+ description="Get a single random GAIA question to work on"
177
+ ),
178
+ FunctionTool.from_defaults(
179
+ fn=search_web,
180
+ name="search_web",
181
+ description="Search the web for information about a topic"
182
+ ),
183
+ FunctionTool.from_defaults(
184
+ fn=calculate,
185
+ name="calculate",
186
+ description="Perform mathematical calculations safely"
187
+ ),
188
+ FunctionTool.from_defaults(
189
+ fn=read_file_content,
190
+ name="read_file",
191
+ description="Read content from a file associated with GAIA tasks"
192
+ ),
193
+ FunctionTool.from_defaults(
194
+ fn=get_current_info,
195
+ name="get_current_info",
196
+ description="Get current information about a specific topic"
197
+ )
198
+ ]
199
+ except Exception as e:
200
+ print(f"Error creating tools: {e}")
201
+ gaia_tools = [] __init__.py
202
+
203
+ --- Contents of .\agent\__init__.py ---
204
+
205
+ --- Contents of .\.git\config ---
206
+ [core]
207
+ repositoryformatversion = 0
208
+ filemode = false
209
+ bare = false
210
+ logallrefupdates = true
211
+ symlinks = false
212
+ ignorecase = true
213
+ [remote "origin"]
214
+ url = https://huggingface.co/spaces/LamiaYT/Gaia_Llamaindex_Agent
215
+ fetch = +refs/heads/*:refs/remotes/origin/*
216
+ [branch "main"]
217
+ remote = origin
218
+ merge = refs/heads/main
219
+ vscode-merge-base = origin/main
220
+ vscode-merge-base = origin/main
221
+ description
222
+
223
+ --- Contents of .\.gitattributes ---
224
+ *.7z filter=lfs diff=lfs merge=lfs -text
225
+ *.arrow filter=lfs diff=lfs merge=lfs -text
226
+ *.bin filter=lfs diff=lfs merge=lfs -text
227
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
228
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
229
+ *.ftz filter=lfs diff=lfs merge=lfs -text
230
+ *.gz filter=lfs diff=lfs merge=lfs -text
231
+ *.h5 filter=lfs diff=lfs merge=lfs -text
232
+ *.joblib filter=lfs diff=lfs merge=lfs -text
233
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
234
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
235
+ *.model filter=lfs diff=lfs merge=lfs -text
236
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
237
+ *.npy filter=lfs diff=lfs merge=lfs -text
238
+ *.npz filter=lfs diff=lfs merge=lfs -text
239
+ *.onnx filter=lfs diff=lfs merge=lfs -text
240
+ *.ot filter=lfs diff=lfs merge=lfs -text
241
+ *.parquet filter=lfs diff=lfs merge=lfs -text
242
+ *.pb filter=lfs diff=lfs merge=lfs -text
243
+ *.pickle filter=lfs diff=lfs merge=lfs -text
244
+ *.pkl filter=lfs diff=lfs merge=lfs -text
245
+ *.pt filter=lfs diff=lfs merge=lfs -text
246
+ *.pth filter=lfs diff=lfs merge=lfs -text
247
+ *.rar filter=lfs diff=lfs merge=lfs -text
248
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
249
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
250
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
251
+ *.tar filter=lfs diff=lfs merge=lfs -text
252
+ *.tflite filter=lfs diff=lfs merge=lfs -text
253
+ *.tgz filter=lfs diff=lfs merge=lfs -text
254
+ *.wasm filter=lfs diff=lfs merge=lfs -text
255
+ *.xz filter=lfs diff=lfs merge=lfs -text
256
+ *.zip filter=lfs diff=lfs merge=lfs -text
257
+ *.zst filter=lfs diff=lfs merge=lfs -text
258
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
259
+ agent
260
+ local_llm.py
261
+
262
+ tools.py
263
+
264
+ --- Contents of .\agent\tools.py ---
265
+ # File: agent/tools.py
266
+ try:
267
+ from llama_index.core.tools import FunctionTool
268
+ import sys
269
+ import os
270
+
271
+ # Add the parent directory to the path so we can import utils
272
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
273
+
274
+ from utils.gaia_api import GaiaAPI
275
+ except ImportError as e:
276
+ print(f"Import error in tools.py: {e}")
277
+ # Create a fallback GaiaAPI class if import fails
278
+ class GaiaAPI:
279
+ @classmethod
280
+ def get_questions(cls):
281
+ return [{"task_id": "fallback", "question": "What is 2+2?"}]
282
+
283
+ @classmethod
284
+ def get_random_question(cls):
285
+ return {"task_id": "fallback", "question": "What is 2+2?"}
286
+
287
+ import requests
288
+ from typing import Optional
289
+ import json
290
+
291
+ def get_gaia_questions() -> str:
292
+ """Fetch all GAIA benchmark questions for reference"""
293
+ try:
294
+ questions = GaiaAPI.get_questions()
295
+ result = "Available GAIA Questions:\n"
296
+ for q in questions[:5]: # Show first 5 questions
297
+ result += f"ID: {q['task_id']} - {q['question'][:100]}...\n"
298
+ return result
299
+ except Exception as e:
300
+ return f"Error fetching questions: {str(e)}"
301
+
302
+ def get_random_gaia_question() -> str:
303
+ """Get a single random GAIA question to work on"""
304
+ try:
305
+ question = GaiaAPI.get_random_question()
306
+ return f"Task ID: {question['task_id']}\nQuestion: {question['question']}"
307
+ except Exception as e:
308
+ return f"Error getting random question: {str(e)}"
309
+
310
+ def search_web(query: str) -> str:
311
+ """Search the web for information (mock implementation)"""
312
+ try:
313
+ # This is a simplified web search - you might want to integrate real search API
314
+ # For now, return a mock response
315
+ return f"Search results for '{query}': This is a mock search result. In a real implementation, this would search the web and return relevant information."
316
+ except Exception as e:
317
+ return f"Search failed: {str(e)}"
318
+
319
+ def calculate(expression: str) -> str:
320
+ """Safely evaluate mathematical expressions"""
321
+ try:
322
+ # Only allow safe mathematical operations
323
+ allowed_chars = set('0123456789+-*/.() ')
324
+ if not all(c in allowed_chars for c in expression):
325
+ return "Error: Invalid characters in expression"
326
+
327
+ result = eval(expression)
328
+ return str(result)
329
+ except Exception as e:
330
+ return f"Calculation error: {str(e)}"
331
+
332
+ def read_file_content(file_path: str) -> str:
333
+ """Read content from a file (for GAIA tasks that include files)"""
334
+ try:
335
+ with open(file_path, 'r', encoding='utf-8') as f:
336
+ content = f.read()
337
+ return content[:1000] # Limit content length
338
+ except Exception as e:
339
+ return f"Error reading file: {str(e)}"
340
+
341
+ def get_current_info(topic: str) -> str:
342
+ """Get current information about a topic"""
343
+ return f"Current information about '{topic}': This is a mock response. In a real implementation, this would fetch current information from reliable sources."
344
+
345
+ # Create the tools list for the agent
346
+ try:
347
+ gaia_tools = [
348
+ FunctionTool.from_defaults(
349
+ fn=get_gaia_questions,
350
+ name="get_gaia_questions",
351
+ description="Fetch all available GAIA benchmark questions"
352
+ ),
353
+ FunctionTool.from_defaults(
354
+ fn=get_random_gaia_question,
355
+ name="get_random_question",
356
+ description="Get a single random GAIA question to work on"
357
+ ),
358
+ FunctionTool.from_defaults(
359
+ fn=search_web,
360
+ name="search_web",
361
+ description="Search the web for information about a topic"
362
+ ),
363
+ FunctionTool.from_defaults(
364
+ fn=calculate,
365
+ name="calculate",
366
+ description="Perform mathematical calculations safely"
367
+ ),
368
+ FunctionTool.from_defaults(
369
+ fn=read_file_content,
370
+ name="read_file",
371
+ description="Read content from a file associated with GAIA tasks"
372
+ ),
373
+ FunctionTool.from_defaults(
374
+ fn=get_current_info,
375
+ name="get_current_info",
376
+ description="Get current information about a specific topic"
377
+ )
378
+ ]
379
+ except Exception as e:
380
+ print(f"Error creating tools: {e}")
381
+ gaia_tools = [] __init__.py
382
+
383
+ --- Contents of .\agent\__init__.py ---
384
+ app.py
385
+
386
+ --- Contents of .\app.py ---
387
+ import os
388
+ import sys
389
+ import json
390
+ import traceback
391
+ from typing import List, Dict
392
+ import warnings
393
+
394
+ # Suppress warnings for cleaner output
395
+ warnings.filterwarnings("ignore", category=FutureWarning)
396
+ warnings.filterwarnings("ignore", category=UserWarning)
397
+
398
+ import gradio as gr
399
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
400
+
401
+ # --- Environment variable setup to fix permission issues ---
402
+ def setup_environment():
403
+ env_vars = {
404
+ "NLTK_DATA": "/tmp/nltk_data",
405
+ "MPLCONFIGDIR": "/tmp/matplotlib_cache",
406
+ "HF_HOME": "/tmp/huggingface_cache",
407
+ "TORCH_HOME": "/tmp/torch_cache",
408
+ "TRANSFORMERS_CACHE": "/tmp/huggingface_cache"
409
+ }
410
+
411
+ for var, path in env_vars.items():
412
+ os.environ[var] = path
413
+ os.makedirs(path, exist_ok=True)
414
+
415
+
416
+ for var, path in env_vars.items():
417
+ os.environ[var] = path
418
+ # Create directory if it doesn't exist
419
+ try:
420
+ os.makedirs(path, exist_ok=True)
421
+ print(f"✅ Created/verified directory: {path}")
422
+ except PermissionError:
423
+ print(f"⚠️ Permission denied for {path}, using /tmp fallback")
424
+ fallback_path = f"/tmp/{var.lower()}"
425
+ os.environ[var] = fallback_path
426
+ os.makedirs(fallback_path, exist_ok=True)
427
+ except Exception as e:
428
+ print(f"❌ Error setting up {var}: {e}")
429
+
430
+ # Setup environment first
431
+ setup_environment()
432
+
433
+ # Import nltk AFTER setting environment variables
434
+ try:
435
+ import nltk
436
+ # Download required NLTK data upfront
437
+ nltk.download('punkt', download_dir=os.environ["NLTK_DATA"], quiet=True)
438
+ nltk.download('stopwords', download_dir=os.environ["NLTK_DATA"], quiet=True)
439
+ print("✅ NLTK data downloaded successfully")
440
+ except Exception as e:
441
+ print(f"⚠️ NLTK setup warning: {e}")
442
+
443
+ # Add current directory to path for local imports
444
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
445
+
446
+ # Import dependencies with better error handling
447
+ try:
448
+ from utils.gaia_api import GaiaAPI
449
+ print("✅ GaiaAPI imported successfully")
450
+ except ImportError as e:
451
+ print(f"⚠️ Failed to import GaiaAPI: {e}")
452
+ # Create a fallback GaiaAPI
453
+ class GaiaAPI:
454
+ @classmethod
455
+ def get_questions(cls):
456
+ return [{"task_id": "fallback", "question": "What is 2+2?"}]
457
+ @classmethod
458
+ def get_random_question(cls):
459
+ return {"task_id": "fallback", "question": "What is 2+2?"}
460
+ @classmethod
461
+ def submit_answers(cls, username, code_url, answers):
462
+ return {"error": "GaiaAPI not available", "score": 0}
463
+
464
+ # Initialize global agent state
465
+ AGENT_READY = False
466
+ agent = None
467
+ initialization_error = None
468
+ agent_info = {}
469
+
470
+ def initialize_agent():
471
+ """Initialize the LlamaIndex agent with comprehensive error handling"""
472
+ global agent, AGENT_READY, initialization_error, agent_info
473
+
474
+ try:
475
+ print("🔄 Starting agent initialization...")
476
+
477
+ # Import agent-related modules
478
+ print("📦 Importing modules...")
479
+ from agent.local_llm import LocalLLM
480
+ from agent.tools import gaia_tools
481
+ from llama_index.core.agent import ReActAgent
482
+ from llama_index.core.memory import ChatMemoryBuffer
483
+
484
+ agent_info["modules_imported"] = True
485
+ print("✅ All modules imported successfully!")
486
+
487
+ print("🤖 Initializing Local LLM...")
488
+ local_llm = LocalLLM()
489
+ llm = local_llm.get_llm()
490
+ agent_info["llm_type"] = llm.__class__.__name__
491
+
492
+ print("🧠 Creating ReAct Agent...")
493
+ memory = ChatMemoryBuffer.from_defaults(token_limit=2000)
494
+
495
+ # Check if we have a proper LLM or mock
496
+ if hasattr(llm, 'chat') and llm.__class__.__name__ != 'MockLLM':
497
+ agent = ReActAgent.from_tools(
498
+ tools=gaia_tools,
499
+ llm=llm,
500
+ memory=memory,
501
+ verbose=True,
502
+ max_iterations=3
503
+ )
504
+ agent_info["agent_type"] = "ReActAgent"
505
+ print("✅ ReAct Agent initialized successfully!")
506
+ else:
507
+ agent = llm # Use the mock LLM directly
508
+ agent_info["agent_type"] = "MockLLM"
509
+ print("⚠️ Using mock mode - agent partially ready")
510
+
511
+ agent_info["tools_count"] = len(gaia_tools) if 'gaia_tools' in locals() else 0
512
+ AGENT_READY = True
513
+ print("🎉 Agent initialization complete!")
514
+
515
+ except Exception as e:
516
+ error_msg = f"Failed to initialize agent: {str(e)}"
517
+ print(f"❌ {error_msg}")
518
+ traceback.print_exc()
519
+ AGENT_READY = False
520
+ agent = None
521
+ initialization_error = error_msg
522
+ agent_info["error"] = error_msg
523
+
524
+ # Initialize agent
525
+ initialize_agent()
526
+
527
+ def process_single_question(question_text: str) -> str:
528
+ """Process a single GAIA question through the agent"""
529
+ if not AGENT_READY:
530
+ error_msg = "❌ Agent not ready. "
531
+ if initialization_error:
532
+ error_msg += f"Error: {initialization_error}"
533
+ return error_msg
534
+
535
+ if not question_text.strip():
536
+ return "❌ Please enter a question."
537
+
538
+ try:
539
+ enhanced_prompt = f"""
540
+ Answer the following question directly and concisely. Do not include "FINAL ANSWER" or any other prefixes in your response. Just provide the answer.
541
+
542
+ Question: {question_text}
543
+ """
544
+
545
+ print(f"🤔 Processing question: {question_text[:50]}...")
546
+
547
+ # FIXED: Use .complete() instead of .chat() to avoid chat template errors
548
+ if hasattr(agent, 'query'):
549
+ response = agent.query(enhanced_prompt)
550
+ elif hasattr(agent, 'complete'):
551
+ # Use complete() method for models without chat templates
552
+ response = agent.complete(enhanced_prompt)
553
+ answer = response.text if hasattr(response, 'text') else str(response)
554
+ elif hasattr(agent, 'chat'):
555
+ # Only use chat if it's the MockLLM or a proper chat model
556
+ try:
557
+ response = agent.chat([{"role": "user", "content": enhanced_prompt}])
558
+ answer = response.message.content if hasattr(response, 'message') else str(response)
559
+ except Exception as chat_error:
560
+ # Fallback to complete if chat fails
561
+ print(f"⚠️ Chat method failed, trying complete: {chat_error}")
562
+ if hasattr(agent, 'complete'):
563
+ response = agent.complete(enhanced_prompt)
564
+ answer = response.text if hasattr(response, 'text') else str(response)
565
+ else:
566
+ raise chat_error
567
+ else:
568
+ answer = "Mock response: I would analyze this question and provide an answer."
569
+
570
+ # Clean up the answer if it wasn't already processed above
571
+ if 'answer' not in locals():
572
+ answer = str(response).strip()
573
+
574
+ # Remove common prefixes from the answer
575
+ for prefix in ["FINAL ANSWER:", "Answer:", "The answer is:", "Final answer:"]:
576
+ if answer.startswith(prefix):
577
+ answer = answer[len(prefix):].strip()
578
+
579
+ print(f"✅ Generated answer: {answer[:50]}...")
580
+ return answer
581
+
582
+ except Exception as e:
583
+ error_msg = f"❌ Error processing question: {str(e)}"
584
+ print(error_msg)
585
+ return error_msg
586
+
587
+ def process_all_questions() -> str:
588
+ """Process all GAIA questions and prepare answers for submission"""
589
+ if not AGENT_READY:
590
+ return "❌ Agent not ready."
591
+
592
+ try:
593
+ print("📥 Fetching all GAIA questions...")
594
+ questions = GaiaAPI.get_questions()
595
+ processed_answers = []
596
+
597
+ print(f"🔄 Processing {len(questions)} questions...")
598
+ for i, question in enumerate(questions):
599
+ print(f"Processing question {i + 1}/{len(questions)}: {question['task_id']}")
600
+ answer = process_single_question(question['question'])
601
+ processed_answers.append({
602
+ "task_id": question['task_id'],
603
+ "submitted_answer": answer
604
+ })
605
+
606
+ # Save answers to file
607
+ output_file = "/app/gaia_answers.json"
608
+ with open(output_file, "w") as f:
609
+ json.dump(processed_answers, f, indent=2)
610
+
611
+ summary = f"✅ Processed {len(processed_answers)} questions.\n"
612
+ summary += f"💾 Answers saved to {output_file}\n"
613
+ summary += "📋 First 3 answers:\n"
614
+ for ans in processed_answers[:3]:
615
+ summary += f"- {ans['task_id']}: {ans['submitted_answer'][:50]}...\n"
616
+
617
+ print(summary)
618
+ return summary
619
+
620
+ except Exception as e:
621
+ error_msg = f"❌ Error processing questions: {str(e)}"
622
+ print(error_msg)
623
+ traceback.print_exc()
624
+ return error_msg
625
+
626
+ def submit_to_gaia(username: str, code_url: str) -> str:
627
+ """Submit answers to GAIA benchmark"""
628
+ if not AGENT_READY:
629
+ return "❌ Agent not ready."
630
+
631
+ if not username or not code_url:
632
+ return "❌ Please provide both username and code URL."
633
+
634
+ try:
635
+ answers_file = "/app/gaia_answers.json"
636
+ with open(answers_file, "r") as f:
637
+ answers = json.load(f)
638
+ print(f"📤 Submitting {len(answers)} answers...")
639
+ except FileNotFoundError:
640
+ return "❌ No processed answers found. Please process them first."
641
+
642
+ try:
643
+ result = GaiaAPI.submit_answers(username, code_url, answers)
644
+ if "error" in result:
645
+ return f"❌ Submission failed: {result['error']}"
646
+ score = result.get("score", "Unknown")
647
+ success_msg = f"✅ Submission successful!\n📊 Score: {score}"
648
+ print(success_msg)
649
+ return success_msg
650
+ except Exception as e:
651
+ error_msg = f"❌ Submission error: {str(e)}"
652
+ print(error_msg)
653
+ return error_msg
654
+
655
+ def get_sample_question() -> str:
656
+ """Load a sample question for testing"""
657
+ try:
658
+ question = GaiaAPI.get_random_question()
659
+ return question['question']
660
+ except Exception as e:
661
+ return f"Error loading sample question: {str(e)}"
662
+
663
+ def get_system_status() -> str:
664
+ """Get detailed system status for debugging"""
665
+ status = "🔍 System Status:\n\n"
666
+
667
+ # Agent status
668
+ status += f"🤖 Agent Ready: {'✅ Yes' if AGENT_READY else '❌ No'}\n"
669
+ if initialization_error:
670
+ status += f"❌ Error: {initialization_error}\n"
671
+
672
+ # Agent info
673
+ status += f"🧠 LLM Type: {agent_info.get('llm_type', 'Unknown')}\n"
674
+ status += f"🔧 Agent Type: {agent_info.get('agent_type', 'Unknown')}\n"
675
+ status += f"🛠️ Tools Count: {agent_info.get('tools_count', 0)}\n"
676
+
677
+ # Environment
678
+ status += "\n📁 Environment Variables:\n"
679
+ for var in ["NLTK_DATA", "HF_HOME", "MPLCONFIGDIR", "TORCH_HOME"]:
680
+ path = os.environ.get(var, 'Not set')
681
+ exists = "✅" if os.path.exists(path) else "❌"
682
+ status += f" {var}: {path} {exists}\n"
683
+
684
+ # Directory permissions
685
+ status += "\n📂 Directory Status:\n"
686
+ for path in ["/app", "/tmp"]:
687
+ try:
688
+ writable = os.access(path, os.W_OK)
689
+ status += f" {path}: {'✅ Writable' if writable else '❌ Not writable'}\n"
690
+ except:
691
+ status += f" {path}: ❌ Error checking\n"
692
+
693
+ return status
694
+
695
+ # ---------- Gradio UI ----------
696
+ with gr.Blocks(title="🦙 GAIA LlamaIndex Agent", theme=gr.themes.Soft()) as demo:
697
+ gr.Markdown(f"""
698
+ # 🦙 GAIA Benchmark Agent with LlamaIndex
699
+
700
+ This agent uses LlamaIndex with a local LLM to tackle GAIA benchmark questions.
701
+
702
+ **Status:** {"✅ Ready" if AGENT_READY else "❌ Not Ready"}
703
+ {f"**Error:** {initialization_error}" if initialization_error else ""}
704
+ """)
705
+
706
+ with gr.Tab("🔬 Test Single Question"):
707
+ gr.Markdown("Test the agent with individual questions")
708
+
709
+ with gr.Row():
710
+ with gr.Column():
711
+ question_input = gr.Textbox(
712
+ label="Question",
713
+ placeholder="Enter a GAIA question or click 'Load Sample'",
714
+ lines=3
715
+ )
716
+ with gr.Row():
717
+ sample_btn = gr.Button("🎲 Load Sample Question")
718
+ process_btn = gr.Button("🚀 Process Question", variant="primary")
719
+
720
+ with gr.Column():
721
+ answer_output = gr.Textbox(
722
+ label="Agent Answer",
723
+ lines=5,
724
+ interactive=False
725
+ )
726
+
727
+ sample_btn.click(get_sample_question, outputs=question_input)
728
+ process_btn.click(process_single_question, inputs=question_input, outputs=answer_output)
729
+
730
+ with gr.Tab("📊 Full Evaluation"):
731
+ gr.Markdown("Process all GAIA questions and prepare for submission")
732
+
733
+ process_all_btn = gr.Button("🔄 Process All Questions", variant="primary")
734
+ processing_output = gr.Textbox(label="Processing Status", lines=10, interactive=False)
735
+
736
+ process_all_btn.click(process_all_questions, outputs=processing_output)
737
+
738
+ with gr.Tab("🏆 Submit to GAIA"):
739
+ gr.Markdown("""
740
+ Submit your processed answers to the GAIA benchmark for official scoring.
741
+
742
+ **Requirements:**
743
+ 1. Your Hugging Face username
744
+ 2. Link to your Space code (e.g., https://huggingface.co/spaces/your-username/gaia-agent)
745
+ """)
746
+
747
+ with gr.Row():
748
+ with gr.Column():
749
+ username_input = gr.Textbox(label="HF Username", placeholder="your-username")
750
+ code_url_input = gr.Textbox(label="Space Code URL", placeholder="https://huggingface.co/spaces/your-username/gaia-agent")
751
+ submit_btn = gr.Button("🎯 Submit to GAIA", variant="primary")
752
+
753
+ with gr.Column():
754
+ submission_output = gr.Textbox(label="Submission Result", lines=5, interactive=False)
755
+
756
+ submit_btn.click(submit_to_gaia, inputs=[username_input, code_url_input], outputs=submission_output)
757
+
758
+ with gr.Tab("ℹ️ System Status"):
759
+ gr.Markdown("## System Information and Debugging")
760
+
761
+ refresh_btn = gr.Button("🔄 Refresh Status")
762
+ status_output = gr.Textbox(label="System Status", lines=20, interactive=False)
763
+
764
+ # Load initial status
765
+ demo.load(get_system_status, outputs=status_output)
766
+ refresh_btn.click(get_system_status, outputs=status_output)
767
+
768
+ if __name__ == "__main__":
769
+ print("🚀 Starting Gradio interface...")
770
+ demo.launch(
771
+ server_name="0.0.0.0",
772
+ server_port=7860,
773
+ show_error=True
774
+
775
+ )Dockerfile
776
+
777
+ --- Contents of .\Dockerfile ---
778
+ # Use a base Python image with better compatibility
779
+ FROM python:3.10-slim
780
+
781
+ # Set environment variables to fix permission issues (use /tmp paths)
782
+ ENV PYTHONUNBUFFERED=1
783
+ ENV NLTK_DATA=/tmp/nltk_data
784
+ ENV MPLCONFIGDIR=/tmp/matplotlib_cache
785
+ ENV HF_HOME=/tmp/huggingface_cache
786
+ ENV TORCH_HOME=/tmp/torch_cache
787
+ ENV TRANSFORMERS_CACHE=/tmp/huggingface_cache
788
+ ENV GRADIO_SERVER_NAME=0.0.0.0
789
+ ENV GRADIO_SERVER_PORT=7860
790
+
791
+ # Create app user and group for better security
792
+ RUN groupadd -r appuser && useradd -r -g appuser -u 1000 -m -s /bin/bash appuser
793
+
794
+ # Set working directory
795
+ WORKDIR /app
796
+
797
+ # Create cache directories with proper permissions
798
+ RUN mkdir -p /tmp/nltk_data \
799
+ /tmp/matplotlib_cache \
800
+ /tmp/huggingface_cache \
801
+ /tmp/torch_cache \
802
+ && chown -R appuser:appuser /tmp
803
+
804
+ # Install system dependencies
805
+ RUN apt-get update && apt-get install -y \
806
+ gcc \
807
+ g++ \
808
+ git \
809
+ curl \
810
+ && rm -rf /var/lib/apt/lists/*
811
+
812
+ # Copy requirements first for better Docker layer caching
813
+ COPY requirements.txt .
814
+
815
+ # Install Python dependencies
816
+ RUN pip install --upgrade pip && \
817
+ pip install --no-cache-dir -r requirements.txt
818
+
819
+ # Copy application code
820
+ COPY . .
821
+
822
+ # Change ownership of app files
823
+ RUN chown -R appuser:appuser /app
824
+
825
+ # Switch to non-root user
826
+ USER appuser
827
+
828
+ # Create a startup script
829
+ RUN echo '#!/bin/bash\n\
830
+ echo "Starting GAIA Agent..."\n\
831
+ echo "Environment check:"\n\
832
+ echo "NLTK_DATA: $NLTK_DATA"\n\
833
+ echo "HF_HOME: $HF_HOME"\n\
834
+ echo "MPLCONFIGDIR: $MPLCONFIGDIR"\n\
835
+ echo "Working directory: $(pwd)"\n\
836
+ echo "User: $(whoami)"\n\
837
+ python app.py' > /app/start.sh && chmod +x /app/start.sh
838
+
839
+ # Expose the port
840
+ EXPOSE 7860
841
+
842
+ # Health check (optional but helpful)
843
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
844
+ CMD curl -f http://localhost:7860/ || exit 1
845
+
846
+ # Run the application
847
+ CMD ["/app/start.sh"]
848
+ models
849
+ packages.txt
850
+
851
+ --- Contents of .\packages.txt ---
852
+ libgl1
853
+ libglib2.0-0README.md
854
+
855
+ --- Contents of .\README.md ---
856
+ ---
857
+ title: Gaia Llamaindex Agent
858
+ emoji: 📈
859
+ colorFrom: pink
860
+ colorTo: yellow
861
+ sdk: docker
862
+ pinned: false
863
+ short_description: Gaia Llamaindex Agent
864
+ ---
865
+
866
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
867
+ requirements.txt
868
+
869
+ --- Contents of .\requirements.txt ---
870
+ # Core dependencies
871
+ gradio>=4.0.0
872
+ requests>=2.31.0
873
+
874
+ # LlamaIndex core
875
+ llama-index>=0.10.0
876
+ llama-index-llms-huggingface>=0.2.0
877
+
878
+ # Transformers and ML libraries
879
+ transformers>=4.35.0
880
+ torch>=2.0.0
881
+ tokenizers>=0.15.0
882
+
883
+ # NLP dependencies
884
+ nltk>=3.8.1
885
+
886
+ # Data processing
887
+ numpy>=1.24.0
888
+ pandas>=2.0.0
889
+
890
+ # Optional: for better model performance
891
+ accelerate>=0.24.0
892
+ bitsandbytes>=0.41.0
893
+
894
+ # Utilities
895
+ typing-extensions>=4.5.0
896
+ pydantic>=2.0.0str.py
897
+
898
+ --- Contents of .\str.py ---
899
+ import os
900
+
901
+ def write_file_contents(file_path, output_file):
902
+ """Write the contents of a file to the output file."""
903
+ try:
904
+ with open(file_path, 'r', encoding='utf-8') as f:
905
+ output_file.write(f"\n--- Contents of {file_path} ---\n")
906
+ output_file.write(f.read())
907
+ except Exception as e:
908
+ output_file.write(f"Could not read file {file_path}: {e}\n")
909
+
910
+ def write_structure_and_contents(dir_path, output_file, indent=0):
911
+ """Recursively write the directory structure and file contents to the output file."""
912
+ for item in os.listdir(dir_path):
913
+ path = os.path.join(dir_path, item)
914
+ output_file.write(' ' * indent + item + '\n')
915
+ if os.path.isdir(path):
916
+ write_structure_and_contents(path, output_file, indent + 4)
917
+ else:
918
+ write_file_contents(path, output_file)
919
+
920
+ if __name__ == "__main__":
921
+ folder_path = '.' # Change this to your folder path
922
+ output_file_path = 'directory_structure_and_contents.txt' # Output file path
923
+
924
+ with open(output_file_path, 'w', encoding='utf-8') as output_file:
925
+ write_structure_and_contents(folder_path, output_file)
926
+
927
+ print(f"Directory structure and contents have been written to {output_file_path}")
928
+ utils
929
+ gaia_api.py
930
+
931
+ --- Contents of .\utils\gaia_api.py ---
932
+ # File: utils/gaia_api.py
933
+ import requests
934
+ from typing import List, Dict, Optional
935
+ import json
936
+
937
+ class GaiaAPI:
938
+ """Client for interacting with GAIA Benchmark API"""
939
+
940
+ # Fixed API endpoint
941
+ BASE_URL = "https://agents-course-unit4-scoring.hf.space"
942
+
943
+ @classmethod
944
+ def get_questions(cls) -> List[Dict]:
945
+ """Fetch all GAIA questions"""
946
+ try:
947
+ response = requests.get(f"{cls.BASE_URL}/questions")
948
+ response.raise_for_status()
949
+ return response.json()
950
+ except Exception as e:
951
+ print(f"Error fetching questions: {str(e)}")
952
+ # Return sample questions for testing
953
+ return cls._get_sample_questions()
954
+
955
+ @classmethod
956
+ def get_random_question(cls) -> Dict:
957
+ """Get a single random question"""
958
+ try:
959
+ response = requests.get(f"{cls.BASE_URL}/random-question")
960
+ response.raise_for_status()
961
+ return response.json()
962
+ except Exception as e:
963
+ print(f"Error fetching random question: {str(e)}")
964
+ return cls._get_sample_questions()[0]
965
+
966
+ @classmethod
967
+ def get_file(cls, task_id: str) -> bytes:
968
+ """Download file associated with task"""
969
+ try:
970
+ response = requests.get(f"{cls.BASE_URL}/files/{task_id}")
971
+ response.raise_for_status()
972
+ return response.content
973
+ except Exception as e:
974
+ print(f"Error fetching file for task {task_id}: {str(e)}")
975
+ return b""
976
+
977
+ @classmethod
978
+ def submit_answers(cls, username: str, agent_code: str, answers: List[Dict]) -> Dict:
979
+ """Submit answers to GAIA for scoring"""
980
+ try:
981
+ payload = {
982
+ "username": username,
983
+ "agent_code": agent_code,
984
+ "answers": answers
985
+ }
986
+ response = requests.post(f"{cls.BASE_URL}/submit", json=payload)
987
+ response.raise_for_status()
988
+ return response.json()
989
+ except Exception as e:
990
+ print(f"Error submitting answers: {str(e)}")
991
+ return {"error": str(e), "score": 0}
992
+
993
+ @classmethod
994
+ def _get_sample_questions(cls) -> List[Dict]:
995
+ """Sample questions for testing when API is unavailable"""
996
+ return [
997
+ {
998
+ "task_id": "sample_001",
999
+ "question": "What is the capital of France?",
1000
+ "level": 1,
1001
+ "final_answer": "Paris"
1002
+ },
1003
+ {
1004
+ "task_id": "sample_002",
1005
+ "question": "Calculate 15 * 8 + 7",
1006
+ "level": 1,
1007
+ "final_answer": "127"
1008
+ },
1009
+ {
1010
+ "task_id": "sample_003",
1011
+ "question": "Name three programming languages commonly used for web development",
1012
+ "level": 1,
1013
+ "final_answer": "JavaScript, Python, PHP"
1014
+ }
1015
+ ] __init__.py
1016
+
1017
+ --- Contents of .\utils\__init__.py ---
packages.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ libgl1
2
+ libglib2.0-0
str.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ def write_file_contents(file_path, output_file):
4
+ """Write the contents of a file to the output file."""
5
+ try:
6
+ with open(file_path, 'r', encoding='utf-8') as f:
7
+ output_file.write(f"\n--- Contents of {file_path} ---\n")
8
+ output_file.write(f.read())
9
+ except Exception as e:
10
+ output_file.write(f"Could not read file {file_path}: {e}\n")
11
+
12
+ def write_structure_and_contents(dir_path, output_file, indent=0):
13
+ """Recursively write the directory structure and file contents to the output file."""
14
+ for item in os.listdir(dir_path):
15
+ path = os.path.join(dir_path, item)
16
+ output_file.write(' ' * indent + item + '\n')
17
+ if os.path.isdir(path):
18
+ write_structure_and_contents(path, output_file, indent + 4)
19
+ else:
20
+ write_file_contents(path, output_file)
21
+
22
+ if __name__ == "__main__":
23
+ folder_path = '.' # Change this to your folder path
24
+ output_file_path = 'directory_structure_and_contents.txt' # Output file path
25
+
26
+ with open(output_file_path, 'w', encoding='utf-8') as output_file:
27
+ write_structure_and_contents(folder_path, output_file)
28
+
29
+ print(f"Directory structure and contents have been written to {output_file_path}")