Skip to content

Commit a9b5411

Browse files
Add aguvis download script
1 parent a66a5e6 commit a9b5411

2 files changed

Lines changed: 273 additions & 0 deletions

File tree

scripts/agents/get_aguvis_data.py

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to download, process, and upload the aguvis-stage2 dataset.
4+
Downloads from huggingface.co/datasets/xlangai/aguvis-stage2 and uploads to smolagents/aguvis-stage-2
5+
"""
6+
7+
import gc
8+
import json
9+
import os
10+
import shutil
11+
import zipfile
12+
from pathlib import Path
13+
from typing import Any, Dict, List
14+
15+
from datasets import Dataset, DatasetDict
16+
from dotenv import load_dotenv
17+
from huggingface_hub import HfApi, login, snapshot_download
18+
from PIL import Image
19+
20+
load_dotenv(override=True)
21+
22+
23+
def discover_dataset_config(dataset_path: str) -> List[Dict[str, Any]]:
24+
"""Discover dataset configuration by scanning the data/aguvis/train directory."""
25+
dataset_dir = Path(dataset_path)
26+
train_dir = dataset_dir / "data" / "aguvis" / "train"
27+
28+
if not train_dir.exists():
29+
raise FileNotFoundError(f"Train directory not found: {train_dir}")
30+
31+
configs = []
32+
33+
# Find all JSON files in the train directory
34+
for json_file in train_dir.glob("*.json"):
35+
base_name = json_file.stem.replace("-l1", "").replace("-l2", "")
36+
37+
# Determine the images folder based on the base name
38+
images_folder = None
39+
40+
# Generate potential folder names by trying common patterns
41+
potential_folders = [base_name, f"{base_name}/images"]
42+
43+
# Find the first existing folder
44+
for folder in potential_folders:
45+
full_folder_path = dataset_dir / folder
46+
if full_folder_path.exists():
47+
images_folder = folder
48+
break
49+
50+
if images_folder is None:
51+
print(
52+
f"Warning: No images folder found for {base_name}, trying default pattern"
53+
)
54+
images_folder = f"{base_name}/images"
55+
56+
config = {
57+
"json_path": str(json_file.relative_to(dataset_dir)),
58+
"images_folder": images_folder,
59+
"sampling_strategy": "all", # Default to all for now
60+
"split_name": base_name,
61+
}
62+
63+
configs.append(config)
64+
print(f"Discovered config: {base_name} -> {images_folder}")
65+
66+
return configs
67+
68+
69+
def download_dataset(
70+
repo_id: str = "xlangai/aguvis-stage2", local_dir: str = "./aguvis_raw"
71+
) -> str:
72+
"""Download the dataset using snapshot_download."""
73+
print(f"Downloading dataset from {repo_id}...")
74+
try:
75+
local_path = snapshot_download(
76+
repo_id=repo_id, local_dir=local_dir, repo_type="dataset"
77+
)
78+
print(f"Dataset downloaded to: {local_path}")
79+
return local_path
80+
except Exception as e:
81+
print(f"Error downloading dataset: {e}")
82+
print("This might be due to authentication issues or network problems.")
83+
raise
84+
85+
86+
def extract_zip_files(dataset_path: str):
87+
"""Extract all zip files found in the dataset directory."""
88+
print("Extracting zip files...")
89+
dataset_dir = Path(dataset_path)
90+
91+
for zip_file in dataset_dir.rglob("*.zip"):
92+
print(f"Extracting: {zip_file}")
93+
extract_dir = zip_file.parent / zip_file.stem
94+
95+
with zipfile.ZipFile(zip_file, "r") as zip_ref:
96+
zip_ref.extractall(extract_dir)
97+
98+
print(f"Extracted to: {extract_dir}")
99+
100+
101+
def load_images_from_folder(
102+
images_folder: Path, image_paths: List[str]
103+
) -> List[Image.Image]:
104+
"""Load images from the specified folder."""
105+
images = []
106+
for img_path in image_paths:
107+
full_path = images_folder / img_path
108+
if full_path.exists():
109+
try:
110+
img = Image.open(full_path)
111+
images.append(img.copy())
112+
img.close()
113+
except Exception as e:
114+
print(f"Warning: Could not load image {full_path}: {e}")
115+
else:
116+
print(f"Warning: Image not found: {full_path}")
117+
return images
118+
119+
120+
def convert_to_chat_format(data_item: Dict[str, Any]) -> List[Dict[str, Any]]:
121+
"""Convert data item to chat template format."""
122+
# This is a placeholder - you'll need to adapt this based on the actual data structure
123+
# The exact conversion depends on how the original data is structured
124+
chat_messages = []
125+
126+
# Example conversion - adapt based on actual data structure
127+
if "conversations" in data_item:
128+
for conv in data_item["conversations"]:
129+
if "from" in conv and "value" in conv:
130+
role = "user" if conv["from"] == "human" else "assistant"
131+
message = {"role": role, "content": conv["value"]}
132+
chat_messages.append(message)
133+
elif "instruction" in data_item and "response" in data_item:
134+
chat_messages = [
135+
{"role": "user", "content": data_item["instruction"]},
136+
{"role": "assistant", "content": data_item["response"]},
137+
]
138+
139+
return chat_messages
140+
141+
142+
def process_split(config: Dict[str, Any], dataset_path: str) -> Dataset:
143+
"""Process a single dataset split."""
144+
print(f"Processing split: {config['split_name']}")
145+
146+
dataset_dir = Path(dataset_path)
147+
json_path = dataset_dir / config["json_path"]
148+
images_folder = dataset_dir / config["images_folder"]
149+
150+
if not json_path.exists():
151+
print(f"Warning: JSON file not found: {json_path}")
152+
return None
153+
154+
if not images_folder.exists():
155+
print(f"Warning: Images folder not found: {images_folder}")
156+
return None
157+
158+
# Load JSON data
159+
with open(json_path, "r") as f:
160+
data = json.load(f)
161+
162+
processed_data = []
163+
164+
for item in data:
165+
try:
166+
# Extract image paths from the data item
167+
image_paths = []
168+
if "images" in item:
169+
image_paths = (
170+
item["images"]
171+
if isinstance(item["images"], list)
172+
else [item["images"]]
173+
)
174+
elif "image" in item:
175+
image_paths = [item["image"]]
176+
177+
# Load images
178+
images = load_images_from_folder(images_folder, image_paths)
179+
180+
# Convert to chat format
181+
texts = convert_to_chat_format(item)
182+
183+
processed_data.append({"images": images, "texts": texts})
184+
185+
except Exception as e:
186+
print(f"Warning: Error processing item: {e}")
187+
continue
188+
189+
print(f"Processed {len(processed_data)} items for split {config['split_name']}")
190+
191+
# Create dataset
192+
dataset = Dataset.from_list(processed_data)
193+
return dataset
194+
195+
196+
def upload_dataset(
197+
dataset_dict: DatasetDict, repo_id: str = "smolagents/aguvis-stage-2"
198+
):
199+
"""Upload the processed dataset to HuggingFace Hub."""
200+
print(f"Uploading dataset to {repo_id}...")
201+
202+
# Create the repository if it doesn't exist
203+
api = HfApi()
204+
try:
205+
api.create_repo(repo_id, repo_type="dataset", exist_ok=True)
206+
except Exception as e:
207+
print(f"Repository creation info: {e}")
208+
209+
# Push to hub
210+
try:
211+
dataset_dict.push_to_hub(repo_id)
212+
print(f"Dataset uploaded successfully to {repo_id}")
213+
except Exception as e:
214+
print(f"Error uploading dataset: {e}")
215+
print("This might be due to authentication issues or insufficient permissions.")
216+
raise
217+
218+
219+
def authenticate_huggingface():
220+
"""Authenticate with HuggingFace Hub using token."""
221+
hf_token = os.getenv("HF_TOKEN")
222+
if hf_token:
223+
print("Authenticating with HuggingFace Hub using token...")
224+
login(token=hf_token)
225+
else:
226+
raise ValueError("HF_TOKEN environment variable not set.")
227+
228+
229+
def main():
230+
"""Main function to orchestrate the entire process."""
231+
print("Starting aguvis-stage2 dataset processing...")
232+
233+
# Step 0: Authenticate with HuggingFace Hub
234+
authenticate_huggingface()
235+
236+
# Step 1: Download dataset
237+
dataset_path = download_dataset()
238+
239+
# Step 2: Extract zip files
240+
extract_zip_files(dataset_path)
241+
242+
# Step 3: Discover dataset configuration
243+
dataset_configs = discover_dataset_config(dataset_path)
244+
245+
# Step 4: Process each split
246+
dataset_dict = {}
247+
248+
for config in dataset_configs:
249+
print(f"\n{'=' * 50}")
250+
dataset = process_split(config, dataset_path)
251+
252+
if dataset is not None:
253+
dataset_dict[config["split_name"]] = dataset
254+
255+
# Force garbage collection to manage memory
256+
gc.collect()
257+
258+
# Step 5: Create DatasetDict and upload
259+
if dataset_dict:
260+
final_dataset = DatasetDict(dataset_dict)
261+
upload_dataset(final_dataset)
262+
else:
263+
print("No datasets were successfully processed.")
264+
265+
# Cleanup
266+
print("\nCleaning up temporary files...")
267+
shutil.rmtree(dataset_path, ignore_errors=True)
268+
269+
print("Process completed!")
270+
271+
272+
if __name__ == "__main__":
273+
main()

0 commit comments

Comments
 (0)