StarpowerTechnology's picture
Upload 31 files
262eb2c verified
Raw History Blame Contribute Delete
3.08 kB
from __future__ import annotations
import csv
import json
from collections.abc import Iterator
from pathlib import Path
SUPPORTED_EXTENSIONS = {".txt", ".md", ".jsonl", ".json", ".csv", ".parquet"}
def discover_files(path: str | Path) -> list[Path]:
root = Path(path).expanduser().resolve()
if root.is_file():
files = [root]
elif root.is_dir():
files = [item for item in root.rglob("*") if item.is_file()]
else:
raise FileNotFoundError(root)
supported = sorted(item for item in files if item.suffix.lower() in SUPPORTED_EXTENSIONS)
if not supported:
raise ValueError(f"No supported data files found under {root}")
return supported
def iter_documents(files: list[Path], text_field: str = "text") -> Iterator[str]:
for path in files:
suffix = path.suffix.lower()
if suffix in {".txt", ".md"}:
text = path.read_text(encoding="utf-8", errors="replace")
if text.strip():
yield text
elif suffix == ".jsonl":
with path.open("r", encoding="utf-8", errors="replace") as handle:
for line_number, line in enumerate(handle, 1):
if not line.strip():
continue
value = json.loads(line)
text = value.get(text_field) if isinstance(value, dict) else None
if isinstance(text, str) and text.strip():
yield text
elif text is None:
raise ValueError(f"Missing string field {text_field!r} in {path}:{line_number}")
elif suffix == ".json":
value = json.loads(path.read_text(encoding="utf-8", errors="replace"))
records = value if isinstance(value, list) else [value]
for index, record in enumerate(records):
text = record.get(text_field) if isinstance(record, dict) else None
if isinstance(text, str) and text.strip():
yield text
elif text is None:
raise ValueError(f"Missing string field {text_field!r} in {path}, record {index}")
elif suffix == ".csv":
with path.open("r", encoding="utf-8", errors="replace", newline="") as handle:
for index, record in enumerate(csv.DictReader(handle), 2):
text = record.get(text_field)
if isinstance(text, str) and text.strip():
yield text
elif text is None:
raise ValueError(f"Missing field {text_field!r} in {path}:{index}")
elif suffix == ".parquet":
try:
import pyarrow.parquet as pq
except ImportError as error:
raise RuntimeError("Parquet scanning requires pyarrow") from error
table = pq.read_table(path, columns=[text_field])
for text in table[text_field].to_pylist():
if isinstance(text, str) and text.strip():
yield text