Soumik-404 commited on
Commit
d7eda54
·
1 Parent(s): 3379d24

updated models

Browse files
Dockerfile CHANGED
@@ -24,7 +24,7 @@ RUN pip install --no-cache-dir "youtube-transcript-api>=1.2.4"
24
 
25
  COPY --chown=appuser:appuser . .
26
 
27
- RUN mkdir -p /app/models && python3 -c "from huggingface_hub import snapshot_download; snapshot_download(repo_id='BAAI/bge-small-en-v1.5', local_dir='/app/models/bge-384'); snapshot_download(repo_id='BAAI/bge-base-en-v1.5', local_dir='/app/models/bge-768'); snapshot_download(repo_id='BAAI/bge-large-en-v1.5', local_dir='/app/models/bge-1024')" && chown -R appuser:appuser /app/models
28
 
29
  RUN mkdir -p /app/logs && \
30
  chown -R appuser:appuser /app/logs
 
24
 
25
  COPY --chown=appuser:appuser . .
26
 
27
+ RUN mkdir -p /app/models && python3 -c "from huggingface_hub import snapshot_download; snapshot_download(repo_id='ibm-granite/granite-embedding-small-english-r2', local_dir='/app/models/bge-384'); snapshot_download(repo_id='nomic-ai/modernbert-embed-base', local_dir='/app/models/bge-768'); snapshot_download(repo_id='lightonai/modernbert-embed-large', local_dir='/app/models/bge-1024')" && chown -R appuser:appuser /app/models
28
 
29
  RUN mkdir -p /app/logs && \
30
  chown -R appuser:appuser /app/logs
app/api/v1/embeddings.py CHANGED
@@ -3,12 +3,13 @@ from __future__ import annotations
3
  import asyncio
4
  import concurrent.futures
5
  import os
 
6
 
7
  from fastapi import APIRouter, Depends, HTTPException
8
 
9
  from app.api.deps import require_auth, get_embeddings_service
10
  from app.core.logger import get_logger
11
- from app.models.schemas import EmbeddingRequest, EmbeddingResponse
12
  from app.services.embeddings_service import EmbeddingService
13
 
14
  router = APIRouter()
@@ -27,7 +28,7 @@ async def create_embeddings(
27
  token: str = Depends(require_auth),
28
  embedding_service: EmbeddingService = Depends(get_embeddings_service),
29
  ) -> EmbeddingResponse:
30
- _logger.info("Embedding request: dim=%s, content_len=%s", body.dimension, len(body.content))
31
 
32
  if not embedding_service.is_loaded(body.dimension):
33
  _logger.error("Model dim=%s not loaded. Loaded: %s", body.dimension, embedding_service.loaded_dimensions)
@@ -39,24 +40,52 @@ async def create_embeddings(
39
  },
40
  )
41
 
 
42
  try:
43
  loop = asyncio.get_running_loop()
44
- embeddings = await loop.run_in_executor(
45
  _thread_pool,
46
  embedding_service.generate_embedding,
47
  body.content,
48
  body.dimension,
49
  )
50
-
51
- _logger.info("Embedding success: dim=%s, vector_len=%s", body.dimension, len(embeddings))
 
52
  return EmbeddingResponse(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  success=True,
54
- embeddings=embeddings,
 
55
  dimension=body.dimension,
56
  )
57
- except Exception as exc:
58
- _logger.error("Embedding error: %s", exc)
59
- raise HTTPException(
60
- status_code=500,
61
- detail={"success": False, "message": str(exc)},
62
- )
 
 
 
 
 
 
3
  import asyncio
4
  import concurrent.futures
5
  import os
6
+ import time
7
 
8
  from fastapi import APIRouter, Depends, HTTPException
9
 
10
  from app.api.deps import require_auth, get_embeddings_service
11
  from app.core.logger import get_logger
12
+ from app.models.schemas import EmbeddingItem, EmbeddingRequest, EmbeddingResponse
13
  from app.services.embeddings_service import EmbeddingService
14
 
15
  router = APIRouter()
 
28
  token: str = Depends(require_auth),
29
  embedding_service: EmbeddingService = Depends(get_embeddings_service),
30
  ) -> EmbeddingResponse:
31
+ _logger.info("Embedding request: dim=%s, items=%s", body.dimension, len(body.content))
32
 
33
  if not embedding_service.is_loaded(body.dimension):
34
  _logger.error("Model dim=%s not loaded. Loaded: %s", body.dimension, embedding_service.loaded_dimensions)
 
40
  },
41
  )
42
 
43
+ start = time.perf_counter()
44
  try:
45
  loop = asyncio.get_running_loop()
46
+ vectors = await loop.run_in_executor(
47
  _thread_pool,
48
  embedding_service.generate_embedding,
49
  body.content,
50
  body.dimension,
51
  )
