my-api-embedding / main.py
chuong0306's picture
Upload main.py
c3b10b5 verified
Raw
History Blame Contribute Delete
2.13 kB
from __future__ import annotations
import os
from typing import Union
import torch
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sentence_transformers import SentenceTransformer
DEFAULT_MODEL_NAME = "keepitreal/vietnamese-sbert"
MODEL_NAME = os.getenv("MODEL_NAME", DEFAULT_MODEL_NAME)
app = FastAPI(title="Free Embedding API")
ERROR_MESSAGE = None
try:
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
MODEL = SentenceTransformer(MODEL_NAME, device=DEVICE)
except Exception as exc: # pragma: no cover - startup failure is surfaced by the endpoint.
import traceback
ERROR_MESSAGE = f"{exc}\n{traceback.format_exc()}"
print(f"Failed to load embedding model: {ERROR_MESSAGE}")
DEVICE = "unavailable"
MODEL = None
class EmbedRequest(BaseModel):
input: Union[str, list[str]]
class EmbedResponse(BaseModel):
embedding: Union[list[float], list[list[float]]]
model: str
@app.get("/")
def read_root() -> dict[str, Union[str, None]]:
return {
"status": "ok" if MODEL is not None else "model_unavailable",
"model": MODEL_NAME,
"device": DEVICE,
"error": ERROR_MESSAGE,
}
@app.post("/v1/embeddings", response_model=EmbedResponse)
async def get_embeddings(request: EmbedRequest) -> EmbedResponse:
if MODEL is None:
raise HTTPException(status_code=500, detail="Embedding model was not loaded.")
sentences = request.input
is_single_input = isinstance(sentences, str)
if is_single_input:
sentences = [sentences]
sentences = [sentence for sentence in sentences if sentence.strip()]
if not sentences:
raise HTTPException(status_code=400, detail="Input must not be empty.")
try:
embeddings = MODEL.encode(sentences, normalize_embeddings=True)
embeddings_list = embeddings.tolist()
except Exception as exc:
raise HTTPException(status_code=500, detail=f"Embedding failed: {exc}") from exc
if is_single_input:
embeddings_list = embeddings_list[0]
return EmbedResponse(embedding=embeddings_list, model=MODEL_NAME)