jacob-c commited on
Commit
cc2dcec
·
1 Parent(s): 96110c3
Files changed (1) hide show
  1. app.py +137 -29
app.py CHANGED
@@ -249,12 +249,11 @@ I need EXACTLY {num_phrases} lines of lyrics - one line for each musical phrase.
249
  CRITICAL INSTRUCTIONS:
250
  - Each line MUST be VERY SHORT with only {min_syllables}-{max_syllables} syllables (aim for {avg_syllables} or fewer)
251
  - PRIORITIZE BREVITY - use fewer syllables rather than more
252
- - Keep each line SIMPLE and DIRECT - avoid complex phrases
253
- - Break complete thoughts across MULTIPLE LINES rather than fitting them into one line
254
- - Think of each line as part of a flowing conversation, not a complete sentence
255
- - Each phrase should fit into one measure of music
256
  - Use simple, short words whenever possible
257
- - End each line at a natural speaking pause point
258
 
259
  FORMAT:
260
  - Just write {num_phrases} plain text lines
@@ -263,15 +262,24 @@ FORMAT:
263
  - Don't use any tags or markers
264
  - Don't include section labels like [Verse] or [Chorus]
265
 
266
- EXAMPLE OF WHAT I WANT:
267
- Empty chair ({min_syllables} syllables)
268
- Waiting by the door ({avg_syllables} syllables)
269
- Memories fade ({min_syllables+1} syllables)
270
- Into silence ({avg_syllables-1} syllables)
271
- Your ghost remains ({avg_syllables} syllables)
272
- (... and so on)
273
 
274
- JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES, KEEPING EACH LINE TO {min_syllables}-{max_syllables} SYLLABLES.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  """
276
 
277
  # Generate lyrics using the LLM model
@@ -631,37 +639,137 @@ def analyze_lyrics_rhythm_match(lyrics, lyric_templates, genre="pop"):
631
  result += f"- Average stress pattern accuracy: {avg_stress_percentage:.1f}%\n"
632
  result += f"- Overall rhythmic accuracy: {((range_match_rate + avg_stress_percentage) / 2):.1f}%\n"
633
 
634
- # Add guidance on ideal distribution for syllables
635
- result += f"\n**Syllable Distribution Guidance:**\n"
 
 
 
 
 
 
 
636
  result += f"- Aim for {min([t.get('min_expected', 3) for t in lyric_templates])}-{max([t.get('max_expected', 7) for t in lyric_templates])} syllables per line\n"
637
- result += f"- Break complete thoughts across multiple lines for a more natural flow\n"
638
- result += f"- Allow sentences to span 2-3 measures for better musical phrasing\n"
 
639
 
640
  # Add genre-specific notes
641
  result += f"\n**Genre Notes ({genre}):**\n"
642
 
643
  # Add appropriate genre notes based on genre
644
  if genre.lower() == "pop":
645
- result += "- Pop lyrics are typically concise with 3-7 syllables per musical phrase\n"
646
- result += "- Strong beats often align with stressed syllables in important words\n"
647
  elif genre.lower() == "rock":
648
- result += "- Rock lyrics favor brevity with 3-6 syllables per musical phrase\n"
649
- result += "- Emphasis on strong beats for rhythmic impact\n"
650
  elif genre.lower() == "country":
651
- result += "- Country lyrics tend toward clear storytelling with 3-6 syllables per phrase\n"
652
- result += "- Natural speech rhythms are important for authentic delivery\n"
653
  elif genre.lower() == "disco":
654
- result += "- Disco lyrics work well with 4-7 syllables per musical phrase\n"
655
- result += "- Rhythmic patterns often emphasize dance-friendly phrasing\n"
656
  elif genre.lower() == "metal":
657
- result += "- Metal lyrics balance intensity with 3-7 syllables per musical phrase\n"
658
- result += "- Strong syllables on strong beats create powerful impact\n"
659
  else:
660
- result += "- This genre typically works well with concise, focused phrasing\n"
661
- result += "- Consider breaking complete thoughts across multiple lines\n"
662
 
663
  return result
664
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665
  # Create Gradio interface
666
  def create_interface():
667
  with gr.Blocks(title="Music Analysis & Lyrics Generator") as demo:
 
249
  CRITICAL INSTRUCTIONS:
250
  - Each line MUST be VERY SHORT with only {min_syllables}-{max_syllables} syllables (aim for {avg_syllables} or fewer)
251
  - PRIORITIZE BREVITY - use fewer syllables rather than more
252
+ - CONNECT YOUR LINES - spread complete thoughts across 2-3 consecutive lines
253
+ - Create SENTENCE FLOW across lines instead of making each line independent
254
+ - Let sentence clauses and phrases flow naturally across multiple lines
255
+ - Each individual line should still fit into one measure of music
256
  - Use simple, short words whenever possible
 
257
 
258
  FORMAT:
259
  - Just write {num_phrases} plain text lines
 
262
  - Don't use any tags or markers
263
  - Don't include section labels like [Verse] or [Chorus]
264
 
265
+ EXAMPLE OF CONNECTED THOUGHTS ACROSS LINES:
 
 
 
 
 
 
266
 
267
+ Moonlight falls (3 syllables)
268
+ through my window pane (5 syllables)
269
+ as I wait for you (5 syllables)
270
+
271
+ Notice how these 3 lines form ONE complete sentence.
272
+
273
+ Another example:
274
+
275
+ Whispers fade (3 syllables)
276
+ in the morning light (5 syllables)
277
+ leaving memories (5 syllables)
278
+ of our last goodbye (5 syllables)
279
+
280
+ These 4 lines form a connected thought, not independent statements.
281
+
282
+ JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES, KEEPING EACH LINE TO {min_syllables}-{max_syllables} SYLLABLES, WITH CONNECTED THOUGHTS ACROSS LINES.
283
  """
