Afsha001 commited on
Commit
a012a80
Β·
verified Β·
1 Parent(s): eb27bae

update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -44
app.py CHANGED
@@ -16,7 +16,7 @@ from sklearn.preprocessing import normalize
16
  st.set_page_config(
17
  page_title="Image Captioning Refinement Fusion System",
18
  layout="wide",
19
- initial_sidebar_state="expanded"
20
  )
21
 
22
  JINA_KEY = os.environ.get("JINA_KEY", "")
@@ -87,20 +87,6 @@ def image_to_data_uri(image: Image.Image) -> str:
87
  b64 = base64.b64encode(raw).decode()
88
  return f"data:image/jpeg;base64,{b64}"
89
 
90
- # ============================================================================
91
- # STEP 1 β€” FLORENCE-2-LARGE: 5 DISTINCT CAPTION APPROACHES
92
- #
93
- # Cap 1: <CAPTION> greedy
94
- # β†’ single concise sentence, primary subject only
95
- # Cap 2: <CAPTION> sampling temp=1.0
96
- # β†’ alt-text accessibility style, concise but different phrasing
97
- # Cap 3: <DETAILED_CAPTION> temp=0.7
98
- # β†’ paragraph describing foreground, background, colors
99
- # Cap 4: <DETAILED_CAPTION> temp=1.1
100
- # β†’ focuses on mood, atmosphere, implied action
101
- # Cap 5: <MORE_DETAILED_CAPTION> temp=0.8
102
- # β†’ exhaustive breakdown of every visible element
103
- # ============================================================================
104
  def generate_captions_florence(image: Image.Image, florence_proc, florence_mod) -> list:
105
 
106
  captions = []
@@ -246,25 +232,25 @@ def majority_voting(captions, itm, jina, cosine) -> tuple:
246
  def fuse_captions(cap1: str, cap2: str, qwen_tok, qwen_mod) -> str:
247
 
248
  system_prompt = (
249
- "You write image captions. "
250
  "You will receive two captions of the same image. "
251
- "Your job is to combine them into one detailed caption. "
252
- "Include ALL specific details you find: "
253
- "the clothing colors and style of each person, "
254
  "what each person looks like and what they are doing, "
255
- "the objects and surroundings visible around them, "
256
- "and the setting or background of the scene. "
257
- "Write 5 to 6 sentences. Use simple, clear, everyday words. "
258
- "Do NOT summarize or shorten β€” keep every specific detail. "
259
- "Only include what is clearly visible. "
260
  "Return ONLY the caption, nothing else."
261
  )
262
 
263
  user_prompt = (
264
  f"Caption A: {cap1}\n"
265
  f"Caption B: {cap2}\n\n"
266
- "Write a detailed caption that includes all the clothing, "
267
- "people, objects and background in details:"
268
  )
269
 
270
  try:
@@ -282,8 +268,11 @@ def fuse_captions(cap1: str, cap2: str, qwen_tok, qwen_mod) -> str:
282
  with torch.no_grad():
283
  generated_ids = qwen_mod.generate(
284
  **model_inputs,
285
- max_new_tokens=120,
286
- do_sample=False
 
 
 
287
  )
288
 
289
  output_ids = generated_ids[0][len(model_inputs.input_ids[0]):]
@@ -293,6 +282,16 @@ def fuse_captions(cap1: str, cap2: str, qwen_tok, qwen_mod) -> str:
293
  if fused.lower().startswith(prefix.lower()):
294
  fused = fused[len(prefix):].strip()
295
 
 
 
 
 
 
 
 
 
 
 
296
  return fused if fused else cap1
297
 
298
  except Exception as e:
@@ -340,10 +339,6 @@ def compute_caption_quality(image, final_caption, blip_proc, blip_itm) -> tuple:
340
  avg_score = round((itm_score + cosine_score) / 2, 4)
341
  return avg_score, round(itm_score, 4), round(cosine_score, 4)
342
 
