| |
| """ |
| engine_llm.py – LLM Lyric Expander Module (Local Model: microsoft/phi-2) |
| Generates only: Song Title + 2 verses (8 lines each, rhyming and flowing). |
| """ |
|
|
| import torch |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from typing import Tuple |
|
|
| MODEL_NAME = "microsoft/phi-2" |
|
|
| _tokenizer = None |
| _model = None |
|
|
| def _load_model(): |
| global _tokenizer, _model |
| if _tokenizer is None: |
| _tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) |
| _model = AutoModelForCausalLM.from_pretrained( |
| MODEL_NAME, |
| torch_dtype=torch.float32, |
| trust_remote_code=True, |
| low_cpu_mem_usage=True |
| ) |
| return _tokenizer, _model |
|
|
| def run_llm_lyric_expander(brief_text: str) -> Tuple[str, str]: |
| """ |
| Generate only: Song Title + 2 verses (8 lines each, rhyming and flowing). |
| No extra text, no sections, no production notes. |
| """ |
| if not brief_text or brief_text.strip() == "": |
| return "⚠️ Please provide a creative brief.", "No brief provided." |
|
|
| try: |
| tokenizer, model = _load_model() |
|
|
| prompt = f"""You are a songwriter. Based on the creative brief below, output ONLY: |
| 1. A song title |
| 2. Two verses of exactly 8 lines each (16 lines total) |
| Each verse must rhyme and flow. Do not add any extra text, comments, or sections. |
| |
| Creative Brief: |
| {brief_text} |
| |
| Output format: |
| Title: [Your Title] |
| |
| [Verse 1] |
| Line 1 |
| Line 2 |
| Line 3 |
| Line 4 |
| Line 5 |
| Line 6 |
| Line 7 |
| Line 8 |
| |
| [Verse 2] |
| Line 1 |
| Line 2 |
| Line 3 |
| Line 4 |
| Line 5 |
| Line 6 |
| Line 7 |
| Line 8 |
| |
| Now output exactly that:""" |
|
|
| inputs = tokenizer(prompt, return_tensors="pt") |
| with torch.no_grad(): |
| outputs = model.generate( |
| inputs.input_ids, |
| max_new_tokens=512, |
| temperature=0.8, |
| top_p=0.9, |
| do_sample=True, |
| pad_token_id=tokenizer.eos_token_id, |
| repetition_penalty=1.1 |
| ) |
| full_output = tokenizer.decode(outputs[0], skip_special_tokens=True) |
| |
| lyrics = full_output[len(prompt):].strip() |
| if not lyrics: |
| lyrics = _fallback_lyrics(brief_text) |
| return lyrics, "✅ Lyrics generated using microsoft/phi-2 (local model) – no external API needed." |
|
|
| except Exception as e: |
| return _fallback_lyrics(brief_text), f"❌ Local model error: {str(e)}" |
|
|
| def _fallback_lyrics(brief_text: str) -> str: |
| return f"""Title: Echoes of the Creative Brief |
| |
| [Verse 1] |
| The image pulses, a hidden beat, |
| Colors and edges, a rhythmic heat. |
| The prompt whispers, a story untold, |
| In the machine, the future unfolds. |
| The seed is planted, the BPM set, |
| A vision of sound, a path to beget. |
| The LLM listens, the brief is read, |
| A symphony born from the image's thread. |
| |
| [Verse 2] |
| Let the music rise, let the lyrics flow, |
| The truth of the image begins to show. |
| In the resonance, we find the key, |
| The answer is here, and it's set to be free. |
| And so the song completes the frame, |
| A circle closed, a legend named. |
| The LYGO suite, the final sight, |
| A journey from sound into light.""" |