AKSazgar commited on
Commit
7040489
·
1 Parent(s): 43f83e5

Add ECG AI7 Gradio application

Browse files

- Add app.py with full ECG interpretation functionality
- Support for English and Farsi output languages
- Add requirements.txt with necessary dependencies
- Update README.md with detailed documentation

Files changed (3) hide show
  1. README.md +34 -2
  2. app.py +232 -0
  3. requirements.txt +6 -0
README.md CHANGED
@@ -1,12 +1,44 @@
1
  ---
2
  title: ECG Instruct Llama 3.2 11B Vision
3
- emoji: 📈
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
  sdk_version: 5.49.1
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: ECG Instruct Llama 3.2 11B Vision
3
+ emoji: 🫀
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
  sdk_version: 5.49.1
8
  app_file: app.py
9
  pinned: false
10
+ license: apache-2.0
11
  ---
12
 
13
+ # 🫀 ECG AI7 - Intelligent ECG Interpretation
14
+
15
+ An AI-powered ECG interpretation tool using Llama 3.2 11B Vision, fine-tuned specifically for electrocardiogram analysis.
16
+
17
+ ## Features
18
+
19
+ - **Advanced ECG Analysis**: Powered by Llama 3.2 11B Vision model fine-tuned on ECG data
20
+ - **Bilingual Support**: Generate reports in both English and Farsi (Persian)
21
+ - **Clinical Context**: Add patient information for more personalized interpretations
22
+ - **User-Friendly Interface**: Simple upload and analyze workflow
23
+
24
+ ## How to Use
25
+
26
+ 1. Upload an ECG image (12-lead ECG works best)
27
+ 2. Optionally add patient information or clinical notes
28
+ 3. Select your preferred output language (English or Farsi)
29
+ 4. Click Submit and wait for the AI analysis
30
+
31
+ ## Important Disclaimer
32
+
33
+ ⚠️ This tool is for **educational and research purposes only**. AI-generated interpretations should be verified by licensed cardiologists. Always consult with qualified healthcare professionals for medical decisions.
34
+
35
+ ## Model
36
+
37
+ This Space uses the [ECG-Instruct-Llama-3.2-11B-Vision](https://huggingface.co/AKSazgar/ECG-Instruct-Llama-3.2-11B-Vision) model.
38
+
39
+ ## Technical Details
40
+
41
+ - **Model**: Llama 3.2 11B Vision (fine-tuned)
42
+ - **Framework**: PyTorch + Transformers
43
+ - **Interface**: Gradio
44
+ - **Languages**: English, Farsi (Persian)
app.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ ECG AI7 - ECG Interpretation using Llama 3.2 11B Vision
4
+ Gradio interface for Hugging Face Spaces
5
+ """
6
+
7
+ import torch
8
+ from transformers import MllamaForConditionalGeneration, AutoProcessor, TextStreamer
9
+ from PIL import Image
10
+ import gradio as gr
11
+ import os
12
+
13
+ # Model configuration
14
+ MODEL_ID = "AKSazgar/ECG-Instruct-Llama-3.2-11B-Vision"
15
+
16
+ print(f"Loading model: {MODEL_ID}")
17
+ print("This may take a few minutes on first load...")
18
+
19
+ # Load model and processor
20
+ model = MllamaForConditionalGeneration.from_pretrained(
21
+ MODEL_ID,
22
+ torch_dtype=torch.bfloat16,
23
+ device_map="auto",
24
+ )
25
+
26
+ processor = AutoProcessor.from_pretrained(MODEL_ID)
27
+
28
+ print("Model loaded successfully!")
29
+
30
+
31
+ # Helper functions
32
+ def _strip_assistant_prefix_safe(s: str) -> str:
33
+ """Safely strip assistant prefix from generated text"""
34
+ s = s.lstrip()
35
+ # Only remove a leading role block if it literally starts the text
36
+ for prefix in ("user", "assistant", "User", "Assistant"):
37
+ if s.startswith(prefix):
38
+ idx = s.find("\n\n")
39
+ if idx != -1:
40
+ return s[idx+2:].lstrip()
41
+ idx = s.find("\n")
42
+ if idx != -1:
43
+ return s[idx+1:].lstrip()
44
+ return s
45
+
46
+
47
+ def generate_full_report(image_path: str, query: str, *,
48
+ max_new_tokens: int = 1600,
49
+ do_stream: bool = False,
50
+ temperature: float = 0.0) -> str:
51
+ """
52
+ Generate ECG interpretation report
53
+
54
+ Args:
55
+ image_path: local path to ECG image
56
+ query: instruction string for the model
57
+ max_new_tokens: maximum tokens to generate
58
+ do_stream: whether to stream output (for terminal use)
59
+ temperature: sampling temperature (0.0 = greedy)
60
+
61
+ Returns:
62
+ Full decoded interpretation report
63
+ """
64
+ image = Image.open(image_path).convert("RGB")
65
+
66
+ # Build single user turn: image + text
67
+ messages = [
68
+ {"role": "user", "content": [
69
+ {"type": "image"},
70
+ {"type": "text", "text": query}
71
+ ]}
72
+ ]
73
+
74
+ # Create prompt compatible with processor
75
+ input_text = processor.apply_chat_template(messages, add_generation_prompt=True)
76
+ inputs = processor(text=input_text, images=image, return_tensors="pt")
77
+
78
+ # Move inputs to same device as model
79
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
80
+
81
+ # Setup streamer if requested
82
+ streamer = TextStreamer(processor.tokenizer, skip_prompt=True) if do_stream else None
83
+
84
+ # Generate
85
+ with torch.no_grad():
86
+ out_ids = model.generate(
87
+ **inputs,
88
+ streamer=streamer,
89
+ max_new_tokens=max_new_tokens,
90
+ use_cache=True,
91
+ do_sample=False if temperature == 0.0 else True,
92
+ temperature=temperature,
93
+ top_p=1.0,
94
+ )
95
+
96
+ # Decode full generated text
97
+ full_raw = processor.batch_decode(out_ids, skip_special_tokens=True)[0]
98
+ full_clean = _strip_assistant_prefix_safe(full_raw)
99
+ return full_clean
100
+
101
+
102
+ def translate_to_farsi(english_text: str, max_new_tokens: int = 1600) -> str:
103
+ """Translate English text to Persian using the same model"""
104
+ msgs = [
105
+ {"role": "user", "content": [
106
+ {"type": "text",
107
+ "text": "فقط متن زیر را به فارسی روان ترجمه کن و فقط ترجمه را برگردان:\n\n" + english_text}
108
+ ]}
109
+ ]
110
+ prompt = processor.apply_chat_template(msgs, add_generation_prompt=True)
111
+ inputs = processor(text=prompt, return_tensors="pt")
112
+
113
+ # Move to device
114
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
115
+
116
+ with torch.no_grad():
117
+ out = model.generate(
118
+ **inputs,
119
+ max_new_tokens=max_new_tokens,
120
+ do_sample=False,
121
+ temperature=0.0,
122
+ top_p=1.0
123
+ )
124
+
125
+ ans = processor.batch_decode(out, skip_special_tokens=True)[0]
126
+ return _strip_assistant_prefix_safe(ans)
127
+
128
+
129
+ # Gradio interface function
130
+ def analyze_ecg_gradio(image, text_instruction="", language="Farsi"):
131
+ """
132
+ Main function for Gradio interface
133
+
134
+ Args:
135
+ image: uploaded ECG image filepath (string path)
136
+ text_instruction: optional clinical note / context
137
+ language: output language (English or Farsi)
138
+
139
+ Returns:
140
+ Full AI-generated ECG interpretation report
141
+ """
142
+ try:
143
+ print(f"Received image: {image}")
144
+ print(f"Text instruction: {text_instruction}")
145
+ print(f"Language: {language}")
146
+
147
+ # Build query
148
+ query = "You are an expert cardiologist. "
149
+ if text_instruction:
150
+ query += f"Patient info: {text_instruction}. "
151
+ query += "Write an in-depth diagnosis report from this ECG data, including the final diagnosis."
152
+
153
+ # Generate report in English
154
+ print("Generating report in English...")
155
+ report = generate_full_report(image, query, max_new_tokens=1600, do_stream=False)
156
+
157
+ # Translate to Farsi if requested
158
+ if language == "Farsi":
159
+ print("Translating to Farsi...")
160
+ report = translate_to_farsi(report, max_new_tokens=1600)
161
+
162
+ print("Report generated successfully!")
163
+ return report
164
+
165
+ except Exception as e:
166
+ import traceback
167
+ error_msg = f"Error: {str(e)}\n\nTraceback:\n{traceback.format_exc()}"
168
+ print(error_msg)
169
+ return error_msg
170
+
171
+
172
+ # Create Gradio interface
173
+ demo = gr.Interface(
174
+ fn=analyze_ecg_gradio,
175
+ inputs=[
176
+ gr.Image(type="filepath", label="ECG Image"),
177
+ gr.Textbox(
178
+ lines=2,
179
+ placeholder="Optional: Enter patient info or clinical notes (e.g., '55-year-old male with chest pain')",
180
+ label="Clinical Note"
181
+ ),
182
+ gr.Dropdown(
183
+ choices=["English", "Farsi"],
184
+ value="Farsi",
185
+ label="Output Language"
186
+ ),
187
+ ],
188
+ outputs=gr.Textbox(
189
+ label="AI ECG Report",
190
+ lines=20,
191
+ show_copy_button=True
192
+ ),
193
+ title="🫀 ECG AI7 - Intelligent ECG Interpretation",
194
+ description="""
195
+ Upload an ECG image to get an AI-powered interpretation.
196
+
197
+ **Features:**
198
+ - Advanced ECG analysis using Llama 3.2 11B Vision
199
+ - Support for English and Farsi (Persian) output
200
+ - Optional patient context for more personalized reports
201
+
202
+ **Note:** This is an AI assistant tool and should not replace professional medical diagnosis.
203
+ """,
204
+ examples=[
205
+ ["example_ecg.jpg", "55-year-old male with chest pain", "English"],
206
+ ["example_ecg.jpg", "بیمار 55 ساله مرد با درد قفسه سینه", "Farsi"],
207
+ ] if os.path.exists("example_ecg.jpg") else None,
208
+ article="""
209
+ ### About
210
+ This application uses a fine-tuned Llama 3.2 11B Vision model specifically trained for ECG interpretation.
211
+
212
+ ### How to Use
213
+ 1. Upload an ECG image (12-lead ECG works best)
214
+ 2. Optionally add patient information or clinical context
215
+ 3. Select your preferred output language (English or Farsi)
216
+ 4. Click Submit and wait for the AI analysis
217
+
218
+ ### Important Disclaimer
219
+ This tool is for educational and research purposes. Always consult with qualified healthcare
220
+ professionals for medical decisions. AI-generated interpretations should be verified by licensed
221
+ cardiologists.
222
+
223
+ ---
224
+ Model: [ECG-Instruct-Llama-3.2-11B-Vision](https://huggingface.co/AKSazgar/ECG-Instruct-Llama-3.2-11B-Vision)
225
+ """,
226
+ theme=gr.themes.Soft(),
227
+ allow_flagging="never",
228
+ )
229
+
230
+ # Launch the app
231
+ if __name__ == "__main__":
232
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ torch>=2.0.0
2
+ transformers>=4.45.0
3
+ accelerate>=0.20.0
4
+ Pillow>=10.0.0
5
+ sentencepiece>=0.1.99
6
+ protobuf>=3.20.0