manoskary commited on
Commit
504f83e
·
verified ·
1 Parent(s): 736f3ee

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -31
app.py CHANGED
@@ -5,6 +5,12 @@ This app provides a simple interface for generating symbolic music using NotaGen
5
  It accepts three parameters (period, composer, instrumentation) and returns ABC notation.
6
 
7
  The ABC notation can then be processed by WeaveMuse locally for XML/PDF conversion.
 
 
 
 
 
 
8
  """
9
 
10
  import gradio as gr
@@ -12,19 +18,145 @@ import spaces
12
  import torch
13
  import logging
14
  import traceback
15
- from weavemuse.tools.notagen_tool import NotaGenTool
 
 
 
 
16
 
17
- # Set up logging
18
  logging.basicConfig(level=logging.INFO)
19
  logger = logging.getLogger(__name__)
20
 
21
- # Initialize the NotaGen tool
22
- # This will use GPU if available in the HuggingFace Space
 
 
 
 
23
  device = "cuda"
24
- logger.info(f"Initializing NotaGen tool on device: {device}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  try:
27
- notagen_tool = NotaGenTool(device=device)
28
  logger.info("✅ NotaGen tool initialized successfully!")
29
  except Exception as e:
30
  logger.error(f"❌ Failed to initialize NotaGen tool: {e}")
@@ -32,11 +164,20 @@ except Exception as e:
32
  notagen_tool = None
33
 
34
 
 
 
 
 
 
 
35
  @spaces.GPU(duration=120)
36
  def generate_abc(period: str, composer: str, instrumentation: str) -> str:
37
  """
38
  Generate ABC notation using NotaGen.
39
 
 
 
 
40
  Args:
41
  period: Musical period (e.g., Baroque, Classical, Romantic)
42
  composer: Composer style (e.g., Bach, Mozart, Chopin)
@@ -54,31 +195,14 @@ def generate_abc(period: str, composer: str, instrumentation: str) -> str:
54
  logger.info(f"Generating ABC for: {period}-{composer}-{instrumentation}")
55
 
56
  # Call the NotaGen tool's forward method
57
- # This will return a formatted string with file paths
58
  result = notagen_tool.forward(
59
  period=period,
60
  composer=composer,
61
  instrumentation=instrumentation
62
- )
63
 
64
- # Extract just the ABC content from the result
65
- # The result contains file paths and other info, but we only need the ABC
66
- if "Error:" in result:
67
- logger.error(f"Generation error: {result}")
68
- return result
69
-
70
- # Parse the result to extract ABC content
71
- # The result format is: "Successfully generated...\n\nABC notation preview:\n```\n{abc}```"
72
- if "ABC notation preview:" in result:
73
- abc_start = result.find("```\n") + 4
74
- abc_end = result.rfind("\n```")
75
- if abc_start > 3 and abc_end > abc_start:
76
- abc_content = result[abc_start:abc_end]
77
- logger.info(f"✅ Successfully generated ABC notation ({len(abc_content)} chars)")
78
- return abc_content
79
-
80
- # If we can't parse it, return the full result
81
- logger.warning("Could not parse ABC from result, returning full result")
82
  return result
83
 
84
  except Exception as e:
@@ -170,8 +294,4 @@ with gr.Blocks(title="NotaGen - Symbolic Music Generation") as demo:
170
 
171
  # Launch the app
172
  if __name__ == "__main__":
173
- demo.launch(
174
- server_name="0.0.0.0", # Allow external access
175
- server_port=7860, # Default HF Spaces port
176
- share=False # No need to share, HF handles this
177
- )
 
5
  It accepts three parameters (period, composer, instrumentation) and returns ABC notation.
6
 
7
  The ABC notation can then be processed by WeaveMuse locally for XML/PDF conversion.
