deepguess commited on
Commit
cb142b0
Β·
1 Parent(s): 3844b8f

updated app

Browse files
Files changed (1) hide show
  1. app.py +203 -90
app.py CHANGED
@@ -3,6 +3,7 @@ import spaces
3
  import torch
4
  from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
5
  import os
 
6
 
7
  # Model setup
8
  processor = AutoProcessor.from_pretrained("deepguess/weather-vlm-qwen2.5-7b", trust_remote_code=True)
@@ -14,61 +15,72 @@ model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
14
  model.eval()
15
 
16
  # Title and description
17
- TITLE = "🌦️ Weather Vision-Language Model (Qwen2.5-VL-7B Fine-tuned)"
18
 
19
  DESCRIPTION = """
20
- ## About This Model
21
 
22
- This is a **fine-tuned Qwen2.5-VL-7B** model specialized for meteorological image analysis. It has been trained on weather-related visual data to provide detailed analysis of various weather phenomena.
 
 
 
 
 
23
 
24
- ### ⚠️ Important Disclaimer
25
- **This is an experimental small-scale fine-tuned model and should NEVER be used for:**
26
- - Making real meteorological decisions
27
- - Emergency weather warnings
28
- - Flight planning or navigation
29
- - Any safety-critical applications
30
- - Professional weather forecasting
31
-
32
- **This model is for educational and research purposes only.**
33
-
34
- ### Model Details
35
- - **Base Model**: Qwen2.5-VL-7B-Instruct
36
- - **Fine-tuning**: LoRA (r=32, alpha=32)
37
- - **Training**: Custom weather image dataset
38
- - **Parameters**: 8.29B
39
- - **Precision**: BF16
40
-
41
- ### What it can analyze:
42
- - ☁️ Cloud types and formations
43
- - 🌧️ Precipitation patterns
44
- - πŸŒͺ️ Storm systems
45
- - πŸ“‘ Satellite imagery
46
- - πŸ“Š Weather maps and charts
47
- - 🌈 Atmospheric phenomena
48
  """
49
 
