File size: 6,233 Bytes
aa52cca e14c7dc aa52cca ce426de 588d12a ce426de 588d12a b7a086c aa52cca ce426de aa52cca ce426de aa52cca f02c7c0 aa52cca 83289b3 aa52cca feb3cd8 aa52cca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | """
Indian Art SD LoRA API
Main application entry point
Optimized for HuggingFace Spaces ZeroGPU
"""
import gradio_client.utils as client_utils
import functools
_original_json_schema_to_python_type = client_utils._json_schema_to_python_type
@functools.wraps(_original_json_schema_to_python_type)
def _patched_json_schema_to_python_type(schema, defs=None):
# Handle bool schema case that causes "argument of type 'bool' is not iterable"
if isinstance(schema, bool):
return "Any"
# Handle case where schema might be None or other non-dict types
if schema is None:
return "Any"
if not isinstance(schema, dict):
return str(type(schema).__name__)
return _original_json_schema_to_python_type(schema, defs)
client_utils._json_schema_to_python_type = _patched_json_schema_to_python_type
# Also patch the public function if it exists
if hasattr(client_utils, 'json_schema_to_python_type'):
client_utils.json_schema_to_python_type = _patched_json_schema_to_python_type
import os
import sys
import json
import gradio as gr
from PIL import Image
# Add src to path
sys.path.insert(0, os.path.dirname(__file__))
from src.config import Config
from src.model import IndianArtGenerator
from src.utils import ensure_directories
# Global generator instance
generator = IndianArtGenerator()
# Hardcoded generation settings
DEFAULT_WIDTH = 512
DEFAULT_HEIGHT = 512
DEFAULT_STEPS = 30
DEFAULT_GUIDANCE = 7.5
DEFAULT_LORA_SCALE = 0.8
DEFAULT_SEED = -1 # Random
# def get_generator():
# """Lazy initialization of model"""
# if generator.pipe is None:
# generator.load_model()
# return generator
try:
import spaces
ZERO_GPU_AVAILABLE = True
except ImportError:
ZERO_GPU_AVAILABLE = False
def conditional_gpu_decorator(fn):
if ZERO_GPU_AVAILABLE:
return spaces.GPU(duration=60)(fn)
return fn
@conditional_gpu_decorator
def generate_api(prompt: str, art_style: str):
"""
Generate image from prompt and art style.
All generation parameters are hardcoded constants.
"""
if not prompt or not prompt.strip():
raise gr.Error("Prompt cannot be empty")
if len(prompt) > 1000:
raise gr.Error("Prompt too long (max 1000 chars)")
# gen = get_generator()
#Lazy-load inside GPU context, so ZEROGPU can map weights onto GPU
if generator.pipe is None:
generator.load_model()
image, metadata = generator.generate(
prompt=prompt,
negative_prompt="", # Uses default negatives from config
art_style=art_style,
width=DEFAULT_WIDTH,
height=DEFAULT_HEIGHT,
num_inference_steps=DEFAULT_STEPS,
guidance_scale=DEFAULT_GUIDANCE,
lora_scale=DEFAULT_LORA_SCALE,
seed=DEFAULT_SEED,
num_images=1
)
return image, json.dumps(metadata, indent=2)
def create_ui():
"""Create minimal Gradio interface"""
css = """
.gradio-container {max-width: 800px !important;}
.image-output {height: auto !important; max-height: 600px;}
"""
with gr.Blocks(
title="Indian Art Generator",
theme=gr.themes.Soft(),
css=css
) as demo:
gr.Markdown("""
<div style="text-align: center;">
<h1>Indian Traditional Art Generator</h1>
<p>Describe your scene and select an art style</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
prompt = gr.Textbox(
label="Prompt",
placeholder="peacock surrounded by floral patterns",
lines=3
)
art_style = gr.Dropdown(
choices=list(Config.ART_STYLES.keys()),
value="none",
label="Art Style Prefix",
info="Select a style to enhance your prompt, or 'none' for raw prompt"
)
generate_btn = gr.Button(
"Generate",
variant="primary",
size="lg"
)
# Hidden constants display
with gr.Accordion("Generation Settings"):
gr.Markdown(f"""
- Resolution: {DEFAULT_WIDTH}x{DEFAULT_HEIGHT}
- Steps: {DEFAULT_STEPS}
- Guidance: {DEFAULT_GUIDANCE}
- LoRA Scale: {DEFAULT_LORA_SCALE}
- Seed: Random
""")
with gr.Column(scale=1):
output_image = gr.Image(
label="Generated Artwork",
type="pil",
elem_classes=["image-output"],
format="png"
)
output_metadata = gr.Textbox(
label="Metadata (JSON)",
lines=8,
interactive=False,
)
# Examples
gr.Examples(
examples=[
["peacock with elaborate geometric feathers", "madhubani"],
["village scene with farmers and traditional huts", "warli"],
["tiger in dense jungle with dotted patterns", "gond"],
["radha krishna under flowering tree", "pattachitra"],
["goddess lakshmi with gold ornaments", "tanjore"],
["elephant decorated for festival procession", "miniature"],
],
inputs=[prompt, art_style],
label="Example Prompts"
)
generate_btn.click(
fn=generate_api,
inputs=[prompt, art_style],
outputs=[output_image, output_metadata]
)
return demo
if __name__ == "__main__":
ensure_directories()
Config.validate()
print("Starting Indian Art Generator...")
print(f"Base Model: {Config.BASE_MODEL}")
print(f"LoRA Path: {Config.LORA_PATH or 'Not configured'}")
print(f"Hardcoded settings: {DEFAULT_WIDTH}x{DEFAULT_HEIGHT}, {DEFAULT_STEPS} steps")
demo = create_ui()
demo.launch(
server_name="0.0.0.0",
server_port=int(os.getenv("PORT", 7860)),
share=True,
show_error=True,
) |