Boogu-Image / app.py
Celeskry's picture
Update app.py
0e320b4 verified
Raw
History Blame Contribute Delete
5.75 kB
import os
# Thiết lập môi trường trước khi import torch
os.environ.setdefault("device", "cuda:0")
import boogu.utils.import_utils as _import_utils
_import_utils._triton_available = False
import io
import json
import torch
import spaces
from PIL import Image
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.responses import StreamingResponse
import gradio as gr
from boogu.pipelines.boogu.pipeline_boogu import BooguImagePipeline
# --- KHỞI TẠO MODEL TURBO DUY NHẤT ---
TURBO_ID = "Boogu/Boogu-Image-0.1-Edit-Turbo"
AOTI_REPO = "multimodalart/Boogu-Image-0.1-Edit-aoti"
print("Đang tải model Boogu Image Turbo...")
# Load trực tiếp pipeline từ Turbo_ID, tái sử dụng các thành phần để tối ưu RAM
turbo_pipe = BooguImagePipeline.from_pretrained(
TURBO_ID,
torch_dtype=torch.bfloat16,
trust_remote_code=True
)
turbo_pipe.to("cuda")
# Vá lỗi AoTI để tăng tốc độ nếu môi trường Hugging Face hỗ trợ
try:
from pathlib import Path
from huggingface_hub import snapshot_download
from spaces.zero.torch.aoti import aoti_load_from_module_dir
_block_dir = Path(snapshot_download(AOTI_REPO)) / "BooguImageTransformerBlock"
if (_block_dir / "package.pt2").exists():
aoti_load_from_module_dir(turbo_pipe.transformer.single_stream_layers, _block_dir)
print("AoTI đã được cấu hình thành công cho Turbo!")
except Exception as exc:
print(f"Không load được AoTI, chạy mặc định (Eager mode): {exc}")
MAX_SEED = 2**31 - 1
RESOLUTIONS = {
"1K": {"pixels": 1024 * 1024, "side": 2048},
"2K": {"pixels": 2048 * 2048, "side": 4096},
}
# --- HÀM XỬ LÝ CHÍNH TRÊN ZEROGPU ---
def _duration(image, instruction, resolution, num_inference_steps, *args, **kwargs):
# Pinned cho model Turbo, thời gian chạy rất ngắn
base = int(num_inference_steps) * 4 + 40
return base * 2 if resolution == "2K" else base
@spaces.GPU(duration=_duration)
def generate_turbo_core(input_image_pil, instruction, resolution, num_inference_steps, seed):
res = RESOLUTIONS[resolution]
generator = torch.Generator("cuda").manual_seed(seed)
# Model Turbo ép cố định guidance scale về 1.0 (CFG off) theo đặc tả của tác giả
text_guidance_scale = 1.0
image_guidance_scale = 1.0
if input_image_pil is None:
# Text to Image
size = 1024 if resolution == "1K" else 2048
result = turbo_pipe(
instruction=[instruction.strip()],
negative_instruction="",
height=size,
width=size,
max_input_image_pixels=res["pixels"],
max_input_image_side_length=res["side"],
num_inference_steps=int(num_inference_steps),
text_guidance_scale=float(text_guidance_scale),
generator=generator,
device="cuda",
).images[0]
else:
# Image to Image / Edit
temp_path = "temp_input_turbo.jpg"
input_image_pil.save(temp_path)
result = turbo_pipe(
instruction=[instruction.strip()],
input_image_paths=[[temp_path]],
input_images=[[input_image_pil]],
negative_instruction="",
height=None,
width=None,
max_input_image_pixels=res["pixels"],
max_input_image_side_length=res["side"],
align_res=True,
num_inference_steps=int(num_inference_steps),
text_guidance_scale=float(text_guidance_scale),
image_guidance_scale=float(image_guidance_scale),
generator=generator,
device="cuda",
).images[0]
if os.path.exists(temp_path):
os.remove(temp_path)
return result
# --- DỰNG FASTAPI ROUTER ---
app = FastAPI(title="Boogu Image Turbo API")
@app.post("/api/generate")
async def api_generate(
instruction: str = Form(...),
image: UploadFile = File(None),
resolution: str = Form("1K"), # "1K" hoặc "2K"
num_inference_steps: int = Form(4), # Mặc định lý tưởng cho Turbo là 4 steps
seed: int = Form(0)
):
if not instruction.strip():
raise HTTPException(status_code=400, detail="Prompt không được để trống")
input_image_pil = None
if image:
try:
image_bytes = await image.read()
input_image_pil = Image.open(io.BytesIO(image_bytes)).convert("RGB")
except Exception:
raise HTTPException(status_code=400, detail="File ảnh gửi lên không hợp lệ")
if seed == 0:
seed = int(torch.randint(0, MAX_SEED, (1,)).item())
try:
# Gọi hàm core xử lý trên ZeroGPU
output_pil = generate_turbo_core(
input_image_pil, instruction, resolution, num_inference_steps, seed
)
# Đóng gói ảnh thành định dạng WEBP trả về stream binary trực tiếp
img_io = io.BytesIO()
output_pil.save(img_io, format="WEBP", quality=95)
img_io.seek(0)
return StreamingResponse(img_io, media_type="image/webp")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Lỗi xử lý GPU: {str(e)}")
# --- PHẦN GRADIO ĐỂ GIỮ CHỖ CHẠY TRÊN HUGGING FACE SPACES ZEROGPU ---
with gr.Blocks() as demo:
gr.Markdown("# 🍊 Boogu Image TURBO API is Active!")
gr.Markdown("Gửi request POST tới endpoint: `https://<your-space-url>/api/generate` để tạo hoặc edit ảnh siêu tốc.")
# Nhúng FastAPI app vào Gradio Server
gr.mount_gradio_app(app, demo, path="/")
if __name__ == "__main__":
demo.queue().launch()