Qi Cai commited on
Commit ·
e9da9b4
1
Parent(s): ebcf92b
change
Browse files
app.py
CHANGED
|
@@ -89,13 +89,17 @@ def _headers() -> dict:
|
|
| 89 |
return {"Authorization": f"Bearer {API_TOKEN}"}
|
| 90 |
|
| 91 |
|
| 92 |
-
def create_request(prompt, wh_ratio):
|
| 93 |
"""
|
| 94 |
Submit an image generation request to the API.
|
| 95 |
|
| 96 |
Args:
|
| 97 |
prompt (str): Text prompt describing the image to generate
|
| 98 |
wh_ratio (str): Aspect ratio for the output image (e.g. "16:9")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
Returns:
|
| 101 |
str: Task ID
|
|
@@ -104,7 +108,8 @@ def create_request(prompt, wh_ratio):
|
|
| 104 |
APIError: If the API request fails
|
| 105 |
"""
|
| 106 |
logger.info(
|
| 107 |
-
f"Starting create_request with prompt='{prompt[:50]}...',
|
|
|
|
| 108 |
)
|
| 109 |
|
| 110 |
if not prompt or not prompt.strip():
|
|
@@ -115,11 +120,19 @@ def create_request(prompt, wh_ratio):
|
|
| 115 |
logger.error(f"Invalid wh_ratio: {wh_ratio}. Valid options: {WH_RATIO_OPTIONS}")
|
| 116 |
raise ValueError(f"Invalid aspect ratio. Must be one of: {', '.join(WH_RATIO_OPTIONS)}")
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
model_params = {
|
| 119 |
"prompt": prompt,
|
| 120 |
"wh_ratio": wh_ratio,
|
| 121 |
"model_id": MODEL_ID,
|
| 122 |
"n": 1,
|
|
|
|
|
|
|
| 123 |
}
|
| 124 |
|
| 125 |
url = _build_request_url()
|
|
@@ -527,6 +540,84 @@ textarea:focus, input:focus,
|
|
| 527 |
background: #ffffff !important;
|
| 528 |
}
|
| 529 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
/* Footer tagline */
|
| 531 |
.tagline {
|
| 532 |
text-align: center;
|
|
@@ -780,6 +871,24 @@ def create_ui():
|
|
| 780 |
info="Width : Height",
|
| 781 |
)
|
| 782 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 783 |
with gr.Row():
|
| 784 |
clear_btn = gr.Button("Clear", variant="secondary", scale=1)
|
| 785 |
generate_btn = gr.Button("Generate", variant="primary", scale=3)
|
|
@@ -799,9 +908,11 @@ def create_ui():
|
|
| 799 |
elem_classes=["image-output"],
|
| 800 |
)
|
| 801 |
|
| 802 |
-
def generate_with_status(prompt, wh_ratio_value):
|
| 803 |
logger.info(
|
| 804 |
-
f"Starting image generation with prompt='{(prompt or '')[:50]}...',
|
|
|
|
|
|
|
| 805 |
)
|
| 806 |
|
| 807 |
yield None, _status_html("Sending request to API…", "running")
|
|
@@ -817,13 +928,23 @@ def create_ui():
|
|
| 817 |
yield None, _status_html(f"Invalid aspect ratio “{wh_ratio_value}”", "error")
|
| 818 |
return
|
| 819 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 820 |
if FAKE_TEST:
|
| 821 |
logger.info("FAKE_TEST mode active — bypassing real API call")
|
| 822 |
yield from _fake_generation_iter(prompt, wh_ratio_value)
|
| 823 |
return
|
| 824 |
|
| 825 |
logger.info("Creating API request")
|
| 826 |
-
task_id = create_request(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 827 |
yield None, _status_html(f"Request submitted · Task {task_id[:8]}…", "running")
|
| 828 |
|
| 829 |
start_time = time.time()
|
|
@@ -921,7 +1042,7 @@ def create_ui():
|
|
| 921 |
html = _status_html(_queue_text(waiting, running), "running")
|
| 922 |
return None, html, True, html
|
| 923 |
|
| 924 |
-
def _generate_wrapped(prompt_value, wh_ratio_value):
|
| 925 |
"""Click handler #2 — queued.
|
| 926 |
|
| 927 |
Wraps the existing generator and, on the FIRST yield, also flips
|
|
@@ -929,7 +1050,9 @@ def create_ui():
|
|
| 929 |
lets the generator's own `yield`s drive it (Generating XXs → ...).
|
| 930 |
"""
|
| 931 |
first = True
|
| 932 |
-
for image, status_html in generate_with_status(
|
|
|
|
|
|
|
| 933 |
if first:
|
| 934 |
first = False
|
| 935 |
yield image, status_html, False
|
|
@@ -944,7 +1067,7 @@ def create_ui():
|
|
| 944 |
show_progress="hidden",
|
| 945 |
).then(
|
| 946 |
fn=_generate_wrapped,
|
| 947 |
-
inputs=[prompt, wh_ratio],
|
| 948 |
outputs=[output_image, status_msg, queued_state],
|
| 949 |
show_progress="minimal",
|
| 950 |
show_progress_on=[generate_btn],
|
|
|
|
| 89 |
return {"Authorization": f"Bearer {API_TOKEN}"}
|
| 90 |
|
| 91 |
|
| 92 |
+
def create_request(prompt, wh_ratio, enable_prompt_refine=True, seed=-1):
|
| 93 |
"""
|
| 94 |
Submit an image generation request to the API.
|
| 95 |
|
| 96 |
Args:
|
| 97 |
prompt (str): Text prompt describing the image to generate
|
| 98 |
wh_ratio (str): Aspect ratio for the output image (e.g. "16:9")
|
| 99 |
+
enable_prompt_refine (bool): Whether to let the backend rewrite/expand
|
| 100 |
+
the prompt before generation. Sent to the API as 0 / 1.
|
| 101 |
+
seed (int): Generation seed. -1 means the backend will pick one
|
| 102 |
+
randomly; any other integer fixes the seed for reproducible runs.
|
| 103 |
|
| 104 |
Returns:
|
| 105 |
str: Task ID
|
|
|
|
| 108 |
APIError: If the API request fails
|
| 109 |
"""
|
| 110 |
logger.info(
|
| 111 |
+
f"Starting create_request with prompt='{prompt[:50]}...', "
|
| 112 |
+
f"wh_ratio={wh_ratio}, enable_prompt_refine={enable_prompt_refine}, seed={seed}"
|
| 113 |
)
|
| 114 |
|
| 115 |
if not prompt or not prompt.strip():
|
|
|
|
| 120 |
logger.error(f"Invalid wh_ratio: {wh_ratio}. Valid options: {WH_RATIO_OPTIONS}")
|
| 121 |
raise ValueError(f"Invalid aspect ratio. Must be one of: {', '.join(WH_RATIO_OPTIONS)}")
|
| 122 |
|
| 123 |
+
try:
|
| 124 |
+
seed_int = int(seed)
|
| 125 |
+
except (TypeError, ValueError):
|
| 126 |
+
logger.warning(f"Invalid seed value '{seed}', falling back to -1 (random)")
|
| 127 |
+
seed_int = -1
|
| 128 |
+
|
| 129 |
model_params = {
|
| 130 |
"prompt": prompt,
|
| 131 |
"wh_ratio": wh_ratio,
|
| 132 |
"model_id": MODEL_ID,
|
| 133 |
"n": 1,
|
| 134 |
+
"enable_prompt_refine": 1 if enable_prompt_refine else 0,
|
| 135 |
+
"seed": seed_int,
|
| 136 |
}
|
| 137 |
|
| 138 |
url = _build_request_url()
|
|
|
|
| 540 |
background: #ffffff !important;
|
| 541 |
}
|
| 542 |
|
| 543 |
+
/* Advanced options row — keeps the refine switch + seed input visually paired */
|
| 544 |
+
.advanced-row {
|
| 545 |
+
gap: 14px !important;
|
| 546 |
+
margin-top: 2px;
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
/* Refine toggle — render the gradio checkbox as an Apple-style pill switch */
|
| 550 |
+
.refine-toggle {
|
| 551 |
+
background: #f5f5f7 !important;
|
| 552 |
+
border-radius: 12px !important;
|
| 553 |
+
border: 1px solid rgba(0,0,0,0.05) !important;
|
| 554 |
+
padding: 10px 14px !important;
|
| 555 |
+
}
|
| 556 |
+
.refine-toggle label {
|
| 557 |
+
display: flex !important;
|
| 558 |
+
align-items: center !important;
|
| 559 |
+
gap: 10px !important;
|
| 560 |
+
cursor: pointer;
|
| 561 |
+
}
|
| 562 |
+
.refine-toggle input[type="checkbox"] {
|
| 563 |
+
appearance: none;
|
| 564 |
+
-webkit-appearance: none;
|
| 565 |
+
width: 38px;
|
| 566 |
+
height: 22px;
|
| 567 |
+
border-radius: 999px !important;
|
| 568 |
+
background: #d2d2d7 !important;
|
| 569 |
+
position: relative;
|
| 570 |
+
cursor: pointer;
|
| 571 |
+
transition: background 0.18s ease;
|
| 572 |
+
border: none !important;
|
| 573 |
+
flex-shrink: 0;
|
| 574 |
+
margin: 0 !important;
|
| 575 |
+
}
|
| 576 |
+
.refine-toggle input[type="checkbox"]::after {
|
| 577 |
+
content: "";
|
| 578 |
+
position: absolute;
|
| 579 |
+
top: 2px;
|
| 580 |
+
left: 2px;
|
| 581 |
+
width: 18px;
|
| 582 |
+
height: 18px;
|
| 583 |
+
border-radius: 50%;
|
| 584 |
+
background: #ffffff;
|
| 585 |
+
box-shadow: 0 1px 3px rgba(0,0,0,0.15), 0 1px 1px rgba(0,0,0,0.06);
|
| 586 |
+
transition: transform 0.18s ease;
|
| 587 |
+
}
|
| 588 |
+
.refine-toggle input[type="checkbox"]:checked {
|
| 589 |
+
background: #30d158 !important;
|
| 590 |
+
}
|
| 591 |
+
.refine-toggle input[type="checkbox"]:checked::after {
|
| 592 |
+
transform: translateX(16px);
|
| 593 |
+
}
|
| 594 |
+
.refine-toggle input[type="checkbox"]:focus-visible {
|
| 595 |
+
box-shadow: 0 0 0 4px rgba(0,113,227,0.15) !important;
|
| 596 |
+
}
|
| 597 |
+
.refine-toggle .wrap > label > span,
|
| 598 |
+
.refine-toggle label > span {
|
| 599 |
+
color: #1d1d1f !important;
|
| 600 |
+
font-size: 14px !important;
|
| 601 |
+
font-weight: 500 !important;
|
| 602 |
+
letter-spacing: 0.01em;
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
/* Seed number input — match the prompt/dropdown rounding */
|
| 606 |
+
.seed-input input[type="number"] {
|
| 607 |
+
border-radius: 12px !important;
|
| 608 |
+
padding: 10px 14px !important;
|
| 609 |
+
font-variant-numeric: tabular-nums;
|
| 610 |
+
}
|
| 611 |
+
/* Hide the native spinner buttons on number inputs for a cleaner look */
|
| 612 |
+
.seed-input input[type="number"]::-webkit-outer-spin-button,
|
| 613 |
+
.seed-input input[type="number"]::-webkit-inner-spin-button {
|
| 614 |
+
-webkit-appearance: none;
|
| 615 |
+
margin: 0;
|
| 616 |
+
}
|
| 617 |
+
.seed-input input[type="number"] {
|
| 618 |
+
-moz-appearance: textfield;
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
/* Footer tagline */
|
| 622 |
.tagline {
|
| 623 |
text-align: center;
|
|
|
|
| 871 |
info="Width : Height",
|
| 872 |
)
|
| 873 |
|
| 874 |
+
with gr.Row(elem_classes=["advanced-row"], equal_height=True):
|
| 875 |
+
enable_prompt_refine = gr.Checkbox(
|
| 876 |
+
value=True,
|
| 877 |
+
label="Prompt Refine",
|
| 878 |
+
info="Let the model rewrite & enrich your prompt",
|
| 879 |
+
elem_classes=["refine-toggle"],
|
| 880 |
+
scale=1,
|
| 881 |
+
)
|
| 882 |
+
seed = gr.Number(
|
| 883 |
+
value=-1,
|
| 884 |
+
label="Seed",
|
| 885 |
+
info="Use -1 for a random seed",
|
| 886 |
+
precision=0,
|
| 887 |
+
minimum=-1,
|
| 888 |
+
elem_classes=["seed-input"],
|
| 889 |
+
scale=1,
|
| 890 |
+
)
|
| 891 |
+
|
| 892 |
with gr.Row():
|
| 893 |
clear_btn = gr.Button("Clear", variant="secondary", scale=1)
|
| 894 |
generate_btn = gr.Button("Generate", variant="primary", scale=3)
|
|
|
|
| 908 |
elem_classes=["image-output"],
|
| 909 |
)
|
| 910 |
|
| 911 |
+
def generate_with_status(prompt, wh_ratio_value, enable_prompt_refine_value, seed_value):
|
| 912 |
logger.info(
|
| 913 |
+
f"Starting image generation with prompt='{(prompt or '')[:50]}...', "
|
| 914 |
+
f"wh_ratio={wh_ratio_value}, enable_prompt_refine={enable_prompt_refine_value}, "
|
| 915 |
+
f"seed={seed_value}"
|
| 916 |
)
|
| 917 |
|
| 918 |
yield None, _status_html("Sending request to API…", "running")
|
|
|
|
| 928 |
yield None, _status_html(f"Invalid aspect ratio “{wh_ratio_value}”", "error")
|
| 929 |
return
|
| 930 |
|
| 931 |
+
try:
|
| 932 |
+
seed_int = int(seed_value) if seed_value is not None else -1
|
| 933 |
+
except (TypeError, ValueError):
|
| 934 |
+
seed_int = -1
|
| 935 |
+
|
| 936 |
if FAKE_TEST:
|
| 937 |
logger.info("FAKE_TEST mode active — bypassing real API call")
|
| 938 |
yield from _fake_generation_iter(prompt, wh_ratio_value)
|
| 939 |
return
|
| 940 |
|
| 941 |
logger.info("Creating API request")
|
| 942 |
+
task_id = create_request(
|
| 943 |
+
prompt,
|
| 944 |
+
wh_ratio_value,
|
| 945 |
+
enable_prompt_refine=bool(enable_prompt_refine_value),
|
| 946 |
+
seed=seed_int,
|
| 947 |
+
)
|
| 948 |
yield None, _status_html(f"Request submitted · Task {task_id[:8]}…", "running")
|
| 949 |
|
| 950 |
start_time = time.time()
|
|
|
|
| 1042 |
html = _status_html(_queue_text(waiting, running), "running")
|
| 1043 |
return None, html, True, html
|
| 1044 |
|
| 1045 |
+
def _generate_wrapped(prompt_value, wh_ratio_value, enable_prompt_refine_value, seed_value):
|
| 1046 |
"""Click handler #2 — queued.
|
| 1047 |
|
| 1048 |
Wraps the existing generator and, on the FIRST yield, also flips
|
|
|
|
| 1050 |
lets the generator's own `yield`s drive it (Generating XXs → ...).
|
| 1051 |
"""
|
| 1052 |
first = True
|
| 1053 |
+
for image, status_html in generate_with_status(
|
| 1054 |
+
prompt_value, wh_ratio_value, enable_prompt_refine_value, seed_value
|
| 1055 |
+
):
|
| 1056 |
if first:
|
| 1057 |
first = False
|
| 1058 |
yield image, status_html, False
|
|
|
|
| 1067 |
show_progress="hidden",
|
| 1068 |
).then(
|
| 1069 |
fn=_generate_wrapped,
|
| 1070 |
+
inputs=[prompt, wh_ratio, enable_prompt_refine, seed],
|
| 1071 |
outputs=[output_image, status_msg, queued_state],
|
| 1072 |
show_progress="minimal",
|
| 1073 |
show_progress_on=[generate_btn],
|