50
- # Predefined prompts for different analysis types
51
  PROMPT_TEMPLATES = {
52
- "General": "What's the weather in this image?",
53
- "Clouds": "What cloud types are shown?",
54
- "Storm": "Analyze any storms in this image.",
55
- "Forecast": "What weather is likely coming?",
56
- "Technical": "Give a technical weather analysis.",
57
- "Simple": "Explain this weather simply.",
58
- "Hazards": "What weather hazards are visible?",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
- # Example images setup
62
- EXAMPLES = [
63
- ["examples/thunderstorm.jpg", "Storm", 0.7, 256],
64
- ["examples/cumulus_clouds.jpg", "Clouds", 0.7, 256],
65
- ["examples/satellite_hurricane.jpg", "Technical", 0.7, 384],
66
- ["examples/fog_morning.jpg", "General", 0.7, 256],
67
- ["examples/weather_map.jpg", "Forecast", 0.7, 384],
68
- ] if os.path.exists("examples") else []
69
 
70
- @spaces.GPU(duration=60)
71
- def analyze_weather_image(image, analysis_type, custom_prompt, temperature, max_tokens):
72
  if image is None:
73
  return "Please upload an image to analyze."
74
 
@@ -76,12 +88,15 @@ def analyze_weather_image(image, analysis_type, custom_prompt, temperature, max_
76
  model.cuda()
77
 
78
  # Use custom prompt if provided, otherwise use template
79
- prompt = custom_prompt if custom_prompt.strip() else PROMPT_TEMPLATES.get(analysis_type, PROMPT_TEMPLATES["General"])
 
 
 
80
 
81
  # Prepare messages
82
  messages = [{
83
  "role": "system",
84
- "content": "You are a meteorological analysis assistant. Provide detailed, accurate analysis of weather images while clearly stating any limitations or uncertainties."
85
  }, {
86
  "role": "user",
87
  "content": [
@@ -100,17 +115,27 @@ def analyze_weather_image(image, analysis_type, custom_prompt, temperature, max_
100
  max_new_tokens=max_tokens,
101
  temperature=temperature,
102
  do_sample=True,
103
- top_p=0.95,
104
- repetition_penalty=1.1
105
  )
106
 
107
  # Decode response
108
  response = processor.batch_decode(outputs[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0]
109
 
110
- return response
 
 
 
 
111
 
112
  # Create Gradio interface
113
- with gr.Blocks(title=TITLE, theme=gr.themes.Base()) as demo:
 
 
 
 
 
 
114
  gr.Markdown(f"# {TITLE}")
115
  gr.Markdown(DESCRIPTION)
116
 
@@ -127,33 +152,57 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base()) as demo:
127
  analysis_type = gr.Dropdown(
128
  label="Analysis Type",
129
  choices=list(PROMPT_TEMPLATES.keys()),
130
- value="General"
 
 
 
 
 
 
 
 
 
131
  )
132
 
 
 
 
133
  # Custom prompt option
134
  with gr.Accordion("Custom Prompt (Optional)", open=False):
135
  custom_prompt = gr.Textbox(
136
- label="Enter your own prompt",
137
- placeholder="Leave empty to use the selected analysis type template",
138
  lines=3
139
  )
140
 
141
  # Advanced settings
142
  with gr.Accordion("Advanced Settings", open=False):
143
- temperature = gr.Slider(
144
- minimum=0.1,
145
- maximum=1.0,
146
- value=0.7,
147
- step=0.1,
148
- label="Temperature (creativity)"
149
- )
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  max_tokens = gr.Slider(
152
  minimum=128,
153
- maximum=512,
154
- value=256,
155
- step=32,
156
- label="Max Output Length"
 
157
  )
158
 
159
  # Analyze button
@@ -163,47 +212,111 @@ with gr.Blocks(title=TITLE, theme=gr.themes.Base()) as demo:
163
  # Output area
164
  output = gr.Textbox(
165
  label="Analysis Results",
166
- lines=20,
167
- max_lines=25,
168
- show_copy_button=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  )
170
 
171
  # Examples section
172
- if EXAMPLES:
 
 
 
 
 
 
 
 
173
  gr.Examples(
174
- examples=EXAMPLES,
175
- inputs=[image_input, analysis_type, temperature, max_tokens],
176
  outputs=output,
177
- fn=lambda img, typ, temp, tok: analyze_weather_image(img, typ, "", temp, tok),
178
- cache_examples=False
 
179
  )
180
 
181
  # Tips section
182
- with gr.Accordion("πŸ“š Usage Tips", open=False):
183
  gr.Markdown("""
184
- ### Getting the Best Results:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
- 1. **Image Quality**: Use clear, high-resolution weather images
187
- 2. **Image Types**: Works best with:
188
- - Satellite imagery
189
- - Ground-based sky photos
190
- - Weather radar images
191
- - Weather maps and charts
192
- 3. **Analysis Types**: Choose the most relevant analysis type for your image
193
- 4. **Temperature**: Lower values (0.3-0.5) for factual analysis, higher (0.7-0.9) for more detailed descriptions
194
- 5. **Custom Prompts**: Be specific about what aspects you want analyzed
195
 
196
- ### Limitations:
197
- - Cannot predict exact future weather
198
- - May misidentify rare phenomena
199
- - Not suitable for professional use
200
- - Analysis quality depends on image clarity
 
 
 
 
 
201
  """)
202
 
 
 
 
 
 
 
 
203
  # Set up event handler
204
  analyze_btn.click(
205
  fn=analyze_weather_image,
206
- inputs=[image_input, analysis_type, custom_prompt, temperature, max_tokens],
207
  outputs=output
208
  )
209
 
 
3
  import torch
4
  from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
5
  import os
6
+ from datetime import datetime
7
 
8
  # Model setup
9
  processor = AutoProcessor.from_pretrained("deepguess/weather-vlm-qwen2.5-7b", trust_remote_code=True)
 
15
  model.eval()
16
 
17
  # Title and description
18
+ TITLE = "🌦️ Weather Analysis VLM (Qwen2.5-VL-7B Fine-tuned)"
19
 
20
  DESCRIPTION = """
21
+ ## Advanced Weather Image Analysis
22
 
23
+ This model specializes in analyzing weather data including:
24
+ - **Model Outputs**: GFS, HRRR, ECMWF, NAM analysis
25
+ - **Soundings**: Skew-T diagrams, hodographs, SHARPpy analysis
26
+ - **Observations**: Surface obs, satellite, radar imagery
27
+ - **Forecasts**: Deterministic and ensemble model outputs
28
+ - **Severe Weather**: Convective parameters, SPC outlooks
29
 
30
+ ### ⚠️ Disclaimer
31
+ **For educational and research purposes only. Not for operational forecasting.**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  """
33
 
34
+ # Enhanced prompts based on your data categories
35
  PROMPT_TEMPLATES = {
36
+ "Quick Analysis": "Describe the weather in this image.",
37
+ "Model Output": "Analyze this model output. What patterns and features are shown?",
38
+ "Sounding Analysis": "Analyze this sounding. Discuss stability, shear, and severe potential.",
39
+ "Radar/Satellite": "Describe the features in this radar or satellite image.",
40
+ "Severe Weather": "Assess severe weather potential based on this image.",
41
+ "Technical Deep Dive": "Provide detailed technical analysis including parameters and meteorological significance.",
42
+ "Forecast Discussion": "Based on this image, what weather evolution is expected?",
43
+ "Pattern Recognition": "Identify synoptic patterns, jet streaks, troughs, ridges, and fronts.",
44
+ "Ensemble Analysis": "Analyze ensemble spread, uncertainty, and most likely scenarios.",
45
+ "Winter Weather": "Analyze precipitation type, accumulation potential, and impacts.",
46
+ }
47
+
48
+ # System prompts for different analysis modes
49
+ SYSTEM_PROMPTS = {
50
+ "technical": """You are an expert meteorologist providing technical analysis. Focus on:
51
+ - Specific parameter values and thresholds
52
+ - Physical processes and dynamics
53
+ - Pattern recognition and anomalies
54
+ - Forecast confidence and uncertainty
55
+ Use technical terminology appropriately.""",
56
+
57
+ "educational": """You are a meteorology instructor. Explain concepts clearly while maintaining accuracy.
58
+ Point out key features and explain their significance. Use some technical terms but define them.""",
59
+
60
+ "operational": """You are providing a weather briefing. Focus on:
61
+ - Current conditions and trends
62
+ - Expected evolution
63
+ - Impacts and hazards
64
+ - Timing of changes
65
+ Be concise but thorough.""",
66
+
67
+ "research": """You are analyzing meteorological data for research purposes. Discuss:
68
+ - Interesting features or anomalies
69
+ - Comparison to climatology
70
+ - Physical mechanisms
71
+ - Uncertainty quantification"""
72
  }
73
 
74
+ # Analysis mode descriptions
75
+ MODE_INFO = {
76
+ "technical": "Detailed technical analysis for meteorologists",
77
+ "educational": "Clear explanations for learning",
78
+ "operational": "Focused briefing style",
79
+ "research": "In-depth research perspective"
80
+ }
 
81
 
82
+ @spaces.GPU(duration=90)
83
+ def analyze_weather_image(image, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p):
84
  if image is None:
85
  return "Please upload an image to analyze."
86
 
 
88
  model.cuda()
89
 
90
  # Use custom prompt if provided, otherwise use template
91
+ prompt = custom_prompt.strip() if custom_prompt.strip() else PROMPT_TEMPLATES.get(analysis_type, PROMPT_TEMPLATES["Quick Analysis"])
92
+
93
+ # Select system prompt based on mode
94
+ system_content = SYSTEM_PROMPTS.get(analysis_mode, SYSTEM_PROMPTS["technical"])
95
 
96
  # Prepare messages
97
  messages = [{
98
  "role": "system",
99
+ "content": system_content
100
  }, {
101
  "role": "user",
102
  "content": [
 
115
  max_new_tokens=max_tokens,
116
  temperature=temperature,
117
  do_sample=True,
118
+ top_p=top_p,
119
+ repetition_penalty=1.05
120
  )
121
 
122
  # Decode response
123
  response = processor.batch_decode(outputs[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0]
124
 
125
+ # Add metadata
126
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
127
+ metadata = f"\n\n---\n*Analysis completed: {timestamp} | Mode: {analysis_mode} | Type: {analysis_type}*"
128
+
129
+ return response + metadata
130
 
131
  # Create Gradio interface
132
+ with gr.Blocks(title=TITLE, theme=gr.themes.Base(), css="""
133
+ .gradio-container { font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; }
134
+ .markdown-text { font-size: 14px; }
135
+ #analysis-output { font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; }
136
+ .gr-button-primary { background-color: #2563eb; }
137
+ .gr-button-primary:hover { background-color: #1e40af; }
138
+ """) as demo:
139
  gr.Markdown(f"# {TITLE}")
140
  gr.Markdown(DESCRIPTION)
141
 
 
152
  analysis_type = gr.Dropdown(
153
  label="Analysis Type",
154
  choices=list(PROMPT_TEMPLATES.keys()),
155
+ value="Quick Analysis",
156
+ info="Select the type of analysis you need"
157
+ )
158
+
159
+ # Analysis mode selector
160
+ analysis_mode = gr.Radio(
161
+ label="Analysis Mode",
162
+ choices=list(MODE_INFO.keys()),
163
+ value="technical",
164
+ info="Choose the style and depth of analysis"
165
  )
166
 
167
+ # Mode description
168
+ mode_description = gr.Markdown(value=MODE_INFO["technical"], elem_id="mode-desc")
169
+
170
  # Custom prompt option
171
  with gr.Accordion("Custom Prompt (Optional)", open=False):
172
  custom_prompt = gr.Textbox(
173
+ label="Enter your specific question or analysis request",
174
+ placeholder="E.g., 'Focus on the 500mb vorticity patterns' or 'Explain the hodograph curvature'",
175
  lines=3
176
  )
177
 
178
  # Advanced settings
179
  with gr.Accordion("Advanced Settings", open=False):
180
+ with gr.Row():
181
+ temperature = gr.Slider(
182
+ minimum=0.1,
183
+ maximum=1.0,
184
+ value=0.7,
185
+ step=0.05,
186
+ label="Temperature",
187
+ info="Lower = more focused, Higher = more varied"
188
+ )
189
+
190
+ top_p = gr.Slider(
191
+ minimum=0.5,
192
+ maximum=1.0,
193
+ value=0.95,
194
+ step=0.05,
195
+ label="Top-p",
196
+ info="Nucleus sampling threshold"
197
+ )
198
 
199
  max_tokens = gr.Slider(
200
  minimum=128,
201
+ maximum=1024,
202
+ value=512,
203
+ step=64,
204
+ label="Max Output Length",
205
+ info="Longer for detailed analysis"
206
  )
207
 
208
  # Analyze button
 
212
  # Output area
213
  output = gr.Textbox(
214
  label="Analysis Results",
215
+ lines=25,
216
+ max_lines=30,
217
+ show_copy_button=True,
218
+ elem_id="analysis-output"
219
+ )
220
+
221
+ # Common weather data categories for quick access
222
+ with gr.Accordion("πŸ“Š Quick Templates for Common Data Types", open=False):
223
+ gr.Markdown("""
224
+ ### Click to load analysis templates:
225
+ """)
226
+ with gr.Row():
227
+ gr.Button("500mb Analysis", size="sm").click(
228
+ lambda: "Analyze the 500mb height and wind patterns. Identify troughs, ridges, jet streaks, and vorticity.",
229
+ outputs=custom_prompt
230
+ )
231
+ gr.Button("Sounding Analysis", size="sm").click(
232
+ lambda: "Analyze this sounding for stability, CAPE, shear, LCL, LFC, and severe weather parameters.",
233
+ outputs=custom_prompt
234
+ )
235
+ gr.Button("Composite Reflectivity", size="sm").click(
236
+ lambda: "Analyze radar reflectivity patterns, storm structure, intensity, and movement.",
237
+ outputs=custom_prompt
238
+ )
239
+ with gr.Row():
240
+ gr.Button("Surface Analysis", size="sm").click(
241
+ lambda: "Analyze surface features including fronts, pressure centers, convergence, and boundaries.",
242
+ outputs=custom_prompt
243
+ )
244
+ gr.Button("Ensemble Spread", size="sm").click(
245
+ lambda: "Analyze ensemble spread, clustering, and probabilistic information.",
246
+ outputs=custom_prompt
247
+ )
248
+ gr.Button("Convective Parameters", size="sm").click(
249
+ lambda: "Analyze CAPE, CIN, SRH, bulk shear, and composite parameters for severe potential.",
250
+ outputs=custom_prompt
251
  )
252
 
253
  # Examples section
254
+ example_data = [
255
+ ["examples/500mb_heights.jpg", "Model Output", "technical", 0.7, 512],
256
+ ["examples/sounding.jpg", "Sounding Analysis", "educational", 0.7, 512],
257
+ ["examples/radar_composite.jpg", "Radar/Satellite", "operational", 0.7, 384],
258
+ ["examples/spc_outlook.jpg", "Severe Weather", "operational", 0.7, 512],
259
+ ["examples/ensemble_spaghetti.jpg", "Ensemble Analysis", "research", 0.8, 640],
260
+ ] if os.path.exists("examples") else []
261
+
262
+ if example_data:
263
  gr.Examples(
264
+ examples=example_data,
265
+ inputs=[image_input, analysis_type, analysis_mode, temperature, max_tokens],
266
  outputs=output,
267
+ fn=lambda img, typ, mode, temp, tok: analyze_weather_image(img, typ, "", mode, temp, tok, 0.95),
268
+ cache_examples=False,
269
+ label="Example Analyses"
270
  )
271
 
272
  # Tips section
273
+ with gr.Accordion("πŸ’‘ Pro Tips for Best Results", open=False):
274
  gr.Markdown("""
275
+ ### Image Guidelines:
276
+ - **Resolution**: Higher resolution images yield better analysis
277
+ - **Clarity**: Ensure text/contours are legible
278
+ - **Completeness**: Include colorbars, titles, valid times
279
+
280
+ ### Analysis Tips by Data Type:
281
+
282
+ **Model Output (GFS, HRRR, ECMWF, NAM):**
283
+ - Include initialization and valid times
284
+ - Specify if you want focus on particular features
285
+ - Ask about ensemble uncertainty if applicable
286
+
287
+ **Soundings (Skew-T, Hodographs):**
288
+ - Ensure all parameters are visible
289
+ - Ask about specific levels or layers
290
+ - Request shear calculations or thermodynamic analysis
291
 
292
+ **Radar/Satellite:**
293
+ - Include timestamp and location
294
+ - Specify interest in particular features
295
+ - Ask about storm motion or development
 
 
 
 
 
296
 
297
+ **Surface/Upper Air Charts:**
298
+ - Ensure contours and labels are clear
299
+ - Ask about specific features or patterns
300
+ - Request frontal analysis or jet stream discussion
301
+
302
+ ### Parameter Settings:
303
+ - **Temperature 0.3-0.5**: Factual, consistent analysis
304
+ - **Temperature 0.6-0.8**: Balanced analysis with some interpretation
305
+ - **Temperature 0.9-1.0**: More speculative, exploring possibilities
306
+ - **Max Tokens**: Use 256-384 for quick analysis, 512-768 for detailed
307
  """)
308
 
309
+ # Update mode description when mode changes
310
+ analysis_mode.change(
311
+ lambda mode: MODE_INFO[mode],
312
+ inputs=analysis_mode,
313
+ outputs=mode_description
314
+ )
315
+
316
  # Set up event handler
317
  analyze_btn.click(
318
  fn=analyze_weather_image,
319
+ inputs=[image_input, analysis_type, custom_prompt, analysis_mode, temperature, max_tokens, top_p],
320
  outputs=output
321
  )
322