52
+ except Exception as exc:
53
+ elapsed = (time.perf_counter() - start) * 1000
54
+ _logger.error("Embedding error: %s", exc)
55
  return EmbeddingResponse(
56
+ success=False,
57
+ time_ms=round(elapsed, 3),
58
+ success_count=0,
59
+ failed_count=len(body.content),
60
+ error_message=str(exc),
61
+ results=[
62
+ EmbeddingItem(
63
+ success=False,
64
+ time_ms=0,
65
+ error_message=str(exc),
66
+ )
67
+ for _ in body.content
68
+ ],
69
+ )
70
+
71
+ total_ms = (time.perf_counter() - start) * 1000
72
+ per_item_ms = total_ms / len(body.content)
73
+
74
+ results = [
75
+ EmbeddingItem(
76
  success=True,
77
+ time_ms=round(per_item_ms, 3),
78
+ embeddings=vec,
79
  dimension=body.dimension,
80
  )
81
+ for vec in vectors
82
+ ]
83
+
84
+ _logger.info("Embedding success: dim=%s, items=%s, total_ms=%s", body.dimension, len(results), round(total_ms, 3))
85
+ return EmbeddingResponse(
86
+ success=True,
87
+ time_ms=round(total_ms, 3),
88
+ success_count=len(results),
89
+ failed_count=0,
90
+ results=results,
91
+ )
app/models/__init__.py CHANGED
@@ -7,6 +7,7 @@ from app.models.schemas import (
7
  BatchUrlRequest,
8
  ConversionMetadata,
9
  ConversionResponse,
 
10
  EmbeddingRequest,
11
  EmbeddingResponse,
12
  HealthResponse,
@@ -21,6 +22,7 @@ __all__ = [
21
  "ConversionResult",
22
  "ConversionMetadata",
23
  "ConversionResponse",
 
24
  "EmbeddingRequest",
25
  "EmbeddingResponse",
26
  "UrlRequest",
 
7
  BatchUrlRequest,
8
  ConversionMetadata,
9
  ConversionResponse,
10
+ EmbeddingItem,
11
  EmbeddingRequest,
12
  EmbeddingResponse,
13
  HealthResponse,
 
22
  "ConversionResult",
23
  "ConversionMetadata",
24
  "ConversionResponse",
25
+ "EmbeddingItem",
26
  "EmbeddingRequest",
27
  "EmbeddingResponse",
28
  "UrlRequest",
app/models/schemas.py CHANGED
@@ -224,12 +224,23 @@ class DatabaseQueryResponse(BaseModel):
224
  error: Optional[DatabaseQueryError] = None
225
 
226
 
 
 
 
 
 
 
 
 
227
  class EmbeddingRequest(BaseModel):
228
- content: str = Field(..., min_length=1, description="Text to embed")
229
  dimension: int = Field(default=384, ge=384, le=1024, description="Target embedding dimension (384, 768, or 1024)")
230
 
231
 
232
  class EmbeddingResponse(BaseModel):
233
  success: bool
234
- embeddings: List[float]
235
- dimension: int
 
 
 
 
224
  error: Optional[DatabaseQueryError] = None
225
 
226
 
227
+ class EmbeddingItem(BaseModel):
228
+ success: bool
229
+ time_ms: float
230
+ embeddings: List[float] = Field(default_factory=list)
231
+ dimension: int = 0
232
+ error_message: Optional[str] = None
233
+
234
+
235
  class EmbeddingRequest(BaseModel):
236
+ content: List[str] = Field(..., min_length=1, max_length=10, description="Array of text strings to embed (max 10)")
237
  dimension: int = Field(default=384, ge=384, le=1024, description="Target embedding dimension (384, 768, or 1024)")
238
 
239
 
240
  class EmbeddingResponse(BaseModel):
241
  success: bool
242
+ time_ms: float
243
+ success_count: int
244
+ failed_count: int
245
+ error_message: Optional[str] = None
246
+ results: List[EmbeddingItem]
app/services/embeddings_service.py CHANGED
@@ -10,9 +10,9 @@ from sentence_transformers import SentenceTransformer
10
  _logger = logging.getLogger(__name__)
11
 
12
  _MODEL_MAP: Dict[int, str] = {
13
- 384: "BAAI/bge-small-en-v1.5",
14
- 768: "BAAI/bge-base-en-v1.5",
15
- 1024: "BAAI/bge-large-en-v1.5",
16
  }
17
 
18
 
@@ -53,7 +53,7 @@ class EmbeddingService:
53
  for dim in _MODEL_MAP:
54
  self.load_model(dim)
55
 
56
- def generate_embedding(self, text: str, dimension: int) -> List[float]:
57
  if dimension not in self._models:
58
  raise ValueError(f"Model for dimension {dimension} not loaded")
59
  model = self._models[dimension]
 
10
  _logger = logging.getLogger(__name__)
11
 
12
  _MODEL_MAP: Dict[int, str] = {
13
+ 384: "ibm-granite/granite-embedding-small-english-r2",
14
+ 768: "nomic-ai/modernbert-embed-base",
15
+ 1024: "lightonai/modernbert-embed-large",
16
  }
17
 
18
 
 
53
  for dim in _MODEL_MAP:
54
  self.load_model(dim)
55
 
56
+ def generate_embedding(self, text: List[str], dimension: int) -> List[List[float]]:
57
  if dimension not in self._models:
58
  raise ValueError(f"Model for dimension {dimension} not loaded")
59
  model = self._models[dimension]
requirements.txt CHANGED
@@ -11,7 +11,9 @@ onnxruntime>=1.18.0
11
  pillow>=10.0.0
12
  pypdfium2>=4.30.0
13
  pandas>=2.0.0
14
- sentence-transformers==3.3.1
 
 
15
  spacy>=3.7.0
16
  phonenumbers>=8.13.0
17
 
 
11
  pillow>=10.0.0
12
  pypdfium2>=4.30.0
13
  pandas>=2.0.0
14
+ sentence-transformers==5.6.0
15
+ transformers==5.12.1
16
+ torch==2.12.1
17
  spacy>=3.7.0
18
  phonenumbers>=8.13.0
19