chatbot-rag / src /storage.py
scythe327's picture
Upload folder using huggingface_hub
55ed2b1 verified
Raw
History Blame Contribute Delete
5.77 kB
import json
import os
from pathlib import Path
import polars as pl
from huggingface_hub import HfApi, hf_hub_download, upload_file
from huggingface_hub.utils import RepositoryNotFoundError
from src.config import Config
from src.utils import load_json, save_json
class Storage:
def __init__(self, config: Config, hf_token: str, username: str):
self.config = config
self.hf_token = hf_token
self.username = username
self.dataset_id = f"{username}/{config.dataset_repo_id}"
self.api = HfApi(token=hf_token)
self.config.data_dir.mkdir(parents=True, exist_ok=True)
def save_local(self, pages_df: pl.DataFrame, chunks_df: pl.DataFrame, facts_df: pl.DataFrame):
self.config.data_dir.mkdir(parents=True, exist_ok=True)
if not pages_df.is_empty():
pages_df.write_parquet(self.config.pages_file)
if not chunks_df.is_empty():
chunks_df.write_parquet(self.config.chunks_file)
if not facts_df.is_empty():
facts_df.write_parquet(self.config.facts_file)
save_json(
{
"pages": len(pages_df),
"chunks": len(chunks_df),
"facts": len(facts_df),
"has_indexes": (
self.config.faiss_file.exists()
and self.config.bm25_file.exists()
),
},
self.config.metadata_file,
)
def load_local(self) -> dict:
result = {"pages": pl.DataFrame(), "chunks": pl.DataFrame(), "facts": pl.DataFrame()}
if self.config.pages_file.exists():
result["pages"] = pl.read_parquet(self.config.pages_file)
if self.config.chunks_file.exists():
result["chunks"] = pl.read_parquet(self.config.chunks_file)
if self.config.facts_file.exists():
result["facts"] = pl.read_parquet(self.config.facts_file)
return result
def push_to_hub(self):
self._ensure_dataset_repo()
files_to_upload = []
if self.config.pages_file.exists():
files_to_upload.append(self.config.pages_file)
if self.config.chunks_file.exists():
files_to_upload.append(self.config.chunks_file)
if self.config.facts_file.exists():
files_to_upload.append(self.config.facts_file)
if self.config.faiss_file.exists():
files_to_upload.append(self.config.faiss_file)
if self.config.bm25_file.exists():
files_to_upload.append(self.config.bm25_file)
if self.config.metadata_file.exists():
files_to_upload.append(self.config.metadata_file)
for file_path in files_to_upload:
try:
upload_file(
path_or_fileobj=str(file_path),
path_in_repo=file_path.name,
repo_id=self.dataset_id,
repo_type="dataset",
token=self.hf_token,
)
except Exception as e:
print(f"Failed to upload {file_path.name}: {e}")
return f"https://huggingface.co/datasets/{self.dataset_id}"
def pull_from_hub(self) -> dict:
result = {"pages": pl.DataFrame(), "chunks": pl.DataFrame(), "facts": pl.DataFrame()}
if not self._repo_exists():
return result
self.config.data_dir.mkdir(parents=True, exist_ok=True)
file_mapping = {
self.config.pages_path: "pages",
self.config.chunks_path: "chunks",
self.config.facts_path: "facts",
self.config.faiss_index_path: None,
self.config.bm25_index_path: None,
self.config.metadata_path: None,
}
for file_name, key in file_mapping.items():
try:
downloaded = hf_hub_download(
repo_id=self.dataset_id,
filename=file_name,
repo_type="dataset",
token=self.hf_token,
local_dir=self.config.data_dir,
local_dir_use_symlinks=False,
)
except Exception:
continue
if self.config.pages_file.exists():
result["pages"] = pl.read_parquet(self.config.pages_file)
if self.config.chunks_file.exists():
result["chunks"] = pl.read_parquet(self.config.chunks_file)
if self.config.facts_file.exists():
result["facts"] = pl.read_parquet(self.config.facts_file)
return result
def _ensure_dataset_repo(self):
try:
self.api.repo_info(repo_id=self.dataset_id, repo_type="dataset")
except RepositoryNotFoundError:
self.api.create_repo(
repo_id=self.dataset_id,
repo_type="dataset",
private=False,
exist_ok=True,
)
def _repo_exists(self) -> bool:
try:
self.api.repo_info(repo_id=self.dataset_id, repo_type="dataset")
return True
except RepositoryNotFoundError:
return False
def has_local_data(self) -> bool:
return self.config.pages_file.exists() and self.config.chunks_file.exists()
def get_stats(self) -> dict:
stats = {"pages": 0, "chunks": 0, "facts": 0, "indexes": False}
try:
meta = load_json(self.config.metadata_file) if self.config.metadata_file.exists() else {}
return {
"pages": meta.get("pages", 0),
"chunks": meta.get("chunks", 0),
"facts": meta.get("facts", 0),
"indexes": meta.get("has_indexes", False),
}
except Exception:
return stats