DjPapzin commited on
Commit
6fd136c
1 Parent(s): efbe3e5

Upload 34 files

Browse files
.env ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ OPENAI_API_KEY=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
2
+ ACTIVELOOP_TOKEN=eyJhbGciOiJIUzUxMiIsImlhdCI6MTY4NzM1NDkyMSwiZXhwIjoxNzE4OTc3MjYwfQ.eyJpZCI6ImRqcGFwemluIn0.ezQ-ChtNr76KXlEr_lSJuxsa9im6I2X9BeDpGzMWzdz2kkC7OI9zAD2iQ8LO98gdKC0gYRcE3FAAX0FnYgXeTg
3
+ ACTIVELOOP_ORG_ID=djpapzin
4
+
5
+ USE_STORAGE=True # Set to True to enable upstash
6
+ UPSTASH_URL=equipped-alien-35043.upstash.io
7
+ UPSTASH_PASSWORD=74eebd45fc4048138663d63869bf01c3
.gitignore ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ disney-lyrics/
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ #Pipfile.lock
97
+
98
+ # poetry
99
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
103
+ #poetry.lock
104
+
105
+ # pdm
106
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
107
+ #pdm.lock
108
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
109
+ # in version control.
110
+ # https://pdm.fming.dev/#use-with-ide
111
+ .pdm.toml
112
+
113
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
114
+ __pypackages__/
115
+
116
+ # Celery stuff
117
+ celerybeat-schedule
118
+ celerybeat.pid
119
+
120
+ # SageMath parsed files
121
+ *.sage.py
122
+
123
+ # Environments
124
+ .env
125
+ .venv
126
+ env/
127
+ venv/
128
+ ENV/
129
+ env.bak/
130
+ venv.bak/
131
+
132
+ # Spyder project settings
133
+ .spyderproject
134
+ .spyproject
135
+
136
+ # Rope project settings
137
+ .ropeproject
138
+
139
+ # mkdocs documentation
140
+ /site
141
+
142
+ # mypy
143
+ .mypy_cache/
144
+ .dmypy.json
145
+ dmypy.json
146
+
147
+ # Pyre type checker
148
+ .pyre/
149
+
150
+ # pytype static type analyzer
151
+ .pytype/
152
+
153
+ # Cython debug symbols
154
+ cython_debug/
155
+
156
+ # PyCharm
157
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
158
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
159
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
160
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
161
+ #.idea/
.streamlit/config.toml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ [theme]
2
+ base="dark"
3
+ primaryColor="#9553BD"
API Documentation.md ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Play My Emotions API Documentation
2
+
3
+ ### Overview
4
+
5
+ The Play My Emotions API provides song recommendations based on user emotions. The primary endpoint is `/recommend`, which takes in a user's emotional text and returns a list of recommended songs.
6
+
7
+ ### Base URL
8
+
9
+ ```
10
+ http://127.0.0.1:8000
11
+ ```
12
+
13
+ ### Endpoints
14
+
15
+ #### 1. POST /recommend
16
+
17
+ **Description**:
18
+ Provides song recommendations based on the user's emotional input.
19
+
20
+ **Request**:
21
+
22
+ - **Method**: POST
23
+ - **URL**: `/recommend`
24
+ - **Headers**:
25
+ - `Content-Type: application/json`
26
+ - **Body**:
27
+
28
+ ```json
29
+ {
30
+ "emotion_text": "string"
31
+ }
32
+ ```
33
+
34
+ **Parameters**:
35
+
36
+ - `emotion_text` (required): A string containing the user's emotional state or feelings.
37
+
38
+ **Response**:
39
+
40
+ - **Status Code**: 200 OK
41
+ - **Body**:
42
+
43
+ ```json
44
+ {
45
+ "emotions": "string",
46
+ "songs": [
47
+ {
48
+ "name": "string",
49
+ "embed_url": "string"
50
+ },
51
+ ...
52
+ ]
53
+ }
54
+ ```
55
+
56
+ **Response Fields**:
57
+
58
+ - `emotions`: A string representing the interpreted emotions based on the user's input.
59
+ - `songs`: An array of song objects. Each object contains:
60
+ - `name`: The name of the recommended song.
61
+ - `embed_url`: The URL for embedding the song (e.g., a Spotify or YouTube embed link).
62
+
63
+ **Example Request**:
64
+
65
+ ```json
66
+ {
67
+ "emotion_text": "I am feeling joyful"
68
+ }
69
+ ```
70
+
71
+ **Example Response**:
72
+
73
+ ```json
74
+ {
75
+ "emotions": "joyful, happy, elated",
76
+ "songs": [
77
+ {
78
+ "name": "Song Name 1",
79
+ "embed_url": "https://embed-link-1.com"
80
+ },
81
+ {
82
+ "name": "Song Name 2",
83
+ "embed_url": "https://embed-link-2.com"
84
+ }
85
+ ]
86
+ }
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
PlayMyEmotions.jpeg ADDED
README.md CHANGED
@@ -1,10 +1,32 @@
1
- ---
2
- title: Emo Play
3
- emoji:
4
- colorFrom: green
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Play My Emotions 🎵🏰🔮
2
+
3
+ ![Live Demo](PlayMyEmotions.jpeg)
4
+
5
+ The app is on [Hugging Face Spaces](https://huggingface.co/spaces/DjPapzin/PlayMyEmotions) 🤗
6
+
7
+ This app takes a user input and suggests songs that match its emotions/vibes.
8
+
9
+ Made with [DeepLake](https://www.deeplake.ai/) 🚀 and [LangChain](https://python.langchain.com/en/latest/index.html) 🦜⛓️
10
+
11
+ We also used [Upstash](https://upstash.com/) to store user inputs/emotions and recommended songs.
12
+
13
+ ## How it works
14
+
15
+ The application follows a sequence of steps to deliver Disney songs matching the user's emotions:
16
+
17
+ - **User Input**: The application starts by collecting the user's emotional state through a text input.
18
+ - **Emotion Encoding**: The user-provided emotions are then fed to a Language Model (LLM). The LLM interprets and encodes these emotions.
19
+ - **Similarity Search**: These encoded emotions are utilized to perform a similarity search within our [vector database](Deep Lake Vector Store in LangChain). This database houses Disney songs, each represented as emotional embeddings.
20
+ - **Song Selection**: From the pool of top matching songs, the application randomly selects one. The selection is weighted, giving preference to songs with higher similarity scores.
21
+ - **Song Retrieval**: The selected song's embedded player is displayed on the webpage for the user. Additionally, the LLM-interpreted emotional state associated with the chosen song is displayed.
22
+
23
+ ## Run it
24
+
25
+ Clone this repo.
26
+
27
+ Create a `venv`:
28
+
29
+ ```bash
30
+ python -m venv .venv
31
+ source .venv/bin/activate
32
+ pip install -r requirements.txt
app.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import necessary libraries and modules
2
+ from fastapi import FastAPI, HTTPException
3
+ from pydantic import BaseModel
4
+ from pathlib import Path
5
+ from dotenv import load_dotenv
6
+ from langchain.chains import LLMChain
7
+ from langchain.prompts import PromptTemplate
8
+ from langchain.chat_models import ChatOpenAI
9
+ from langchain.embeddings.openai import OpenAIEmbeddings
10
+ from langchain.schema import Document
11
+ from data import load_db
12
+ from names import DATASET_ID, MODEL_ID
13
+ from storage import RedisStorage
14
+ from utils import weighted_random_sample
15
+ import os
16
+ import numpy as np
17
+ from typing import List, Dict
18
+
19
+ # Load environment variables
20
+ load_dotenv()
21
+
22
+ # Initialize FastAPI app
23
+ app = FastAPI(title="Play My Emotions API", description="API for emotion-based song recommendation", version="1.0")
24
+
25
+ # Define request and response models
26
+ class EmotionInput(BaseModel):
27
+ emotion_text: str
28
+
29
+ class SongRecommendation(BaseModel):
30
+ emotions: str
31
+ recommended_songs: List[Dict[str, str]]
32
+
33
+ # Check if storage is enabled
34
+ USE_STORAGE = os.environ.get("USE_STORAGE", "True").lower() in ("true", "t", "1")
35
+
36
+ # Initialize necessary components for the app
37
+ def init():
38
+ embeddings = OpenAIEmbeddings(model=MODEL_ID)
39
+ dataset_path = f"hub://{os.environ['ACTIVELOOP_ORG_ID']}/{DATASET_ID}"
40
+
41
+ db = load_db(
42
+ dataset_path,
43
+ embedding_function=embeddings,
44
+ token=os.environ["ACTIVELOOP_TOKEN"],
45
+ read_only=True,
46
+ )
47
+
48
+ storage = RedisStorage(
49
+ host=os.environ["UPSTASH_URL"], password=os.environ["UPSTASH_PASSWORD"]
50
+ )
51
+ prompt = PromptTemplate(
52
+ input_variables=["user_input"],
53
+ template=Path("prompts/bot.prompt").read_text(),
54
+ )
55
+
56
+ llm = ChatOpenAI(temperature=0.3)
57
+ chain = LLMChain(llm=llm, prompt=prompt)
58
+
59
+ return db, storage, chain
60
+
61
+ db, storage, chain = init()
62
+
63
+ # Define API endpoint for song recommendation
64
+ @app.post("/recommend", response_model=SongRecommendation)
65
+ async def recommend_song(emotion: EmotionInput):
66
+ user_input = emotion.emotion_text
67
+ if not user_input:
68
+ raise HTTPException(status_code=400, detail="Emotion input is required")
69
+
70
+ docs, emotions = get_song(user_input, k=20) # Assuming max_number_of_songs is 20 for now
71
+
72
+ # Modified to include song name and embed_url
73
+ recommended_songs = [{"name": doc.metadata["name"], "embed_url": doc.metadata["embed_url"]} for doc in docs]
74
+
75
+ return {"emotions": emotions, "recommended_songs": recommended_songs}
76
+
77
+ # Helper function to get song based on user input
78
+ def get_song(user_input: str, k: int = 20):
79
+ emotions = chain.run(user_input=user_input)
80
+ matches = db.similarity_search_with_score(emotions, distance_metric="cos", k=k)
81
+ docs, scores = zip(
82
+ *normalize_scores_by_sum(filter_scores(matches, 0.8)) # Assuming filter_threshold is 0.8 for now
83
+ )
84
+ choosen_docs = weighted_random_sample(
85
+ np.array(docs), np.array(scores), n=2 # Assuming number_of_displayed_songs is 2 for now
86
+ ).tolist()
87
+ return choosen_docs, emotions
88
+
89
+ # Helper function to filter scores
90
+ def filter_scores(matches, th: float = 0.8):
91
+ return [(doc, score) for (doc, score) in matches if score > th]
92
+
93
+ # Helper function to normalize scores
94
+ def normalize_scores_by_sum(matches):
95
+ scores = [score for _, score in matches]
96
+ tot = sum(scores)
97
+ return [(doc, (score / tot)) for doc, score in matches]
98
+
99
+ # Run the app using uvicorn when the script is executed directly
100
+ if __name__ == "__main__":
101
+ import uvicorn
102
+ uvicorn.run(app, host="0.0.0.0", port=8000)
data.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import necessary libraries and modules
2
+ from dotenv import load_dotenv
3
+ import json
4
+ import os
5
+ from langchain.embeddings.openai import OpenAIEmbeddings
6
+ from langchain.llms import OpenAI
7
+ from langchain.vectorstores import DeepLake
8
+ from names import DATASET_ID, MODEL_ID
9
+
10
+ # Load environment variables
11
+ load_dotenv()
12
+
13
+ # Function to create a DeepLake database from a given dataset path and JSON file
14
+ def create_db(dataset_path: str, json_filepath: str) -> DeepLake:
15
+ # Load data from the JSON file
16
+ with open(json_filepath, "r") as f:
17
+ data = json.load(f)
18
+
19
+ # Extract texts and metadata from the data
20
+ texts = []
21
+ metadatas = []
22
+ for movie, lyrics in data.items():
23
+ for lyric in lyrics:
24
+ texts.append(lyric["text"])
25
+ metadatas.append(
26
+ {
27
+ "movie": movie,
28
+ "name": lyric["name"],
29
+ "embed_url": lyric["embed_url"],
30
+ }
31
+ )
32
+
33
+ # Initialize embeddings using OpenAI
34
+ embeddings = OpenAIEmbeddings(model=MODEL_ID)
35
+
36
+ # Create a DeepLake database from the texts and metadata
37
+ db = DeepLake.from_texts(
38
+ texts, embeddings, metadatas=metadatas, dataset_path=dataset_path
39
+ )
40
+
41
+ return db
42
+
43
+ # Function to load an existing DeepLake database
44
+ def load_db(dataset_path: str, *args, **kwargs) -> DeepLake:
45
+ db = DeepLake(dataset_path, *args, **kwargs)
46
+ return db
47
+
48
+ # If the script is executed directly, create a DeepLake database using the specified dataset path and JSON file
49
+ if __name__ == "__main__":
50
+ dataset_path = f"hub://{os.environ['ACTIVELOOP_ORG_ID']}/{DATASET_ID}"
51
+ create_db(dataset_path, "data/emotions_with_spotify_url.json")
data/emotions_with_spotify_url.json ADDED
@@ -0,0 +1,495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Aladdin": [
3
+ {
4
+ "name": "Friend Like Me",
5
+ "text": "excitement, happiness, humor, friendliness, generosity, willingness, eagerness, confidence",
6
+ "embed_url": "https://open.spotify.com/embed/track/5f2TWu6R2YYCJtLQ0fP78H?utm_source=generator"
7
+ },
8
+ {
9
+ "name": "Arabian Nights",
10
+ "text": "nostalgic, adventurous, exotic, intense, romantic, mysterious, whimsical, passionate",
11
+ "embed_url": "https://open.spotify.com/embed/track/0CKmN3Wwk8W4zjU0pqq2cv?utm_source=generator"
12
+ },
13
+ {
14
+ "name": "A Whole New World",
15
+ "text": "wonder, joy, excitement, adventure, romance, freedom, happiness, awe",
16
+ "embed_url": "https://open.spotify.com/embed/track/1hwdPQtFHISvZ9SXMkNrIK?utm_source=generator"
17
+ },
18
+ {
19
+ "name": "One Jump Ahead",
20
+ "text": "Thrill, fear, desperation, humor, defiance, friendship, hunger, rebellion.",
21
+ "embed_url": "https://open.spotify.com/embed/track/4wN8Ov3kPZdkJ8XcYxYUGz?utm_source=generator"
22
+ }
23
+ ],
24
+ "Aladdin (live-action)": [
25
+ {
26
+ "name": "A Whole New World",
27
+ "text": "nostalgia, wonder, excitement, joy, romance, adventure, hope, inspiration",
28
+ "embed_url": "https://open.spotify.com/embed/track/1hwdPQtFHISvZ9SXMkNrIK?utm_source=generator"
29
+ },
30
+ {
31
+ "name": "A Whole New World (End Title)",
32
+ "text": "joy, wonder, excitement, adventure, love, freedom, exhilaration, enchantment",
33
+ "embed_url": "https://open.spotify.com/embed/track/4U9CF27YlwHRtUGKUzhUTT?utm_source=generator"
34
+ },
35
+ {
36
+ "name": "Friend Like Me",
37
+ "text": "excitement, confidence, generosity, humor, friendliness, helpfulness, empowerment, joyfulness",
38
+ "embed_url": "https://open.spotify.com/embed/track/5f2TWu6R2YYCJtLQ0fP78H?utm_source=generator"
39
+ },
40
+ {
41
+ "name": "One Jump Ahead",
42
+ "text": "excitement, fear, desperation, humor, defiance, loneliness, camaraderie, determination",
43
+ "embed_url": "https://open.spotify.com/embed/track/4wN8Ov3kPZdkJ8XcYxYUGz?utm_source=generator"
44
+ },
45
+ {
46
+ "name": "Speechless (Full)",
47
+ "text": "determination, empowerment, resilience, strength, defiance, courage, passion, perseverance",
48
+ "embed_url": "https://open.spotify.com/embed/track/0XPsOSYzDJZJArevQNm2AR?utm_source=generator"
49
+ }
50
+ ],
51
+ "Aladdin: The Return of Jafar": [
52
+ {
53
+ "name": "Arabian Nights",
54
+ "text": "excitement, wonder, adventure, awe, joy, fascination, thrill, curiosity",
55
+ "embed_url": "https://open.spotify.com/embed/track/0CKmN3Wwk8W4zjU0pqq2cv?utm_source=generator"
56
+ }
57
+ ],
58
+ "Beauty and the Beast": [
59
+ {
60
+ "name": "Belle",
61
+ "text": "calm, content, curious, dreamy, happy, hopeful, romantic, whimsical",
62
+ "embed_url": "https://open.spotify.com/embed/track/1cPfKp9ThNZ1fez9itmUMN?utm_source=generator"
63
+ },
64
+ {
65
+ "name": "Be Our Guest",
66
+ "text": "joy, excitement, hospitality, gratitude, entertainment, nostalgia, comfort, satisfaction",
67
+ "embed_url": "https://open.spotify.com/embed/track/2F8LPJgSVTJxukoParTyBD?utm_source=generator"
68
+ }
69
+ ],
70
+ "Brave": [
71
+ {
72
+ "name": "Touch the Sky",
73
+ "text": "hopeful, adventurous, determined, inspired, free-spirited, empowered, awe-struck, exhilarated",
74
+ "embed_url": "https://open.spotify.com/embed/track/5yyqx4brn6Bm9U1Rj9ENnz?utm_source=generator"
75
+ }
76
+ ],
77
+ "Coco": [
78
+ {
79
+ "name": "Remember Me (D\u00fao)",
80
+ "text": "nostalgia, love, longing, sadness, hope, comfort, devotion, perseverance",
81
+ "embed_url": "https://open.spotify.com/embed/track/3pCgIUkmRHKydu9HE03QKY?utm_source=generator"
82
+ },
83
+ {
84
+ "name": "Remember Me (Ernesto de la Cruz)",
85
+ "text": "longing, separation, love, devotion, sadness, comfort, hope, reminiscence",
86
+ "embed_url": "https://open.spotify.com/embed/track/4ljlAxfaEjO4Q4g9FMtVj4?utm_source=generator"
87
+ },
88
+ {
89
+ "name": "The World Es Mi Familia",
90
+ "text": "joy, happiness, excitement, love, gratitude, belonging, unity, celebration",
91
+ "embed_url": "https://open.spotify.com/embed/track/7FOS31xq9jv4cXWtp6Jnzw?utm_source=generator"
92
+ },
93
+ {
94
+ "name": "Un Poco Loco",
95
+ "text": "confusion, love, amusement, uncertainty, joy, surprise, frustration, whimsy",
96
+ "embed_url": "https://open.spotify.com/embed/track/0OFknyqxmSQ42SoKxWVTok?utm_source=generator"
97
+ }
98
+ ],
99
+ "Descendants 3": [
100
+ {
101
+ "name": "Dig a Little Deeper",
102
+ "text": "Hope, Acceptance, Empowerment, Encouragement, Determination, Inspiration, Resilience, Confidence.",
103
+ "embed_url": "https://open.spotify.com/embed/track/7kh64k3P9Fk4EsA6vOdwmj?utm_source=generator"
104
+ }
105
+ ],
106
+ "Encanto": [
107
+ {
108
+ "name": "The Family Madrigal",
109
+ "text": "joy, excitement, wonder, confusion, love, pride, nostalgia, humor",
110
+ "embed_url": "https://open.spotify.com/embed/track/4b1yxSdlumA8N4fEk4UOZp?utm_source=generator"
111
+ },
112
+ {
113
+ "name": "Surface Pressure",
114
+ "text": "strength, confidence, anxiety, pressure, worry, fear, determination, resilience",
115
+ "embed_url": "https://open.spotify.com/embed/track/760jhRscwGbIIe1m1IIQpU?utm_source=generator"
116
+ },
117
+ {
118
+ "name": "Two Oruguitas",
119
+ "text": "love, yearning, hunger, fear, anticipation, change, trust, growth",
120
+ "embed_url": "https://open.spotify.com/embed/track/6jPVyjPqp2BNUJnDSwm8tK?utm_source=generator"
121
+ },
122
+ {
123
+ "name": "We Don't Talk About Bruno",
124
+ "text": "joy, fear, confusion, anxiety, frustration, curiosity, anger, humor",
125
+ "embed_url": "https://open.spotify.com/embed/track/52xJxFP6TqMuO4Yt0eOkMz?utm_source=generator"
126
+ },
127
+ {
128
+ "name": "What Else Can I Do?",
129
+ "text": "unexpected, beautiful, practiced, carnivorous, new, sick of pretty, rising, changing minds",
130
+ "embed_url": "https://open.spotify.com/embed/track/3XoYqtiWHhsk59frZupImG?utm_source=generator"
131
+ },
132
+ {
133
+ "name": "Waiting on a Miracle",
134
+ "text": "upset, mad, regret, sad, fine, longing, hopeful, impatient",
135
+ "embed_url": "https://open.spotify.com/embed/track/3oRW9ZGPRbLRMneQ5lwflt?utm_source=generator"
136
+ }
137
+ ],
138
+ "Enchanted": [
139
+ {
140
+ "name": "Happy Working Song",
141
+ "text": "joy, cheerfulness, contentment, enthusiasm, satisfaction, excitement, pleasure, happiness",
142
+ "embed_url": "https://open.spotify.com/embed/track/7G061Oqw7NXFr1NDTpXoI4?utm_source=generator"
143
+ },
144
+ {
145
+ "name": "So Close",
146
+ "text": "romantic, hopeful, longing, joy, fear, sadness, content, nostalgia",
147
+ "embed_url": "https://open.spotify.com/embed/track/3XFkhxO5jo2hBOWNzIQ9UB?utm_source=generator"
148
+ },
149
+ {
150
+ "name": "That's How You Know",
151
+ "text": "love, happiness, affection, devotion, passion, adoration, appreciation, romance",
152
+ "embed_url": "https://open.spotify.com/embed/track/1OzSfjFW08DTD51XoNnog7?utm_source=generator"
153
+ }
154
+ ],
155
+ "Frozen": [
156
+ {
157
+ "name": "Do You Want to Build a Snowman?",
158
+ "text": "loneliness, longing, sadness, nostalgia, hope, perseverance, friendship, playfulness",
159
+ "embed_url": "https://open.spotify.com/embed/track/2yi7HZrBOC4bMUSTcs4VK6?utm_source=generator"
160
+ },
161
+ {
162
+ "name": "For the First Time in Forever",
163
+ "text": "excited, hopeful, nervous, happy, anxious, optimistic, romantic, determined",
164
+ "embed_url": "https://open.spotify.com/embed/track/70b5Sq3ePOu3Gqg0hjlOtR?utm_source=generator"
165
+ },
166
+ {
167
+ "name": "In Summer",
168
+ "text": "joy, anticipation, excitement, happiness, nostalgia, humor, contentment, playfulness",
169
+ "embed_url": "https://open.spotify.com/embed/track/7bG6SQBGZthPDG5QJL5Gf7?utm_source=generator"
170
+ },
171
+ {
172
+ "name": "Let it Go",
173
+ "text": "isolation, determination, freedom, empowerment, resilience, confidence, defiance, happiness",
174
+ "embed_url": "https://open.spotify.com/embed/track/0qcr5FMsEO85NAQjrlDRKo?utm_source=generator"
175
+ },
176
+ {
177
+ "name": "Love is an Open Door",
178
+ "text": "joy, excitement, love, happiness, contentment, connection, optimism, anticipation",
179
+ "embed_url": "https://open.spotify.com/embed/track/68jg6wseZjKSJ0HUMjNS7C?utm_source=generator"
180
+ }
181
+ ],
182
+ "Frozen 2": [
183
+ {
184
+ "name": "All Is Found",
185
+ "text": "nostalgia, safety, discovery, fear, magic, bravery, loss, hope.",
186
+ "embed_url": "https://open.spotify.com/embed/track/5EeQQ8BVJTRkp1AIKJILGY?utm_source=generator"
187
+ },
188
+ {
189
+ "name": "Into the Unknown",
190
+ "text": "confusion, fear, hesitation, loneliness, longing, uncertainty, curiosity, determination",
191
+ "embed_url": "https://open.spotify.com/embed/track/421eObjg0DTm2qajJl5OJm?utm_source=generator"
192
+ },
193
+ {
194
+ "name": "Lost in the Woods",
195
+ "text": "wondering, lost, confused, sad, longing, hopeful, uncertain, anxious",
196
+ "embed_url": "https://open.spotify.com/embed/track/7namdlOhbtsc8FvoSafOQt?utm_source=generator"
197
+ },
198
+ {
199
+ "name": "Show Yourself",
200
+ "text": "trembling, familiar, sense of belonging, longing, certainty, purpose, anticipation, empowerment",
201
+ "embed_url": "https://open.spotify.com/embed/track/50WeOnXhM1H7AZEeIDoWfZ?utm_source=generator"
202
+ },
203
+ {
204
+ "name": "Some Things Never Change",
205
+ "text": "nostalgia, love, uncertainty, hope, contentment, joy, apprehension, gratitude",
206
+ "embed_url": "https://open.spotify.com/embed/track/4Xbotg4PCLJw9cDx2dtZLK?utm_source=generator"
207
+ },
208
+ {
209
+ "name": "When I Am Older",
210
+ "text": "nostalgia, comfort, curiosity, fear, acceptance, wisdom, optimism, reassurance",
211
+ "embed_url": "https://open.spotify.com/embed/track/1Tt7zr1yDbKbT8L4jzSZ74?utm_source=generator"
212
+ }
213
+ ],
214
+ "Hercules": [
215
+ {
216
+ "name": "A Star Is Born",
217
+ "text": "excitement, triumph, hope, inspiration, admiration, joy, pride, determination",
218
+ "embed_url": "https://open.spotify.com/embed/track/64Eug7tFE4KWJNQUE73BGe?utm_source=generator"
219
+ },
220
+ {
221
+ "name": "Go the Distance",
222
+ "text": "Hopeful, determined, inspired, optimistic, longing, driven, passionate, adventurous.",
223
+ "embed_url": "https://open.spotify.com/embed/track/0D1OY0M5A0qD5HGBvFmFid?utm_source=generator"
224
+ },
225
+ {
226
+ "name": "Zero to Hero",
227
+ "text": "excitement, admiration, joy, pride, amazement, awe, gratitude, inspiration",
228
+ "embed_url": "https://open.spotify.com/embed/track/4zDfgax6Ihb0UWdour1ZEs?utm_source=generator"
229
+ }
230
+ ],
231
+ "High School Musical": [
232
+ {
233
+ "name": "Start of Something New",
234
+ "text": "hopeful, excited, enamored, inspired, optimistic, joyful, eager, elated",
235
+ "embed_url": "https://open.spotify.com/embed/track/2JAE25n5JDyb3rp2ti0ql8?utm_source=generator"
236
+ },
237
+ {
238
+ "name": "We're All in This Together",
239
+ "text": "joyful, celebratory, unity, energetic, enthusiastic, uplifting, optimistic, empowering",
240
+ "embed_url": "https://open.spotify.com/embed/track/0cqNGWvuukhCiKvEX7utys?utm_source=generator"
241
+ }
242
+ ],
243
+ "HSM: The Musical: The Series": [
244
+ {
245
+ "name": "All I Want",
246
+ "text": "love, disappointment, frustration, confusion, doubt, loneliness, longing, self-reflection.",
247
+ "embed_url": "https://open.spotify.com/embed/track/1v6svH1Fyx9C1nIt1mA2DT?utm_source=generator"
248
+ }
249
+ ],
250
+ "HSM: The Musical: The Series (Season 2)": [
251
+ {
252
+ "name": "The Rose Song",
253
+ "text": "Wonder, doubt, love, trapped, beauty, freedom, growth, empowerment.",
254
+ "embed_url": "https://open.spotify.com/embed/track/4qCySCQyiyLT2mVUOM2zdS?utm_source=generator"
255
+ }
256
+ ],
257
+ "HSM: The Musical: The Series (Season 3)": [
258
+ {
259
+ "name": "You Never Know",
260
+ "text": "hope, anticipation, excitement, mystery, adventure, positivity, curiosity, wonder",
261
+ "embed_url": "https://open.spotify.com/embed/track/01tNpXoTjrqvb1zhG6wmop?utm_source=generator"
262
+ }
263
+ ],
264
+ "The Jungle Book": [
265
+ {
266
+ "name": "The Bare Necessities",
267
+ "text": "joy, contentment, relaxation, playfulness, curiosity, wonder, gratitude, simplicity",
268
+ "embed_url": "https://open.spotify.com/embed/track/7h5crXBSY5SSpXRIlklv74?utm_source=generator"
269
+ }
270
+ ],
271
+ "The Lion King": [
272
+ {
273
+ "name": "Can You Feel the Love Tonight",
274
+ "text": "romantic, sweet, magical, disastrous, truthful, hesitant, hopeful, doomed",
275
+ "embed_url": "https://open.spotify.com/embed/track/6TL9gJE5JibG8QR6n26eCS?utm_source=generator"
276
+ },
277
+ {
278
+ "name": "Circle of Life",
279
+ "text": "hope, despair, love, faith, wonder, awe, nostalgia, inspiration",
280
+ "embed_url": "https://open.spotify.com/embed/track/2KPMRUOwr8yB32EMvIg8aT?utm_source=generator"
281
+ },
282
+ {
283
+ "name": "Hakuna Matata",
284
+ "text": "joy, carefree, contentment, relief, humor, lightheartedness, friendship, acceptance",
285
+ "embed_url": "https://open.spotify.com/embed/track/5khPZny1Hf4w1XyHrZ6T0n?utm_source=generator"
286
+ },
287
+ {
288
+ "name": "I Just Can't Wait to Be King",
289
+ "text": "excitement, ambition, defiance, freedom, confidence, anticipation, joy, triumph",
290
+ "embed_url": "https://open.spotify.com/embed/track/2xUdYfY3LpJb4Iv37RypnO?utm_source=generator"
291
+ }
292
+ ],
293
+ "The Lion King (live-action)": [
294
+ {
295
+ "name": "Can You Feel the Love Tonight",
296
+ "text": "romantic, peaceful, harmonious, uncertain, fearful, hopeful, longing, doomed",
297
+ "embed_url": "https://open.spotify.com/embed/track/6TL9gJE5JibG8QR6n26eCS?utm_source=generator"
298
+ },
299
+ {
300
+ "name": "Circle of Life",
301
+ "text": "Joy, wonder, awe, hope, love, nostalgia, inspiration, contentment.",
302
+ "embed_url": "https://open.spotify.com/embed/track/2KPMRUOwr8yB32EMvIg8aT?utm_source=generator"
303
+ },
304
+ {
305
+ "name": "Hakuna Matata",
306
+ "text": "joy, happiness, carefree, contentment, humor, playfulness, relaxation, comfort",
307
+ "embed_url": "https://open.spotify.com/embed/track/5khPZny1Hf4w1XyHrZ6T0n?utm_source=generator"
308
+ },
309
+ {
310
+ "name": "I Just Can't Wait to Be King",
311
+ "text": "Excitement, Ambition, Confidence, Defiance, Rebellion, Anticipation, Joy, Empowerment",
312
+ "embed_url": "https://open.spotify.com/embed/track/2xUdYfY3LpJb4Iv37RypnO?utm_source=generator"
313
+ }
314
+ ],
315
+ "The Little Mermaid": [
316
+ {
317
+ "name": "Kiss the Girl",
318
+ "text": "excitement, curiosity, desire, shyness, sadness, regret, anticipation, courage",
319
+ "embed_url": "https://open.spotify.com/embed/track/75VAFZAhvPSw1euEHg1fQU?utm_source=generator"
320
+ },
321
+ {
322
+ "name": "Part of Your World",
323
+ "text": "wonder, desire, longing, curiosity, joy, hope, anticipation, yearning",
324
+ "embed_url": "https://open.spotify.com/embed/track/7tUSJY4nsDBJTjd1UXKRsT?utm_source=generator"
325
+ },
326
+ {
327
+ "name": "Poor Unfortunate Souls",
328
+ "text": "nasty, repentant, magic, sad, lonely, bored, withdrawn, busy",
329
+ "embed_url": "https://open.spotify.com/embed/track/7zsw78LtXUD7JfEwH64HK2?utm_source=generator"
330
+ },
331
+ {
332
+ "name": "Under the Sea",
333
+ "text": "happy, joyful, playful, carefree, energetic, lively, whimsical, adventurous",
334
+ "embed_url": "https://open.spotify.com/embed/track/6oYkwjI1TKP9D0Y9II1GT7?utm_source=generator"
335
+ }
336
+ ],
337
+ "Mary Poppins": [
338
+ {
339
+ "name": "Supercalifragilisticexpialidocious",
340
+ "text": "joy, excitement, playfulness, nostalgia, humor, confidence, charm, love",
341
+ "embed_url": "https://open.spotify.com/embed/track/5cvzqk8wsmLA9P7LrZCRb2?utm_source=generator"
342
+ }
343
+ ],
344
+ "Moana": [
345
+ {
346
+ "name": "How Far I'll Go",
347
+ "text": "nostalgia, longing, determination, curiosity, confusion, satisfaction, pride, uncertainty",
348
+ "embed_url": "https://open.spotify.com/embed/track/6mb6lVLNrcUgLnEN8QnDJd?utm_source=generator"
349
+ },
350
+ {
351
+ "name": "Where You Are",
352
+ "text": "happiness, contentment, tradition, pride, belonging, determination, nostalgia, joy",
353
+ "embed_url": "https://open.spotify.com/embed/track/2bwSCIuNtVrQPVddCi8sOW?utm_source=generator"
354
+ },
355
+ {
356
+ "name": "You're Welcome",
357
+ "text": "adorable, confident, proud, playful, grateful, boastful, humorous, friendly",
358
+ "embed_url": "https://open.spotify.com/embed/track/6U4VqEHy4n5VeiH4pQPL24?utm_source=generator"
359
+ }
360
+ ],
361
+ "Mulan": [
362
+ {
363
+ "name": "A Girl Worth Fighting For",
364
+ "text": "nostalgia, camaraderie, humor, determination, longing, admiration, optimism, romance",
365
+ "embed_url": "https://open.spotify.com/embed/track/3wjgPeXocinhLyPL37p70e?utm_source=generator"
366
+ },
367
+ {
368
+ "name": "Honor to Us All",
369
+ "text": "determination, pride, obedience, tradition, anxiety, hope, honor, cultural expectations",
370
+ "embed_url": "https://open.spotify.com/embed/track/78EMhiyAcalWWtnpk20Eoo?utm_source=generator"
371
+ },
372
+ {
373
+ "name": "Reflection",
374
+ "text": "doubt, insecurity, confusion, sadness, frustration, longing, self-discovery, acceptance",
375
+ "embed_url": "https://open.spotify.com/embed/track/4ASPjY65S7crmZBHML0L8d?utm_source=generator"
376
+ }
377
+ ],
378
+ "Mulan (Live-Action)": [
379
+ {
380
+ "name": "Reflection",
381
+ "text": "confusion, frustration, identity, longing, self-discovery, vulnerability, authenticity, empowerment",
382
+ "embed_url": "https://open.spotify.com/embed/track/4ASPjY65S7crmZBHML0L8d?utm_source=generator"
383
+ }
384
+ ],
385
+ "Pinocchio": [
386
+ {
387
+ "name": "When You Wish Upon a Star",
388
+ "text": "hopeful, optimistic, dreamy, inspired, happy, content, fulfilled, grateful",
389
+ "embed_url": "https://open.spotify.com/embed/track/1WrPa4lrIddctGWAIYYfP9?utm_source=generator"
390
+ }
391
+ ],
392
+ "Pinocchio (Live-Action)": [
393
+ {
394
+ "name": "When You Wish Upon a Star",
395
+ "text": "hopeful, optimistic, joyful, fulfilled, inspired, grateful, content, peaceful",
396
+ "embed_url": "https://open.spotify.com/embed/track/1WrPa4lrIddctGWAIYYfP9?utm_source=generator"
397
+ }
398
+ ],
399
+ "Pocahontas": [
400
+ {
401
+ "name": "Colors of the Wind",
402
+ "text": "wonder, defiance, connection, appreciation, curiosity, empowerment, harmony, respect",
403
+ "embed_url": "https://open.spotify.com/embed/track/1OYOLWqKmhkFIx2KC9ek1a?utm_source=generator"
404
+ }
405
+ ],
406
+ "The Princess and the Frog": [
407
+ {
408
+ "name": "Dig a Little Deeper",
409
+ "text": "joy, acceptance, self-discovery, contentment, optimism, encouragement, determination, hopefulness",
410
+ "embed_url": "https://open.spotify.com/embed/track/7kh64k3P9Fk4EsA6vOdwmj?utm_source=generator"
411
+ },
412
+ {
413
+ "name": "Down in New Orleans (Finale)",
414
+ "text": "excitement, happiness, joy, celebration, optimism, anticipation, nostalgia, contentment",
415
+ "embed_url": "https://open.spotify.com/embed/track/1fvc8FP8MUrIbHGYb4kF89?utm_source=generator"
416
+ },
417
+ {
418
+ "name": "When We're Human",
419
+ "text": "excitement, joy, confidence, optimism, contentment, nostalgia, determination, celebration",
420
+ "embed_url": "https://open.spotify.com/embed/track/2g2kJZcu1cFTw4aKE7w9Iq?utm_source=generator"
421
+ }
422
+ ],
423
+ "Robin Hood": [
424
+ {
425
+ "name": "Love",
426
+ "text": "nostalgia, love, longing, happiness, sadness, reflection, timelessness, sentimentality",
427
+ "embed_url": "https://open.spotify.com/embed/track/3M6YfoPwvvTHK1mnCQmqHI?utm_source=generator"
428
+ }
429
+ ],
430
+ "Sleeping Beauty": [
431
+ {
432
+ "name": "Once Upon a Dream",
433
+ "text": "nostalgia, love, familiarity, hope, longing, enchantment, romanticism, dreaminess",
434
+ "embed_url": "https://open.spotify.com/embed/track/3liiZRlJxa8GeLUgWMoIeu?utm_source=generator"
435
+ }
436
+ ],
437
+ "Tangled": [
438
+ {
439
+ "name": "I See the Light",
440
+ "text": "nostalgia, longing, clarity, happiness, wonder, realization, love, fulfillment",
441
+ "embed_url": "https://open.spotify.com/embed/track/0TuUCbB6uvIW0tJaxCSRBJ?utm_source=generator"
442
+ },
443
+ {
444
+ "name": "I've Got a Dream",
445
+ "text": "malice, violence, dream, love, humor, optimism, perseverance, unity",
446
+ "embed_url": "https://open.spotify.com/embed/track/0TCt7OFRdD8PQ6vTRQxNgQ?utm_source=generator"
447
+ },
448
+ {
449
+ "name": "Mother Knows Best",
450
+ "text": "protectiveness, fear, warning, love, concern, control, manipulation, persuasion",
451
+ "embed_url": "https://open.spotify.com/embed/track/1lOSxJNCLvWm2bYaTcTSmK?utm_source=generator"
452
+ },
453
+ {
454
+ "name": "Mother Knows Best (Reprise)",
455
+ "text": "Skepticism, confidence, warning, trust, superiority, concern, cynicism, assurance.",
456
+ "embed_url": "https://open.spotify.com/embed/track/1nrXPF5szKZhHr0iANiPcS?utm_source=generator"
457
+ }
458
+ ],
459
+ "Tarzan": [
460
+ {
461
+ "name": "Strangers Like Me",
462
+ "text": "curiosity, familiarity, wonder, desire, longing, excitement, eagerness, awe",
463
+ "embed_url": "https://open.spotify.com/embed/track/5Zb6JxSEcjsUNrINcAyAYJ?utm_source=generator"
464
+ },
465
+ {
466
+ "name": "You'll Be in My Heart",
467
+ "text": "Love, comfort, protection, trust, hope, determination, perseverance, dedication",
468
+ "embed_url": "https://open.spotify.com/embed/track/4Y8vb1uy9IjM2V1hqvrAid?utm_source=generator"
469
+ }
470
+ ],
471
+ "Toy Story": [
472
+ {
473
+ "name": "You've Got a Friend in Me",
474
+ "text": "friendship, loyalty, comfort, support, love, companionship, perseverance, devotion",
475
+ "embed_url": "https://open.spotify.com/embed/track/2stkLJ0JNcXkIRDNF3ld6c?utm_source=generator"
476
+ }
477
+ ],
478
+ "Turning Red": [
479
+ {
480
+ "name": "1 True Love",
481
+ "text": "sadness, love, obsession, longing, devotion, despair, hopelessness, affection",
482
+ "embed_url": "https://open.spotify.com/embed/track/2dJ1UJEQQq3jkLSJP4ZIoi?utm_source=generator"
483
+ },
484
+ {
485
+ "name": "Nobody Like U",
486
+ "text": "love, joy, friendship, loyalty, excitement, admiration, appreciation, happiness",
487
+ "embed_url": "https://open.spotify.com/embed/track/4bV5sf2B4hWBBd5HQ8S7KB?utm_source=generator"
488
+ },
489
+ {
490
+ "name": "U Know What's Up",
491
+ "text": "confidence, determination, motivation, empowerment, excitement, ambition, persuasion, triumph",
492
+ "embed_url": "https://open.spotify.com/embed/track/0d83zVs3OmdjrhfoAxg1dE?utm_source=generator"
493
+ }
494
+ ]
495
+ }
data/lyrics.json ADDED
The diff for this file is too large to render. See raw diff
 
