VigneshVS2005 commited on
Commit
f8dd93d
·
1 Parent(s): ae18450

Revamp explanation generation in YOLO model using FLAN-T5, and add Florence-2 Fusion model

Browse files
ai_router.py CHANGED
@@ -4,6 +4,7 @@ from models.gemini_vision import gemini_vision_answer
4
  from models.groq_vision import groq_vision_answer
5
  from models.blip_yolo_model import blip_yolo_answer
6
  from models.hf_boss_api import hf_boss_answer
 
7
 
8
  try:
9
  from deep_translator import GoogleTranslator
@@ -30,6 +31,8 @@ def route_model(model_choice, image, question, lang="en"):
30
  cap, ans, exp = groq_vision_answer(image, question, lang)
31
  elif model_choice == "hf_boss":
32
  cap, ans, exp = hf_boss_answer(image, question, lang)
 
 
33
  else:
34
  cap, ans, exp = "Unknown", "Invalid", "Invalid"
35
 
 
4
  from models.groq_vision import groq_vision_answer
5
  from models.blip_yolo_model import blip_yolo_answer
6
  from models.hf_boss_api import hf_boss_answer
7
+ from models.florence_fusion_model import florence_answer
8
 
9
  try:
10
  from deep_translator import GoogleTranslator
 
31
  cap, ans, exp = groq_vision_answer(image, question, lang)
32
  elif model_choice == "hf_boss":
33
  cap, ans, exp = hf_boss_answer(image, question, lang)
34
+ elif model_choice == "florence":
35
+ cap, ans, exp = florence_answer(image, question, lang)
36
  else:
37
  cap, ans, exp = "Unknown", "Invalid", "Invalid"
38
 
models/blip_yolo_model.py CHANGED
@@ -1,15 +1,24 @@
1
  import torch
 
2
  from models.blip_model import processor_cap, model_cap, processor_vqa, model_vqa
3
  from config import DEVICE
4
 
5
  try:
6
  from ultralytics import YOLO
7
- # Setting verbose=False to minimize logs
8
  yolo_model = YOLO("yolov8n.pt")
9
  except Exception as e:
10
  print("YOLO initialization failed:", e)
11
  yolo_model = None
12
 
 
 
 
 
 
 
 
 
 
13
  def blip_yolo_answer(image, question, lang="en"):
14
  objects_detected = []
15
  if yolo_model is not None:
@@ -21,11 +30,9 @@ def blip_yolo_answer(image, question, lang="en"):
21
  except:
22
  pass
23
 
24
- det_str = "None"
25
- if objects_detected:
26
- unique_objs = list(set(objects_detected))
27
- counts = {obj: objects_detected.count(obj) for obj in unique_objs}
28
- det_str = ", ".join([f"{count} {obj}(s)" for obj, count in counts.items()])
29
 
30
  if image.mode != "RGB":
31
  image = image.convert("RGB")
@@ -35,16 +42,24 @@ def blip_yolo_answer(image, question, lang="en"):
35
  cap_output = model_cap.generate(**cap_inputs, max_new_tokens=30)
36
  caption = processor_cap.decode(cap_output[0], skip_special_tokens=True).strip()
37
 
38
- if objects_detected:
39
- caption = f"YOLO objects: {det_str}. General scene: {caption}"
40
-
41
- # Feed YOLO logic directly into BLIP reasoning via question parameter
42
- context_question = f"Given objects {det_str}, {question}" if objects_detected else question
43
  vqa_inputs = processor_vqa(images=image, text=context_question, return_tensors="pt").to(DEVICE)
44
  with torch.no_grad():
45
  vqa_output = model_vqa.generate(**vqa_inputs, max_new_tokens=20)
46
  answer = processor_vqa.decode(vqa_output[0], skip_special_tokens=True).strip()
47
 
48
- explanation = f"YOLO precisely identified [{det_str}]. BLIP synthesized the final reasoning."
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  return caption, answer, explanation
 
1
  import torch
2
+ from transformers import T5Tokenizer, T5ForConditionalGeneration
3
  from models.blip_model import processor_cap, model_cap, processor_vqa, model_vqa
4
  from config import DEVICE
5
 
6
  try:
7
  from ultralytics import YOLO
 
8
  yolo_model = YOLO("yolov8n.pt")
9
  except Exception as e:
10
  print("YOLO initialization failed:", e)
11
  yolo_model = None
12
 
13
+ # Initialize FLAN-T5 specifically to synthesize intelligent explanations locally
14
+ try:
15
+ tokenizer_t5 = T5Tokenizer.from_pretrained("google/flan-t5-base")
16
+ model_t5 = T5ForConditionalGeneration.from_pretrained("google/flan-t5-base").to(DEVICE)
17
+ model_t5.eval()
18
+ except Exception as e:
19
+ tokenizer_t5 = None
20
+ model_t5 = None
21
+
22
  def blip_yolo_answer(image, question, lang="en"):
