stablecat / app.py
poonnatuch's picture
final I think its done
a04a096
# app.py (ไฟล์นี้จะถูกอัปโหลดไปยัง Hugging Face Space)
import gradio as gr
from PIL import Image
import torch
from diffusers import DiffusionPipeline
import transformers # จำเป็นสำหรับ diffusers
import accelerate # จำเป็นสำหรับ diffusers
# --- ตรวจสอบและตั้งค่า Device ---
# Hugging Face Spaces มักจะตั้งค่า CUDA_VISIBLE_DEVICES ให้ถูกต้องแล้ว
# แต่โค้ดนี้ก็ยังใช้ได้ดี
if torch.cuda.is_available():
device = "cuda"
# ใช้ float16 เพื่อประหยัด VRAM บน GPU
# สำหรับ SDXL แนะนำให้ใช้ variant="fp16" ด้วย
torch_dtype = torch.float16
print(f"ใช้ GPU: {torch.cuda.get_device_name(0)}")
else:
device = "cpu"
# CPU ไม่รองรับ float16 โดยตรงสำหรับบาง operations
torch_dtype = torch.float32
print("ไม่พบ GPU, จะใช้ CPU (อาจช้ามากสำหรับ Stable Diffusion)")
# --- โหลดโมเดล Stable Diffusion ---
# โหลดโมเดลนอกฟังก์ชัน generate เพื่อให้โหลดเพียงครั้งเดียวเมื่อแอปเริ่มทำงาน
model_id = "stabilityai/stable-diffusion-xl-base-1.0"
pipe = None # กำหนดค่าเริ่มต้นเป็น None
try:
print(f"กำลังโหลดโมเดล: {model_id}")
pipe = DiffusionPipeline.from_pretrained(
model_id,
torch_dtype=torch_dtype,
use_safetensors=True,
# ใช้ variant fp16 ถ้ามี GPU เพื่อลดขนาดโมเดลและ VRAM
variant="fp16" if device == "cuda" else None
)
pipe = pipe.to(device)
print(f"โหลดโมเดล {model_id} สำเร็จ และย้ายไปที่ {device}")
# --- Optimizations สำหรับ GPU ---
if device == "cuda":
# เปิดใช้งาน memory efficient attention ด้วย xformers (ถ้าติดตั้ง)
# ช่วยลด VRAM ได้มาก
try:
import xformers.ops
pipe.enable_xformers_memory_efficient_attention()
print("เปิดใช้งาน xformers memory efficient attention")
except ImportError:
print("xformers ไม่ได้ติดตั้งหรือไม่พร้อมใช้งาน, ไม่สามารถเปิดใช้งาน memory efficient attention ได้")
except Exception as e:
print(f"เกิดข้อผิดพลาดในการเปิดใช้งาน xformers: {e}")
# Optional: เปิดใช้งาน attention slicing (อาจช่วยลด VRAM ได้อีก แต่ช้าลงเล็กน้อย)
# pipe.enable_attention_slicing()
# print("เปิดใช้งาน attention slicing")
# Optional: เปิดใช้งาน sequential CPU offload (ลด VRAM ได้มาก แต่ช้าลงมาก)
# pipe.enable_sequential_cpu_offload()
# print("เปิดใช้งาน sequential CPU offload")
except Exception as e:
print(f"เกิดข้อผิดพลาดในการโหลดโมเดล: {e}")
print("อาจเกิดจาก VRAM ไม่เพียงพอ หรือการเชื่อมต่ออินเทอร์เน็ตมีปัญหา")
pipe = None # ตั้งค่า pipe เป็น None หากโหลดไม่สำเร็จ
# --- ฟังก์ชันสร้างภาพสำหรับ Gradio ---
def generate_image_for_gradio(prompt: str):
# ตรวจสอบว่าโมเดลโหลดสำเร็จหรือไม่
if pipe is None:
error_message = "โมเดล Stable Diffusion ยังไม่ได้โหลด หรือเกิดข้อผิดพลาดในการโหลด"
print(error_message)
# ส่งคืนภาพ placeholder หรือข้อความแสดงข้อผิดพลาด
# สร้างภาพสีแดงพร้อมข้อความแสดงข้อผิดพลาด
img = Image.new('RGB', (256, 256), color = (255, 0, 0))
from PIL import ImageDraw, ImageFont
draw = ImageDraw.Draw(img)
try:
# ลองโหลดฟอนต์มาตรฐาน
font = ImageFont.load_default()
except:
font = None # ใช้ค่าเริ่มต้นถ้าโหลดฟอนต์ไม่ได้
text_to_display = "Error: Model not loaded"
if font:
# ใช้ textbbox สำหรับ PIL เวอร์ชันใหม่
try:
bbox = draw.textbbox((0, 0), text_to_display, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
except:
# Fallback สำหรับ PIL เวอร์ชันเก่า
text_width, text_height = draw.textsize(text_to_display, font)
text_x = (256 - text_width) // 2
text_y = (256 - text_height) // 2
draw.text((text_x, text_y), text_to_display, fill=(255,255,255), font=font)
else:
draw.text((10, 10), text_to_display, fill=(255,255,255))
return img # ส่งคืนภาพแสดงข้อผิดพลาด
print(f"\nกำลังสร้างภาพสำหรับ Prompt: \"{prompt}\"")
print(f"Device: {device}")
# กำหนดค่าพารามิเตอร์การสร้างภาพ
# ค่าเหล่านี้ปรับได้ตามต้องการ แต่ค่าเริ่มต้นนี้เหมาะสำหรับ Free GPU
num_inference_steps = 25 # จำนวนขั้นตอน (20-50)
guidance_scale = 7.0 # ความเข้มข้นของ prompt (5-15)
# ลดขนาดภาพลงเพื่อประหยัด VRAM
height = 768
width = 768
# Negative prompt เพื่อควบคุมสิ่งที่ไม่ต้องการ
negative_prompt = "blurry, low quality, cartoon, watermark, text, ugly, deformed, extra limbs, missing limbs"
try:
# เรียก pipeline เพื่อสร้างภาพ
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=num_inference_steps,
guidance_scale=guidance_scale,
height=height,
width=width
).images[0] # .images จะคืนค่าเป็น list, เราต้องการภาพแรก
print("สร้างภาพสำเร็จ!")
return image
except torch.cuda.OutOfMemoryError:
oom_message = "เกิดข้อผิดพลาด: VRAM ไม่เพียงพอ ลองลดขนาดภาพ หรือใช้โมเดลที่เล็กกว่า"
print(oom_message)
# ส่งคืนภาพสีส้มพร้อมข้อความแสดง VRAM Error
img = Image.new('RGB', (256, 256), color = (255, 165, 0))
from PIL import ImageDraw, ImageFont
draw = ImageDraw.Draw(img)
try:
font = ImageFont.load_default()
except:
font = None
text_to_display = "Error: Out of VRAM"
if font:
try:
bbox = draw.textbbox((0, 0), text_to_display, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
except:
text_width, text_height = draw.textsize(text_to_display, font)
text_x = (256 - text_width) // 2
text_y = (256 - text_height) // 2
draw.text((text_x, text_y), text_to_display, fill=(0,0,0), font=font)
else:
draw.text((10, 10), text_to_display, fill=(0,0,0))
return img
except Exception as e:
print(f"เกิดข้อผิดพลาดในการสร้างภาพ: {e}")
# ส่งคืนภาพสีแดงพร้อมข้อความแสดงข้อผิดพลาดทั่วไป
img = Image.new('RGB', (256, 256), color = (255, 0, 0))
from PIL import ImageDraw, ImageFont
draw = ImageDraw.Draw(img)
try:
font = ImageFont.load_default()
except:
font = None
# แสดงข้อความ error บางส่วน
text_to_display = "Error: " + str(e)[:50] + "..."
if font:
try:
bbox = draw.textbbox((0, 0), text_to_display, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
except:
text_width, text_height = draw.textsize(text_to_display, font)
text_x = (256 - text_width) // 2
text_y = (256 - text_height) // 2
draw.text((text_x, text_y), text_to_display, fill=(255,255,255), font=font)
else:
draw.text((10, 10), text_to_display, fill=(255,255,255))
return img
# --- สร้าง Gradio Interface ---
iface = gr.Interface(
fn=generate_image_for_gradio,
inputs=gr.Textbox(lines=2, placeholder="Enter your prompt here...", label="Prompt"),
outputs=gr.Image(type="pil", label="Generated Image"),
title="Stable Diffusion XL Text-to-Image (Hugging Face Free GPU Demo)",
description="Generate images using Stable Diffusion XL 1.0 on a free Hugging Face GPU Space. May be slow or fail due to resource limits like VRAM.",
examples=[
["A cute cat wearing a hat, cinematic lighting"],
["A beautiful sunset over mountains, digital art"],
["An epic fantasy landscape, highly detailed, trending on artstation"]
]
)
# --- รัน Interface (สำหรับทดสอบ local หรือเมื่อ deploy บน Hugging Face Spaces) ---
if __name__ == "__main__":
# บน Hugging Face Spaces ไม่ต้องใส่ share=True
# ถ้าทดสอบ local และต้องการ share ให้ใส่ share=True
iface.launch()