284
 
285
  # Generate lyrics using the LLM model
 
639
  result += f"- Average stress pattern accuracy: {avg_stress_percentage:.1f}%\n"
640
  result += f"- Overall rhythmic accuracy: {((range_match_rate + avg_stress_percentage) / 2):.1f}%\n"
641
 
642
+ # Analyze sentence flow across lines
643
+ sentence_flow_analysis = analyze_sentence_flow(lines)
644
+ result += f"\n**Sentence Flow Analysis:**\n"
645
+ result += f"- Connected thought groups: {sentence_flow_analysis['connected_groups']} detected\n"
646
+ result += f"- Average lines per thought: {sentence_flow_analysis['avg_lines_per_group']:.1f}\n"
647
+ result += f"- Flow quality: {sentence_flow_analysis['flow_quality']}\n"
648
+
649
+ # Add guidance on ideal distribution for syllables and sentence flow
650
+ result += f"\n**Syllable & Flow Guidance:**\n"
651
  result += f"- Aim for {min([t.get('min_expected', 3) for t in lyric_templates])}-{max([t.get('max_expected', 7) for t in lyric_templates])} syllables per line\n"
652
+ result += f"- Break complete thoughts across 2-3 lines for natural flow\n"
653
+ result += f"- Connect your lyrics with sentence fragments that flow across lines\n"
654
+ result += f"- Use conjunctions, prepositions, and dependent clauses to connect lines\n"
655
 
656
  # Add genre-specific notes
657
  result += f"\n**Genre Notes ({genre}):**\n"
658
 
659
  # Add appropriate genre notes based on genre
660
  if genre.lower() == "pop":
661
+ result += "- Pop lyrics work well with thoughts spanning 2-3 musical phrases\n"
662
+ result += "- Create flow by connecting lines with transitions like 'as', 'when', 'through'\n"
663
  elif genre.lower() == "rock":
664
+ result += "- Rock lyrics benefit from short phrases that build into complete thoughts\n"
665
+ result += "- Use line breaks strategically to emphasize key words\n"
666
  elif genre.lower() == "country":
667
+ result += "- Country lyrics tell stories that flow naturally across multiple lines\n"
668
+ result += "- Connect narrative elements across phrases for authentic storytelling\n"
669
  elif genre.lower() == "disco":
670
+ result += "- Disco lyrics work well with phrases that create rhythmic momentum\n"
671
+ result += "- Use line transitions that maintain energy and flow\n"
672
  elif genre.lower() == "metal":
673
+ result += "- Metal lyrics can create intensity by breaking phrases at dramatic points\n"
674
+ result += "- Connect lines to build tension and release across measures\n"
675
  else:
676
+ result += "- This genre works well with connected thoughts across multiple lines\n"
677
+ result += "- Aim for natural speech flow rather than complete thoughts per line\n"
678
 
679
  return result
680
 