23
  objects_detected = []
24
  if yolo_model is not None:
 
30
  except:
31
  pass
32
 
33
+ unique_objs = list(set(objects_detected))
34
+ counts = {obj: objects_detected.count(obj) for obj in unique_objs}
35
+ det_str = ", ".join([f"{count} {obj}(s)" for obj, count in counts.items()]) if objects_detected else "no distinct YOLO objects"
 
 
36
 
37
  if image.mode != "RGB":
38
  image = image.convert("RGB")
 
42
  cap_output = model_cap.generate(**cap_inputs, max_new_tokens=30)
43
  caption = processor_cap.decode(cap_output[0], skip_special_tokens=True).strip()
44
 
45
+ context_question = f"The image features {caption} and {det_str}. {question}"
 
 
 
 
46
  vqa_inputs = processor_vqa(images=image, text=context_question, return_tensors="pt").to(DEVICE)
47
  with torch.no_grad():
48
  vqa_output = model_vqa.generate(**vqa_inputs, max_new_tokens=20)
49
  answer = processor_vqa.decode(vqa_output[0], skip_special_tokens=True).strip()
50
 
51
+ if model_t5 is not None:
52
+ prompt = f"Explain logically why the answer to the question '{question}' is '{answer}', knowing the scene is {caption} and precisely contains {det_str}. Be concise and logical."
53
+ input_ids = tokenizer_t5(prompt, return_tensors="pt").input_ids.to(DEVICE)
54
+ with torch.no_grad():
55
+ out = model_t5.generate(input_ids, max_new_tokens=50)
56
+ explanation = tokenizer_t5.decode(out[0], skip_special_tokens=True)
57
+ # Capitalize first letter strictly
58
+ explanation = explanation[0].upper() + explanation[1:] if len(explanation) > 0 else explanation
59
+ else:
60
+ explanation = f"The visual structure shows {caption} alongside {det_str}, directly leading to the conclusion that the answer is {answer}."
61
+
62
+ if objects_detected:
63
+ caption = f"YOLO found: {det_str}. Scene: {caption}"
64
 
65
  return caption, answer, explanation
models/florence_fusion_model.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from transformers import AutoProcessor, AutoModelForCausalLM
3
+ from config import DEVICE
4
+ import gc
5
+
6
+ processor_florence = None
7
+ model_florence = None
8
+
9
+ def load_florence():
10
+ global processor_florence, model_florence
11
+ if model_florence is not None:
12
+ return
13
+ try:
14
+ processor_florence = AutoProcessor.from_pretrained("microsoft/Florence-2-base-ft", trust_remote_code=True)
15
+ model_florence = AutoModelForCausalLM.from_pretrained("microsoft/Florence-2-base-ft", trust_remote_code=True).to(DEVICE)
16
+ model_florence.eval()
17
+ except Exception as e:
18
+ print("Florence-2 failed to load:", e)
19
+
20
+ def florence_answer(image, question, lang="en"):
21
+ load_florence()
22
+ if model_florence is None:
23
+ return "Server Error", "Florence-2 Not Loaded", "The model ran out of memory or failed to load on the Hugging Face space."
24
+
25
+ if image.mode != "RGB":
26
+ image = image.convert("RGB")
27
+
28
+ def run_task(task_prompt, text_input=None):
29
+ prompt = task_prompt if text_input is None else task_prompt + text_input
30
+ inputs = processor_florence(text=prompt, images=image, return_tensors="pt").to(DEVICE)
31
+ with torch.no_grad():
32
+ generated_ids = model_florence.generate(
33
+ input_ids=inputs["input_ids"],
34
+ pixel_values=inputs["pixel_values"],
35
+ max_new_tokens=100,
36
+ num_beams=3
37
+ )
38
+ generated_text = processor_florence.batch_decode(generated_ids, skip_special_tokens=False)[0]
39
+ parsed = processor_florence.post_process_generation(generated_text, task=task_prompt, image_size=(image.width, image.height))
40
+ return parsed[task_prompt]
41
+
42
+ try:
43
+ # Step 1: Detailed Captioning
44
+ caption = run_task("<MORE_DETAILED_CAPTION>")
45
+
46
+ # Step 2: VQA Answering
47
+ answer = run_task("<VQA>", question)
48
+
49
+ # Step 3: Explanation Logic
50
+ # Florence-2 dense captions act as a perfect contextual reasoning base
51
+ explanation = f"Florence-2 performed a massive deep visual scan, identifying: '{caption}'. Because of these precise extracted contextual elements, the model deduced the answer is {answer}."
52
+
53
+ return caption, answer, explanation
54
+ except Exception as e:
55
+ return "Florence API Error", "Execution Crashed", repr(e)
static/app.js CHANGED
@@ -2,7 +2,7 @@
2
  let appState = {
3
  username: '',
4
  logs: [],
5
- stats: { total: 0, local: 0, yolo: 0, gemini: 0, groq: 0, hf_boss: 0 },
6
  geminiEnabled: true
7
  };
