Spaces:
Running
Running
enabling MCP server
Browse files
app.py
CHANGED
@@ -4,8 +4,8 @@ import io
|
|
4 |
import random
|
5 |
import os
|
6 |
import time
|
|
|
7 |
from PIL import Image
|
8 |
-
from deep_translator import GoogleTranslator
|
9 |
import json
|
10 |
|
11 |
# Project by Nymbo
|
@@ -15,36 +15,76 @@ API_TOKEN = os.getenv("HF_READ_TOKEN")
|
|
15 |
headers = {"Authorization": f"Bearer {API_TOKEN}"}
|
16 |
timeout = 100
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
return None
|
22 |
|
23 |
key = random.randint(0, 999)
|
24 |
-
|
25 |
-
API_TOKEN = random.choice([os.getenv("HF_READ_TOKEN")])
|
26 |
-
headers = {"Authorization": f"Bearer {API_TOKEN}"}
|
27 |
-
|
28 |
-
# Translate the prompt from Russian to English if necessary
|
29 |
-
prompt = GoogleTranslator(source='ru', target='en').translate(prompt)
|
30 |
-
print(f'\033[1mGeneration {key} translation:\033[0m {prompt}')
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
payload = {
|
38 |
-
"inputs":
|
39 |
-
"
|
40 |
-
"steps": steps,
|
41 |
-
"cfg_scale": cfg_scale,
|
42 |
-
"seed": seed if seed != -1 else random.randint(1, 1000000000),
|
43 |
-
"strength": strength,
|
44 |
-
"parameters": {
|
45 |
-
"width": width, # Pass the width to the API
|
46 |
-
"height": height # Pass the height to the API
|
47 |
-
}
|
48 |
}
|
49 |
|
50 |
# Send the request to the API and handle the response
|
@@ -55,12 +95,12 @@ def query(prompt, is_negative=False, steps=35, cfg_scale=7, sampler="DPM++ 2M Ka
|
|
55 |
if response.status_code == 503:
|
56 |
raise gr.Error(f"{response.status_code} : The model is being loaded")
|
57 |
raise gr.Error(f"{response.status_code}")
|
58 |
-
|
59 |
try:
|
60 |
# Convert the response content into an image
|
61 |
image_bytes = response.content
|
62 |
image = Image.open(io.BytesIO(image_bytes))
|
63 |
-
print(f'\033[1mGeneration {key} completed!\033[0m ({
|
64 |
return image
|
65 |
except Exception as e:
|
66 |
print(f"Error when trying to open the image: {e}")
|
@@ -110,7 +150,21 @@ with gr.Blocks(theme='Nymbo/Nymbo_Theme', css=css) as app:
|
|
110 |
image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")
|
111 |
|
112 |
# Bind the button to the query function with the added width and height inputs
|
113 |
-
text_button.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
# Launch the Gradio app
|
116 |
app.launch(show_api=True, share=False, mcp_server=True)
|
|
|
4 |
import random
|
5 |
import os
|
6 |
import time
|
7 |
+
from typing import Optional
|
8 |
from PIL import Image
|
|
|
9 |
import json
|
10 |
|
11 |
# Project by Nymbo
|
|
|
15 |
headers = {"Authorization": f"Bearer {API_TOKEN}"}
|
16 |
timeout = 100
|
17 |
|
18 |
+
def query(
|
19 |
+
prompt: str,
|
20 |
+
negative_prompt: str = "",
|
21 |
+
steps: int = 35,
|
22 |
+
cfg_scale: float = 7,
|
23 |
+
sampler: str = "DPM++ 2M Karras",
|
24 |
+
seed: int = -1,
|
25 |
+
strength: float = 0.7,
|
26 |
+
width: int = 1024,
|
27 |
+
height: int = 1024,
|
28 |
+
) -> Optional[Image.Image]:
|
29 |
+
"""Generate an image from a text prompt using FLUX.1-Krea via the Hugging Face Inference API.
|
30 |
+
|
31 |
+
This function is exposed as an MCP tool via Gradio. It accepts common text-to-image
|
32 |
+
parameters and returns a single generated image.
|
33 |
+
|
34 |
+
Args:
|
35 |
+
prompt: The main text prompt describing the desired image. Required.
|
36 |
+
negative_prompt: Text describing what should be avoided in the image.
|
37 |
+
steps: Number of denoising steps (quality vs speed). Typical range 1–100.
|
38 |
+
cfg_scale: Classifier-free guidance scale (adherence to prompt). Typical range 1–20.
|
39 |
+
sampler: Sampling/scheduler method name. If unsupported by the backend, it may be ignored.
|
40 |
+
seed: Random seed. Use -1 for a random seed on each call.
|
41 |
+
strength: Image-to-image strength (0–1). Not used for pure text-to-image but included for compatibility.
|
42 |
+
width: Output image width in pixels. Usually multiples of 32.
|
43 |
+
height: Output image height in pixels. Usually multiples of 32.
|
44 |
+
|
45 |
+
Returns:
|
46 |
+
A PIL.Image if generation succeeds; otherwise None.
|
47 |
+
|
48 |
+
Raises:
|
49 |
+
gr.Error: If the backend returns a non-200 HTTP status.
|
50 |
+
"""
|
51 |
+
if not prompt:
|
52 |
return None
|
53 |
|
54 |
key = random.randint(0, 999)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
+
api_token = os.getenv("HF_READ_TOKEN")
|
57 |
+
if not api_token:
|
58 |
+
raise gr.Error("Missing HF_READ_TOKEN environment variable.")
|
59 |
+
|
60 |
+
headers = {"Authorization": f"Bearer {api_token}"}
|
61 |
+
|
62 |
+
# Slightly augment the prompt for higher quality
|
63 |
+
prompt_aug = f"{prompt} | ultra detail, ultra elaboration, ultra quality, perfect."
|
64 |
+
print(f'\033[1mGeneration {key}:\033[0m {prompt_aug}')
|
65 |
+
|
66 |
+
# Compute seed value
|
67 |
+
seed_value = seed if seed != -1 else random.randint(1, 1_000_000_000)
|
68 |
+
|
69 |
+
# Prepare payload aligned with HF Inference API conventions
|
70 |
+
parameters = {
|
71 |
+
"num_inference_steps": steps,
|
72 |
+
"guidance_scale": cfg_scale,
|
73 |
+
"width": width,
|
74 |
+
"height": height,
|
75 |
+
"seed": seed_value,
|
76 |
+
# Best-effort: some backends accept scheduler/sampler names; safe to send.
|
77 |
+
"scheduler": sampler,
|
78 |
+
}
|
79 |
+
if negative_prompt and negative_prompt.strip():
|
80 |
+
parameters["negative_prompt"] = negative_prompt
|
81 |
+
# Include strength only if meaningful
|
82 |
+
if 0 < strength <= 1:
|
83 |
+
parameters["strength"] = strength
|
84 |
+
|
85 |
payload = {
|
86 |
+
"inputs": prompt_aug,
|
87 |
+
"parameters": parameters,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
}
|
89 |
|
90 |
# Send the request to the API and handle the response
|
|
|
95 |
if response.status_code == 503:
|
96 |
raise gr.Error(f"{response.status_code} : The model is being loaded")
|
97 |
raise gr.Error(f"{response.status_code}")
|
98 |
+
|
99 |
try:
|
100 |
# Convert the response content into an image
|
101 |
image_bytes = response.content
|
102 |
image = Image.open(io.BytesIO(image_bytes))
|
103 |
+
print(f'\033[1mGeneration {key} completed!\033[0m ({prompt_aug})')
|
104 |
return image
|
105 |
except Exception as e:
|
106 |
print(f"Error when trying to open the image: {e}")
|
|
|
150 |
image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")
|
151 |
|
152 |
# Bind the button to the query function with the added width and height inputs
|
153 |
+
text_button.click(
|
154 |
+
query,
|
155 |
+
inputs=[
|
156 |
+
text_prompt,
|
157 |
+
negative_prompt,
|
158 |
+
steps,
|
159 |
+
cfg,
|
160 |
+
method,
|
161 |
+
seed,
|
162 |
+
strength,
|
163 |
+
width,
|
164 |
+
height,
|
165 |
+
],
|
166 |
+
outputs=image_output,
|
167 |
+
)
|
168 |
|
169 |
# Launch the Gradio app
|
170 |
app.launch(show_api=True, share=False, mcp_server=True)
|