Chris Addis commited on
Commit
f074acd
·
1 Parent(s): 0ff4dd6
Files changed (3) hide show
  1. .ipynb_checkpoints/app-checkpoint.py +2 -20
  2. app-Copy1.py +2 -20
  3. app.py +138 -137
.ipynb_checkpoints/app-checkpoint.py CHANGED
@@ -1,7 +1,6 @@
1
  import gradio as gr
2
  import numpy as np
3
  from PIL import Image
4
- import io
5
  import os
6
  import requests
7
  import json
@@ -12,16 +11,6 @@ import csv
12
  import tempfile
13
  import datetime
14
 
15
- # Load environment variables from .env file if it exists (for local development)
16
- # On Hugging Face Spaces, the secrets are automatically available as environment variables
17
- if os.path.exists(".env"):
18
- load_dotenv()
19
-
20
- from io import BytesIO
21
- import numpy as np
22
- import requests
23
- from PIL import Image
24
-
25
  # import libraries
26
  from library.utils_model import *
27
  from library.utils_html import *
@@ -29,12 +18,6 @@ from library.utils_prompt import *
29
 
30
  OR = OpenRouterAPI()
31
 
32
- # Path for storing user preferences
33
- PREFERENCES_FILE = "data/user_preferences.csv"
34
-
35
- # Ensure directory exists
36
- os.makedirs(os.path.dirname(PREFERENCES_FILE), exist_ok=True)
37
-
38
  # Define model pricing information (approximate costs per 100 image API calls)