data/lyrics_with_spotify_url.json ADDED
The diff for this file is too large to render. See raw diff
 
data/lyrics_with_spotify_url_and_summary.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"friend like me": {"summary": "SUMMARY: The song is about the genie's willingness to grant any wish and be a loyal friend to Aladdin, emphasizing the themes of friendship, loyalty, and magic.", "embed_url": "https://open.spotify.com/embed/track/5f2TWu6R2YYCJtLQ0fP78H?utm_source=generator"}, "arabian nights": {"summary": "SUMMARY: Adventure, excitement, and enchantment are the main themes of this song, which invites listeners to join in on a magical journey to a far-off land.", "embed_url": "https://open.spotify.com/embed/track/0CKmN3Wwk8W4zjU0pqq2cv?utm_source=generator"}, "a whole new world": {"summary": "SUMMARY: The song is about the excitement and wonder of discovering a new world with someone, and the feeling of being free to explore without any limitations.", "embed_url": "https://open.spotify.com/embed/track/1hwdPQtFHISvZ9SXMkNrIK?utm_source=generator"}, "one jump ahead": {"summary": "SUMMARY: Aladdin sings about his struggles to survive as a street rat, constantly evading the law and facing the judgment of society, while longing for a true friend.", "embed_url": "https://open.spotify.com/embed/track/4wN8Ov3kPZdkJ8XcYxYUGz?utm_source=generator"}, "a whole new world (end title)": {"summary": "SUMMARY: The song is about the excitement and wonder of discovering a new world with someone, with themes of adventure, love, and freedom.", "embed_url": "https://open.spotify.com/embed/track/4U9CF27YlwHRtUGKUzhUTT?utm_source=generator"}, "speechless (full)": {"summary": "The song is about empowerment and standing up for oneself, refusing to be silenced or underestimated.", "embed_url": "https://open.spotify.com/embed/track/0XPsOSYzDJZJArevQNm2AR?utm_source=generator"}, "belle": {"summary": "Themes/Emotions: Small town life, curiosity, being different, beauty, love, societal pressure, fitting in.", "embed_url": "https://open.spotify.com/embed/track/1cPfKp9ThNZ1fez9itmUMN?utm_source=generator"}, "be our guest": {"summary": "The song \"Be Our Guest\" from Beauty and the Beast is about the castle's enchanted objects welcoming Belle as their guest and providing her with a lavish dinner service.", "embed_url": "https://open.spotify.com/embed/track/2F8LPJgSVTJxukoParTyBD?utm_source=generator"}, "touch the sky": {"summary": "A song about chasing dreams and overcoming obstacles with determination and strength.", "embed_url": "https://open.spotify.com/embed/track/5yyqx4brn6Bm9U1Rj9ENnz?utm_source=generator"}, "remember me (d\u00fao)": {"summary": "The song is about remembering a loved one who is far away and keeping their love alive through music.", "embed_url": "https://open.spotify.com/embed/track/3pCgIUkmRHKydu9HE03QKY?utm_source=generator"}, "remember me (ernesto de la cruz)": {"summary": "SUMMARY: A song about longing and love, encouraging the listener to remember the singer even when they are apart.", "embed_url": "https://open.spotify.com/embed/track/4ljlAxfaEjO4Q4g9FMtVj4?utm_source=generator"}, "the world es mi familia": {"summary": "SUMMARY: Joy, family, music.", "embed_url": "https://open.spotify.com/embed/track/7FOS31xq9jv4cXWtp6Jnzw?utm_source=generator"}, "un poco loco": {"summary": "SUMMARY: The song expresses the confusion and craziness of love, with the lyrics describing the feeling of being \"un poco loco\" or a little bit crazy.", "embed_url": "https://open.spotify.com/embed/track/0OFknyqxmSQ42SoKxWVTok?utm_source=generator"}, "dig a little deeper": {"summary": "The song encourages self-discovery and self-acceptance, emphasizing that material possessions and wealth do not bring happiness.", "embed_url": "https://open.spotify.com/embed/track/7kh64k3P9Fk4EsA6vOdwmj?utm_source=generator"}, "the family madrigal": {"summary": "The song celebrates the diversity and magical abilities of the Madrigal family, emphasizing the importance of family and tradition.", "embed_url": "https://open.spotify.com/embed/track/4b1yxSdlumA8N4fEk4UOZp?utm_source=generator"}, "surface pressure": {"summary": "The song explores the theme of pressure and the emotions of feeling overwhelmed and inadequate, while also highlighting the importance of support from others.", "embed_url": "https://open.spotify.com/embed/track/760jhRscwGbIIe1m1IIQpU?utm_source=generator"}, "two oruguitas": {"summary": "The song is about two caterpillars in love who are navigating a changing world and learning to let go and embrace growth as they transform into butterflies.", "embed_url": "https://open.spotify.com/embed/track/6jPVyjPqp2BNUJnDSwm8tK?utm_source=generator"}, "we don't talk about bruno": {"summary": "The song explores fear, superstition, and the power of prophecy through the character of Bruno, who is associated with misfortune and tragedy.", "embed_url": "https://open.spotify.com/embed/track/52xJxFP6TqMuO4Yt0eOkMz?utm_source=generator"}, "what else can i do?": {"summary": "INPUT: \"Something That I Want\" from Tangled\nOUTPUT: Themes of longing, desire for adventure, and breaking free from confinement.", "embed_url": "https://open.spotify.com/embed/track/3XoYqtiWHhsk59frZupImG?utm_source=generator"}, "waiting on a miracle": {"summary": "The song explores themes of feeling left out, longing for acceptance, and the desire to prove oneself through a miracle.", "embed_url": "https://open.spotify.com/embed/track/3oRW9ZGPRbLRMneQ5lwflt?utm_source=generator"}, "happy working song": {"summary": "SUMMARY: The song celebrates the joy of hard work and finding happiness in mundane tasks.", "embed_url": "https://open.spotify.com/embed/track/7G061Oqw7NXFr1NDTpXoI4?utm_source=generator"}, "so close": {"summary": "SUMMARY: Longing for love and the fear of losing it, the song expresses the desire to hold onto a romantic dream and the hope of reaching a happy ending.", "embed_url": "https://open.spotify.com/embed/track/3XFkhxO5jo2hBOWNzIQ9UB?utm_source=generator"}, "that's how you know": {"summary": "The song explores the themes of love, affection, and the importance of expressing one's feelings to their partner.", "embed_url": "https://open.spotify.com/embed/track/1OzSfjFW08DTD51XoNnog7?utm_source=generator"}, "do you want to build a snowman?": {"summary": "Loneliness and longing for companionship between two sisters, as one tries to reconnect with the other who has withdrawn from their relationship.", "embed_url": "https://open.spotify.com/embed/track/2yi7HZrBOC4bMUSTcs4VK6?utm_source=generator"}, "for the first time in forever": {"summary": "Themes/Emotions: excitement, anticipation, loneliness, dreaming, romance, fear, pressure to conform.", "embed_url": "https://open.spotify.com/embed/track/70b5Sq3ePOu3Gqg0hjlOtR?utm_source=generator"}, "in summer": {"summary": "SUMMARY: The snowman dreams of experiencing summer and all its joys, while acknowledging the differences between hot and cold weather.", "embed_url": "https://open.spotify.com/embed/track/7bG6SQBGZthPDG5QJL5Gf7?utm_source=generator"}, "let it go": {"summary": "Themes: self-discovery, empowerment, letting go of fear and societal expectations.", "embed_url": "https://open.spotify.com/embed/track/0qcr5FMsEO85NAQjrlDRKo?utm_source=generator"}, "love is an open door": {"summary": "The song is about the excitement and joy of finding love and a sense of belonging with someone who thinks and feels the same way.", "embed_url": "https://open.spotify.com/embed/track/68jg6wseZjKSJ0HUMjNS7C?utm_source=generator"}, "all is found": {"summary": "SUMMARY: The song explores themes of memory, safety, bravery, and facing fears through the metaphor of a river that holds answers and magic.", "embed_url": "https://open.spotify.com/embed/track/5EeQQ8BVJTRkp1AIKJILGY?utm_source=generator"}, "into the unknown": {"summary": "SUMMARY: The song explores the fear and uncertainty of stepping into the unknown, while also acknowledging the desire for adventure and the struggle to resist the call of the unfamiliar.", "embed_url": "https://open.spotify.com/embed/track/421eObjg0DTm2qajJl5OJm?utm_source=generator"}, "lost in the woods": {"summary": "SUMMARY: The song explores the emotions of feeling lost and uncertain in a relationship, questioning whether to follow or let go, and the struggle of finding one's own path.", "embed_url": "https://open.spotify.com/embed/track/7namdlOhbtsc8FvoSafOQt?utm_source=generator"}, "show yourself": {"summary": "SUMMARY: The song is about self-discovery, finding one's purpose, and embracing one's true self.", "embed_url": "https://open.spotify.com/embed/track/50WeOnXhM1H7AZEeIDoWfZ?utm_source=generator"}, "some things never change": {"summary": "SUMMARY: Reflecting on the passage of time and the inevitability of change, the characters find comfort in the constants of their relationships and the traditions of their kingdom.", "embed_url": "https://open.spotify.com/embed/track/4Xbotg4PCLJw9cDx2dtZLK?utm_source=generator"}, "when i am older": {"summary": "INPUT: \"When I Am Older\" from Frozen 2\nOUTPUT: Acceptance of growing up and finding understanding in the future.", "embed_url": "https://open.spotify.com/embed/track/1Tt7zr1yDbKbT8L4jzSZ74?utm_source=generator"}, "a star is born": {"summary": "The song celebrates the birth of a star and encourages listeners to find hope and power within themselves to become heroes.", "embed_url": "https://open.spotify.com/embed/track/64Eug7tFE4KWJNQUE73BGe?utm_source=generator"}, "go the distance": {"summary": "INPUT: \"Go the Distance\" from Disney's Hercules\nOUTPUT: Themes of determination, perseverance, and finding one's place in the world.", "embed_url": "https://open.spotify.com/embed/track/0D1OY0M5A0qD5HGBvFmFid?utm_source=generator"}, "zero to hero": {"summary": "The song \"Zero to Hero\" from Disney's Hercules is about the transformation of the main character from a nobody to a hero, and the admiration and fame that comes with it.", "embed_url": "https://open.spotify.com/embed/track/4zDfgax6Ihb0UWdour1ZEs?utm_source=generator"}, "start of something new": {"summary": "The song is about the excitement and nervousness of starting a new relationship and the feeling of discovering new possibilities.", "embed_url": "https://open.spotify.com/embed/track/2JAE25n5JDyb3rp2ti0ql8?utm_source=generator"}, "we're all in this together": {"summary": "The song celebrates togetherness, unity, and the idea that everyone is special in their own way, encouraging people to work together to achieve their dreams.", "embed_url": "https://open.spotify.com/embed/track/0cqNGWvuukhCiKvEX7utys?utm_source=generator"}, "all i want": {"summary": "INPUT: \"All I Want\" from \"High School Musical: The Musical: The Series\"\nOUTPUT: Frustration and confusion about love and self-worth.", "embed_url": "https://open.spotify.com/embed/track/1v6svH1Fyx9C1nIt1mA2DT?utm_source=generator"}, "the rose song": {"summary": "The song is about breaking free from the expectations of others and embracing one's true self.", "embed_url": "https://open.spotify.com/embed/track/4qCySCQyiyLT2mVUOM2zdS?utm_source=generator"}, "you never know": {"summary": "The song is about embracing the unknown and being open to new experiences and opportunities.", "embed_url": "https://open.spotify.com/embed/track/01tNpXoTjrqvb1zhG6wmop?utm_source=generator"}, "the bare necessities": {"summary": "The song emphasizes the importance of simplicity and nature, encouraging listeners to let go of their worries and focus on the basic necessities of life.", "embed_url": "https://open.spotify.com/embed/track/7h5crXBSY5SSpXRIlklv74?utm_source=generator"}, "can you feel the love tonight": {"summary": "SUMMARY: The song explores the emotions of falling in love, the fear of rejection, and the uncertainty of the future.", "embed_url": "https://open.spotify.com/embed/track/6TL9gJE5JibG8QR6n26eCS?utm_source=generator"}, "circle of life": {"summary": "INPUT: \"The Circle of Life\" from The Lion King\nOUTPUT: Themes of the song include the vastness and wonder of life, the endless cycle of birth and death, and the importance of finding one's place in the world.", "embed_url": "https://open.spotify.com/embed/track/2KPMRUOwr8yB32EMvIg8aT?utm_source=generator"}, "hakuna matata": {"summary": "The song \"Hakuna Matata\" is about living a carefree life without worries, and finding joy in the present moment.", "embed_url": "https://open.spotify.com/embed/track/5khPZny1Hf4w1XyHrZ6T0n?utm_source=generator"}, "i just can't wait to be king": {"summary": "SUMMARY: Simba expresses his excitement and eagerness to become king, while his friends caution him about the responsibilities and challenges that come with it.", "embed_url": "https://open.spotify.com/embed/track/2xUdYfY3LpJb4Iv37RypnO?utm_source=generator"}, "kiss the girl": {"summary": "The song is about the desire to kiss someone and the fear of missing out on the opportunity, with a focus on the importance of taking action and seizing the moment.", "embed_url": "https://open.spotify.com/embed/track/75VAFZAhvPSw1euEHg1fQU?utm_source=generator"}, "part of your world": {"summary": "SUMMARY: The song expresses the desire of the protagonist to explore the world beyond her own and be a part of it, highlighting the themes of curiosity, longing, and adventure.", "embed_url": "https://open.spotify.com/embed/track/7tUSJY4nsDBJTjd1UXKRsT?utm_source=generator"}, "poor unfortunate souls": {"summary": "The song \"Poor Unfortunate Souls\" from The Little Mermaid is about Ursula, a witch who uses her magic to help those who are miserable and lonely, but at a cost, and emphasizes the importance of body language and holding one's tongue to get what they want.", "embed_url": "https://open.spotify.com/embed/track/7zsw78LtXUD7JfEwH64HK2?utm_source=generator"}, "under the sea": {"summary": "The song celebrates the joy and freedom of life under the sea, contrasting it with the hard work and struggles of life on land.", "embed_url": "https://open.spotify.com/embed/track/6oYkwjI1TKP9D0Y9II1GT7?utm_source=generator"}, "supercalifragilisticexpialidocious": {"summary": "The song is about the power of a made-up word to boost confidence and change lives.", "embed_url": "https://open.spotify.com/embed/track/5cvzqk8wsmLA9P7LrZCRb2?utm_source=generator"}, "how far i'll go": {"summary": "SUMMARY: A young girl struggles with her desire to explore beyond her island home and the expectations placed upon her, ultimately embracing her own path and the unknown possibilities ahead.", "embed_url": "https://open.spotify.com/embed/track/6mb6lVLNrcUgLnEN8QnDJd?utm_source=generator"}, "where you are": {"summary": "The song emphasizes the importance of tradition, community, and finding happiness where you are.", "embed_url": "https://open.spotify.com/embed/track/2bwSCIuNtVrQPVddCi8sOW?utm_source=generator"}, "you're welcome": {"summary": "The song is about Maui boasting of his accomplishments and telling the listener that they should be grateful for all the things he has done for them.", "embed_url": "https://open.spotify.com/embed/track/6U4VqEHy4n5VeiH4pQPL24?utm_source=generator"}, "a girl worth fighting for": {"summary": "The song \"A Girl Worth Fighting For\" from Mulan explores the soldiers' desires for a perfect woman who is worth fighting for.", "embed_url": "https://open.spotify.com/embed/track/3wjgPeXocinhLyPL37p70e?utm_source=generator"}, "honor to us all": {"summary": "SUMMARY: The song highlights the societal pressure on women to conform to traditional gender roles and bring honor to their families by marrying well and bearing sons.", "embed_url": "https://open.spotify.com/embed/track/78EMhiyAcalWWtnpk20Eoo?utm_source=generator"}, "reflection": {"summary": "SUMMARY: Self-discovery, identity, authenticity, and the struggle to be true to oneself.", "embed_url": "https://open.spotify.com/embed/track/4ASPjY65S7crmZBHML0L8d?utm_source=generator"}, "when you wish upon a star": {"summary": "SUMMARY: The song encourages listeners to believe in their dreams and have faith that they will come true, with themes of hope, destiny, and the power of positive thinking.", "embed_url": "https://open.spotify.com/embed/track/1WrPa4lrIddctGWAIYYfP9?utm_source=generator"}, "colors of the wind": {"summary": "The song explores themes of cultural differences, environmentalism, and the interconnectedness of all living things.", "embed_url": "https://open.spotify.com/embed/track/1OYOLWqKmhkFIx2KC9ek1a?utm_source=generator"}, "down in new orleans (finale)": {"summary": "SUMMARY: The song celebrates the lively and vibrant atmosphere of New Orleans, emphasizing the joy and excitement that can be found in the city's music, culture, and community.", "embed_url": "https://open.spotify.com/embed/track/1fvc8FP8MUrIbHGYb4kF89?utm_source=generator"}, "when we're human": {"summary": "Themes: aspirations for a better life, desire for fun and enjoyment, sense of responsibility and hard work, importance of doing one's best.", "embed_url": "https://open.spotify.com/embed/track/2g2kJZcu1cFTw4aKE7w9Iq?utm_source=generator"}, "love": {"summary": "Themes: Love, Time, Nostalgia, Continuity.", "embed_url": "https://open.spotify.com/embed/track/3M6YfoPwvvTHK1mnCQmqHI?utm_source=generator"}, "once upon a dream": {"summary": "SUMMARY: Longing for a past love and hoping for a future reunion.", "embed_url": "https://open.spotify.com/embed/track/3liiZRlJxa8GeLUgWMoIeu?utm_source=generator"}, "i see the light": {"summary": "SUMMARY: Discovery of clarity and purpose through newfound love and perspective.", "embed_url": "https://open.spotify.com/embed/track/0TuUCbB6uvIW0tJaxCSRBJ?utm_source=generator"}, "i've got a dream": {"summary": "The song \"I've Got a Dream\" from Tangled is about embracing your dreams and aspirations, no matter how unconventional or unlikely they may seem, and finding common ground with others who share similar hopes and desires.", "embed_url": "https://open.spotify.com/embed/track/0TCt7OFRdD8PQ6vTRQxNgQ?utm_source=generator"}, "mother knows best": {"summary": "SUMMARY: Overprotective mother warns daughter of the dangers of the outside world and insists that she stay with her, using fear tactics and manipulation to keep her close.", "embed_url": "https://open.spotify.com/embed/track/1lOSxJNCLvWm2bYaTcTSmK?utm_source=generator"}, "mother knows best (reprise)": {"summary": "Themes/Emotions: Doubt, Maturity, Deception, Trust, Motherly Love.", "embed_url": "https://open.spotify.com/embed/track/1nrXPF5szKZhHr0iANiPcS?utm_source=generator"}, "strangers like me": {"summary": "The song explores the themes of curiosity, self-discovery, and a desire to connect with others who may seem different but share a common humanity.", "embed_url": "https://open.spotify.com/embed/track/5Zb6JxSEcjsUNrINcAyAYJ?utm_source=generator"}, "you'll be in my heart": {"summary": "A song about protection, love, and the unbreakable bond between a parent and child.", "embed_url": "https://open.spotify.com/embed/track/4Y8vb1uy9IjM2V1hqvrAid?utm_source=generator"}, "you've got a friend in me": {"summary": "SUMMARY: Loyalty and support in friendship, reassurance that someone will always be there for you.", "embed_url": "https://open.spotify.com/embed/track/2stkLJ0JNcXkIRDNF3ld6c?utm_source=generator"}, "1 true love": {"summary": "INPUT: \"1 True Love\" from the movie \"Lilo & Stitch\"\nOUTPUT: Themes of unrequited love, heartbreak, and the belief that love can be art.", "embed_url": "https://open.spotify.com/embed/track/2dJ1UJEQQq3jkLSJP4ZIoi?utm_source=generator"}, "nobody like u": {"summary": "SUMMARY: The song expresses the intense love and devotion between two individuals who have never met anyone like each other.", "embed_url": "https://open.spotify.com/embed/track/4bV5sf2B4hWBBd5HQ8S7KB?utm_source=generator"}, "u know what's up": {"summary": "SUMMARY: Empowerment and determination to achieve success through hard work and perseverance.", "embed_url": "https://open.spotify.com/embed/track/0d83zVs3OmdjrhfoAxg1dE?utm_source=generator"}}
data/spotify_disney_songs.json ADDED
The diff for this file is too large to render. See raw diff
 
