Skip to content

Instantly share code, notes, and snippets.

@timothywarner
Last active February 27, 2025 22:03
Show Gist options
  • Save timothywarner/4c55d2edee8eeebc9b2dab722e10ab4e to your computer and use it in GitHub Desktop.
Save timothywarner/4c55d2edee8eeebc9b2dab722e10ab4e to your computer and use it in GitHub Desktop.
A tongue-in-cheek implementation that combines Retrieval Augmented Generation (RAG) with time manipulation to generate ragtime music. This script demonstrates the perfect intersection of AI humor and dad jokes - where modern machine learning techniques meet historical music genres. The pun works on multiple levels: 1. RAG (Retrieval Augmented Ge…
#!/usr/bin/env python3
"""
RAG_time Music Generator
A clever demonstration of Retrieval Augmented Generation (RAG)
and time manipulation to create MIDI music.
Scott Joplin meets LLMs: The perfect mashup nobody asked for.
This is what happens when a programmer makes a music pun:
R.A.G. (Retrieval Augmented Generation) + time manipulation = RAGtime
"""
# Standard library imports
import random
import time
from datetime import datetime
from typing import Dict, List, Tuple, Union, Optional, Any
# Third-party imports
try:
import numpy as np
import torch
from midiutil import MIDIFile
from transformers import AutoTokenizer, AutoModel
except ImportError as e:
print(f"Error importing required libraries: {e}")
print("Please install required packages: pip install numpy torch midiutil transformers")
exit(1)
# === R.A.G Component: Retrieval Augmented Generation ===
class MusicKnowledgeBase:
"""Simulated knowledge base of musical patterns and theory.
This class provides a mock implementation of a retrieval system
for ragtime music knowledge, including patterns, composers, and pieces.
"""
def __init__(self) -> None:
"""Initialize the knowledge base with ragtime music information."""
# The "Retrieval" in RAGtime
self.ragtime_patterns: List[str] = [
"C E G C' - E G C' E'", # C major arpeggio with extension
"G B D' G' - B D' G' B'", # G major arpeggio with extension
"F A C' F' - A C' F' A'", # F major arpeggio with extension
"Left hand stride pattern: low bass note, chord, chord, chord",
"Syncopated melody with emphasis on off-beats",
]
self.composers: List[str] = ["Scott Joplin", "James Scott", "Joseph Lamb"]
self.famous_pieces: Dict[str, List[str]] = {
"Scott Joplin": ["Maple Leaf Rag", "The Entertainer", "Elite Syncopations"],
"James Scott": ["Frog Legs Rag", "Grace and Beauty", "Climax Rag"],
"Joseph Lamb": ["American Beauty Rag", "Bohemia Rag", "Ragtime Nightingale"]
}
def retrieve(self, query: str) -> List[str]:
"""Simulate retrieval of relevant musical knowledge.
Args:
query: The search query string
Returns:
A list of relevant musical knowledge items
"""
# In a real RAG system, this would use embeddings and vector search
# But in this pun, we're just pretending to be smart
results: List[str] = []
if "pattern" in query.lower():
results.extend(self.ragtime_patterns)
if "composer" in query.lower():
results.extend(self.composers)
if "piece" in query.lower() or "composition" in query.lower():
for composer, pieces in self.famous_pieces.items():
results.extend([f"{piece} by {composer}" for piece in pieces])
# If no specific query matches, return a mix of information
if not results:
results = [random.choice(self.ragtime_patterns)]
composer = random.choice(self.composers)
results.append(f"Inspired by {composer}")
try:
results.append(f"Similar to {random.choice(self.famous_pieces[composer])}")
except (KeyError, IndexError):
# Fallback in case of unexpected data issues
results.append("Similar to classic ragtime pieces")
return results
# === Time Manipulation Component ===
class TimeManipulator:
"""Manipulates time signatures and tempo for music generation.
This class handles all time-related aspects of ragtime music generation,
including time signatures, tempos, and timestamp-based seeding.
"""
def __init__(self) -> None:
"""Initialize the time manipulator with ragtime-appropriate parameters."""
# The "time" in RAGtime
self.time_signatures: List[Tuple[int, int]] = [(2, 4), (4, 4)] # Common ragtime time signatures
self.tempos: range = range(85, 110) # Classic ragtime tempos (BPM)
def get_time_signature(self) -> Tuple[int, int]:
"""Return an appropriate ragtime time signature.
Returns:
A tuple of (numerator, denominator) for the time signature
"""
# Classic ragtime is typically in 2/4 time
return random.choice(self.time_signatures)
def get_tempo(self) -> int:
"""Return an appropriate ragtime tempo.
Returns:
An integer representing tempo in BPM
"""
# Ragtime is typically played at moderate tempos
# Just like this code should be read at a moderate tempo to get the joke
return random.choice(self.tempos)
def get_timestamp(self) -> Dict[str, int]:
"""Return the current time as a musical seed.
Returns:
A dictionary containing time components
"""
now = datetime.now()
# Use the current time components as musical seeds
# See what we did there? TIME components... for RAGtime...
return {
"hour": now.hour,
"minute": now.minute,
"second": now.second,
"microsecond": now.microsecond
}
# === Music Generator ===
class RAG_time_Generator:
"""Generates ragtime music using RAG and time manipulation.
This class combines the knowledge retrieval and time manipulation
components to generate ragtime music in a humorous demonstration
of the RAG + time = RAGtime pun.
"""
def __init__(self) -> None:
"""Initialize the RAGtime generator with its component systems."""
# Combining RAG + time = RAGtime. Get it? GET IT?
self.knowledge_base = MusicKnowledgeBase()
self.time_manipulator = TimeManipulator()
def generate(self, seed_query: str = "Generate a classic ragtime pattern") -> Dict[str, Any]:
"""Generate a ragtime music piece.
Args:
seed_query: The query to retrieve musical knowledge
Returns:
A dictionary containing the generation results
"""
try:
# Step 1: Retrieve musical knowledge (the RAG part)
print("🔍 Retrieving musical knowledge...")
musical_knowledge = self.knowledge_base.retrieve(seed_query)
# Step 2: Get time-based parameters (the time part)
print("⏱️ Manipulating time parameters...")
time_signature = self.time_manipulator.get_time_signature()
tempo = self.time_manipulator.get_tempo()
timestamp = self.time_manipulator.get_timestamp()
# Step 3: Create the MIDI file (simulated)
print("🎵 Generating MIDI sequence...")
print("🎩 Putting the RAG and time together to make... wait for it...")
midi_file = self._create_midi(musical_knowledge, time_signature, tempo, timestamp)
return {
"knowledge_used": musical_knowledge,
"time_signature": f"{time_signature[0]}/{time_signature[1]}",
"tempo": tempo,
"timestamp_seed": timestamp,
"midi_file": midi_file
}
except Exception as e:
print(f"Error generating RAGtime music: {e}")
# Return a minimal result in case of error
return {
"error": str(e),
"knowledge_used": [],
"time_signature": "2/4",
"tempo": 100,
"timestamp_seed": {},
"midi_file": "error_ragtime.mid"
}
def _create_midi(self, knowledge: List[str], time_signature: Tuple[int, int],
tempo: int, timestamp: Dict[str, int]) -> str:
"""Simulate MIDI file creation.
Args:
knowledge: Retrieved musical knowledge
time_signature: The time signature as (numerator, denominator)
tempo: The tempo in BPM
timestamp: Time components for seeding
Returns:
The filename of the generated MIDI file
"""
# This is a simplified simulation - a real implementation would create an actual MIDI file
# But the pun is 100% real
try:
return f"ragtime_{timestamp['hour']}_{timestamp['minute']}_{timestamp['second']}.mid"
except KeyError:
# Fallback in case of missing timestamp components
return f"ragtime_{int(time.time())}.mid"
def main() -> None:
"""Run the RAGtime music generator demonstration."""
print("🎹 RAG_time Music Generator 🎹")
print("Combining Retrieval Augmented Generation with Time Manipulation")
print("-" * 60)
# Scott Joplin would be so proud. Or confused. Probably confused.
generator = RAG_time_Generator()
print("Generating a new RAGtime composition...")
result = generator.generate("Generate a syncopated ragtime pattern in the style of Scott Joplin")
if "error" in result:
print(f"\n❌ Generation Error: {result['error']}")
else:
print("\n✨ Generation Complete! ✨")
print(f"Time Signature: {result['time_signature']}")
print(f"Tempo: {result['tempo']} BPM")
print(f"Musical Knowledge Applied:")
for i, knowledge in enumerate(result['knowledge_used'], 1):
print(f" {i}. {knowledge}")
print(f"Output File: {result['midi_file']}")
print("\nRAGtime: Where we retrieve musical knowledge and manipulate time signatures... get it? 🎩🎵")
print("The perfect intersection of AI and dad jokes. You're welcome, LinkedIn.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment