blackmistcode commited on
Commit
c8f026d
·
verified ·
1 Parent(s): 074853a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +2 -74
app.py CHANGED
@@ -1,7 +1,6 @@
1
  import spaces
2
  import torch
3
  import gradio as gr
4
- import re
5
  from transformers import AutoProcessor, AutoModelForImageTextToText
6
  MODEL_ID = "google/medgemma-1.5-4b-it"
7
  processor = AutoProcessor.from_pretrained(MODEL_ID)
@@ -10,76 +9,12 @@ UNUSED95_ID = processor.tokenizer.convert_tokens_to_ids('<unused95>')
10
  EOT_ID = processor.tokenizer.convert_tokens_to_ids('<end_of_turn>')
11
  def extract_response(output_ids, input_length):
12
  ids = output_ids.tolist()
13
-
14
- # Strategy 1: MedGemma uses <unused95> to separate thought from answer
15
  if UNUSED95_ID in ids:
16
  idx = ids.index(UNUSED95_ID)
17
  response_ids = ids[idx + 1:]
18
  else:
19
- # Strategy 2: Skip the input prompt and look for answer in the rest
20
  response_ids = ids[input_length:]
21
-
22
- text = processor.decode(response_ids, skip_special_tokens=True).strip()
23
-
24
- # Strip explicit "thought" prefix if present
25
- text = re.sub(r'^thought\s*\n?', '', text, flags=re.IGNORECASE)
26
-
27
- # Strategy 3: If the output is mixed reasoning + answer, find where Spanish starts
28
- # Look for the first substantial Spanish sentence
29
- spanish_markers = [
30
- r'(?:^|\n{2,})(El paciente\s)',
31
- r'(?:^|\n{2,})(Se observa\s)',
32
- r'(?:^|\n{2,})(Los resultados\s)',
33
- r'(?:^|\n{2,})(La interpretación\s)',
34
- r'(?:^|\n{2,})(Hallazgos\s)',
35
- r'(?:^|\n{2,})(Recomendaciones\s)',
36
- r'(?:^|\n{2,})(Análisis\s)',
37
- r'(?:^|\n{2,})(Interpretación\s)',
38
- r'(?:^|\n{2,})(En resumen\s)',
39
- r'(?:^|\n{2,})(Conclusiones\s)',
40
- r'(?:^|\n{2,})(Diagnóstico\s)',
41
- r'(?:^|\n{2,})(Evaluación\s)',
42
- r'(?:^|\n{2,})(Nota\s)',
43
- r'(?:^|\n{2,})(Observaciones\s)',
44
- r'(?:^|\n{2,})(Resumen\s)',
45
- r'(?:^|\n{2,})(Síntesis\s)',
46
- r'(?:^|\n{2,})(Conclusión\s)',
47
- r'(?:^|\n{2,})([ÁÉÍÓÚÑ][a-záéíóúñ]+)', # Any Spanish sentence starting with capital accented letter
48
- ]
49
-
50
- for pattern in spanish_markers:
51
- match = re.search(pattern, text, re.IGNORECASE)
52
- if match:
53
- start_idx = match.start()
54
- if start_idx > 0:
55
- text = text[start_idx:]
56
- break
57
-
58
- # Strip remaining reasoning artifacts
59
- text = re.sub(r"Here'?s a thinking process[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
60
- text = re.sub(r"Understand the Role[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
61
- text = re.sub(r"Analyze the Request[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
62
- text = re.sub(r"Review the Lab Results[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
63
- text = re.sub(r"Synthesize Findings[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
64
- text = re.sub(r"Formulate Clinical Interpretation[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
65
- text = re.sub(r"Refine Interpretation[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)", '', text, flags=re.IGNORECASE)
66
-
67
- # Strip numbered step headers
68
- text = re.sub(r'^\d+\.\s*\*\*[^*]+\*\*[\s\S]*?(?=\n{2,}[A-ZÁÉÍÓÚÑ]|\Z)', '', text, flags=re.MULTILINE)
69
- text = re.sub(r'^\d+\.\s*\*\*[^*]+\*\*\s*$', '', text, flags=re.MULTILINE)
70
-
71
- # Final cleanup
72
- text = text.strip()
73
- text = re.sub(r'\n{3,}', '\n\n', text)
74
-
75
- # Strategy 4: Validate we have actual clinical content
76
- has_spanish = bool(re.search(r'[áéíóúñÁÉÍÓÚÑ]', text))
77
- has_substance = len(text) > 50 # At least 50 chars of actual text
78
-
79
- if not has_spanish or not has_substance:
80
- return "ERROR: El modelo generó razonamiento interno pero no alcanzó a producir la interpretación clínica dentro del límite de tokens. Intenta con un análisis más breve o sin imágenes."
81
-
82
- return text
83
  @spaces.GPU(duration=90)
84
  def analyze(image1, image2, image3, image4, text_prompt):
85
  images = [img for img in [image1, image2, image3, image4] if img is not None]
@@ -91,15 +26,8 @@ def analyze(image1, image2, image3, image4, text_prompt):
91
  messages, add_generation_prompt=True, tokenize=True,
92
  return_dict=True, return_tensors="pt"
93
  ).to(model.device, dtype=torch.bfloat16)
94
-
95
  with torch.inference_mode():
96
- output = model.generate(
97
- **inputs,
98
- max_new_tokens=2048,
99
- do_sample=False,
100
- temperature=0.1,
101
- )
102
-
103
  return extract_response(output[0], inputs['input_ids'].shape[1])
104
  demo = gr.Interface(
105
  fn=analyze,
 
1
  import spaces
2
  import torch
3
  import gradio as gr
 
4
  from transformers import AutoProcessor, AutoModelForImageTextToText
5
  MODEL_ID = "google/medgemma-1.5-4b-it"
6
  processor = AutoProcessor.from_pretrained(MODEL_ID)
 
9
  EOT_ID = processor.tokenizer.convert_tokens_to_ids('<end_of_turn>')
10
  def extract_response(output_ids, input_length):
11
  ids = output_ids.tolist()
 
 
12
  if UNUSED95_ID in ids:
13
  idx = ids.index(UNUSED95_ID)
14
  response_ids = ids[idx + 1:]
15
  else:
 
16
  response_ids = ids[input_length:]
17
+ return processor.decode(response_ids, skip_special_tokens=True).strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  @spaces.GPU(duration=90)
19
  def analyze(image1, image2, image3, image4, text_prompt):
20
  images = [img for img in [image1, image2, image3, image4] if img is not None]
 
26
  messages, add_generation_prompt=True, tokenize=True,
27
  return_dict=True, return_tensors="pt"
28
  ).to(model.device, dtype=torch.bfloat16)
 
29
  with torch.inference_mode():
30
+ output = model.generate(**inputs, max_new_tokens=2048, eos_token_id=EOT_ID)
 
 
 
 
 
 
31
  return extract_response(output[0], inputs['input_ids'].shape[1])
32
  demo = gr.Interface(
33
  fn=analyze,