Spaces:
Sleeping
Sleeping
Commit ·
5f6a110
1
Parent(s): 6a8e4ed
feat: re-run Helping Hands with post-processing and scale sample PDFs to 12 documents
Browse files- public/sample_pdfs/2025 03 SEIS ukraine_socio-economic_researchpaper.pdf +3 -0
- public/sample_pdfs/Analysis of the impact of refugees from Ukraine on the economy of Poland.pdf +3 -0
- public/sample_pdfs/LCRP_2021.pdf +3 -0
- public/sample_pdfs/LCRP_2025.pdf +3 -0
- public/sample_pdfs/LebanonResp2025.pdf +3 -0
- public/sample_pdfs/NAVIGATING HEALTH AND WELL-BEING CHALLENGES FOR REFUGEES FROM UKRAINE - 2nd Edition.pdf +3 -0
- public/sample_pdfs/Poland Analysis of the impact of refugees from Ukraine on the economy of Poland – March 2024.pdf +3 -0
- public/sample_pdfs/Revised Ukraine Situation 2025 2026 RRP FINAL (5).pdf +3 -0
- public/sample_pdfs/SESRE_WBG.pdf +3 -0
- public/sample_pdfs/Somalia_Baseline.pdf +3 -0
- public/sample_pdfs/Somalia_NSP.pdf +3 -0
- scripts/extract_sample_pdfs.py +104 -1
- upload_to_hf.py +9 -0
public/sample_pdfs/2025 03 SEIS ukraine_socio-economic_researchpaper.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:329a144b0e723f56e7a92cd2d8dfd9ea079f4b72e53ce438f60a1dad548e2fca
|
| 3 |
+
size 1645202
|
public/sample_pdfs/Analysis of the impact of refugees from Ukraine on the economy of Poland.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6b28a968cc33c174aa7a3d0a1d9cd5085a0abbc903c22b291343ae672028d6fd
|
| 3 |
+
size 4130712
|
public/sample_pdfs/LCRP_2021.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1b9cf25fb6c4de71347f8e4ca4ca8f1a3c38a117d3579e47b9d0f765f017a858
|
| 3 |
+
size 6052678
|
public/sample_pdfs/LCRP_2025.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a43d3516a7167905824d3af1ca73e2386bc5be4dd95c3c3eabfa0cf14ed02a92
|
| 3 |
+
size 8826747
|
public/sample_pdfs/LebanonResp2025.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a43d3516a7167905824d3af1ca73e2386bc5be4dd95c3c3eabfa0cf14ed02a92
|
| 3 |
+
size 8826747
|
public/sample_pdfs/NAVIGATING HEALTH AND WELL-BEING CHALLENGES FOR REFUGEES FROM UKRAINE - 2nd Edition.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6ab3d2ffa6da1f73a0f86b6ef8c5d82764852dc9f52521bb623233d10dcea4e3
|
| 3 |
+
size 2795909
|
public/sample_pdfs/Poland Analysis of the impact of refugees from Ukraine on the economy of Poland – March 2024.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:886eaed5ee0626e201b9758b1e20107aaf73b3e75fe498fbbc693b151230cdf1
|
| 3 |
+
size 4932124
|
public/sample_pdfs/Revised Ukraine Situation 2025 2026 RRP FINAL (5).pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bf0fca50ffdef6653f70151422acc0a8252dcf69bf91eb13e765db1dee413684
|
| 3 |
+
size 6135356
|
public/sample_pdfs/SESRE_WBG.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3b5a3405d248c5ae0b6f486bf7132edefc3615d2b2f2f7219ddea5dfe4fa8ff6
|
| 3 |
+
size 9205502
|
public/sample_pdfs/Somalia_Baseline.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cdae67484a86a004e61d50b866445f57473822c9749dfcca21562d3a6a86067a
|
| 3 |
+
size 1370622
|
public/sample_pdfs/Somalia_NSP.pdf
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9b1e81e04cfdea69865a61c2d59291ee91c596c597d5278612a8e697ee571a22
|
| 3 |
+
size 92582
|
scripts/extract_sample_pdfs.py
CHANGED
|
@@ -17,6 +17,77 @@ EXTRACTIONS_DIR = APP_ROOT / "annotation_data" / "sample_extractions"
|
|
| 17 |
LINKS_DIR = APP_ROOT / "annotation_data" / "sample_data"
|
| 18 |
LINKS_FILE = LINKS_DIR / "sample_pdf_links.json"
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
def main():
|
| 21 |
if not PDFS_DIR.exists():
|
| 22 |
print(f"Error: {PDFS_DIR} does not exist.")
|
|
@@ -42,6 +113,33 @@ def main():
|
|
| 42 |
doc_name = f"doc_{i}"
|
| 43 |
print(f"\n[{i}/{len(pdf_files)}] Processing: {pdf_path.name} -> {doc_name}")
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
try:
|
| 46 |
doc = fitz.open(str(pdf_path))
|
| 47 |
num_pages = len(doc)
|
|
@@ -58,7 +156,7 @@ def main():
|
|
| 58 |
result = extractor.extract_from_text(
|
| 59 |
text,
|
| 60 |
include_confidence=True,
|
| 61 |
-
use_classifier=
|
| 62 |
extract_provenance=True,
|
| 63 |
dataset_threshold=0.3,
|
| 64 |
apply_heuristics=True,
|
|
@@ -110,6 +208,11 @@ def main():
|
|
| 110 |
dest_dir.mkdir(parents=True, exist_ok=True)
|
| 111 |
dest_file = dest_dir / f"{doc_name}_direct_judged.jsonl"
|
| 112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
with open(dest_file, "w", encoding="utf-8") as f:
|
| 114 |
json.dump(pages_data, f, indent=2, ensure_ascii=False)
|
| 115 |
|
|
|
|
| 17 |
LINKS_DIR = APP_ROOT / "annotation_data" / "sample_data"
|
| 18 |
LINKS_FILE = LINKS_DIR / "sample_pdf_links.json"
|
| 19 |
|
| 20 |
+
def merge_existing_annotations(dest_file, new_pages_data):
|
| 21 |
+
"""
|
| 22 |
+
Reads existing pages data from dest_file, extracts human annotations
|
| 23 |
+
and validations, and merges them into new_pages_data.
|
| 24 |
+
"""
|
| 25 |
+
if not dest_file.exists():
|
| 26 |
+
return new_pages_data
|
| 27 |
+
|
| 28 |
+
try:
|
| 29 |
+
with open(dest_file, "r", encoding="utf-8") as f:
|
| 30 |
+
old_pages_data = json.load(f)
|
| 31 |
+
except Exception as e:
|
| 32 |
+
print(f" Warning: Could not read existing file {dest_file} for merging: {e}")
|
| 33 |
+
return new_pages_data
|
| 34 |
+
|
| 35 |
+
# Map page number to its human annotations and validations
|
| 36 |
+
page_merges = {}
|
| 37 |
+
for old_page in old_pages_data:
|
| 38 |
+
page_num = old_page.get("document", {}).get("pages", [0])[0]
|
| 39 |
+
human_added = []
|
| 40 |
+
val_map = {} # dataset_name (lower) -> validations list
|
| 41 |
+
|
| 42 |
+
for ds in old_page.get("datasets", []):
|
| 43 |
+
ds_name = ds.get("dataset_name", {})
|
| 44 |
+
name_text = ds_name.get("text", "") if isinstance(ds_name, dict) else str(ds_name)
|
| 45 |
+
if not name_text:
|
| 46 |
+
continue
|
| 47 |
+
|
| 48 |
+
# Check if it is human added
|
| 49 |
+
is_human = (ds.get("source") == "human" or ds.get("annotator") is not None)
|
| 50 |
+
if is_human:
|
| 51 |
+
human_added.append(ds)
|
| 52 |
+
|
| 53 |
+
# Check if it has human validations
|
| 54 |
+
vals = ds.get("validations", [])
|
| 55 |
+
if vals:
|
| 56 |
+
val_map[name_text.lower()] = vals
|
| 57 |
+
|
| 58 |
+
page_merges[page_num] = {
|
| 59 |
+
"human_added": human_added,
|
| 60 |
+
"val_map": val_map
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
# Merge into new_pages_data
|
| 64 |
+
for new_page in new_pages_data:
|
| 65 |
+
page_num = new_page.get("document", {}).get("pages", [0])[0]
|
| 66 |
+
merge_info = page_merges.get(page_num)
|
| 67 |
+
if not merge_info:
|
| 68 |
+
continue
|
| 69 |
+
|
| 70 |
+
# 1. Restore validations for model-extracted datasets
|
| 71 |
+
for ds in new_page.get("datasets", []):
|
| 72 |
+
ds_name = ds.get("dataset_name", {})
|
| 73 |
+
name_text = ds_name.get("text", "") if isinstance(ds_name, dict) else str(ds_name)
|
| 74 |
+
if name_text.lower() in merge_info["val_map"]:
|
| 75 |
+
ds["validations"] = merge_info["val_map"][name_text.lower()]
|
| 76 |
+
|
| 77 |
+
# 2. Append human-added datasets
|
| 78 |
+
existing_names = {
|
| 79 |
+
(ds.get("dataset_name", {}).get("text", "") if isinstance(ds.get("dataset_name"), dict) else str(ds.get("dataset_name"))).lower()
|
| 80 |
+
for ds in new_page.get("datasets", [])
|
| 81 |
+
}
|
| 82 |
+
for ds in merge_info["human_added"]:
|
| 83 |
+
ds_name = ds.get("dataset_name", {})
|
| 84 |
+
name_text = ds_name.get("text", "") if isinstance(ds_name, dict) else str(ds_name)
|
| 85 |
+
if name_text.lower() not in existing_names:
|
| 86 |
+
new_page["datasets"].append(ds)
|
| 87 |
+
existing_names.add(name_text.lower())
|
| 88 |
+
|
| 89 |
+
return new_pages_data
|
| 90 |
+
|
| 91 |
def main():
|
| 92 |
if not PDFS_DIR.exists():
|
| 93 |
print(f"Error: {PDFS_DIR} does not exist.")
|
|
|
|
| 113 |
doc_name = f"doc_{i}"
|
| 114 |
print(f"\n[{i}/{len(pdf_files)}] Processing: {pdf_path.name} -> {doc_name}")
|
| 115 |
|
| 116 |
+
dest_dir = EXTRACTIONS_DIR / doc_name / "raw"
|
| 117 |
+
dest_file = dest_dir / f"{doc_name}_direct_judged.jsonl"
|
| 118 |
+
|
| 119 |
+
if dest_file.exists() and doc_name != "doc_1":
|
| 120 |
+
print(f" Existing extraction file found at: {dest_file}")
|
| 121 |
+
print(" Skipping model extraction and reading existing file...")
|
| 122 |
+
try:
|
| 123 |
+
with open(dest_file, "r", encoding="utf-8") as f:
|
| 124 |
+
pages_data = json.load(f)
|
| 125 |
+
num_pages = len(pages_data)
|
| 126 |
+
has_ds = any(len(p.get("datasets", [])) > 0 for p in pages_data)
|
| 127 |
+
link_entry = {
|
| 128 |
+
"index": i,
|
| 129 |
+
"src_docname": doc_name,
|
| 130 |
+
"original_name": pdf_path.stem,
|
| 131 |
+
"landing_page_url": f"/sample_pdfs/{pdf_path.name}",
|
| 132 |
+
"direct_pdf_url": f"/sample_pdfs/{pdf_path.name}",
|
| 133 |
+
"status": "success",
|
| 134 |
+
"has_revalidation": True,
|
| 135 |
+
"has_datasets": has_ds,
|
| 136 |
+
"num_pages": num_pages
|
| 137 |
+
}
|
| 138 |
+
links.append(link_entry)
|
| 139 |
+
continue
|
| 140 |
+
except Exception as e:
|
| 141 |
+
print(f" Error reading existing file: {e}. Re-running extraction...")
|
| 142 |
+
|
| 143 |
try:
|
| 144 |
doc = fitz.open(str(pdf_path))
|
| 145 |
num_pages = len(doc)
|
|
|
|
| 156 |
result = extractor.extract_from_text(
|
| 157 |
text,
|
| 158 |
include_confidence=True,
|
| 159 |
+
use_classifier=True,
|
| 160 |
extract_provenance=True,
|
| 161 |
dataset_threshold=0.3,
|
| 162 |
apply_heuristics=True,
|
|
|
|
| 208 |
dest_dir.mkdir(parents=True, exist_ok=True)
|
| 209 |
dest_file = dest_dir / f"{doc_name}_direct_judged.jsonl"
|
| 210 |
|
| 211 |
+
if doc_name == "doc_1" and dest_file.exists():
|
| 212 |
+
print(f" Merging existing annotations/validations for {doc_name}...")
|
| 213 |
+
pages_data = merge_existing_annotations(dest_file, pages_data)
|
| 214 |
+
has_ds = any(len(p.get("datasets", [])) > 0 for p in pages_data)
|
| 215 |
+
|
| 216 |
with open(dest_file, "w", encoding="utf-8") as f:
|
| 217 |
json.dump(pages_data, f, indent=2, ensure_ascii=False)
|
| 218 |
|
upload_to_hf.py
CHANGED
|
@@ -3,6 +3,15 @@ from pathlib import Path
|
|
| 3 |
from huggingface_hub import HfApi, create_repo
|
| 4 |
|
| 5 |
token = os.environ.get("HF_TOKEN")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
if not token:
|
| 7 |
raise ValueError("HF_TOKEN not found in environment.")
|
| 8 |
|
|
|
|
| 3 |
from huggingface_hub import HfApi, create_repo
|
| 4 |
|
| 5 |
token = os.environ.get("HF_TOKEN")
|
| 6 |
+
if not token:
|
| 7 |
+
# Try reading from .env file
|
| 8 |
+
env_path = Path(__file__).resolve().parent / ".env"
|
| 9 |
+
if env_path.exists():
|
| 10 |
+
for line in env_path.read_text().splitlines():
|
| 11 |
+
if line.startswith("HF_TOKEN="):
|
| 12 |
+
token = line.split("=", 1)[1].strip()
|
| 13 |
+
break
|
| 14 |
+
|
| 15 |
if not token:
|
| 16 |
raise ValueError("HF_TOKEN not found in environment.")
|
| 17 |
|