8
 
@@ -358,6 +358,7 @@ async function fetchLogs() {
358
  appState.stats.gemini = appState.logs.filter(l => ['gemini', 'external'].includes(l.model.toLowerCase())).length;
359
  appState.stats.groq = appState.logs.filter(l => l.model.toLowerCase().includes('groq')).length;
360
  appState.stats.hf_boss = appState.logs.filter(l => l.model.toLowerCase().includes('hf_boss') || l.model.toLowerCase().includes('boss')).length;
 
361
 
362
  updateDashboardView();
363
  } catch(err) {
@@ -411,12 +412,12 @@ function initChart() {
411
 
412
  function getChartData() {
413
  return {
414
- labels: ['Local BLIP', 'Local YOLO', 'Gemini AI', 'Groq Vision', 'HF Boss API'],
415
  datasets: [{
416
  label: 'Queries',
417
- data: [appState.stats.local, appState.stats.yolo, appState.stats.gemini, appState.stats.groq, appState.stats.hf_boss],
418
- backgroundColor: ['rgba(16, 185, 129, 0.6)', 'rgba(52, 211, 153, 0.6)', 'rgba(99, 102, 241, 0.6)', 'rgba(245, 158, 11, 0.6)', 'rgba(139, 92, 246, 0.6)'],
419
- borderColor: ['rgba(16, 185, 129, 1)', 'rgba(52, 211, 153, 1)', 'rgba(99, 102, 241, 1)', 'rgba(245, 158, 11, 1)', 'rgba(139, 92, 246, 1)'],
420
  borderWidth: 1, borderRadius: 6
421
  }]
422
  };
 
2
  let appState = {
3
  username: '',
4
  logs: [],
5
+ stats: { total: 0, local: 0, yolo: 0, gemini: 0, groq: 0, hf_boss: 0, florence: 0 },
6
  geminiEnabled: true
7
  };
8
 
 
358
  appState.stats.gemini = appState.logs.filter(l => ['gemini', 'external'].includes(l.model.toLowerCase())).length;
359
  appState.stats.groq = appState.logs.filter(l => l.model.toLowerCase().includes('groq')).length;
360
  appState.stats.hf_boss = appState.logs.filter(l => l.model.toLowerCase().includes('hf_boss') || l.model.toLowerCase().includes('boss')).length;
361
+ appState.stats.florence = appState.logs.filter(l => l.model.toLowerCase().includes('florence') || l.model.toLowerCase().includes('fusion')).length;
362
 
363
  updateDashboardView();
364
  } catch(err) {
 
412
 
413
  function getChartData() {
414
  return {
415
+ labels: ['Local BLIP', 'Local YOLO', 'Gemini AI', 'Groq Vision', 'HF API', 'Florence Fusion'],
416
  datasets: [{
417
  label: 'Queries',
418
+ data: [appState.stats.local, appState.stats.yolo, appState.stats.gemini, appState.stats.groq, appState.stats.hf_boss, appState.stats.florence],
419
+ backgroundColor: ['rgba(16, 185, 129, 0.6)', 'rgba(52, 211, 153, 0.6)', 'rgba(99, 102, 241, 0.6)', 'rgba(245, 158, 11, 0.6)', 'rgba(139, 92, 246, 0.6)', 'rgba(236, 72, 153, 0.6)'],
420
+ borderColor: ['rgba(16, 185, 129, 1)', 'rgba(52, 211, 153, 1)', 'rgba(99, 102, 241, 1)', 'rgba(245, 158, 11, 1)', 'rgba(139, 92, 246, 1)', 'rgba(236, 72, 153, 1)'],
421
  borderWidth: 1, borderRadius: 6
422
  }]
423
  };
templates/index.html CHANGED
@@ -100,6 +100,7 @@
100
  <option value="gemini" id="gemini-option">Gemini 3.1 Flash Vision (High Quota)</option>
101
  <option value="groq" id="groq-option">Groq Native Vision: Llama 4 Scout</option>
102
  <option value="hf_boss" id="hf-option">Hugging Face API: Llama 11B Vision (Unlimited Boss)</option>
 
103
  </select>
104
  </div>
105
  <div class="control-group" style="flex: 1;">
 
100
  <option value="gemini" id="gemini-option">Gemini 3.1 Flash Vision (High Quota)</option>
101
  <option value="groq" id="groq-option">Groq Native Vision: Llama 4 Scout</option>
102
  <option value="hf_boss" id="hf-option">Hugging Face API: Llama 11B Vision (Unlimited Boss)</option>
103
+ <option value="florence" id="florence-option">Florence-2 Fusion (Local Ultimate)</option>
104
  </select>
105
  </div>
106
  <div class="control-group" style="flex: 1;">