carterwward
update cache
374f6c2
import os
import gradio as gr
import spotipy
import uvicorn
from urllib import request
from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import HTMLResponse, RedirectResponse
from starlette.requests import Request as SRequest
from fastapi.responses import HTMLResponse
from fastapi.responses import RedirectResponse
from src.playlist_builder import *
from src.evolutionary_alrogithm import Population, simple_mutation, simple_crossover, THUMBS_UP, THUMBS_DOWN, ADD_TO_PLAYLIST
from src.spotipy_utils import get_auth_manager
NUM_SONGS = 9
DEFAULT_MUTATION_SIZE = 0.25
SONG_CHOICES = [THUMBS_UP, THUMBS_DOWN, ADD_TO_PLAYLIST]
OPTIONS_TITLE = """# 🧬 Options"""
APP_HEADER = """# Evolutionary Playlist Builder"""
EXPLORATION_HEADER = """## Rate of Exploration"""
PLAYLIST_HEADER = """## Current Playlist"""
FAST_API_KEY = os.environ["FAST_API_KEY"]
app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key=FAST_API_KEY)
@app.get('/', response_class=HTMLResponse)
async def homepage(request: SRequest):
auth_manager = get_auth_manager() # Need auth manager to generate Spotify API authentication url.
auth_url = auth_manager.get_authorize_url()
return "<a href='" + auth_url + "'>Login to Spotify</a>"
def initialize_playlist_builder():
demo = gr.Blocks()
with demo:
gr.Markdown(APP_HEADER)
with gr.Row():
# Initialize app attributes
do_crossover = gr.State(False)
do_mutation = gr.State(False)
population = Population(NUM_SONGS, DEFAULT_MUTATION_SIZE, mutation_function=simple_mutation, crossover_function=simple_crossover)
population_state = gr.State(population)
# Generate blank traversal visualization.
initial_traversal_history = population.generate_traversal_viz()
# Layout first column.
with gr.Column():
gr.Markdown(
f"""
This app is still in development mode so if you want the ability to add a playlist to your library, email carterward4@gmail.com with your name, spotify email, and the subject as PLAYLIST ACCESS REQUEST.
""")
options = gr.Box(visible=False)
with options:
gr.Markdown(OPTIONS_TITLE)
crossover_radio = gr.Radio(choices=CROSSOVER_OPTIONS, value=None, label="Crossover?") # radio button for crossover options.
mutation_radio = gr.Radio(choices=MUTATION_OPTIONS, value=None, label="Mutate?") # radio button for mutation options.
gr.Markdown(EXPLORATION_HEADER, visible=False)
mutation_size_slider = gr.Slider(minimum=0.0, maximum=1.0, value=DEFAULT_MUTATION_SIZE
, interactive=True, show_label=False, visible=False) # slider controlling mutation slide. Values restricted between 0 and 1.
history_block = gr.Plot(initial_traversal_history, label="Search History") # Plot block for blank viz.
gr.Markdown(PLAYLIST_HEADER)
playlist_display = gr.TextArea(value=population.get_playlist_block_value(), max_lines=10000, show_label=False) # Blank playlist display.
playlist_name = gr.Textbox(interactive=True, label="Enter the name for this playlist!") # Auth. URL entry.
add_playlist = gr.Button(value="Add Playlist to Spotify Library")
# tracking_viz_button = gr.Button(value="Generate Direction Tracking Viz") # Button to add to playlist
playlist_added_message = gr.Markdown(ADDED_TO_PLAYLIST, visible=False)
# Build grid layout with initial song art and options.
index_blocks = []
name_blocks = []
image_blocks = []
dropdown_blocks = []
preview_blocks = []
with gr.Column():
# Init seed options
seed_option = gr.Radio(SEED_OPTIONS, value=SEED_OPTIONS[-1], label="Seed generation?", show_label=True)
seed_options_container = gr.Box(visible=False)
with seed_options_container:
seed_track_search = gr.Textbox(value = None, interactive=True, label="Enter the track name!", show_label=True)
seed_artist_search = gr.Textbox(value = None, interactive=True, label="Enter the artist name!", show_label=True)
search_button = gr.Button(value = "Search for seed!")
search_results = gr.Dropdown(label="Search result options", interactive=True)
# Init population grid.
pop_container = gr.Box(visible=False)
with pop_container:
for row in range(0, population.size, 3): # Iterate over track rows.
with gr.Row():
for col in range(3): # Iterate over track columns.
with gr.Box():
track_index = row + col
if track_index < len(population.pop):
current_song = population.pop[track_index]
song_preview = current_song.get_preview_url()
track_image = gr.Image(value=current_song.get_image_url(), show_label=False, visible=True).style(height=175, width=175)
track_title = gr.Markdown(value=f"{current_song.name} by {current_song.artist}", show_label=False)
track_dropdown = gr.Dropdown(SONG_CHOICES, label = track_index, show_label=False)
else:
track_image = None
song_preview = None
track_image = gr.Image(value=None, show_label=False, visible=True).style(height=175, width=175)
track_title = gr.Markdown(value=f"", show_label=False, visible=True)
track_dropdown = gr.Dropdown(SONG_CHOICES, label = track_index, show_label=False, visible=True)
index_blocks.append(gr.TextArea(value=track_index, visible=False)) # Init index blocks to keep track of everything.
# Render initial images.
image_blocks.append(track_image)
# Add names.
name_blocks.append(track_title)
# Dropdown for song options.
dropdown_blocks.append(track_dropdown)
# Add song preview if it exists.
if song_preview:
preview_blocks.append(gr.Audio(value=song_preview, show_label=False))
else:
preview_blocks.append(gr.Audio(value=song_preview, show_label=False, visible=False))
with gr.Box():
next_generation = gr.Button(value="Next Generation").style(full_width=True)
# Mapping change functions to class methods.
crossover_radio.change(
fn=set_crossover_option,
inputs=[crossover_radio],
outputs=[do_crossover]
)
mutation_radio.change(
fn=set_mutation_option,
inputs=[population_state, do_crossover, mutation_radio],
outputs=[mutation_size_slider, crossover_radio, do_crossover, do_mutation, population_state]
)
mutation_size_slider.change(
fn=update_mutation_size,
inputs=[population_state, mutation_size_slider],
outputs=[population_state]
)
seed_option.change(
fn=change_seed_option,
inputs=[seed_option, population_state],
outputs=[seed_options_container, options, seed_track_search, seed_artist_search, search_results, population_state]
)
search_button.click(
fn=search_for_seed,
inputs=[population_state, seed_artist_search, seed_track_search],
outputs=[population_state, search_results]
)
search_results.change(
fn=set_pop_seed,
inputs=[population_state, search_results],
outputs=[population_state]
)
# Set function to hangle change in dropdown value for each track.
for index_block, dropdown_block in zip(index_blocks, dropdown_blocks):
dropdown_block.change(
fn=set_track_state,
inputs=[population_state, index_block, dropdown_block],
outputs=[population_state]
)
# Set function to generate next generation of tracks.
next_generation.click(
fn=get_next_generation,
inputs=[population_state, do_mutation, do_crossover],
outputs=[pop_container, options, population_state, playlist_display, *image_blocks, *name_blocks, *dropdown_blocks, *preview_blocks, history_block]
)
add_playlist.click(
fn=add_playlist_to_spotify,
inputs=[population_state, playlist_name],
outputs=[playlist_added_message]
)
# tracking_viz_button.click(
# fn=generate_population_direction_tracking_viz,
# inputs=[population_state]
# )
return demo
gradio_app = initialize_playlist_builder()
playlist_app = gr.mount_gradio_app(app, gradio_app, "/gradio", gradio_api_url="http://localhost:7860/")
uvicorn.run(app, host="0.0.0.0", port=7860)