8
+
9
+ IMPORTANT: Zero GPU Strategy
10
+ ----------------------------
11
+ - Model initialization and weight downloading happen OUTSIDE @spaces.GPU decorated functions
12
+ - Only the actual inference happens inside the GPU-allocated function
13
+ - This ensures efficient GPU usage (only during inference, not during setup)
14
  """
15
 
16
  import gradio as gr
 
18
  import torch
19
  import logging
20
  import traceback
21
+ import os
22
+ from smolagents import Tool
23
+ from typing import Optional
24
+ from weavemuse.models.notagen.inference import inference_patch, download_model_weights
25
+
26
 
 
27
  logging.basicConfig(level=logging.INFO)
28
  logger = logging.getLogger(__name__)
29
 
30
+ # ============================================================================
31
+ # INITIALIZATION PHASE (Outside GPU allocation)
32
+ # ============================================================================
33
+ # Download model weights and prepare everything BEFORE GPU functions are called
34
+ # This ensures GPU is only used for actual inference, not for setup
35
+
36
  device = "cuda"
37
+ logger.info(f"Preparing NotaGen tool on device: {device}")
38
+
39
+
40
+ class SimpleNotaGenTool(Tool):
41
+ """
42
+ Simple tool for symbolic music generation using NotaGen model.
43
+
44
+ This tool can:
45
+ - Generate ABC notation from text prompts
46
+ - Create music in specific styles and periods
47
+ - Generate compositions for specified instrumentation
48
+ - Handle conditional generation with period-composer-instrumentation prompts
49
+ - Convert ABC to XML, PDF, MIDI, and MP3 formats
50
+ - Generate PDF images for visual display
51
+
52
+ Note: This is a simplified version without VRAM management.
53
+ """
54
+
55
+ # Class attributes required by smolagents
56
+ name = "notagen"
57
+ description = (
58
+ "Generates symbolic music in ABC notation format with full conversion capabilities. "
59
+ "Can create compositions only accepts three parameters: musical period, composer, and instrumentation (Use Piano for better results). "
60
+ "composers, and instrumentation. Supports conditional generation with format: "
61
+ "'Period-Composer-Instrumentation' (e.g., 'Romantic-Chopin-Piano'). "
62
+ "Automatically converts to various formats including PDF for visual display."
63
+ )
64
+ inputs = {
65
+ "period": {
66
+ "type": "string",
67
+ "description": "Musical period (e.g., Baroque, Classical, Romantic)",
68
+ },
69
+ "composer": {
70
+ "type": "string",
71
+ "description": "Composer style to emulate (e.g., Bach, Mozart, Chopin)",
72
+ },
73
+ "instrumentation": {
74
+ "type": "string",
75
+ "description": "Instruments to use (e.g., Piano, Violin, Orchestra)",
76
+ }
77
+ }
78
+ output_type = "string"
79
+
80
+ def __init__(
81
+ self,
82
+ device: str = "auto",
83
+ model_id: str = "manoskary/NotaGenX-Quantized",
84
+ output_dir: Optional[str] = None,
85
+ **kwargs
86
+ ):
87
+ """
88
+ Initialize NotaGen tool.
89
+
90
+ Args:
91
+ device: Device to run on ("auto", "cuda", "cpu")
92
+ model_id: NotaGen model ID
93
+ output_dir: Directory for output files
94
+ **kwargs: Additional arguments
95
+ """
96
+
97
+ # NotaGen is smaller model, estimate VRAM usage
98
+ estimated_vram = 2000.0
99
+
100
+ super().__init__()
101
+
102
+ self.output_dir = output_dir or "/tmp/notagen_output"
103
+ self.model_id = model_id
104
+ self.device = device
105
+
106
+ # Download model weights during initialization (outside GPU function)
107
+ self.download_model_weights(repo_id=model_id)
108
+
109
+ os.makedirs(self.output_dir, exist_ok=True)
110
+ logger.info(f"Simple NotaGen tool initialized")
111
+
112
+ def forward(self, period: str, composer: str, instrumentation: str) -> str:
113
+ """
114
+ Generate symbolic music using NotaGen.
115
+
116
+ Args:
117
+ period: Musical period (e.g., Baroque, Classical, Romantic)
118
+ composer: Composer style to emulate (e.g., Bach, Mozart, Chopin)
119
+ instrumentation: Instruments to use (e.g., Piano, Violin, Orchestra)
120
+
121
+ Returns:
122
+ Path to generated ABC file or error message
123
+ """
124
+ logger.info(f"Generating music: {period}-{composer}-{instrumentation}")
125
+
126
+ # Create prompt for NotaGen
127
+ prompt = f"{period}-{composer}-{instrumentation}"
128
+
129
+ # Use the inference function
130
+ inference_fn = inference_patch
131
+ if inference_fn is None:
132
+ raise ImportError("inference_patch not available")
133
+
134
+ # Generate ABC notation (placeholder implementation)
135
+ abc_content = inference_fn(period, composer, instrumentation)
136
+ return abc_content
137
+
138
+ def download_model_weights(self, repo_id="manoskary/NotaGenX"):
139
+ """
140
+ Download model weights from HuggingFace.
141
+
142
+ Args:
143
+ repo_id: Repository ID on HuggingFace
144
+ """
145
+ download_model_weights(repo_id=repo_id)
146
+ logger.info("✅ NotaGen model weights downloaded successfully!")
147
+
148
+
149
+ # ============================================================================
150
+ # TOOL INITIALIZATION (Outside GPU allocation)
151
+ # ============================================================================
152
+ # Initialize the tool and download model weights BEFORE the GPU function is called
153
+ # This ensures:
154
+ # 1. Model weights are downloaded once at startup (not during every inference)
155
+ # 2. GPU is only allocated for actual inference, not for downloading/setup
156
+ # 3. Zero GPU is used efficiently (shorter GPU allocation times)
157
 
158
  try:
159
+ notagen_tool = SimpleNotaGenTool(device=device)
160
  logger.info("✅ NotaGen tool initialized successfully!")
161
  except Exception as e:
162
  logger.error(f"❌ Failed to initialize NotaGen tool: {e}")
 
164
  notagen_tool = None
165
 
166
 
167
+ # ============================================================================
168
+ # GPU-ALLOCATED INFERENCE FUNCTION
169
+ # ============================================================================
170
+ # This function is decorated with @spaces.GPU to request GPU only during execution
171
+ # Model is already loaded, so GPU time is minimal and efficient
172
+
173
  @spaces.GPU(duration=120)
174
  def generate_abc(period: str, composer: str, instrumentation: str) -> str:
175
  """
176
  Generate ABC notation using NotaGen.
177
 
178
+ This function is decorated with @spaces.GPU to allocate GPU only during inference.
179
+ Model weights are already downloaded and prepared outside this function.
180
+
181
  Args:
182
  period: Musical period (e.g., Baroque, Classical, Romantic)
183
  composer: Composer style (e.g., Bach, Mozart, Chopin)
 
195
  logger.info(f"Generating ABC for: {period}-{composer}-{instrumentation}")
196
 
197
  # Call the NotaGen tool's forward method
198
+ # Model is already loaded, this just does the inference
199
  result = notagen_tool.forward(
200
  period=period,
201
  composer=composer,
202
  instrumentation=instrumentation
203
+ )
204
 
205
+ logger.info(f"✅ Successfully generated ABC notation ({len(result)} chars)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  return result
207
 
208
  except Exception as e:
 
294
 
295
  # Launch the app
296
  if __name__ == "__main__":
297
+ demo.launch()