fbetteo commited on
Commit
361b4e2
·
1 Parent(s): c492737

add model

Browse files
Files changed (2) hide show
  1. app.py +86 -3
  2. requirements.txt +4 -0
app.py CHANGED
@@ -1,8 +1,91 @@
1
- from fastapi import FastAPI
 
 
 
 
 
 
 
 
2
 
3
- app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
 
6
  @app.get("/")
7
  def greet_json():
8
- return {"Hello": "World!"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from typing import List
3
+ import numpy as np
4
+ from fastapi import FastAPI, HTTPException
5
+ from pydantic import BaseModel, HttpUrl
6
+ from sentence_transformers import SentenceTransformer
7
+ from PIL import Image
8
+ import requests
9
+ from io import BytesIO
10
 
11
+ # Configure logging
12
+ logging.basicConfig(level=logging.INFO)
13
+ logger = logging.getLogger(__name__)
14
+
15
+ app = FastAPI(title="CLIP ViT-B/32 Image Embedding API", version="1.0.0")
16
+
17
+ # Initialize the CLIP model
18
+ logger.info("Loading CLIP ViT-B/32 model...")
19
+ model = SentenceTransformer("clip-ViT-B-32")
20
+ logger.info("Model loaded successfully")
21
+
22
+
23
+ class ImageUrlRequest(BaseModel):
24
+ """Request model for image URL embedding."""
25
+
26
+ image_url: HttpUrl
27
+
28
+
29
+ class EmbeddingResponse(BaseModel):
30
+ """Response model for image embeddings."""
31
+
32
+ embedding: List[float]
33
+ embedding_dimension: int
34
 
35
 
36
  @app.get("/")
37
  def greet_json():
38
+ """Health check endpoint."""
39
+ return {"Hello": "World!", "service": "CLIP ViT-B/32 Image Embedding API"}
40
+
41
+
42
+ @app.post("/embed-image", response_model=EmbeddingResponse)
43
+ def embed_image(request: ImageUrlRequest) -> EmbeddingResponse:
44
+ """
45
+ Generate embeddings for an image from URL using CLIP ViT-B/32 model.
46
+
47
+ Args:
48
+ request: ImageUrlRequest containing the image URL
49
+
50
+ Returns:
51
+ EmbeddingResponse containing the image embedding and its dimension
52
+
53
+ Raises:
54
+ HTTPException: If image cannot be downloaded or processed
55
+ """
56
+ try:
57
+ logger.info(f"Processing image from URL: {request.image_url}")
58
+
59
+ # Download the image from URL
60
+ response = requests.get(str(request.image_url), timeout=30)
61
+ response.raise_for_status()
62
+
63
+ # Open and process the image
64
+ image = Image.open(BytesIO(response.content))
65
+
66
+ # Convert to RGB if necessary (CLIP expects RGB format)
67
+ if image.mode != "RGB":
68
+ image = image.convert("RGB")
69
+
70
+ # Generate embedding using CLIP model
71
+ embedding = model.encode(image)
72
+
73
+ # Convert numpy array to list for JSON serialization
74
+ embedding_list = embedding.tolist()
75
+
76
+ logger.info(
77
+ f"Successfully generated embedding with dimension: {len(embedding_list)}"
78
+ )
79
+
80
+ return EmbeddingResponse(
81
+ embedding=embedding_list, embedding_dimension=len(embedding_list)
82
+ )
83
+
84
+ except requests.exceptions.RequestException as e:
85
+ logger.error(f"Failed to download image from URL: {e}")
86
+ raise HTTPException(
87
+ status_code=400, detail=f"Failed to download image from URL: {str(e)}"
88
+ )
89
+ except Exception as e:
90
+ logger.error(f"Error processing image: {e}")
91
+ raise HTTPException(status_code=500, detail=f"Error processing image: {str(e)}")
requirements.txt CHANGED
@@ -1,2 +1,6 @@
1
  fastapi
2
  uvicorn[standard]
 
 
 
 
 
1
  fastapi
2
  uvicorn[standard]
3
+ numpy==2.1.3
4
+ sentence-transformers==3.2.1
5
+ pillow
6
+ requests