Peterase commited on
Commit
70dc6c7
·
1 Parent(s): f48c629

fix: clean up storage adapter and pin sentence-transformers to 3.0.1

Browse files
app/services/hf_storage_adapter.py CHANGED
@@ -1,7 +1,6 @@
1
  """Hugging Face Hub storage adapter."""
2
  from app.ports.storage import StoragePort
3
  from app.config import get_settings
4
- from typing import Optional
5
  import logging
6
  import os
7
  from pathlib import Path
@@ -12,98 +11,88 @@ settings = get_settings()
12
 
13
  class HFStorageAdapter(StoragePort):
14
  """Hugging Face Hub implementation of StoragePort."""
15
-
16
  def __init__(self):
17
  self.bucket_path = settings.HF_BUCKET_PATH
18
- # Extract repo_id from bucket path: hf://buckets/Peterase/Ragora-doc-store -> Peterase/Ragora-doc-store
19
  self.repo_id = self.bucket_path.replace("hf://buckets/", "")
20
  self.local_cache = Path("/tmp/ragora_cache")
21
  self.local_cache.mkdir(exist_ok=True)
 
 
22
  logger.info(f"Using HF bucket: {self.bucket_path} (repo: {self.repo_id})")
23
-
 
 
24
  async def upload(self, key: str, data: bytes, content_type: str) -> str:
25
- """Upload file to HF bucket."""
26
  try:
27
  # Save locally first
28
  local_path = self.local_cache / key
29
  local_path.parent.mkdir(parents=True, exist_ok=True)
30
-
31
- with open(local_path, 'wb') as f:
32
  f.write(data)
33
-
34
- # Upload to HF bucket using huggingface_hub API
35
  from huggingface_hub import HfApi
36
- api = HfApi()
37
-
38
- # Upload file to the bucket
39
  api.upload_file(
40
  path_or_fileobj=str(local_path),
41
  path_in_repo=key,
42
  repo_id=self.repo_id,
43
  repo_type="dataset"
44
  )
45
-
46
  logger.info(f"Uploaded file: {key}")
47
  return key
48
  except Exception as e:
49
  logger.error(f"Error uploading file: {e}")
50
  raise
51
-
52
  async def download(self, key: str) -> bytes:
53
- """Download file from HF bucket."""
54
  try:
55
- # Check local cache first
56
  local_path = self.local_cache / key
57
-
58
  if not local_path.exists():
59
- # Download from HF bucket using huggingface_hub API
60
  from huggingface_hub import hf_hub_download
61
-
62
  local_path.parent.mkdir(parents=True, exist_ok=True)
63
-
64
- downloaded_path = hf_hub_download(
65
  repo_id=self.repo_id,
66
  filename=key,
67
  repo_type="dataset",
68
  local_dir=str(self.local_cache),
69
- local_dir_use_symlinks=False
70
  )
71
-
72
  logger.info(f"Downloaded file: {key}")
73
-
74
- with open(local_path, 'rb') as f:
75
- data = f.read()
76
-
77
- return data
78
  except Exception as e:
79
  logger.error(f"Error downloading file: {e}")
80
  raise
81
-
82
  async def delete(self, key: str) -> None:
83
- """Delete file from HF bucket."""
84
  try:
85
- # Delete from HF bucket using huggingface_hub API
86
  from huggingface_hub import HfApi
87
- api = HfApi()
88
-
89
  api.delete_file(
90
  path_in_repo=key,
91
  repo_id=self.repo_id,
92
  repo_type="dataset"
93
  )
94
-
95
- # Delete from local cache
96
  local_path = self.local_cache / key
97
  if local_path.exists():
98
  local_path.unlink()
99
-
100
  logger.info(f"Deleted file: {key}")
101
  except Exception as e:
102
  logger.error(f"Error deleting file: {e}")
103
  raise
104
-
105
  async def get_presigned_url(self, key: str, expires: int = 3600) -> str:
106
- """Get presigned URL for downloading."""
107
- # For HF datasets, return the direct HF URL
108
- hf_url = f"https://huggingface.co/datasets/{self.repo_id}/resolve/main/{key}"
109
- return hf_url
 
1
  """Hugging Face Hub storage adapter."""
2
  from app.ports.storage import StoragePort
3
  from app.config import get_settings
 
4
  import logging
5
  import os
6
  from pathlib import Path
 
11
 
12
  class HFStorageAdapter(StoragePort):
13
  """Hugging Face Hub implementation of StoragePort."""
14
+
15
  def __init__(self):