343
- # ============================================================================
344
- # GAUGE β€” updated to match reference style
345
- # Bright saturated zone colors, sharp black needle, clean arc, no dark shades
346
- # ============================================================================
347
  def render_gauge(score, itm, cosine, placeholder):
348
 
349
  if score >= 0.75:
@@ -421,9 +416,7 @@ def render_gauge(score, itm, cosine, placeholder):
421
  unsafe_allow_html=True
422
  )
423
 
424
- # ============================================================================
425
- # SIDEBAR β€” pipeline steps + live accuracy section (session_state)
426
- # ============================================================================
427
  with st.sidebar:
428
  st.title("Image Captioning Refinement Fusion")
429
  st.markdown("---")
@@ -450,8 +443,6 @@ Caption fusion
450
  st.markdown("---")
451
  st.markdown("**Local:** Florence-2, BLIP ITM, Qwen2.5")
452
  st.markdown("**API:** Jina")
453
-
454
- # ── accuracy section ──────────────
455
  st.markdown("---")
456
  st.markdown("### Caption Quality Metrics")
457
  st.markdown("""
@@ -464,9 +455,7 @@ Measures embedding distance
464
  between image and caption.
465
  """)
466
 
467
- # ============================================================================
468
- # MAIN UI
469
- # ============================================================================
470
  st.title("Image Captioning Refinement Fusion System")
471
  st.markdown("Upload an image to generate a refined, grounded caption.")
472
  st.markdown("---")
@@ -499,7 +488,9 @@ if uploaded_file is not None:
499
  status = st.empty()
500
 
501
  status.info("Step 1/6: Generating captions with Florence-2-Large...")
502
- captions = generate_captions_florence(input_image, florence_proc, florence_mod)
 
 
503
  progress.progress(16)
504
 
505
  with st.expander("5 Generated Captions", expanded=True):
@@ -507,7 +498,9 @@ if uploaded_file is not None:
507
  st.write(f"**{i+1}.** {cap}")
508
 
509
  status.info("Step 2/6: Computing BLIP ITM scores...")
510
- itm_scores = compute_itm_scores(input_image, captions, blip_proc, blip_itm)
 
 
511
  progress.progress(32)
512
 
513
  status.info("Step 3/6: Computing Jina Reranker scores...")
@@ -515,7 +508,9 @@ if uploaded_file is not None:
515
  progress.progress(50)
516
 
517
  status.info("Step 4/6: Computing Cosine Similarity scores...")
518
- cosine_scores = compute_cosine_scores(input_image, captions, blip_proc, blip_itm)
 
 
519
  progress.progress(66)
520
 
