| """
|
| hf_dataset_loader.py
|
| ────────────────────
|
| Loads Romanian legal documents from the HuggingFace multi_eurlex dataset
|
| and converts them into the same articles.jsonl format that pipeline.py produces.
|
|
|
| This is a temporary substitute while legislatie.just.ro is rate-limiting us.
|
|
|
| Install: pip install datasets
|
| """
|
|
|
| import json
|
| import re
|
| from pathlib import Path
|
| from datasets import load_dataset
|
|
|
| DATA_DIR = Path("data")
|
| DATA_DIR.mkdir(exist_ok=True)
|
| ARTICLES_FILE = DATA_DIR / "articles.jsonl"
|
|
|
|
|
| def split_into_chunks(text: str, law_id: int, title: str) -> list[dict]:
|
| """
|
| MultiEURLEX documents don't have article boundaries marked
|
| the same way as legislatie.just.ro, so we do a best-effort split.
|
|
|
| Strategy:
|
| 1. Try to split on "Article X" / "Articolul X" patterns first.
|
| 2. If none found, fall back to splitting on paragraph boundaries
|
| (every ~500 characters), so the chunks aren't too big for the embedder.
|
| """
|
|
|
| article_pattern = re.compile(
|
| r"(Articolul\s+\d+|Article\s+\d+)",
|
| re.IGNORECASE
|
| )
|
| matches = list(article_pattern.finditer(text))
|
|
|
| if matches:
|
| chunks = []
|
| for i, match in enumerate(matches):
|
| start = match.start()
|
| end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
|
| chunk_text = text[start:end].strip()
|
| if len(chunk_text) > 80:
|
| chunks.append({
|
| "law_id": law_id,
|
| "law_title": title,
|
| "article_number": match.group(0).strip(),
|
| "text": chunk_text,
|
| "chunk": f"{title}\n{match.group(0).strip()}\n\n{chunk_text}",
|
| })
|
| return chunks
|
|
|
|
|
| paragraphs = [p.strip() for p in text.split("\n\n") if len(p.strip()) > 80]
|
| chunks = []
|
| for i, para in enumerate(paragraphs):
|
| article_num = f"Paragraf {i + 1}"
|
| chunks.append({
|
| "law_id": law_id,
|
| "law_title": title,
|
| "article_number": article_num,
|
| "text": para,
|
| "chunk": f"{title}\n{article_num}\n\n{para}",
|
| })
|
| return chunks
|
|
|
|
|
| def load_and_convert(max_docs: int = 500):
|
| """
|
| Load Romanian documents from multi_eurlex and write them to articles.jsonl.
|
|
|
| max_docs: how many documents to load (500 is a good starting point).
|
| The full dataset is ~30k documents — start small.
|
| """
|
| print("Downloading multi_eurlex Romanian split from HuggingFace...")
|
| print("(This downloads ~200MB on first run, then it's cached locally.)\n")
|
|
|
|
|
| dataset = load_dataset(
|
| "multi_eurlex",
|
| "ro",
|
| split="train",
|
| trust_remote_code=True,
|
| )
|
|
|
| print(f"Dataset loaded. Total documents available: {len(dataset)}")
|
| print(f"Processing first {max_docs} documents...\n")
|
|
|
| total_articles = 0
|
|
|
| with open(ARTICLES_FILE, "w", encoding="utf-8") as f:
|
| for i, doc in enumerate(dataset):
|
| if i >= max_docs:
|
| break
|
|
|
| law_id = i + 1
|
| title = doc.get("text", "")[:80].split("\n")[0].strip() or f"Document {law_id}"
|
| text = doc.get("text", "")
|
|
|
| if not text or len(text) < 100:
|
| continue
|
|
|
| chunks = split_into_chunks(text, law_id, title)
|
| for chunk in chunks:
|
| f.write(json.dumps(chunk, ensure_ascii=False) + "\n")
|
| total_articles += 1
|
|
|
| if (i + 1) % 50 == 0:
|
| print(f" Processed {i + 1}/{max_docs} documents "
|
| f"({total_articles} articles so far)...")
|
|
|
| print(f"\n✓ Done! Wrote {total_articles} articles to {ARTICLES_FILE}")
|
| print(f" File size: {ARTICLES_FILE.stat().st_size // 1024} KB")
|
| print(f"\nNext step: run python indexer.py to build the FAISS index.")
|
|
|
|
|
| if __name__ == "__main__":
|
| load_and_convert(max_docs=500) |