681
+ def analyze_sentence_flow(lines):
682
+ """Analyze how well the lyrics create sentence flow across multiple lines"""
683
+ if not lines or len(lines) < 2:
684
+ return {
685
+ "connected_groups": 0,
686
+ "avg_lines_per_group": 0,
687
+ "flow_quality": "Insufficient lines to analyze"
688
+ }
689
+
690
+ # Simplified analysis looking for grammatical clues of sentence continuation
691
+ continuation_starters = [
692
+ 'and', 'but', 'or', 'nor', 'for', 'yet', 'so', # Coordinating conjunctions
693
+ 'as', 'when', 'while', 'before', 'after', 'since', 'until', 'because', 'although', 'though', # Subordinating conjunctions
694
+ 'with', 'without', 'through', 'throughout', 'beyond', 'beneath', 'under', 'over', 'into', 'onto', # Prepositions
695
+ 'to', 'from', 'by', 'at', 'in', 'on', 'of', # Common prepositions
696
+ 'where', 'how', 'who', 'whom', 'whose', 'which', 'that', # Relative pronouns
697
+ 'if', 'then', # Conditional connectors
698
+ ]
699
+
700
+ # Check for lines that likely continue a thought from previous line
701
+ connected_lines = []
702
+ potential_groups = []
703
+ current_group = [0] # Start with first line
704
+
705
+ for i in range(1, len(lines)):
706
+ # Check if line starts with a continuation word
707
+ words = lines[i].lower().split()
708
+
709
+ # Empty line or no words
710
+ if not words:
711
+ if len(current_group) > 1: # Only consider groups of 2+ lines
712
+ potential_groups.append(current_group.copy())
713
+ current_group = [i]
714
+ continue
715
+
716
+ # Check first word for continuation clues
717
+ first_word = words[0].strip(',.!?;:')
718
+ if first_word in continuation_starters:
719
+ connected_lines.append(i)
720
+ current_group.append(i)
721
+ # Check for absence of capitalization as continuation clue
722
+ elif not first_word[0].isupper() and first_word[0].isalpha():
723
+ connected_lines.append(i)
724
+ current_group.append(i)
725
+ # Check if current line is very short (likely part of a continued thought)
726
+ elif len(words) <= 3 and i < len(lines) - 1:
727
+ # Look ahead to see if next line could be a continuation
728
+ if i+1 < len(lines):
729
+ next_words = lines[i+1].lower().split()
730
+ if next_words and next_words[0] in continuation_starters:
731
+ connected_lines.append(i)
732
+ current_group.append(i)
733
+ else:
734
+ # This might end a group
735
+ if len(current_group) > 1: # Only consider groups of 2+ lines
736
+ potential_groups.append(current_group.copy())
737
+ current_group = [i]
738
+ else:
739
+ # This likely starts a new thought
740
+ if len(current_group) > 1: # Only consider groups of 2+ lines
741
+ potential_groups.append(current_group.copy())
742
+ current_group = [i]
743
+
744
+ # Add the last group if it has multiple lines
745
+ if len(current_group) > 1:
746
+ potential_groups.append(current_group)
747
+
748
+ # Calculate metrics
749
+ connected_groups = len(potential_groups)
750
+
751
+ if connected_groups > 0:
752
+ avg_lines_per_group = sum(len(group) for group in potential_groups) / connected_groups
753
+
754
+ # Determine flow quality
755
+ if connected_groups >= len(lines) / 3 and avg_lines_per_group >= 2.5:
756
+ flow_quality = "Excellent - multiple connected thoughts across lines"
757
+ elif connected_groups >= len(lines) / 4 and avg_lines_per_group >= 2:
758
+ flow_quality = "Good - some connected thoughts across lines"
759
+ elif connected_groups > 0:
760
+ flow_quality = "Fair - limited connection between lines"
761
+ else:
762
+ flow_quality = "Poor - mostly independent lines"
763
+ else:
764
+ avg_lines_per_group = 0
765
+ flow_quality = "Poor - no connected thoughts detected"
766
+
767
+ return {
768
+ "connected_groups": connected_groups,
769
+ "avg_lines_per_group": avg_lines_per_group,
770
+ "flow_quality": flow_quality
771
+ }
772
+
773
  # Create Gradio interface
774
  def create_interface():
775
  with gr.Blocks(title="Music Analysis & Lyrics Generator") as demo: