Abhiroopvanaone commited on
Commit
b46f5fa
Β·
verified Β·
1 Parent(s): e3b05fc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -121
app.py CHANGED
@@ -4,15 +4,14 @@ import torch
4
  from transformers import pipeline
5
  from PIL import Image
6
  import time
 
7
 
8
  # Global model storage
9
  models = {}
10
 
11
- @spaces.GPU
12
- def generate_cadquery_with_zero_gpu(image_data, model_choice, prompt_style):
13
- """Single function that handles everything on Zero GPU."""
14
-
15
- # Model mapping
16
  model_map = {
17
  "GLM-4.5V-AWQ": "QuantTrio/GLM-4.5V-AWQ",
18
  "GLM-4.5V-FP8": "zai-org/GLM-4.5V-FP8",
@@ -21,10 +20,69 @@ def generate_cadquery_with_zero_gpu(image_data, model_choice, prompt_style):
21
 
22
  model_name = model_map[model_choice]
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  # Load model if not already loaded
26
  if model_name not in models:
27
- print(f"πŸ”„ Loading {model_name}...")
28
  pipe = pipeline(
29
  "image-text-to-text",
30
  model=model_name,
@@ -33,27 +91,17 @@ def generate_cadquery_with_zero_gpu(image_data, model_choice, prompt_style):
33
  trust_remote_code=True
34
  )
35
  models[model_name] = pipe
36
- print(f"βœ… Loaded {model_name}")
37
-
38
- pipe = models[model_name]
39
-
40
- # Create prompt
41
- prompts = {
42
- "Simple": "Generate CADQuery Python code for this 3D model:",
43
- "Detailed": "Analyze this 3D CAD model and generate Python CADQuery code. Requirements: Import cadquery as cq, store result in 'result' variable, use proper syntax.",
44
- "Chain-of-Thought": "Analyze this 3D CAD model step by step: 1) Identify geometry 2) Note features 3) Generate CADQuery code. ```python\nimport cadquery as cq\n# Generated code:"
45
- }
46
-
47
- prompt = prompts[prompt_style]
48
 
49
  # Generate
50
  start_time = time.time()
51
 
52
  messages = [
53
  {
54
- "role": "user",
55
  "content": [
56
- {"type": "image", "image": image_data},
57
  {"type": "text", "text": prompt}
58
  ]
59
  }
@@ -61,66 +109,87 @@ def generate_cadquery_with_zero_gpu(image_data, model_choice, prompt_style):
61
 
62
  result = pipe(messages, max_new_tokens=512, temperature=0.7, do_sample=True)
63
 
64
- if isinstance(result, list):
65
  generated_text = result[0].get("generated_text", str(result))
66
  else:
67
  generated_text = str(result)
68
 
69
  generation_time = time.time() - start_time
 
70
 
71
- # Extract code
72
- clean_code = extract_code(generated_text)
73
-
74
- # Format output
75
  output = f"""## 🎯 Generated CADQuery Code
76
 
77
  ```python
78
  {clean_code}
79
  ```
80
 
81
- ## πŸ“Š Info
82
- - **Model**: {model_choice}
83
- - **Time**: {generation_time:.2f}s
84
- - **Style**: {prompt_style}
 
85
 
86
  ## πŸ”§ Usage
87
  ```bash
88
  pip install cadquery
89
- python script.py
90
  ```
 
 
 
91
  """
92
 
93
  return output
94
 
95
  except Exception as e:
96
- return f"❌ **Error**: {str(e)[:300]}"
 
 
 
 
 
 
 
 
97
 
98
- def extract_code(text):
99
- """Extract CADQuery code from generated text."""
100
- text = text.strip()
 
 
101
 
102
  if "```python" in text:
103
  start = text.find("```python") + 9
104
  end = text.find("```", start)
105
- code = text[start:end].strip() if end > start else text[start:].strip()
 
 
 
106
  elif "import cadquery" in text.lower():
107
  lines = text.split('\n')
108
  code_lines = []
109
  started = False
 
110
  for line in lines:
111
  if "import cadquery" in line.lower():
112
  started = True
113
  if started:
114
  code_lines.append(line)
 
115
  code = '\n'.join(code_lines)
116
  else:
117
  code = text
118
 
119
- # Clean up
120
- lines = [line.strip() for line in code.split('\n') if line.strip() and not line.strip().startswith('```')]
121
- final_code = '\n'.join(lines)
 
 
 
 
 
 
122
 
123
- # Ensure proper structure
124
  if "import cadquery" not in final_code:
125
  final_code = "import cadquery as cq\n\n" + final_code
126
 
@@ -134,94 +203,147 @@ def extract_code(text):
134
 
135
  return final_code
136
 
137
- @spaces.GPU
138
- def test_model(model_choice):
139
- """Test model loading."""
140
- model_map = {
141
- "GLM-4.5V-AWQ": "QuantTrio/GLM-4.5V-AWQ",
142
- "GLM-4.5V-FP8": "zai-org/GLM-4.5V-FP8",
143
- "GLM-4.5V": "zai-org/GLM-4.5V"
 
 
 
 
 
144
  }
145
 
146
- try:
147
- model_name = model_map[model_choice]
148
- if model_name not in models:
149
- pipe = pipeline("image-text-to-text", model=model_name, device_map="auto", torch_dtype=torch.float16, trust_remote_code=True)
150
- models[model_name] = pipe
151
- return f"βœ… **{model_choice}** loaded successfully!"
152
- except Exception as e:
153
- return f"❌ **{model_choice}** failed: {str(e)[:200]}"
154
 
155
- # Simple wrapper functions that don't use Gradio context
156
- def generate_wrapper(image, model, style):
157
- if image is None:
158
- return "❌ Please upload an image first."
159
- return generate_cadquery_with_zero_gpu(image, model, style)
160
-
161
- def test_wrapper(model):
162
- return test_model(model)
163
-
164
- # Create interface
165
- with gr.Blocks(title="GLM CAD Generator", theme=gr.themes.Soft()) as demo:
166
-
167
- gr.Markdown("""
168
- # πŸ”§ GLM-4.5V CAD Generator
169
-
170
- Generate CADQuery code from 3D model images using Zero GPU!
171
-
172
- **Models:** AWQ (fastest) β€’ FP8 (balanced) β€’ Full (best quality)
173
- """)
174
-
175
- with gr.Tab("πŸš€ Generate"):
176
- with gr.Row():
177
- with gr.Column():
178
- image_input = gr.Image(type="pil", label="CAD Image")
179
- model_select = gr.Dropdown(
180
- ["GLM-4.5V-AWQ", "GLM-4.5V-FP8", "GLM-4.5V"],
181
- value="GLM-4.5V-AWQ",
182
- label="Model"
183
- )
184
- style_select = gr.Dropdown(
185
- ["Simple", "Detailed", "Chain-of-Thought"],
186
- value="Chain-of-Thought",
187
- label="Style"
188
- )
189
- gen_btn = gr.Button("πŸš€ Generate", variant="primary")
 
 
 
 
 
 
 
 
190
 
191
- with gr.Column():
192
- output_area = gr.Markdown("Upload image and generate!")
 
 
 
193
 
194
- gen_btn.click(generate_wrapper, [image_input, model_select, style_select], output_area)
195
-
196
- with gr.Tab("πŸ§ͺ Test"):
197
- test_select = gr.Dropdown(
198
- ["GLM-4.5V-AWQ", "GLM-4.5V-FP8", "GLM-4.5V"],
199
- value="GLM-4.5V-AWQ",
200
- label="Test Model"
201
- )
202
- test_btn = gr.Button("Test")
203
- test_out = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- test_btn.click(test_wrapper, test_select, test_out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
- with gr.Tab("ℹ️ Help"):
208
- gr.Markdown("""
209
- ## How to Use
210
- 1. Upload clear CAD model image
211
- 2. Select GLM model variant
212
- 3. Choose prompt style
213
- 4. Click Generate
214
-
215
- ## Zero GPU
216
- - A100 allocated automatically
217
- - Pay only when generating
218
- - No idle costs
219
-
220
- ## Tips
221
- - AWQ model is fastest
222
- - Chain-of-Thought works best
223
- - Clear images get better results
224
- """)
225
 
226
  if __name__ == "__main__":
227
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
4
  from transformers import pipeline
5
  from PIL import Image
6
  import time
7
+ import traceback
8
 
9
  # Global model storage
10
  models = {}
11
 
12
+ @spaces.GPU(duration=300)
13
+ def load_glm_model(model_choice):
14
+ """Load GLM model on GPU."""
 
 
15
  model_map = {
16
  "GLM-4.5V-AWQ": "QuantTrio/GLM-4.5V-AWQ",
17
  "GLM-4.5V-FP8": "zai-org/GLM-4.5V-FP8",
 
20
 
21
  model_name = model_map[model_choice]
22
 
23
+ if model_name in models:
24
+ return True, f"βœ… {model_choice} already loaded"
25
+
26
+ try:
27
+ pipe = pipeline(
28
+ "image-text-to-text",
29
+ model=model_name,
30
+ device_map="auto",
31
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
32
+ trust_remote_code=True
33
+ )
34
+
35
+ models[model_name] = pipe
36
+ return True, f"βœ… {model_choice} loaded successfully"
37
+
38
+ except Exception as e:
39
+ error_msg = f"❌ Failed to load {model_choice}: {str(e)[:200]}"
40
+ return False, error_msg
41
+
42
+ @spaces.GPU(duration=120)
43
+ def generate_cadquery_code(image, model_choice, prompt_style):
44
+ """Generate CADQuery code from image."""
45
+
46
+ if image is None:
47
+ return "❌ Please upload an image first."
48
+
49
  try:
50
+ # Create prompt
51
+ prompts = {
52
+ "Simple": "Generate CADQuery Python code for this 3D model:",
53
+ "Detailed": """Analyze this 3D CAD model and generate Python CADQuery code.
54
+
55
+ Requirements:
56
+ - Import cadquery as cq
57
+ - Store result in 'result' variable
58
+ - Use proper CADQuery syntax
59
+
60
+ Code:""",
61
+ "Chain-of-Thought": """Analyze this 3D CAD model step by step:
62
+
63
+ Step 1: Identify the basic geometry (box, cylinder, etc.)
64
+ Step 2: Note any features (holes, fillets, etc.)
65
+ Step 3: Generate clean CADQuery Python code
66
+
67
+ ```python
68
+ import cadquery as cq
69
+
70
+ # Generated code:"""
71
+ }
72
+
73
+ prompt = prompts[prompt_style]
74
+
75
+ # Load model if needed
76
+ model_map = {
77
+ "GLM-4.5V-AWQ": "QuantTrio/GLM-4.5V-AWQ",
78
+ "GLM-4.5V-FP8": "zai-org/GLM-4.5V-FP8",
79
+ "GLM-4.5V": "zai-org/GLM-4.5V"
80
+ }
81
+
82
+ model_name = model_map[model_choice]
83
+
84
  # Load model if not already loaded
85
  if model_name not in models:
 
86
  pipe = pipeline(
87
  "image-text-to-text",
88
  model=model_name,
 
91
  trust_remote_code=True
92
  )
93
  models[model_name] = pipe
94
+ else:
95
+ pipe = models[model_name]
 
 
 
 
 
 
 
 
 
 
96
 
97
  # Generate
98
  start_time = time.time()
99
 
100
  messages = [
101
  {
102
+ "role": "user",
103
  "content": [
104
+ {"type": "image", "image": image},
105
  {"type": "text", "text": prompt}
106
  ]
107
  }
 
109
 
110
  result = pipe(messages, max_new_tokens=512, temperature=0.7, do_sample=True)
111
 
112
+ if isinstance(result, list) and len(result) > 0:
113
  generated_text = result[0].get("generated_text", str(result))
114
  else:
115
  generated_text = str(result)
116
 
117
  generation_time = time.time() - start_time
118
+ clean_code = extract_cadquery_code(generated_text)
119
 
 
 
 
 
120
  output = f"""## 🎯 Generated CADQuery Code
121
 
122
  ```python
123
  {clean_code}
124
  ```
125
 
126
+ ## πŸ“Š Generation Info
127
+ - **Model**: {model_choice}
128
+ - **Time**: {generation_time:.2f} seconds
129
+ - **Prompt**: {prompt_style}
130
+ - **Device**: {"GPU" if torch.cuda.is_available() else "CPU"}
131
 
132
  ## πŸ”§ Usage
133
  ```bash
134
  pip install cadquery
135
+ python your_script.py
136
  ```
137
+
138
+ ## ⚠️ Note
139
+ Generated code may need manual adjustments for complex geometries.
140
  """
141
 
142
  return output
143
 
144
  except Exception as e:
145
+ error_trace = traceback.format_exc()
146
+ return f"""❌ **Generation Failed**
147
+
148
+ **Error**: {str(e)}
149
+
150
+ **Traceback**:
151
+ ```
152
+ {error_trace[:1000]}...
153
+ ```
154
 
155
+ Try a different model variant or check your image."""
156
+
157
+ def extract_cadquery_code(generated_text: str) -> str:
158
+ """Extract clean CADQuery code from generated text."""
159
+ text = generated_text.strip()
160
 
161
  if "```python" in text:
162
  start = text.find("```python") + 9
163
  end = text.find("```", start)
164
+ if end > start:
165
+ code = text[start:end].strip()
166
+ else:
167
+ code = text[start:].strip()
168
  elif "import cadquery" in text.lower():
169
  lines = text.split('\n')
170
  code_lines = []
171
  started = False
172
+
173
  for line in lines:
174
  if "import cadquery" in line.lower():
175
  started = True
176
  if started:
177
  code_lines.append(line)
178
+
179
  code = '\n'.join(code_lines)
180
  else:
181
  code = text
182
 
183
+ lines = code.split('\n')
184
+ cleaned_lines = []
185
+
186
+ for line in lines:
187
+ line = line.strip()
188
+ if line and not line.startswith('```'):
189
+ cleaned_lines.append(line)
190
+
191
+ final_code = '\n'.join(cleaned_lines)
192
 
 
193
  if "import cadquery" not in final_code:
194
  final_code = "import cadquery as cq\n\n" + final_code
195
 
 
203
 
204
  return final_code
205
 
206
+ def test_model_loading(model_choice):
207
+ """Test loading a specific model."""
208
+ success, message = load_glm_model(model_choice)
209
+ return f"## Test Result\n\n{message}"
210
+
211
+ def get_system_info():
212
+ """Get system information."""
213
+ info = {
214
+ "CUDA Available": torch.cuda.is_available(),
215
+ "CUDA Device Count": torch.cuda.device_count() if torch.cuda.is_available() else 0,
216
+ "PyTorch Version": torch.__version__,
217
+ "Device": "GPU" if torch.cuda.is_available() else "CPU"
218
  }
219
 
220
+ info_text = "## πŸ–₯️ System Information\n\n"
221
+ for key, value in info.items():
222
+ info_text += f"- **{key}**: {value}\n"
223
+
224
+ return info_text
 
 
 
225
 
226
+ def create_interface():
227
+ """Create the Gradio interface."""
228
+
229
+ with gr.Blocks(title="GLM-4.5V CAD Generator", theme=gr.themes.Soft()) as demo:
230
+ gr.Markdown("""
231
+ # πŸ”§ GLM-4.5V CAD Generator
232
+
233
+ Upload a 3D CAD model image and generate CADQuery Python code using GLM-4.5V models!
234
+
235
+ **Available Models:**
236
+ - **GLM-4.5V-AWQ**: AWQ quantized (fastest startup)
237
+ - **GLM-4.5V-FP8**: 8-bit quantized (balanced)
238
+ - **GLM-4.5V**: Full precision (best quality)
239
+ """)
240
+
241
+ with gr.Tab("πŸš€ Generate"):
242
+ with gr.Row():
243
+ with gr.Column(scale=1):
244
+ image_input = gr.Image(
245
+ type="pil",
246
+ label="Upload CAD Model Image",
247
+ height=400
248
+ )
249
+
250
+ model_choice = gr.Dropdown(
251
+ choices=["GLM-4.5V-AWQ", "GLM-4.5V-FP8", "GLM-4.5V"],
252
+ value="GLM-4.5V-AWQ",
253
+ label="Select Model"
254
+ )
255
+
256
+ prompt_style = gr.Dropdown(
257
+ choices=["Simple", "Detailed", "Chain-of-Thought"],
258
+ value="Chain-of-Thought",
259
+ label="Prompt Style"
260
+ )
261
+
262
+ generate_btn = gr.Button("πŸš€ Generate CADQuery Code", variant="primary", size="lg")
263
+
264
+ with gr.Column(scale=2):
265
+ output_text = gr.Markdown(
266
+ label="Generated Code",
267
+ value="Upload an image and click 'Generate' to start!"
268
+ )
269
 
270
+ generate_btn.click(
271
+ fn=generate_cadquery_code,
272
+ inputs=[image_input, model_choice, prompt_style],
273
+ outputs=output_text
274
+ )
275
 
276
+ with gr.Tab("πŸ§ͺ Test"):
277
+ with gr.Row():
278
+ with gr.Column():
279
+ test_model_choice = gr.Dropdown(
280
+ choices=["GLM-4.5V-AWQ", "GLM-4.5V-FP8", "GLM-4.5V"],
281
+ value="GLM-4.5V-AWQ",
282
+ label="Model to Test"
283
+ )
284
+ test_btn = gr.Button("πŸ§ͺ Test Model Loading", variant="secondary")
285
+
286
+ with gr.Column():
287
+ test_output = gr.Markdown(value="Click 'Test Model Loading' to check if models work.")
288
+
289
+ test_btn.click(
290
+ fn=test_model_loading,
291
+ inputs=test_model_choice,
292
+ outputs=test_output
293
+ )
294
+
295
+ with gr.Tab("βš™οΈ System"):
296
+ info_output = gr.Markdown()
297
+ refresh_btn = gr.Button("πŸ”„ Refresh System Info")
298
+
299
+ demo.load(fn=get_system_info, outputs=info_output)
300
+ refresh_btn.click(fn=get_system_info, outputs=info_output)
301
 
302
+ with gr.Tab("πŸ“– Help"):
303
+ gr.Markdown("""
304
+ ## 🎯 How to Use
305
+
306
+ 1. **Upload Image**: Clear 3D CAD model images work best
307
+ 2. **Select Model**: GLM-4.5V-AWQ is fastest for testing
308
+ 3. **Choose Prompt**: Chain-of-Thought usually gives best results
309
+ 4. **Generate**: Click the button and wait for results
310
+
311
+ ## πŸ’‘ Tips for Best Results
312
+
313
+ - Use clear, well-lit CAD images
314
+ - Simple geometric shapes work better than complex assemblies
315
+ - Try different prompt styles if first attempt isn't satisfactory
316
+
317
+ ## πŸ”§ Using Generated Code
318
+
319
+ ```bash
320
+ # Install CADQuery
321
+ pip install cadquery
322
+
323
+ # Run your generated code
324
+ python your_cad_script.py
325
+
326
+ # Export to STL
327
+ cq.exporters.export(result, "model.stl")
328
+ ```
329
+
330
+ ## πŸ–₯️ Hardware Requirements
331
+
332
+ - This app runs on GPU-enabled Hugging Face Spaces
333
+ - First model load takes 5-10 minutes
334
+ - Generation takes 15-45 seconds per image
335
+ """)
336
 
337
+ return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
 
339
  if __name__ == "__main__":
340
+ print("πŸš€ Starting GLM-4.5V CAD Generator...")
341
+ print(f"CUDA available: {torch.cuda.is_available()}")
342
+ print(f"PyTorch version: {torch.__version__}")
343
+
344
+ demo = create_interface()
345
+ demo.launch(
346
+ server_name="0.0.0.0",
347
+ server_port=7860,
348
+ show_error=True
349
+ )