39
  MODEL_PRICING = {
40
  "google/gemini-2.0-flash-001": "$0.03",
@@ -94,7 +77,6 @@ def get_base_filename(filepath):
94
 
95
  # Define the Gradio interface
96
  def create_demo():
97
- # --- Updated CSS with model info styling ---
98
  custom_css = """
99
  /* Container for the image component (#current-image-display is the elem_id of gr.Image) */
100
  #current-image-display {
@@ -134,11 +116,11 @@ def create_demo():
134
  gr.Markdown("Developed by the Natural History Museum in Partnership with National Museums Liverpool. Funded by the DCMS Pilot Scheme")
135
  with gr.Column(scale=1):
136
  with gr.Row():
137
- gr.Image("images/nhm_logo.png", show_label=False, height=120,
138
  interactive=False, show_download_button=False,
139
  show_share_button=False, show_fullscreen_button=False,
140
  container=False, elem_id="nhm-logo")
141
- gr.Image("images/nml_logo.png", show_label=False, height=120,
142
  interactive=False, show_download_button=False,
143
  show_share_button=False, show_fullscreen_button=False,
144
  container=False, elem_id="nml-logo")
 
1
  import gradio as gr
2
  import numpy as np
3
  from PIL import Image
 
4
  import os
5
  import requests
6
  import json
 
11
  import tempfile
12
  import datetime
13
 
 
 
 
 
 
 
 
 
 
 
14
  # import libraries
15
  from library.utils_model import *
16
  from library.utils_html import *
 
18
 
19
  OR = OpenRouterAPI()
20
 
 
 
 
 
 
 
21
  # Define model pricing information (approximate costs per 100 image API calls)
22
  MODEL_PRICING = {
23
  "google/gemini-2.0-flash-001": "$0.03",
 
77
 
78
  # Define the Gradio interface
79
  def create_demo():
 
80
  custom_css = """
81
  /* Container for the image component (#current-image-display is the elem_id of gr.Image) */
82
  #current-image-display {
 
116
  gr.Markdown("Developed by the Natural History Museum in Partnership with National Museums Liverpool. Funded by the DCMS Pilot Scheme")
117
  with gr.Column(scale=1):
118
  with gr.Row():
119
+ gr.Image("images/nhm_logo.png", show_label=False, height=100,
120
  interactive=False, show_download_button=False,
121
  show_share_button=False, show_fullscreen_button=False,
122
  container=False, elem_id="nhm-logo")
123
+ gr.Image("images/nml_logo.png", show_label=False, height=100,
124
  interactive=False, show_download_button=False,
125
  show_share_button=False, show_fullscreen_button=False,
126
  container=False, elem_id="nml-logo")
app-Copy1.py CHANGED
@@ -1,7 +1,6 @@
1
  import gradio as gr
2
  import numpy as np
3
  from PIL import Image
4
- import io
5
  import os
6
  import requests
7
  import json
@@ -12,16 +11,6 @@ import csv
12
  import tempfile
13
  import datetime
14
 
15
- # Load environment variables from .env file if it exists (for local development)
16
- # On Hugging Face Spaces, the secrets are automatically available as environment variables
17
- if os.path.exists(".env"):
18
- load_dotenv()
19
-
20
- from io import BytesIO
21
- import numpy as np
22
- import requests
23
- from PIL import Image
24
-
25
  # import libraries
26
  from library.utils_model import *
27
  from library.utils_html import *
@@ -29,12 +18,6 @@ from library.utils_prompt import *
29
 
30
  OR = OpenRouterAPI()
31
 
32
- # Path for storing user preferences
33
- PREFERENCES_FILE = "data/user_preferences.csv"
34
-
35
- # Ensure directory exists
36
- os.makedirs(os.path.dirname(PREFERENCES_FILE), exist_ok=True)
37
-
38
  # Define model pricing information (approximate costs per 100 image API calls)
39
  MODEL_PRICING = {
40
  "google/gemini-2.0-flash-001": "$0.03",
@@ -67,7 +50,6 @@ def get_sys_prompt(length="medium", photograph=False):
67
  dev_prompt += " Repsonses should be a maximum of 450 characters."
68
  return dev_prompt + extra_prompt
69
 
70
-
71
  def create_csv_file_simple(results):
72
  """Create a CSV file from the results and return the path"""
73
  try:
@@ -133,11 +115,11 @@ def create_demo():
133
  gr.Markdown("Developed by the Natural History Museum in Partnership with National Museums Liverpool. Funded by the DCMS Pilot Scheme")
134
  with gr.Column(scale=1):
135
  with gr.Row():
136
- gr.Image("images/nhm_logo.png", show_label=False, height=120,
137
  interactive=False, show_download_button=False,
138
  show_share_button=False, show_fullscreen_button=False,
139
  container=False, elem_id="nhm-logo")
140
- gr.Image("images/nml_logo.png", show_label=False, height=120,
141
  interactive=False, show_download_button=False,
142
  show_share_button=False, show_fullscreen_button=False,
143
  container=False, elem_id="nml-logo")
 
1
  import gradio as gr
2
  import numpy as np
3
  from PIL import Image
 
4
  import os
5
  import requests
6
  import json
 
11
  import tempfile
12
  import datetime
13
 
 
 
 
 
 
 
 
 
 
 
14
  # import libraries
15
  from library.utils_model import *
16
  from library.utils_html import *
 
18
 
19
  OR = OpenRouterAPI()
20
 
 
 
 
 
 
 
21
  # Define model pricing information (approximate costs per 100 image API calls)
22
  MODEL_PRICING = {
23
  "google/gemini-2.0-flash-001": "$0.03",
 
50
  dev_prompt += " Repsonses should be a maximum of 450 characters."
51
  return dev_prompt + extra_prompt
52
 
 
53
  def create_csv_file_simple(results):
54
  """Create a CSV file from the results and return the path"""
55
  try:
 
115
  gr.Markdown("Developed by the Natural History Museum in Partnership with National Museums Liverpool. Funded by the DCMS Pilot Scheme")
116
  with gr.Column(scale=1):
117
  with gr.Row():
118
+ gr.Image("images/nhm_logo.png", show_label=False, height=100,
119
  interactive=False, show_download_button=False,
120
  show_share_button=False, show_fullscreen_button=False,
121
  container=False, elem_id="nhm-logo")
122
+ gr.Image("images/nml_logo.png", show_label=False, height=100,
123
  interactive=False, show_download_button=False,
124
  show_share_button=False, show_fullscreen_button=False,
125
  container=False, elem_id="nml-logo")
app.py CHANGED
@@ -16,15 +16,9 @@ from library.utils_model import *
16
  from library.utils_html import *
17
  from library.utils_prompt import *
18
 
19
- # Get authorized users from environment variable/secret
20
- authorized_users_str = os.environ.get("AUTHORIZED_USER_IDS", "")
21
- AUTHORIZED_USER_IDS = set(authorized_users_str.split(',') if authorized_users_str and authorized_users_str.strip() else [])
22
-
23
-
24
- #Api sdk
25
  OR = OpenRouterAPI()
26
 
27
- # At the top of your script, modify MODEL_PRICING:
28
  MODEL_PRICING = {
29
  "google/gemini-2.0-flash-001": "$0.03",
30
  "gpt-4.1-mini": "$0.07",
@@ -34,29 +28,9 @@ MODEL_PRICING = {
34
  "google/gemini-2.5-flash-preview:thinking": "$0.35",
35
  "gpt-4.1-nano": "$0.02",
36
  "openai/chatgpt-4o-latest": "$0.75",
37
- "meta-llama/llama-4-maverick": "$0.04",
38
- "meta-llama/llama-4-maverick:free": "$0.00" # Added for the free tier
39
  }
40
 
41
- # Define choices and default for unauthenticated users
42
- UNAUTHENTICATED_MODEL_CHOICES = [("Llama 4 Maverick (Free Tier)", "meta-llama/llama-4-maverick:free")]
43
- UNAUTHENTICATED_DEFAULT_MODEL_ID = "meta-llama/llama-4-maverick:free"
44
-
45
- # Your existing default for authenticated users
46
- AUTHENTICATED_DEFAULT_MODEL_ID = "google/gemini-2.0-flash-001"
47
-
48
- # New function to check if current user is authorized
49
- def check_authorization(profile: gr.OAuthProfile | None):
50
- if not AUTHORIZED_USER_IDS: # If the set is empty, no one is authorized by this list
51
- return False
52
- if profile is None:
53
- return False #"Not logged in. Please Login for full access."
54
-
55
- if profile.username in AUTHORIZED_USER_IDS:
56
- return True
57
- else:
58
- return False
59
-
60
  def get_sys_prompt(length="medium", photograph=False):
61
  extra_prompt = ""
62
 
@@ -101,18 +75,6 @@ def get_base_filename(filepath):
101
  filename = os.path.splitext(basename)[0]
102
  return filename
103
 
104
- # Helper function to generate model info markdown
105
- def get_model_info_markdown(model_id, is_authorized):
106
- models_to_search = all_models_list if is_authorized else UNAUTHENTICATED_MODEL_CHOICES
107
- model_name = "Unknown Model"
108
- for name, value in models_to_search:
109
- if value == model_id:
110
- model_name = name
111
- break
112
- cost = MODEL_PRICING.get(model_id, "N/A")
113
- return f"""**Current Model**: {model_name}
114
- **Estimated cost per 100 Images**: {cost}"""
115
-
116
  # Define the Gradio interface
117
  def create_demo():
118
  custom_css = """
@@ -162,8 +124,11 @@ def create_demo():
162
  interactive=False, show_download_button=False,
163
  show_share_button=False, show_fullscreen_button=False,
164
  container=False, elem_id="nml-logo")
 
 
 
165
 
166
- # Define model lists (these will be used by the auth logic)
167
  preferred_models = [
168
  ("Gemini 2.0 Flash (cheap)", "google/gemini-2.0-flash-001"),
169
  ("GPT-4.1 Mini", "gpt-4.1-mini"),
@@ -172,52 +137,106 @@ def create_demo():
172
  ("Gemini 2.5 Pro", "google/gemini-2.5-pro-preview-03-25"),
173
  ("Gemini 2.5 Flash Thinking (Recommended)", "google/gemini-2.5-flash-preview:thinking")
174
  ]
 
175
  additional_models = [
176
  ("GPT-4.1 Nano", "gpt-4.1-nano"),
177
  ("ChatGPT Latest", "openai/chatgpt-4o-latest"),
178
  ("Llama 4 Maverick", "meta-llama/llama-4-maverick")
179
  ]
 
 
180
  all_models_list = preferred_models + additional_models
181
-
182
- # State variables
183
- auth_status_state = gr.State(False) # True if authorized
184
- user_show_all_models_preference_state = gr.State(False) # User's preference for showing all models
185
-
186
  with gr.Row():
 
187
  with gr.Column(scale=1):
188
- upload_button = gr.UploadButton("Click to Upload Images", file_types=["image"], file_count="multiple")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
 
190
  model_choice = gr.Dropdown(
191
- choices=UNAUTHENTICATED_MODEL_CHOICES, # Initial default for unauth
192
- value=UNAUTHENTICATED_DEFAULT_MODEL_ID,
193
  label="Select Model",
194
- interactive=True
195
  )
196
 
197
  length_choice = gr.Radio(
198
  choices=["short", "medium", "long"],
199
- label="Response Length", value="medium",
 
200
  info="Short: max 130 chars | Medium: 250-300 chars | Long: max 450 chars"
201
  )
202
 
203
- # Accordion for advanced settings - visibility controlled by auth
204
- with gr.Accordion("Advanced Settings", open=False, visible=False) as advanced_settings_accordion:
205
- show_all_models_checkbox = gr.Checkbox(
206
  label="Show Additional Models",
207
- value=False, # Will be updated by auth logic
208
- info="Display additional model options in the dropdown above",
209
- interactive=False # Will be updated by auth logic
210
  )
 
211
  content_type = gr.Radio(
212
  choices=["Museum Object", "Photography"],
213
- label="Content Type", value="Museum Object"
 
214
  )
215
 
216
- initial_model_info = get_model_info_markdown(UNAUTHENTICATED_DEFAULT_MODEL_ID, False)
217
- model_info = gr.Markdown(initial_model_info, elem_id="model-info-display")
 
 
 
 
 
 
 
 
 
 
218
 
219
  gr.Markdown("### Uploaded Images")
220
- input_gallery = gr.Gallery(label="Uploaded Image Previews", columns=3, height=150, object_fit="contain", show_label=False)
 
 
 
221
  analyze_button = gr.Button("Generate Alt-Text", variant="primary", size="lg")
222
  image_state = gr.State([])
223
  filename_state = gr.State([])
@@ -225,98 +244,83 @@ def create_demo():
225
 
226
  # Right column: Display area
227
  with gr.Column(scale=2):
228
- # right column UI: current_image, navigation, analysis_text
229
  current_image = gr.Image(
230
- label="Current Image", type="filepath", elem_id="current-image-display",
231
- show_fullscreen_button=True, show_download_button=False,
232
- show_share_button=False, show_label=False
 
 
 
 
233
  )
 
234
  with gr.Row():
235
  prev_button = gr.Button("← Previous", size="sm")
236
  image_counter = gr.Markdown("0 of 0", elem_id="image-counter")
237
  next_button = gr.Button("Next →", size="sm")
 
238
  gr.Markdown("### Generated Alt-text")
239
  analysis_text = gr.Textbox(
240
- label="Generated Text", value="Upload images and click 'Generate Alt-Text'.",
 
241
  lines=6, max_lines=10, interactive=True, show_label=False
242
  )
243
  current_index = gr.State(0)
244
  all_images = gr.State([])
245
  all_results = gr.State([])
246
-
247
- # Function to update UI based on authentication status (called on demo.load)
248
- def handle_auth_change_and_ui_setup(profile: gr.OAuthProfile | None, current_user_pref_show_all: bool):
249
- is_authorized = check_authorization(profile)
 
 
250
 
251
- if is_authorized:
252
- # Authorized User
253
- current_choices = list(all_models_list) if current_user_pref_show_all else list(preferred_models)
254
- current_value = AUTHENTICATED_DEFAULT_MODEL_ID # Reset to default for authed user
255
- # You could add logic here to try and preserve model_choice.value if it's valid in current_choices
256
-
257
- model_dropdown_update = gr.Dropdown.update(choices=current_choices, value=current_value, label="Select Model", interactive=True)
258
- accordion_update = gr.Accordion.update(visible=True)
259
- model_info_text_update = get_model_info_markdown(current_value, True)
260
- show_all_checkbox_update = gr.Checkbox.update(value=current_user_pref_show_all, interactive=True)
261
  else:
262
- # Unauthenticated User
263
- model_dropdown_update = gr.Dropdown.update(choices=UNAUTHENTICATED_MODEL_CHOICES, value=UNAUTHENTICATED_DEFAULT_MODEL_ID, label="Select Model (Free Tier)", interactive=True)
264
- accordion_update = gr.Accordion.update(visible=False)
265
- model_info_text_update = get_model_info_markdown(UNAUTHENTICATED_DEFAULT_MODEL_ID, False)
266
- show_all_checkbox_update = gr.Checkbox.update(value=False, interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
- return is_authorized, model_dropdown_update, accordion_update, model_info_text_update, show_all_checkbox_update
269
-
270
- demo.load(
271
- fn=handle_auth_change_and_ui_setup,
272
- inputs=[user_show_all_models_preference_state], # Pass the state that holds user's preference
273
- outputs=[
274
- auth_status_state,
275
- model_choice,
276
- advanced_settings_accordion,
277
- model_info,
278
- show_all_models_checkbox
279
- ]
280
- )
281
-
282
- # Handle "Show Additional Models" checkbox change
283
- def persist_preference_and_toggle_models_visibility(show_all_checkbox_val: bool, current_model_id: str, is_authorized: bool):
284
- if not is_authorized: # Should not be triggered if checkbox is not interactive
285
- mdl_choice_update = gr.Dropdown.update(choices=UNAUTHENTICATED_MODEL_CHOICES, value=UNAUTHENTICATED_DEFAULT_MODEL_ID)
286
- return show_all_checkbox_val, mdl_choice_update # Persist the (likely False) checkbox value
287
-
288
- # Authorized user
289
- new_choices = list(all_models_list) if show_all_checkbox_val else list(preferred_models)
290
 
291
- new_model_value = current_model_id
292
- if not any(val == current_model_id for _, val in new_choices): # If current model not in new list
293
- new_model_value = AUTHENTICATED_DEFAULT_MODEL_ID # Revert to default
294
- if not any(val == new_model_value for _, val in new_choices): # If default not in new list (edge case)
295
- new_model_value = new_choices[0][1] if new_choices else None
296
-
297
-
298
- mdl_choice_update = gr.Dropdown.update(choices=new_choices, value=new_model_value)
299
- return show_all_checkbox_val, mdl_choice_update # Return new preference and dropdown update
300
-
301
- show_all_models_checkbox.change(
302
- fn=persist_preference_and_toggle_models_visibility,
303
- inputs=[show_all_models_checkbox, model_choice, auth_status_state],
304
- outputs=[user_show_all_models_preference_state, model_choice]
305
  )
306
-
307
- # Update model info when model selection changes
308
- def update_model_info_display(selected_model_id: str, is_authorized: bool):
309
- return get_model_info_markdown(selected_model_id, is_authorized)
310
-
311
  model_choice.change(
312
- fn=update_model_info_display,
313
- inputs=[model_choice, auth_status_state],
314
  outputs=[model_info]
315
  )
316
 
317
  # Handle file uploads
318
  def handle_upload(files, current_paths, current_filenames):
319
- # ... (your existing function, no changes needed here)
320
  file_paths = []
321
  file_names = []
322
  if files:
@@ -325,7 +329,6 @@ def create_demo():
325
  file_names.append(get_base_filename(file.name))
326
  return file_paths, file_paths, file_names, 0, None, "0 of 0", "Upload images and click 'Generate Alt-Text'."
327
 
328
-
329
  upload_button.upload(
330
  fn=handle_upload,
331
  inputs=[upload_button, image_state, filename_state],
@@ -334,8 +337,7 @@ def create_demo():
334
  )
335
 
336
  # Analyze images
337
- def analyze_images(image_paths, current_model_choice_id, length_choice, filenames, content_type_choice):
338
- # Note: current_model_choice_id will be correctly set based on auth status by the UI
339
  if not image_paths:
340
  return [], [], 0, None, "0 of 0", "No images uploaded to analyze.", None
341
 
@@ -348,10 +350,9 @@ def create_demo():
348
  image_id = filenames[i] if i < len(filenames) and filenames[i] else f"Image_{i+1}_{os.path.basename(image_path)}"
349
  try:
350
  img = Image.open(image_path)
351
- prompt0 = prompt_new() # Assuming prompt_new() is defined in your utils
352
- model_name = current_model_choice_id
353
- client_to_use = OR # Ensure OR can handle "meta-llama/llama-4-maverick:free"
354
- # Or add logic here: if model_name == UNAUTHENTICATED_DEFAULT_MODEL_ID: client_to_use = DifferentClient()
355
 
356
  result = client_to_use.generate_caption(
357
  img, model=model_name, max_image_size=512,
@@ -430,7 +431,7 @@ def create_demo():
430
  """)
431
 
432
  return demo
433
-
434
  # Launch the app
435
  if __name__ == "__main__":
436
  app = create_demo()
 
16
  from library.utils_html import *
17
  from library.utils_prompt import *
18
 
 
 
 
 
 
 
19
  OR = OpenRouterAPI()
20
 
21
+ # Define model pricing information (approximate costs per 100 image API calls)
22
  MODEL_PRICING = {
23
  "google/gemini-2.0-flash-001": "$0.03",
24
  "gpt-4.1-mini": "$0.07",
 
28
  "google/gemini-2.5-flash-preview:thinking": "$0.35",
29
  "gpt-4.1-nano": "$0.02",
30
  "openai/chatgpt-4o-latest": "$0.75",
31
+ "meta-llama/llama-4-maverick": "$0.04"
 
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  def get_sys_prompt(length="medium", photograph=False):
35
  extra_prompt = ""
36
 
 
75
  filename = os.path.splitext(basename)[0]
76
  return filename
77
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  # Define the Gradio interface
79
  def create_demo():
80
  custom_css = """
 
124
  interactive=False, show_download_button=False,
125
  show_share_button=False, show_fullscreen_button=False,
126
  container=False, elem_id="nml-logo")
127
+
128
+ # Store model choices and state
129
+ show_all_models_state = gr.State(False)
130
 
131
+ # Define preferred and additional models directly in the function
132
  preferred_models = [
133
  ("Gemini 2.0 Flash (cheap)", "google/gemini-2.0-flash-001"),
134
  ("GPT-4.1 Mini", "gpt-4.1-mini"),
 
137
  ("Gemini 2.5 Pro", "google/gemini-2.5-pro-preview-03-25"),
138
  ("Gemini 2.5 Flash Thinking (Recommended)", "google/gemini-2.5-flash-preview:thinking")
139
  ]
140
+
141
  additional_models = [
142
  ("GPT-4.1 Nano", "gpt-4.1-nano"),
143
  ("ChatGPT Latest", "openai/chatgpt-4o-latest"),
144
  ("Llama 4 Maverick", "meta-llama/llama-4-maverick")
145
  ]
146
+
147
+ # Calculate all models once
148
  all_models_list = preferred_models + additional_models
149
+
150
+ # Default model value
151
+ default_model = "google/gemini-2.0-flash-001"
152
+
 
153
  with gr.Row():
154
+ # Left column: Controls and uploads
155
  with gr.Column(scale=1):
156
+
157
+ ###########################################################################################
158
+
159
+ # Function to check authorization
160
+ def check_authorization(profile: gr.OAuthProfile | None):
161
+ if profile is None:
162
+ return False, "Not logged in. Please Login for full access.", False
163
+
164
+ is_authorized = profile.username in AUTHORIZED_USER_IDS
165
+ return is_authorized
166
+
167
+ #new bit with authroisation
168
+ # define it false to begin with
169
+ auth_state = gr.State(False)
170
+
171
+ demo.load(check_authorization, inputs=None, outputs=[auth_state])
172
+
173
+ if auth_state == False:
174
+ # free version - yeah baby
175
+ login_button = gr.LoginButton()
176
+
177
+ # Define preferred and additional models directly in the function
178
+ preferred_models = [
179
+ ("llama-4-maverick (free)", "meta-llama/llama-4-maverick:free")
180
+ ]
181
+
182
+ all_models_list = preferred_models
183
+
184
+ # Default model value
185
+ default_model = preferred_models[0]
186
+
187
+ ################################## normal stuff below
188
+ upload_button = gr.UploadButton(
189
+ "Click to Upload Images",
190
+ file_types=["image"],
191
+ file_count="multiple"
192
+ )
193
 
194
+ # Model dropdown
195
  model_choice = gr.Dropdown(
196
+ choices=preferred_models,
 
197
  label="Select Model",
198
+ value=default_model
199
  )
200
 
201
  length_choice = gr.Radio(
202
  choices=["short", "medium", "long"],
203
+ label="Response Length",
204
+ value="medium",
205
  info="Short: max 130 chars | Medium: 250-300 chars | Long: max 450 chars"
206
  )
207
 
208
+ # Advanced settings accordion
209
+ with gr.Accordion("Advanced Settings", open=False):
210
+ show_all_models = gr.Checkbox(
211
  label="Show Additional Models",
212
+ value=False,
213
+ info="Display additional model options in the dropdown above"
 
214
  )
215
+
216
  content_type = gr.Radio(
217
  choices=["Museum Object", "Photography"],
218
+ label="Content Type",
219
+ value="Museum Object"
220
  )
221
 
222
+ # Find the default model's display name
223
+ default_model_name = "Unknown Model"
224
+ for name, value in preferred_models:
225
+ if value == default_model:
226
+ default_model_name = name
227
+ break
228
+
229
+ model_info = gr.Markdown(
230
+ f"""**Current Model**: {default_model_name}
231
+ **Estimated cost per 100 Images**: {MODEL_PRICING[default_model]}""",
232
+ elem_id="model-info-display"
233
+ )
234
 
235
  gr.Markdown("### Uploaded Images")
236
+ input_gallery = gr.Gallery(
237
+ label="Uploaded Image Previews", columns=3, height=150,
238
+ object_fit="contain", show_label=False
239
+ )
240
  analyze_button = gr.Button("Generate Alt-Text", variant="primary", size="lg")
241
  image_state = gr.State([])
242
  filename_state = gr.State([])
 
244
 
245
  # Right column: Display area
246
  with gr.Column(scale=2):
 
247
  current_image = gr.Image(
248
+ label="Current Image",
249
+ type="filepath",
250
+ elem_id="current-image-display",
251
+ show_fullscreen_button=True,
252
+ show_download_button=False,
253
+ show_share_button=False,
254
+ show_label=False
255
  )
256
+
257
  with gr.Row():
258
  prev_button = gr.Button("← Previous", size="sm")
259
  image_counter = gr.Markdown("0 of 0", elem_id="image-counter")
260
  next_button = gr.Button("Next →", size="sm")
261
+
262
  gr.Markdown("### Generated Alt-text")
263
  analysis_text = gr.Textbox(
264
+ label="Generated Text",
265
+ value="Upload images and click 'Generate Alt-Text'.",
266
  lines=6, max_lines=10, interactive=True, show_label=False
267
  )
268
  current_index = gr.State(0)
269
  all_images = gr.State([])
270
  all_results = gr.State([])
271
+
272
+ # Handle checkbox change to update model dropdown - modern version
273
+ def toggle_models(show_all, current_model):
274
+ # Make a fresh copy of the models lists to avoid any reference issues
275
+ preferred_choices = list(preferred_models)
276
+ all_choices = list(all_models_list)
277
 
278
+ if show_all:
279
+ # When showing all models, use the fresh copy of all models
280
+ return gr.Dropdown(choices=all_choices, value=current_model)
 
 
 
 
 
 
 
281
  else:
282
+ # Check if current model is in preferred models list
283
+ preferred_values = [value for _, value in preferred_choices]
284
+
285
+ if current_model in preferred_values:
286
+ # Keep the current model if it's in preferred models
287
+ return gr.Dropdown(choices=preferred_choices, value=current_model)
288
+ else:
289
+ # Reset to default model if current model is not in preferred models
290
+ return gr.Dropdown(choices=preferred_choices, value=default_model)
291
+
292
+ # Update model info when model selection changes
293
+ def update_model_info(model_value):
294
+ # Find display name
295
+ model_name = "Unknown Model"
296
+ for name, value in all_models_list:
297
+ if value == model_value:
298
+ model_name = name
299
+ break
300
 
301
+ # Get cost
302
+ cost = MODEL_PRICING.get(model_value, "Unknown")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
 
304
+ # Create markdown
305
+ return f"""**Current Model**: {model_name}
306
+ **Estimated cost per 100 Images**: {cost}"""
307
+
308
+ # Connect checkbox to toggle model choices
309
+ show_all_models.change(
310
+ fn=toggle_models,
311
+ inputs=[show_all_models, model_choice],
312
+ outputs=[model_choice]
 
 
 
 
 
313
  )
314
+
315
+ # Connect model selection to update info
 
 
 
316
  model_choice.change(
317
+ fn=update_model_info,
318
+ inputs=[model_choice],
319
  outputs=[model_info]
320
  )
321
 
322
  # Handle file uploads
323
  def handle_upload(files, current_paths, current_filenames):
 
324
  file_paths = []
325
  file_names = []
326
  if files:
 
329
  file_names.append(get_base_filename(file.name))
330
  return file_paths, file_paths, file_names, 0, None, "0 of 0", "Upload images and click 'Generate Alt-Text'."
331
 
 
332
  upload_button.upload(
333
  fn=handle_upload,
334
  inputs=[upload_button, image_state, filename_state],
 
337
  )
338
 
339
  # Analyze images
340
+ def analyze_images(image_paths, model_choice, length_choice, filenames, content_type_choice):
 
341
  if not image_paths:
342
  return [], [], 0, None, "0 of 0", "No images uploaded to analyze.", None
343
 
 
350
  image_id = filenames[i] if i < len(filenames) and filenames[i] else f"Image_{i+1}_{os.path.basename(image_path)}"
351
  try:
352
  img = Image.open(image_path)
353
+ prompt0 = prompt_new()
354
+ model_name = model_choice
355
+ client_to_use = OR # Default client
 
356
 
357
  result = client_to_use.generate_caption(
358
  img, model=model_name, max_image_size=512,
 
431
  """)
432
 
433
  return demo
434
+
435
  # Launch the app
436
  if __name__ == "__main__":
437
  app = create_demo()