ray-embedding 0.12.3__tar.gz → 0.12.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ray-embedding might be problematic. Click here for more details.
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/PKG-INFO +1 -1
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding/deploy.py +1 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding/dto.py +2 -1
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding/embedding_model.py +37 -8
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding/model_router.py +2 -2
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding.egg-info/PKG-INFO +1 -1
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/setup.cfg +1 -1
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/README.md +0 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/pyproject.toml +0 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding/__init__.py +0 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding.egg-info/SOURCES.txt +0 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding.egg-info/dependency_links.txt +0 -0
- {ray_embedding-0.12.3 → ray_embedding-0.12.5}/ray_embedding.egg-info/top_level.txt +0 -0
|
@@ -17,6 +17,7 @@ def build_model(model_config: ModelDeploymentConfig) -> DeployedModel:
|
|
|
17
17
|
matryoshka_dim = model_config.matryoshka_dim
|
|
18
18
|
trust_remote_code = model_config.trust_remote_code or False
|
|
19
19
|
model_kwargs = model_config.model_kwargs or {}
|
|
20
|
+
cuda_memory_flush_threshold = model_config.cuda_memory_flush_threshold or 0.8
|
|
20
21
|
|
|
21
22
|
if "torch_dtype" in model_kwargs:
|
|
22
23
|
torch_dtype = model_kwargs["torch_dtype"].strip()
|
|
@@ -25,7 +25,6 @@ class ModelRouterConfig(BaseModel):
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class ModelDeploymentConfig(BaseModel):
|
|
28
|
-
deployment: str
|
|
29
28
|
model: str
|
|
30
29
|
served_model_name: str
|
|
31
30
|
batch_size: Optional[int] = 8
|
|
@@ -35,6 +34,8 @@ class ModelDeploymentConfig(BaseModel):
|
|
|
35
34
|
matryoshka_dim: Optional[int] = 768
|
|
36
35
|
trust_remote_code: Optional[bool] = False
|
|
37
36
|
model_kwargs: Optional[Dict[str, Any]] = {}
|
|
37
|
+
cuda_memory_flush_threshold: Optional[float] = 0.8
|
|
38
|
+
deployment: str
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
class AppConfig(BaseModel):
|
|
@@ -4,7 +4,7 @@ import time
|
|
|
4
4
|
from typing import Optional, Dict, Any, List, Union
|
|
5
5
|
|
|
6
6
|
import torch
|
|
7
|
-
from pynvml import nvmlInit, nvmlDeviceGetCount
|
|
7
|
+
from pynvml import nvmlInit, nvmlDeviceGetCount, nvmlDeviceGetHandleByIndex, nvmlDeviceGetMemoryInfo
|
|
8
8
|
from ray import serve
|
|
9
9
|
from sentence_transformers import SentenceTransformer
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ class EmbeddingModel:
|
|
|
14
14
|
def __init__(self, model: str, served_model_name: Optional[str] = None,
|
|
15
15
|
device: Optional[str] = None, backend: Optional[str] = "torch",
|
|
16
16
|
matryoshka_dim: Optional[int] = None, trust_remote_code: Optional[bool] = False,
|
|
17
|
-
model_kwargs: Dict[str, Any] = None):
|
|
17
|
+
model_kwargs: Dict[str, Any] = None, cuda_memory_flush_threshold: Optional[float] = 0.8):
|
|
18
18
|
logging.basicConfig(level=logging.INFO)
|
|
19
19
|
self.logger = logging.getLogger(self.__class__.__name__)
|
|
20
20
|
self.model = model
|
|
@@ -29,6 +29,7 @@ class EmbeddingModel:
|
|
|
29
29
|
self.matryoshka_dim = matryoshka_dim
|
|
30
30
|
self.trust_remote_code = trust_remote_code or False
|
|
31
31
|
self.model_kwargs = model_kwargs or {}
|
|
32
|
+
self.cuda_memory_flush_threshold = cuda_memory_flush_threshold
|
|
32
33
|
self.logger.info(f"Initializing embedding model: {self.model}")
|
|
33
34
|
self.embedding_model = SentenceTransformer(self.model, device=self.init_device, backend=self.backend,
|
|
34
35
|
trust_remote_code=self.trust_remote_code,
|
|
@@ -56,6 +57,10 @@ class EmbeddingModel:
|
|
|
56
57
|
|
|
57
58
|
# Move all embeddings to CPU at once before conversion
|
|
58
59
|
embeddings_list = embeddings.cpu().tolist()
|
|
60
|
+
|
|
61
|
+
# don't wait for GC
|
|
62
|
+
del embeddings
|
|
63
|
+
|
|
59
64
|
return embeddings_list
|
|
60
65
|
|
|
61
66
|
def wait_for_cuda(self, wait: int = 10):
|
|
@@ -64,12 +69,36 @@ class EmbeddingModel:
|
|
|
64
69
|
self.check_health()
|
|
65
70
|
|
|
66
71
|
def check_health(self):
|
|
67
|
-
if self.init_device
|
|
72
|
+
if self.init_device != "cuda":
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
try:
|
|
68
76
|
# Even though CUDA was available at init time,
|
|
69
77
|
# CUDA can become unavailable - this is a known problem in AWS EC2+Docker
|
|
70
78
|
# https://github.com/ray-project/ray/issues/49594
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
nvmlInit()
|
|
80
|
+
count = nvmlDeviceGetCount()
|
|
81
|
+
assert count >= 1, "No CUDA devices found"
|
|
82
|
+
|
|
83
|
+
# replicas only have access to GPU 0
|
|
84
|
+
handle = nvmlDeviceGetHandleByIndex(0)
|
|
85
|
+
mem_info = nvmlDeviceGetMemoryInfo(handle)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
raise RuntimeError(f"CUDA health check failed: {e}")
|
|
88
|
+
|
|
89
|
+
reserved = torch.cuda.memory_reserved() # bytes currently reserved by CUDA cache
|
|
90
|
+
threshold_bytes = self.cuda_memory_flush_threshold * mem_info.total
|
|
91
|
+
|
|
92
|
+
if reserved > threshold_bytes:
|
|
93
|
+
# flush only when cache exceeds the percentage threshold
|
|
94
|
+
torch.cuda.empty_cache()
|
|
95
|
+
|
|
96
|
+
def __del__(self):
|
|
97
|
+
# Clean up and free any remaining GPU memory
|
|
98
|
+
try:
|
|
99
|
+
if hasattr(self, 'embedding_model'):
|
|
100
|
+
del self.embedding_model
|
|
101
|
+
if torch.cuda.is_available():
|
|
102
|
+
torch.cuda.empty_cache()
|
|
103
|
+
except Exception as e:
|
|
104
|
+
self.logger.warning(f"Error during cleanup: {e}")
|
|
@@ -46,7 +46,7 @@ class ModelRouter:
|
|
|
46
46
|
f"to {len(batches)} mini-batches, each with max length {batch_size}.")
|
|
47
47
|
|
|
48
48
|
# Call embedding model replicas in parallel (rate-limited)
|
|
49
|
-
tasks = [self.
|
|
49
|
+
tasks = [self._compute_embeddings_rate_limited(model_handle, batch, dimensions) for batch in batches]
|
|
50
50
|
all_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
51
51
|
|
|
52
52
|
# Retry any failed model calls
|
|
@@ -64,7 +64,7 @@ class ModelRouter:
|
|
|
64
64
|
self.logger.info(f"Successfully computed embeddings from {len(batches)} mini-batches")
|
|
65
65
|
return [emb for result in all_results for emb in result]
|
|
66
66
|
|
|
67
|
-
async def
|
|
67
|
+
async def _compute_embeddings_rate_limited(self, model_handle: DeploymentHandle, batch: List[str], dimensions: int):
|
|
68
68
|
async with self.rate_limiter:
|
|
69
69
|
return await model_handle.remote(batch, dimensions)
|
|
70
70
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|