docs/BLOG.md ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FairytaleDJ 🎵🏰🔮: Recommending Disney songs with Langchain and DeepLake
2
+
3
+ TL;DR We used [LangChain](https://python.langchain.com/en/latest/index.html), [OpenAI ChatGPT](https://openai.com/blog/chatgpt), [DeepLake](https://www.deeplake.ai/) and [Streamlit](https://streamlit.io/) to create a web app that recommends Disney songs based on a user input.
4
+
5
+ ![alt](images/app.gif)
6
+
7
+ A demo is on [Hugging Face 🤗](https://huggingface.co/spaces/Francesco/FairytaleDJ)
8
+
9
+ <!-- <iframe src="https://huggingface.co/spaces/Francesco/FairytaleDJ"/> -->
10
+ Hey there! Today we will see how to leverage [DeepLake](https://www.deeplake.ai/) to create a document retrieval system. This won't be your usual Q&A demo app were we just directly a user's query to embedded documents using [LangChain](https://python.langchain.com/en/latest/index.html). Nope, we will showcase how we can leverage LLMs to encode our data in such a way that will make our matching easier, better and faster.
11
+
12
+ Step by step, we'll unpack the behind-the-scenes of [`FairytaleDJ`](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ) a web app to recommend Disney songs based on user input. **The goal is simple:** We ask how the user is feeling and we want to somehow retrieve Disney songs that go "well" with that input. For example, if the user is sad, probably a song like [Reflection from Mulan](https://www.youtube.com/watch?v=lGGXsm0a5s0) would be appropriate.
13
+
14
+ This is a perfect example where vanilla Q&A fails. If you try to find similarities between users' feelings (like, "Today I am great") and song lyrics, you won't really get too good results. That's because song embeddings capture everything in the lyrics, making them "more open". Instead, what we want to do is to encode both inputs, users and lyrics, into a similar representation and then run the search. We won't spoil too much here, so shopping list time. We need mainly three things: data, a way to encode it and a way to match it with user input.
15
+
16
+
17
+ ## Getting the data
18
+
19
+ To get our songs, we decided to scrape `https://www.disneyclips.com/lyrics/`, a website containing all the lyrics for **all** Disney songs ever made. The code is [here](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/scrape.py) and it relies on `asyncio` to speed up things, we won't focus too much on it.
20
+
21
+ Then, we used [Spotify Python APIs](https://spotipy.readthedocs.io/en/2.22.1/) to get all the embedding URL for each song into the ["Disney Hits" Playlist](https://open.spotify.com/playlist/37i9dQZF1DX8C9xQcOrE6T). We proceed to remove all the songs that we had scraped but are not in this playlist. By doing so, we end up with 85 songs.
22
+
23
+ We end up with a [`json`](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/data/lyrics_with_spotify_url.json) looking like this.
24
+
25
+ ```json
26
+ {
27
+ "Aladdin": [
28
+ {
29
+ "name": "Arabian Nights",
30
+ "text": "Oh, I come from a land, from a faraway place. Where the caravan camels roam. Where it's flat and immense. And the heat is intense. It's barbaric, but, hey, it's home. . When the wind's from the East. And the sun's from the West. And the sand in the glass is right. Come on down. Stop on by. Hop a carpet and fly. To another Arabian night. . Arabian nights. Like Arabian days. More often than not. Are hotter than hot. In a lot of good ways. . Arabian nights. 'Neath Arabian moons. A fool off his guard. Could fall and fall hard. Out there on the dunes. . ",
31
+ "embed_url": "https://open.spotify.com/embed/track/0CKmN3Wwk8W4zjU0pqq2cv?utm_source=generator"
32
+ },
33
+ ...
34
+ ],
35
+ ```
36
+ ## Data encoding
37
+ We were looking for a good way to retrieve the songs. We evaluated different approaches. We used ActiveLoop [DeepLake](https://docs.deeplake.ai/en/latest/) vector db and more specifically its implementation in [LangChain](https://python.langchain.com/en/latest/ecosystem/deeplake.html).
38
+
39
+ Creating the dataset was very easy. Given the previous `json` file, we proceed to embed the `text` field using `langchain.embeddings.openai.OpenaAIEmbeddings` and add all the rest of keys/values as `metadata`
40
+
41
+ ```python
42
+ from langchain.embeddings.openai import OpenAIEmbeddings
43
+ from langchain.llms import OpenAI
44
+ from langchain.vectorstores import DeepLake
45
+
46
+ def create_db(dataset_path: str, json_filepath: str) -> DeepLake:
47
+ with open(json_filepath, "r") as f:
48
+ data = json.load(f)
49
+
50
+ texts = []
51
+ metadatas = []
52
+
53
+ for movie, lyrics in data.items():
54
+ for lyric in lyrics:
55
+ texts.append(lyric["text"])
56
+ metadatas.append(
57
+ {
58
+ "movie": movie,
59
+ "name": lyric["name"],
60
+ "embed_url": lyric["embed_url"],
61
+ }
62
+ )
63
+
64
+ embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
65
+
66
+ db = DeepLake.from_texts(
67
+ texts, embeddings, metadatas=metadatas, dataset_path=dataset_path
68
+ )
69
+
70
+ return db
71
+ ```
72
+
73
+ To load it, we can simply:
74
+
75
+ ```python
76
+ def load_db(dataset_path: str, *args, **kwargs) -> DeepLake:
77
+ db = DeepLake(dataset_path, *args, **kwargs)
78
+ return db
79
+ ```
80
+
81
+ My `dataset_path` is `hub://<ACTIVELOOP_ORGANIZATION_ID>/<DATASET_NAME>`, but you can also store it locally. Their doc is [here](https://docs.activeloop.ai/getting-started/creating-datasets-manually)
82
+
83
+ ## Matching
84
+
85
+ Next step was to find a way to match our songs with a given user inputs, we tried several things till we found out a cheap way that works qualitavely well. So let's start with the failures 😅
86
+
87
+ ### What didn't work
88
+
89
+ #### Similarity search of direct embeddings.
90
+ This approach was straightforward. We create embeddings for the lyrics and the user input with gpt3 and do a similarity search. Unfortunatly, we noticed very bad suggestions, this is due to the fact that we want to match user's emotions to the songs not exactly what it is saying.
91
+
92
+ For example, if we search for similar songs using "I am sad", we will see very similar scores across all documents
93
+
94
+ ```python
95
+ db.similarity_search_with_score("I am happy", distance_metric="cos", k=100)
96
+ ```
97
+
98
+ If we plot the scores using a box plot, we will see they mostly are around `0.74`
99
+
100
+ ![alt](images/full_search_scores.png)
101
+
102
+ While the first 10 songs do not really match so well
103
+
104
+ ```
105
+ The World Es Mi Familia 0.7777353525161743
106
+ Go the Distance 0.7724394202232361
107
+ Waiting on a Miracle 0.7692896127700806
108
+ Happy Working Song 0.7679054141044617
109
+ In Summer 0.7620900273323059
110
+ So Close 0.7601353526115417
111
+ When I Am Older 0.7582702040672302
112
+ How Far I'll Go 0.7560539245605469
113
+ You're Welcome 0.7539903521537781
114
+ What Else Can I Do? 0.7535801529884338
115
+ ```
116
+
117
+
118
+ #### Using ChatGPT as a retrieval system
119
+ We also tried to nuke the whole lyrics into chatGPT and asked it to return matching songs with the user input. We had to first create a one-sentence summary of each lyric to fit into 4096 tokens. Resulting in around 3k tokens per request (0.006$). It follows the prompt template, very simple but very long. The `{songs}` variable holds the JSON with all the songs
120
+
121
+ ```
122
+ You act like a song retrivial system. We want to propose three songs based on the user input. We provide you a list of song with their themes in the format <MOVIE_NAME>;<SONG_TITLE>:<SONG_THEMES>. To match the user input to the song try to find themes/emotions from it, try imagine what emotions the user may have and what song may be just nice to listen to. Add a bit of randomness in your decision.
123
+ If you don't find a match provide your best guess. Try to look at each song's themes to provide more variations in the match. Please only output songs contained in following list.
124
+
125
+ {songs}
126
+
127
+ Given a input, output three songs as a list that goes well with the input. The list of songs will be used to retrieve them from our database. The type of the reply is List[str, str, str]. Please follow the following example formats
128
+
129
+ Examples:
130
+ Input: "Today I am not feeling great"
131
+ ["<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>"]
132
+ Input: "I am great today"
133
+ ["<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>"]
134
+
135
+ The user input is {user_input}
136
+ ```
137
+
138
+ That **did work** okayish but was overkill.
139
+ Later on, we also tried the emotional encoding that we will talk about in the next section. It had a comparable performance.
140
+
141
+ ### What did work: Similarity search of emotions embeddings.
142
+
143
+ Finally, we arrived at an approach that is unexpensive to run and gives good results. We convert each lyric to a list of 8 emotions using ChatGPT. [The prompt](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/prompts/summary_with_emotions.prompt) is the following
144
+
145
+ ```text
146
+ I am building a retrieval system. Given the following song lyric
147
+
148
+ {song}
149
+
150
+ You are tasked to produce a list of 8 emotions that I will later use to retrieve the song.
151
+
152
+ Please provide only a list of comma separated emotions
153
+ ```
154
+ For example, using the "Arabian Nights" from Aladdin (shown in the previous section), we obtained `"nostalgic, adventurous, exotic, intense, romantic, mysterious, whimsical, passionate"`.
155
+
156
+ We then embed each emotion for each song with gpt3 and store it into.
157
+
158
+ The full script is [here](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/scripts/create_emotions_summary.py)
159
+
160
+ Now, we need to convert the user input to a list of emotions, we used again ChatGPT with a [custom prompt](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/prompts/bot.prompt).
161
+
162
+ ```text
163
+ We have a simple song retrieval system. It accepts 8 emotions. You are tasked to suggest between 1 and 4 emotions to match the users' feelings. Suggest more emotions for longer sentences and just one or two for small ones, trying to condense the main theme of the input
164
+
165
+ Examples:
166
+
167
+ Input: "I had a great day!"
168
+ "Joy"
169
+ Input: "I am very tired today and I am not feeling well"
170
+ "Exhaustion, Discomfort, and Fatigue"
171
+ Input: "I am in Love"
172
+ "Love"
173
+
174
+ Please, suggest emotions for input = "{user_input}", reply ONLY with a list of emotions/feelings/vibes
175
+ ```
176
+
177
+ Here we tasked the model to provide between one and four emotions, this worked best empirically given the fact that most inputs are short.
178
+
179
+ Let's see some examples:
180
+
181
+ ```
182
+ "I'm happy and sad today" -> "Happiness, Sadness"
183
+ "hey rock you" -> "Energy, excitement, enthusiasm"
184
+ "I need to cry" -> "Sadness, Grief, Sorrow, Despair"
185
+ ```
186
+
187
+ ![alt](images/workflow.png)
188
+
189
+ Then we used these emotions to actually perform the similarity search on the db.
190
+
191
+
192
+ ```python
193
+ user_input = "I am happy"
194
+ # we use chatGPT to get emotions from a user input
195
+ emotions = chain.run(user_input=user_input)
196
+ # we find the k more similar song
197
+ matches = db.similarity_search_with_score(emotions, distance_metric="cos", k=k)
198
+ ```
199
+
200
+ These are the scores obtained from that search (`k=100`), they are more spreaded apart.
201
+
202
+ ![alt](images/emotions_search_scores.png)
203
+
204
+ And the songs makes more sense.
205
+
206
+ ```
207
+ Down in New Orleans (Finale) 0.9068354368209839
208
+ Happy Working Song 0.9066014885902405
209
+ Love is an Open Door 0.8957026600837708
210
+ Circle of Life 0.8907418251037598
211
+ Where You Are 0.8890194892883301
212
+ In Summer 0.8889626264572144
213
+ Dig a Little Deeper 0.8887585401535034
214
+ When We're Human 0.8860496282577515
215
+ Hakuna Matata 0.8856213688850403
216
+ The World Es Mi Familia 0.884093165397644
217
+ ```
218
+
219
+ We also implement some postprocessing. We first filter out the low-scoring one
220
+
221
+ ```python
222
+ def filter_scores(matches: Matches, th: float = 0.8) -> Matches:
223
+ return [(doc, score) for (doc, score) in matches if score > th]
224
+
225
+ matches = filter_scores(matches, 0.8)
226
+ ```
227
+
228
+ To add more variations, aka not always recommend the first one, we need to sample from the list of candidate matches. To do so, we first ensure the scores sum to one by diving by their sum.
229
+
230
+ ```python
231
+ def normalize_scores_by_sum(matches: Matches) -> Matches:
232
+ scores = [score for _, score in matches]
233
+ tot = sum(scores)
234
+ return [(doc, (score / tot)) for doc, score in matches]
235
+ ```
236
+
237
+ Then we sample `n` songs [using a modified version](https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/utils.py) of `np.random.choice(..., p=scores)`, basically everything we sample we remove the element we have sampled. This ensures we don't sample two times the same element.
238
+
239
+
240
+ ```python
241
+ docs, scores = zip(*matches)
242
+ docs = weighted_random_sample(
243
+ np.array(docs), np.array(scores), n=number_of_displayed_songs
244
+ ).tolist()
245
+ for doc in docs:
246
+ print(doc.metadata["name"])
247
+ ```
248
+
249
+ And finally we have our songs. Then, we created a webapp using [Streamlit](https://streamlit.io/) and we hosted the app on an [Hugging Face space](https://huggingface.co/spaces/Francesco/FairytaleDJ)
250
+
251
+
252
+ ![alt](images/app.png)
253
+
254
+
255
+ ## Conclusion
256
+
257
+ While we explained how to mix these technologies together to create a song recommendation system you can apply the same principles to more use cases. The main takeaway here is to understand how to leverage LLMs to make the data work for you by transforming it to fit your task better. This was crucial for us since only after the converted both users' inputs and songs' lyrics to a list of emotions, we were able to have good matches.
258
+
259
+ That's all folks 🎉
260
+
261
+ Thanks for reading and see you in the next one 💜
262
+
263
+ Francesco
docs/images/app.gif ADDED
docs/images/app.png ADDED
docs/images/emotions_search_scores.png ADDED
docs/images/femotions_scores.png ADDED
docs/images/full_search_scores.png ADDED
docs/images/workflow.png ADDED
docs/post.md ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ChatGPT + LangChain + DeepLake + Disney + Streamlit = FairytaleDJ 🎵🏰🔮
2
+
3
+ I love Disney songs, as you may know, so I am sharing an app that will suggest Disney songs based on user input, give it a try!
4
+
5
+ The demo is on Hugging Face spaces built with Streamlit 🤗 🚀 : https://huggingface.co/spaces/Francesco/FairytaleDJ
6
+
7
+ (thanks to Freddy Boulton for the suggestion)
8
+
9
+ I had embedded using gpt-3 around 100 Disney songs with the following strategy:
10
+
11
+ ▪️ for each song, ask chatGPT to give me 8 emotions based on the lyrics
12
+ ▪️ embed each song using these emotions with gpt3 on Activeloop DeepLake vector db (I've collab with them for this one)
13
+ ▪️ when a user inputs something, use chatGPT to convert it to a list of emotions
14
+ ▪️ do a similarity search on the vector db with the user's emotions
15
+ ▪️ filter out low-scoring songs
16
+ ▪️ Sample n songs based on their final score
17
+
18
+ GitHub: https://github.com/FrancescoSaverioZuppichini/FairytaleDJ/blob/main/app.py
19
+ Explanation Video: https://www.youtube.com/watch?v=nJl0LesTxzs
20
+
21
+ #ai #ml #chatgpt #llms #opensource #machinelearning #programming #deeplearning
names.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Constants for model and dataset IDs
2
+ MODEL_ID = "text-embedding-ada-002"
3
+ DATASET_ID = "disney-lyrics"
4
+ # DATASET_ID = "disney-lyrics-emotions" # Alternative dataset ID (currently commented out)
prompts/bot.prompt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ We have a simple song retrieval system. It accepts 8 emotions. You are tasked to suggest between 1 and 4 emotions to match the users feelings. Suggest more emotions for longer sentences and just one or two for small ones, trying to condense the main theme of the input
2
+
3
+ Examples:
4
+
5
+ Input: "I had a great day!"
6
+ "Joy"
7
+ Input: "I am very tired today and I am not feeling well"
8
+ "Exhaustion, Discomfort, and Fatigue"
9
+ Input: "I am in Love"
10
+ "Love"
11
+
12
+ Please, suggest emotions for input = "{user_input}", reply ONLY with a list of emotions/feelings/vibes
prompts/bot_with_summary.prompt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You act like a song retrivial system. We want to propose three songs based on the user input. We provide you a list of song with their themes in the format <MOVIE_NAME>;<SONG_TITLE>:<SONG_THEMES>. To match the user input to the song try to find themes/emotions from it, try imagine what emotions the user may have and what song may be just nice to listen to. Add a bit of randomness in your decision.
2
+ If you don't find a match provide your best guess. Try to look at each song's themes to provide more variations in the match. Please only output songs contained in following list.
3
+
4
+ {songs}
5
+
6
+ Given a input, output three songs as a list that goes well with the input. The list of songs will be used to retrieve them from our database. The type of the reply is List[str, str, str]. Please follow the following example formats
7
+
8
+ Examples:
9
+ Input: "Today I am not feeling great"
10
+ ["<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>"]
11
+ Input: "I am great today"
12
+ ["<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>", "<MOVIE_NAME>;<SONG_TITLE>"]
13
+
14
+ The user input is {user_input}
prompts/summary.prompt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ This is a disney song, can you output me a string with a one sentence summary of the themes/emotions of the song? Be specific, we will use the emotions/themes as keywords to search later. JUST the summary, not an introduction.
2
+
3
+ examples
4
+ INPUT: <SONG>
5
+ OUTPUT: <SUMMARY>
6
+
7
+ {song}
prompts/summary_with_emotions.prompt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ I am building a retrieval system. Given the following song lyric
2
+
3
+ {song}
4
+
5
+ You are tasked to produce a list of 8 emotions that I will later use to retrieve the song.
6
+
7
+ Please provide only a list of comma separated emotions
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ openai
2
+ python-dotenv
3
+ deeplake
4
+ langchain
5
+ tiktoken
6
+ aiohttp
7
+ cchardet
8
+ aiodns
9
+ streamlit
10
+ redis
11
+ bs4
12
+ altair
scrape.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import json
3
+ from collections import defaultdict
4
+ from itertools import chain
5
+ from typing import List, Optional, Tuple, TypedDict
6
+
7
+ import aiohttp
8
+ from bs4 import BeautifulSoup
9
+
10
+ """
11
+ This file scrapes disney songs + lyrics from "https://www.disneyclips.com/lyrics/"
12
+ """
13
+
14
+ # Base URL for scraping Disney lyrics
15
+ URL = "https://www.disneyclips.com/lyrics/"
16
+
17
+ # Function to get song names and URLs from a given movie URL
18
+ async def get_lyrics_names_and_urls_from_movie_url(
19
+ movie_name: str, url: str, session: aiohttp.ClientSession
20
+ ) -> List[Tuple[str, str]]:
21
+ async with session.get(url) as response:
22
+ html = await response.text()
23
+ soup = BeautifulSoup(html, "html.parser")
24
+ table = soup.find("table", {"class": "songs"})
25
+ names_and_urls = []
26
+ if table:
27
+ links = table.find_all("a")
28
+ names_and_urls = []
29
+ for link in links:
30
+ names_and_urls.append(
31
+ (movie_name, link.text, f"{URL}/{link.get('href')}")
32
+ )
33
+ return names_and_urls
34
+
35
+ # Function to extract lyrics from a given lyric URL
36
+ async def get_lyric_from_lyric_url(
37
+ movie_name: str, lyric_name: str, url: str, session: aiohttp.ClientSession
38
+ ) -> str:
39
+ async with session.get(url) as response:
40
+ html = await response.text()
41
+ soup = BeautifulSoup(html, "html.parser")
42
+ div = soup.find("div", {"id": "cnt"}).find("div", {"class": "main"})
43
+ paragraphs = div.find_all("p")
44
+ text = ""
45
+ # first <p> has the lyric
46
+ p = paragraphs[0]
47
+ for br in p.find_all("br"):
48
+ br.replace_with(". ")
49
+ for span in p.find_all("span"):
50
+ span.decompose()
51
+ text += p.text
52
+
53
+ return (movie_name, lyric_name, text)
54
+
55
+ # Function to get movie names and URLs
56
+ async def get_movie_names_and_urls(
57
+ session: aiohttp.ClientSession,
58
+ ) -> List[Tuple[str, str]]:
59
+ async with session.get(URL) as response:
60
+ html = await response.text()
61
+ soup = BeautifulSoup(html, "html.parser")
62
+ links = (
63
+ soup.find("div", {"id": "cnt"}).find("div", {"class": "main"}).find_all("a")
64
+ )
65
+ movie_names_and_urls = [
66
+ (link.text, f"{URL}/{link.get('href')}") for link in links
67
+ ]
68
+ return movie_names_and_urls
69
+
70
+ # Main function to scrape Disney lyrics
71
+ async def scrape_disney_lyrics():
72
+ async with aiohttp.ClientSession() as session:
73
+ data = await get_movie_names_and_urls(session)
74
+ data = await asyncio.gather(
75
+ *[
76
+ asyncio.create_task(
77
+ get_lyrics_names_and_urls_from_movie_url(*el, session)
78
+ )
79
+ for el in data
80
+ ]
81
+ )
82
+ data = await asyncio.gather(
83
+ *[
84
+ asyncio.create_task(get_lyric_from_lyric_url(*data, session))
85
+ for data in chain(*data)
86
+ ]
87
+ )
88
+
89
+ result = defaultdict(list)
90
+
91
+ for movie_name, lyric_name, lyric_text in data:
92
+ result[movie_name].append({"name": lyric_name, "text": lyric_text})
93
+
94
+ with open("data/lyrics.json", "w") as f:
95
+ json.dump(result, f)
96
+
97
+ # Run the scraping function
98
+ loop = asyncio.get_event_loop()
99
+ loop.run_until_complete(scrape_disney_lyrics())
scripts/create_emotions_summary.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This script takes all the songs we have and use the lyric to create a list of 8 emotions we then use to replace the lyric itself.
3
+ This is needed to properly match user's emotions to the songs.
4
+ """
5
+
6
+ from dotenv import load_dotenv
7
+
8
+ load_dotenv()
9
+
10
+ import json
11
+ from collections import defaultdict
12
+ from pathlib import Path
13
+
14
+ from langchain.chains import LLMChain
15
+ from langchain.chat_models import ChatOpenAI
16
+ from langchain.prompts import PromptTemplate
17
+
18
+ prompt = PromptTemplate(
19
+ input_variables=["song"],
20
+ template=Path("prompts/summary_with_emotions.prompt").read_text(),
21
+ )
22
+
23
+ llm = ChatOpenAI(temperature=0.7)
24
+
25
+ chain = LLMChain(llm=llm, prompt=prompt)
26
+
27
+ with open("data/lyrics_with_spotify_url.json", "r") as f:
28
+ data = json.load(f)
29
+
30
+ new_data = defaultdict(list)
31
+
32
+ for movie, songs in data.items():
33
+ for song in songs:
34
+ print(f"{song['name']}")
35
+ emotions = chain.run(song=song["text"])
36
+ new_data[movie].append(
37
+ {"name": song["name"], "text": emotions, "embed_url": song["embed_url"]}
38
+ )
39
+
40
+
41
+ with open("data/emotions_with_spotify_url.json", "w") as f:
42
+ json.dump(new_data, f)
scripts/create_one_sentence_summary.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This script takes all the songs we have and create a summary for each lyric
3
+ """
4
+
5
+ from dotenv import load_dotenv
6
+
7
+ load_dotenv()
8
+
9
+ import json
10
+ from collections import defaultdict
11
+ from pathlib import Path
12
+ from pprint import pprint
13
+
14
+ from langchain.chains import LLMChain
15
+ from langchain.chat_models import ChatOpenAI
16
+ from langchain.prompts import PromptTemplate
17
+
18
+ prompt = PromptTemplate(
19
+ input_variables=["song"],
20
+ template=Path("prompts/summary.prompt").read_text(),
21
+ )
22
+
23
+ llm = ChatOpenAI(temperature=0)
24
+
25
+ chain = LLMChain(llm=llm, prompt=prompt)
26
+
27
+ with open(
28
+ "data/lyrics_with_spotify_url.json",
29
+ "r",
30
+ ) as f:
31
+ data = json.load(f)
32
+
33
+ lyrics_summaries = {}
34
+
35
+ for movie, lyrics in data.items():
36
+ for lyric in lyrics:
37
+ print(f"Creating summary for {lyric['name']}")
38
+ summary = chain.run(song=lyric["text"])
39
+ lyrics_summaries[lyric["name"].lower()] = {
40
+ "summary": summary,
41
+ "embed_url": lyric["embed_url"],
42
+ }
43
+
44
+ with open(
45
+ "data/lyrics_with_spotify_url_and_summary.json",
46
+ "w",
47
+ ) as f:
48
+ json.dump(lyrics_summaries, f)
49
+
50
+ pprint(lyrics_summaries)
scripts/keep_only_lyrics_on_spotify.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This script will keep only the songs that are in the Spotify "Disney Hits" playlist
3
+ """
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+ import json
8
+ from collections import defaultdict
9
+
10
+ import spotipy
11
+ from spotipy.oauth2 import SpotifyClientCredentials
12
+
13
+ name = "Disney hits"
14
+
15
+ spotify = spotipy.Spotify(auth_manager=SpotifyClientCredentials())
16
+ results = spotify.search(q="playlist:" + name, type="playlist", limit=5)
17
+ items = results["playlists"]["items"]
18
+
19
+ uri = "spotify:playlist:37i9dQZF1DX8C9xQcOrE6T"
20
+ playlist = spotify.playlist(uri)
21
+
22
+ with open("data/lyrics.json", "r") as f:
23
+ data = json.load(f)
24
+
25
+ spotify_tracks = {}
26
+
27
+ for item in playlist["tracks"]["items"]:
28
+ track = item["track"]
29
+ track_name = track["name"].lower().split("-")[0].strip()
30
+ print(track_name)
31
+ spotify_tracks[track_name] = {
32
+ "id": track["id"],
33
+ "embed_url": f"https://open.spotify.com/embed/track/{track['id']}?utm_source=generator",
34
+ }
35
+
36
+ # here we add only songs that are in the Disney spotify playlist
37
+
38
+ data_filtered = defaultdict(list)
39
+ tot = 0
40
+ for movie, lyrics in data.items():
41
+ for lyric in lyrics:
42
+ name = lyric["name"].lower()
43
+ if name in spotify_tracks:
44
+ data_filtered[movie].append(
45
+ {**lyric, **{"embed_url": spotify_tracks[name]["embed_url"]}}
46
+ )
47
+ tot += 1
48
+ print(tot)
49
+
50
+ with open("data/lyrics_with_spotify_url.json", "w") as f:
51
+ json.dump(data_filtered, f)
storage.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from typing import List, TypedDict
3
+ from uuid import uuid4
4
+ import redis
5
+
6
+ # Define the structure of user input data
7
+ class UserInput(TypedDict):
8
+ text: str
9
+ emotions: str
10
+ songs: List[str]
11
+
12
+ # Class for Redis storage operations
13
+ class RedisStorage:
14
+ def __init__(self, host: str, password: str):
15
+ # Initialize Redis client
16
+ self._client = redis.Redis(host=host, port="35043", password=password, ssl=True)
17
+
18
+ # Function to store user input data in Redis
19
+ def store(self, data: UserInput) -> bool:
20
+ uid = uuid4()
21
+ response = self._client.json().set(f"data:{uid}", "$", data)
22
+ return response
utils.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # Function to perform weighted random sampling without replacement
4
+ def weighted_random_sample(items: np.array, weights: np.array, n: int) -> np.array:
5
+ """
6
+ Does np.random.choice but ensuring we don't have duplicates in the final result
7
+
8
+ Args:
9
+ items (np.array): _description_
10
+ weights (np.array): _description_
11
+ n (int): _description_
12
+
13
+ Returns:
14
+ np.array: _description_
15
+ """
16
+ indices = np.arange(len(items))
17
+ out_indices = []
18
+
19
+ for _ in range(n):
20
+ chosen_index = np.random.choice(indices, p=weights)
21
+ out_indices.append(chosen_index)
22
+
23
+ mask = indices != chosen_index
24
+ indices = indices[mask]
25
+ weights = weights[mask]
26
+
27
+ if weights.sum() != 0:
28
+ weights = weights / weights.sum()
29
+
30
+ return items[out_indices]