multimodalart HF Staff commited on
Commit
6a7b482
·
verified ·
1 Parent(s): 0bc7df2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -41
app.py CHANGED
@@ -2,7 +2,6 @@ import gradio as gr
2
  import fal_client
3
  import os
4
  from typing import Optional, List
5
-
6
  from huggingface_hub import whoami
7
 
8
  # It is recommended to create this as a Secret on your Hugging Face Space
@@ -18,22 +17,37 @@ def get_fal_key():
18
  if not FAL_KEY:
19
  raise gr.Error("FAL_KEY is not set. Please add it to your Hugging Face Space secrets.")
20
 
21
- def single_image_generation(prompt: str, image: Optional[str] = None) -> str:
22
- """Handles text-to-image or single image-to-image."""
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  get_fal_key()
24
  if image:
 
25
  image_url = fal_client.upload_file(image)
26
  result = fal_client.run(
27
  "fal-ai/nano-banana/edit",
28
  arguments={"prompt": prompt, "image_url": image_url},
29
  )
30
  else:
 
31
  result = fal_client.run(
32
  "fal-ai/nano-banana", arguments={"prompt": prompt}
33
  )
34
- return result["images"][0]["url"]
35
 
36
- def multi_image_edit(prompt: str, images: List[str]) -> List[str]:
37
  """Handles multi-image editing."""
38
  get_fal_key()
39
  if not images:
@@ -61,79 +75,89 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
61
  with main_interface:
62
  gr.Markdown("## Welcome, PRO User!")
63
  with gr.Row():
 
64
  with gr.Column(scale=1):
65
  prompt_input = gr.Textbox(
66
  label="Prompt",
67
  placeholder="A delicious looking pizza"
68
  )
69
 
70
- with gr.Tabs():
71
- with gr.TabItem("Single Image", id="single"):
 
 
 
 
72
  image_input = gr.Image(
73
  type="filepath",
74
  label="Input Image (Optional for text-to-image)"
75
  )
76
- with gr.TabItem("Multiple Images", id="multiple"):
77
  gallery_input = gr.Gallery(
78
- label="Input Images"
79
  )
80
-
81
  generate_button = gr.Button("Generate", variant="primary")
82
 
 
83
  with gr.Column(scale=1):
84
- # A single gallery can handle one or many images
85
  output_gallery = gr.Gallery(label="Output")
86
 
 
 
 
87
  def unified_generator(
88
  prompt: str,
89
- current_tab: str,
90
  single_image: Optional[str],
91
  multi_images: Optional[List[str]],
 
 
92
  ) -> List[str]:
93
  """
94
- A single handler that routes to the correct function based on the active tab.
 
95
  """
96
- if current_tab == "multiple":
97
- return multi_image_edit(prompt, multi_images)
98
- else: # Handles both text-to-image and single image-to-image
99
- result_url = single_image_generation(prompt, single_image)
100
- return [result_url]
101
-
102
- # The `select` event on the tabs gives us the active tab's ID
103
- selected_tab = gr.Textbox(value="single", visible=False)
104
- for tab in demo.load_queue[0][0].children[1].children: # Hacky way to get tabs
105
- if isinstance(tab, gr.Tab):
106
- tab.select(lambda: tab.id, None, selected_tab)
107
 
 
 
 
 
 
108
  generate_button.click(
109
  unified_generator,
110
- inputs=[prompt_input, selected_tab, image_input, gallery_input],
111
  outputs=[output_gallery],
112
  )
113
 
 
114
  def control_access(
115
  profile: Optional[gr.OAuthProfile] = None,
116
  oauth_token: Optional[gr.OAuthToken] = None
117
  ):
118
  """Controls UI visibility based on user's PRO status."""
119
- if not profile or not oauth_token:
120
- return gr.update(visible=False), gr.update(visible=False)
121
- try:
122
- user_info = whoami(token=oauth_token.token)
123
- if user_info.get("isPro", False):
124
- return gr.update(visible=True), gr.update(visible=False)
125
- else:
126
- message = (
127
- "## ✨ Exclusive Access for PRO Users\n\n"
128
- "Thank you for your interest! This feature is available exclusively for our Hugging Face **PRO** members.\n\n"
129
- "To unlock this and many other benefits, please consider upgrading your account.\n\n"
130
- "### [**Become a PRO Member Today!**](https://huggingface.co/pro)"
131
- )
132
- return gr.update(visible=False), gr.update(visible=True, value=message)
133
- except Exception as e:
134
- gr.Warning(f"Could not verify user status: {e}")
135
  return gr.update(visible=False), gr.update(visible=False)
136
 
 
 
 
 
 
 
 
 
 
 
 
137
  demo.load(control_access, inputs=None, outputs=[main_interface, pro_message])
138
 
139
  if __name__ == "__main__":
 
2
  import fal_client
3
  import os
4
  from typing import Optional, List
 
5
  from huggingface_hub import whoami
6
 
7
  # It is recommended to create this as a Secret on your Hugging Face Space
 
17
  if not FAL_KEY:
18
  raise gr.Error("FAL_KEY is not set. Please add it to your Hugging Face Space secrets.")
19
 