521
  scores_df = pd.DataFrame({
@@ -560,7 +555,6 @@ if uploaded_file is not None:
560
  input_image, final, blip_proc, blip_itm
561
  )
562
 
563
- # Store in session_state so sidebar updates on rerender
564
  st.session_state.avg_score = avg_score
565
  st.session_state.itm_q = itm_q
566
  st.session_state.cosine_q = cosine_q
 
16
  st.set_page_config(
17
  page_title="Image Captioning Refinement Fusion System",
18
  layout="wide",
19
+ initial_sidebar_bar="expanded"
20
  )
21
 
22
  JINA_KEY = os.environ.get("JINA_KEY", "")
 
87
  b64 = base64.b64encode(raw).decode()
88
  return f"data:image/jpeg;base64,{b64}"
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  def generate_captions_florence(image: Image.Image, florence_proc, florence_mod) -> list:
91
 
92
  captions = []
 
232
  def fuse_captions(cap1: str, cap2: str, qwen_tok, qwen_mod) -> str:
233
 
234
  system_prompt = (
235
+ "You write detailed image captions. "
236
  "You will receive two captions of the same image. "
237
+ "Combine them into one complete, detailed caption. "
238
+ "Include ALL visible details: "
239
+ "clothing colors and style of each person, "
240
  "what each person looks like and what they are doing, "
241
+ "objects and surroundings visible in the scene, "
242
+ "and the background or setting. "
243
+ "Write 3 to 4 complete sentences. "
244
+ "Always finish the last sentence properly β€” never leave it incomplete. "
245
+ "Use simple, clear, everyday words. "
246
  "Return ONLY the caption, nothing else."
247
  )
248
 
249
  user_prompt = (
250
  f"Caption A: {cap1}\n"
251
  f"Caption B: {cap2}\n\n"
252
+ "Write a detailed caption covering all clothing, "
253
+ "people, objects and background:"
254
  )
255
 
256
  try:
 
268
  with torch.no_grad():
269
  generated_ids = qwen_mod.generate(
270
  **model_inputs,
271
+ max_new_tokens = 220,
272
+ do_sample = False,
273
+ repetition_penalty = 1.1,
274
+ eos_token_id = qwen_tok.eos_token_id,
275
+ pad_token_id = qwen_tok.eos_token_id
276
  )
277
 
278
  output_ids = generated_ids[0][len(model_inputs.input_ids[0]):]
 
282
  if fused.lower().startswith(prefix.lower()):
283
  fused = fused[len(prefix):].strip()
284
 
285
+ # Safety β€” trim to last complete sentence if still cut off
286
+ if fused and not fused.endswith((".", "!", "?")):
287
+ last_stop = max(
288
+ fused.rfind("."),
289
+ fused.rfind("!"),
290
+ fused.rfind("?")
291
+ )
292
+ if last_stop > len(fused) // 2:
293
+ fused = fused[:last_stop + 1].strip()
294
+
295
  return fused if fused else cap1
296
 
297
  except Exception as e:
 
339
  avg_score = round((itm_score + cosine_score) / 2, 4)
340
  return avg_score, round(itm_score, 4), round(cosine_score, 4)
341
 
 
 
 
 
342
  def render_gauge(score, itm, cosine, placeholder):
343
 
344
  if score >= 0.75:
 
416
  unsafe_allow_html=True
417
  )
418
 
419
+ # ── SIDEBAR ────────────────────────────────────────────────────────
 
 
420
  with st.sidebar:
421
  st.title("Image Captioning Refinement Fusion")
422
  st.markdown("---")
 
443
  st.markdown("---")
444
  st.markdown("**Local:** Florence-2, BLIP ITM, Qwen2.5")
445
  st.markdown("**API:** Jina")
 
 
446
  st.markdown("---")
447
  st.markdown("### Caption Quality Metrics")
448
  st.markdown("""
 
455
  between image and caption.
456
  """)
457
 
458
+ # ── MAIN UI ────────────────────────────────────────────────────────
 
 
459
  st.title("Image Captioning Refinement Fusion System")
460
  st.markdown("Upload an image to generate a refined, grounded caption.")
461
  st.markdown("---")
 
488
  status = st.empty()
489
 
490
  status.info("Step 1/6: Generating captions with Florence-2-Large...")
491
+ captions = generate_captions_florence(
492
+ input_image, florence_proc, florence_mod
493
+ )
494
  progress.progress(16)
495
 
496
  with st.expander("5 Generated Captions", expanded=True):
 
498
  st.write(f"**{i+1}.** {cap}")
499
 
500
  status.info("Step 2/6: Computing BLIP ITM scores...")
501
+ itm_scores = compute_itm_scores(
502
+ input_image, captions, blip_proc, blip_itm
503
+ )
504
  progress.progress(32)
505
 
506
  status.info("Step 3/6: Computing Jina Reranker scores...")
 
508
  progress.progress(50)
509
 
510
  status.info("Step 4/6: Computing Cosine Similarity scores...")
511
+ cosine_scores = compute_cosine_scores(
512
+ input_image, captions, blip_proc, blip_itm
513
+ )
514
  progress.progress(66)
515
 
516
  scores_df = pd.DataFrame({
 
555
  input_image, final, blip_proc, blip_itm
556
  )
557
 
 
558
  st.session_state.avg_score = avg_score
559
  st.session_state.itm_q = itm_q
560
  st.session_state.cosine_q = cosine_q