16
  self.bucket_path = settings.HF_BUCKET_PATH
17
+ # Extract repo_id: hf://buckets/Peterase/Ragora-doc-store -> Peterase/Ragora-doc-store
18
  self.repo_id = self.bucket_path.replace("hf://buckets/", "")
19
  self.local_cache = Path("/tmp/ragora_cache")
20
  self.local_cache.mkdir(exist_ok=True)
21
+ # HF token for authenticated operations (set in HF Space secrets)
22
+ self.hf_token = os.getenv("HF_TOKEN")
23
  logger.info(f"Using HF bucket: {self.bucket_path} (repo: {self.repo_id})")
24
+ if not self.hf_token:
25
+ logger.warning("HF_TOKEN not set - uploads may fail for private repos")
26
+
27
  async def upload(self, key: str, data: bytes, content_type: str) -> str:
28
+ """Upload file to HF dataset repo."""
29
  try:
30
  # Save locally first
31
  local_path = self.local_cache / key
32
  local_path.parent.mkdir(parents=True, exist_ok=True)
33
+
34
+ with open(local_path, "wb") as f:
35
  f.write(data)
36
+
37
+ # Upload using huggingface_hub Python API
38
  from huggingface_hub import HfApi
39
+ api = HfApi(token=self.hf_token)
 
 
40
  api.upload_file(
41
  path_or_fileobj=str(local_path),
42
  path_in_repo=key,
43
  repo_id=self.repo_id,
44
  repo_type="dataset"
45
  )
46
+
47
  logger.info(f"Uploaded file: {key}")
48
  return key
49
  except Exception as e:
50
  logger.error(f"Error uploading file: {e}")
51
  raise
52
+
53
  async def download(self, key: str) -> bytes:
54
+ """Download file from HF dataset repo."""
55
  try:
 
56
  local_path = self.local_cache / key
57
+
58
  if not local_path.exists():
 
59
  from huggingface_hub import hf_hub_download
 
60
  local_path.parent.mkdir(parents=True, exist_ok=True)
61
+ hf_hub_download(
 
62
  repo_id=self.repo_id,
63
  filename=key,
64
  repo_type="dataset",
65
  local_dir=str(self.local_cache),
66
+ token=self.hf_token
67
  )
 
68
  logger.info(f"Downloaded file: {key}")
69
+
70
+ with open(local_path, "rb") as f:
71
+ return f.read()
 
 
72
  except Exception as e:
73
  logger.error(f"Error downloading file: {e}")
74
  raise
75
+
76
  async def delete(self, key: str) -> None:
77
+ """Delete file from HF dataset repo."""
78
  try:
 
79
  from huggingface_hub import HfApi
80
+ api = HfApi(token=self.hf_token)
 
81
  api.delete_file(
82
  path_in_repo=key,
83
  repo_id=self.repo_id,
84
  repo_type="dataset"
85
  )
86
+
 
87
  local_path = self.local_cache / key
88
  if local_path.exists():
89
  local_path.unlink()
90
+
91
  logger.info(f"Deleted file: {key}")
92
  except Exception as e:
93
  logger.error(f"Error deleting file: {e}")
94
  raise
95
+
96
  async def get_presigned_url(self, key: str, expires: int = 3600) -> str:
97
+ """Get direct download URL."""
98
+ return f"https://huggingface.co/datasets/{self.repo_id}/resolve/main/{key}"
 
 
requirements.txt CHANGED
@@ -11,7 +11,7 @@ python-docx==1.1.0
11
 
12
  # Vector & embeddings
13
  qdrant-client==1.7.3
14
- sentence-transformers==2.3.1
15
 
16
  # Storage
17
  minio==7.2.3
@@ -23,12 +23,8 @@ httpx==0.26.0
23
  PyJWT==2.8.0
24
  cryptography==42.0.0
25
 
26
- # Testing
27
- pytest==7.4.4
28
- pytest-asyncio==0.23.3
29
-
30
  # Hugging Face Hub
31
- huggingface-hub>=0.20.0
32
 
33
  # Pinecone (new package name)
34
  pinecone>=5.0.0
 
11
 
12
  # Vector & embeddings
13
  qdrant-client==1.7.3
14
+ sentence-transformers==3.0.1
15
 
16
  # Storage
17
  minio==7.2.3
 
23
  PyJWT==2.8.0
24
  cryptography==42.0.0
25
 
 
 
 
 
26
  # Hugging Face Hub
27
+ huggingface-hub==0.24.0
28
 
29
  # Pinecone (new package name)
30
  pinecone>=5.0.0