20
+ def verify_pro_status(token: Optional[gr.OAuthToken]) -> bool:
21
+ """Verifies if the user is a Hugging Face PRO user using their token."""
22
+ if not token:
23
+ return False
24
+ try:
25
+ user_info = whoami(token=token.token)
26
+ return user_info.get("isPro", False)
27
+ except Exception as e:
28
+ print(f"Could not verify user's PRO status: {e}")
29
+ return False
30
+
31
+ # --- Backend Generation Functions ---
32
+
33
+ def run_single_image_logic(prompt: str, image: Optional[str] = None) -> List[str]:
34
+ """Handles text-to-image or single image-to-image and returns a list."""
35
  get_fal_key()
36
  if image:
37
+ # Single Image-to-Image
38
  image_url = fal_client.upload_file(image)
39
  result = fal_client.run(
40
  "fal-ai/nano-banana/edit",
41
  arguments={"prompt": prompt, "image_url": image_url},
42
  )
43
  else:
44
+ # Text-to-Image
45
  result = fal_client.run(
46
  "fal-ai/nano-banana", arguments={"prompt": prompt}
47
  )
48
+ return [result["images"][0]["url"]]
49
 
50
+ def run_multi_image_logic(prompt: str, images: List[str]) -> List[str]:
51
  """Handles multi-image editing."""
52
  get_fal_key()
53
  if not images:
 
75
  with main_interface:
76
  gr.Markdown("## Welcome, PRO User!")
77
  with gr.Row():
78
+ # LEFT COLUMN: Inputs
79
  with gr.Column(scale=1):
80
  prompt_input = gr.Textbox(
81
  label="Prompt",
82
  placeholder="A delicious looking pizza"
83
  )
84
 
85
+ # Use gr.State to track the active tab
86
+ active_tab_state = gr.State(value="single")
87
+
88
+ with gr.Tabs() as tabs:
89
+ # When a tab is selected, its 'select' event updates the active_tab_state
90
+ with gr.TabItem("Single Image", id="single") as single_tab:
91
  image_input = gr.Image(
92
  type="filepath",
93
  label="Input Image (Optional for text-to-image)"
94
  )
95
+ with gr.TabItem("Multiple Images", id="multiple") as multi_tab:
96
  gallery_input = gr.Gallery(
97
+ label="Input Images", file_types=["image"]
98
  )
99
+
100
  generate_button = gr.Button("Generate", variant="primary")
101
 
102
+ # RIGHT COLUMN: Outputs
103
  with gr.Column(scale=1):
 
104
  output_gallery = gr.Gallery(label="Output")
105
 
106
+ # --- Event Handlers ---
107
+
108
+ # A single, unified generator function
109
  def unified_generator(
110
  prompt: str,
 
111
  single_image: Optional[str],
112
  multi_images: Optional[List[str]],
113
+ active_tab: str,
114
+ oauth_token: Optional[gr.OAuthToken] = None,
115
  ) -> List[str]:
116
  """
117
+ A single handler that verifies PRO status and routes to the correct function.
118
+ The `active_tab` state is the primary source of truth for user intent.
119
  """
120
+ # Server-side security check before any inference
121
+ if not verify_pro_status(oauth_token):
122
+ raise gr.Error("Access Denied. This service is for PRO users only.")
123
+
124
+ # Logic based on the active tab and whether inputs exist
125
+ if active_tab == "multiple" and multi_images:
126
+ return run_multi_image_logic(prompt, multi_images)
127
+ else: # Covers single image, or text-to-image if single_image is None
128
+ return run_single_image_logic(prompt, single_image)
 
 
129
 
130
+ # Cleanly update the state when a tab is selected
131
+ single_tab.select(lambda: "single", None, active_tab_state)
132
+ multi_tab.select(lambda: "multiple", None, active_tab_state)
133
+
134
+ # Wire the button to the unified generator
135
  generate_button.click(
136
  unified_generator,
137
+ inputs=[prompt_input, image_input, gallery_input, active_tab_state, login_button],
138
  outputs=[output_gallery],
139
  )
140
 
141
+ # --- Access Control Logic ---
142
  def control_access(
143
  profile: Optional[gr.OAuthProfile] = None,
144
  oauth_token: Optional[gr.OAuthToken] = None
145
  ):
146
  """Controls UI visibility based on user's PRO status."""
147
+ if not profile:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  return gr.update(visible=False), gr.update(visible=False)
149
 
150
+ if verify_pro_status(oauth_token):
151
+ return gr.update(visible=True), gr.update(visible=False)
152
+ else:
153
+ message = (
154
+ "## ✨ Exclusive Access for PRO Users\n\n"
155
+ "Thank you for your interest! This feature is available exclusively for our Hugging Face **PRO** members.\n\n"
156
+ "To unlock this and many other benefits, please consider upgrading your account.\n\n"
157
+ "### [**Become a PRO Member Today!**](https://huggingface.co/pro)"
158
+ )
159
+ return gr.update(visible=False), gr.update(visible=True, value=message)
160
+
161
  demo.load(control_access, inputs=None, outputs=[main_interface, pro_message])
162
 
163
  if __name__ == "__main__":