server_tes / main.py
andrymamboro's picture
Update main.py
1aefd6b verified
import os
import io
import base64
import torch
from fastapi import FastAPI, Form, File, UploadFile, HTTPException
from diffusers import AutoPipelineForText2Image, AutoPipelineForImage2Image
from PIL import Image
app = FastAPI()
MODEL_ID = "stabilityai/sdxl-turbo"
print("πŸš€ Memuat Mamboro Engine - Dual Mode (Text & Image)...")
try:
# 1. Load untuk Text-to-Image (Generate)
pipe_text = AutoPipelineForText2Image.from_pretrained(
MODEL_ID, torch_dtype=torch.float32, variant="fp16", low_cpu_mem_usage=True
)
pipe_text.to("cpu")
pipe_text.enable_attention_slicing()
# 2. Load untuk Image-to-Image (Edit) - Menggunakan model yang sama dari cache
pipe_edit = AutoPipelineForImage2Image.from_pipe(pipe_text)
print("βœ… Server Ready!")
except Exception as e:
print(f"❌ Gagal Load Model: {e}")
@app.get("/")
def home():
return {"status": "Online", "mode": "Dual (Generate & Edit)"}
@app.post("/generate")
async def generate(prompt: str = Form(...)):
try:
# Gunakan pipe_text karena hanya ada input teks
image = pipe_text(
prompt=prompt,
num_inference_steps=2,
guidance_scale=0.0,
width=512,
height=512
).images[0]
buffered = io.BytesIO()
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return {"image": f"data:image/jpeg;base64,{img_str}"}
except Exception as e:
print(f"❌ Error Generate: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@app.post("/edit")
async def edit(
prompt: str = Form(...),
image_file: UploadFile = File(...),
strength: float = Form(0.5)
):
try:
# Baca semua jenis file gambar (PNG, JPG, WebP, dll)
contents = await image_file.read()
if not contents:
raise HTTPException(status_code=400, detail="File gambar kosong")
# Buka gambar dengan PIL
raw_image = Image.open(io.BytesIO(contents))
# KONVERSI KRITIS: Ubah ke RGB
# Ini penting karena PNG sering punya 4 channel (RGBA), AI cuma mau 3 (RGB)
init_image = raw_image.convert("RGB")
# Resize tetap diperlukan agar RAM tidak meledak
init_image = init_image.resize((512, 512))
print(f"🎨 Editing berbagai format dengan Strength: {strength}")
image = pipe_edit(
prompt=prompt,
image=init_image,
strength=strength,
num_inference_steps=2,
guidance_scale=0.0
).images[0]
# Kembalikan sebagai JPEG agar ringan saat dikirim balik ke HP
buffered = io.BytesIO()
image.save(buffered, format="JPEG", quality=80)
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return {"image": f"data:image/jpeg;base64,{img_str}"}
except Exception as e:
print(f"❌ Error Detail: {str(e)}")
raise HTTPException(status_code=500, detail=f"Gagal memproses gambar: {str(e)}")
@app.post("/edit_ref")
async def edit_with_ref(
prompt: str = Form(...),
main_image: UploadFile = File(...),
ref_image: UploadFile = File(...),
strength: float = Form(0.6)
):
try:
# Baca Gambar Utama
main_bytes = await main_image.read()
main_img = Image.open(io.BytesIO(main_bytes)).convert("RGB").resize((512, 512))
# Baca Gambar Referensi
ref_bytes = await ref_image.read()
ref_img = Image.open(io.BytesIO(ref_bytes)).convert("RGB").resize((512, 512))
# Gabungkan instruksi: Prompt + gaya dari Ref Image
# Di SDXL Turbo sederhana, kita gunakan main_img sebagai init,
# dan ref_img bisa kita olah untuk memperkuat prompt (atau dikirim sebagai controlnet jika ada)
image = pipe_edit(
prompt=f"{prompt}, follow style of reference image",
image=main_img,
strength=strength,
num_inference_steps=2
).images[0]
buffered = io.BytesIO()
image.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return {"image": f"data:image/jpeg;base64,{img_str}"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))