AyushAggarwal commited on
Commit
c1f97cf
·
verified ·
1 Parent(s): b6f37ab

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -98
app.py CHANGED
@@ -1,99 +1,40 @@
1
- # app.py
2
- import os
3
- import io
4
- import base64
5
- import logging
6
- from typing import Optional
7
-
8
- from fastapi import FastAPI, HTTPException
9
- from pydantic import BaseModel
10
- from PIL import Image
11
- import torch
12
-
13
  from diffusers import DiffusionPipeline
14
-
15
- logging.basicConfig(level=logging.INFO)
16
- logger = logging.getLogger("ssd_service")
17
-
18
- class GenerateRequest(BaseModel):
19
- prompt: str
20
- height: Optional[int] = None
21
- width: Optional[int] = None
22
- num_inference_steps: Optional[int] = 25
23
-
24
- app = FastAPI(title="Diffusers SSD-1B service")
25
-
26
- # Lazy global
27
- PIPELINE = None
28
- DEVICE = "cpu"
29
-
30
- def load_model():
31
- global PIPELINE, DEVICE
32
- # Prefer CUDA if available
33
- DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
34
- logger.info(f"Loading model to device: {DEVICE}")
35
-
36
- # If you need authentication for private models, set HUGGINGFACE_TOKEN env var
37
- # hf_token = os.environ.get("HUGGINGFACE_TOKEN", None)
38
- # auth = {"token": hf_token} if hf_token else None
39
-
40
- # This can take time — load once on startup
41
- PIPELINE = DiffusionPipeline.from_pretrained(
42
- "segmind/SSD-1B",
43
- torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32,
44
- use_safetensors=True,
45
- # If you want to use accelerate or offload, consider integration here
46
- )
47
-
48
- # move to device
49
- PIPELINE = PIPELINE.to(DEVICE)
50
-
51
- # Optionally enable attention slicing to save memory
52
- try:
53
- PIPELINE.enable_attention_slicing()
54
- except Exception:
55
- pass
56
-
57
- @app.on_event("startup")
58
- def startup_event():
59
- load_model()
60
- logger.info("Model loaded and service startup finished.")
61
-
62
- @app.get("/health")
63
- def health():
64
- return {"status": "ok", "device": DEVICE}
65
-
66
- @app.post("/generate")
67
- def generate(req: GenerateRequest):
68
- global PIPELINE
69
- if PIPELINE is None:
70
- raise HTTPException(status_code=503, detail="Model not loaded")
71
-
72
- prompt = req.prompt
73
- if not prompt:
74
- raise HTTPException(status_code=400, detail="prompt is required")
75
-
76
- # Run inference (synchronous). Consider queuing for heavy load.
77
- try:
78
- logger.info(f"Generating image for prompt: {prompt[:80]}")
79
- # Customize call as required; return PIL image
80
- output = PIPELINE(prompt=prompt, num_inference_steps=req.num_inference_steps)
81
- images = output.images
82
- if not images:
83
- raise HTTPException(status_code=500, detail="No image produced")
84
-
85
- img = images[0]
86
-
87
- # Resize if requested
88
- if req.width and req.height:
89
- img = img.resize((req.width, req.height), Image.LANCZOS)
90
-
91
- # Convert to PNG bytes
92
- buf = io.BytesIO()
93
- img.save(buf, format="PNG")
94
- buf.seek(0)
95
- b64 = base64.b64encode(buf.read()).decode("utf-8")
96
- return {"image_base64": b64}
97
- except Exception as e:
98
- logger.exception("Generation failed")
99
- raise HTTPException(status_code=500, detail=str(e))
 
1
+ from fastapi import FastAPI
2
+ from fastapi.responses import JSONResponse
 
 
 
 
 
 
 
 
 
 
3
  from diffusers import DiffusionPipeline
4
+ import torch
5
+ import base64
6
+ from io import BytesIO
7
+
8
+ # create fastapi instance
9
+ app = FastAPI()
10
+
11
+ # Detect device
12
+ device = "cuda" if torch.cuda.is_available() else "cpu"
13
+
14
+ # Load the correct pipeline
15
+ pipe = DiffusionPipeline.from_pretrained(
16
+ "segmind/SSD-1B",
17
+ torch_dtype=torch.float16 if device == "cuda" else torch.float32,
18
+ use_safetensors=True,
19
+ )
20
+ pipe = pipe.to(device)
21
+
22
+ # Optional: reduce VRAM usage
23
+ pipe.enable_attention_slicing()
24
+
25
+ @app.get("/")
26
+ def home():
27
+ return {"message": "Segmind SSD-1B API running"}
28
+
29
+ # Define function to generate image from text prompt
30
+ @app.post("/generate-image/")
31
+ def generate_image(prompt: str, negative_prompt: str = None):
32
+ # Run inference
33
+ image = pipe(prompt=prompt, negative_prompt=negative_prompt).images[0]
34
+
35
+ # Convert to base64 string
36
+ buffered = BytesIO()
37
+ image.save(buffered, format="PNG")
38
+ img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
39
+
40
+ return JSONResponse(content={"image_base64": img_str})