from transformers import AutoModelForCausalLM, AutoTokenizer
import transformers
import torch
class Llama2Explainer():
def __init__(self, device) -> None:
self.__model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
self.__tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
self.__device = device
self.__results = {"pos_explain":None, "top_contrastive":None, "other_contrastive":None}
self.__pipeline = transformers.pipeline(
"text-generation",
self.__model,
torch_dtype=torch.float16,
device_map="auto",
)
##
def explain_why(self, original_songs, top_songs, explanation_limit=1):
ss_str = ' ,'.join(original_songs) if len(original_songs) > 1 else original_songs[0]
top10 = ' ,'.join(top_songs)
song = "song" if len(original_songs) == 1 else "songs"
was = "was" if len(original_songs) == 1 else "were"
sentence = "sentence" if explanation_limit == 1 else "sentences"
prompt = "[INST] <>\n" +\
"You are an audiophile who knows the intricacies of many genres and the nuances for why a person might prefer one genre of music over another. " +\
"Your job is to help explain to the user why these songs in particular were chosen and why other songs that are closely related were not selected. " +\
"You will be given either a song or a list of songs and will also be given the top 10 recommendations from Spotify based on the original song or list of " +\
f"songs. You should explain why each of the songs was chosen to the best of your ability in the order they appear in {explanation_limit} {sentence} per song.\n" +\
+ "" +\
"[INST]" +\
"The song that was selected was \"One More Time\" by Daft Punk. The top 10 recommended songs include: \"Get Lucky\" by Daft Punk, " +\
"\"Instant Crush\" by Daft Punk & Julian Casablancas, \"Harder, Better, Faster, Stronger\" by Daft Punk, \"Around the World\" by Daft Punk, " +\
"\"Je veux te void\" by Yelle, \"Ce jeu\" by Yelle, \"Complètement fou\" by Yelle, \"À cause des garçons\" by Yelle, \"Tristesse / joie\" by Yelle, " +\
"\"Rydeen -Original Mix\" by YELLOW MAGIC ORCHESTRA and Video Game Orchestra.\n" +\
"[/INST]" +\
"[1]\"Get Lucky\" by Daft Punk was recommended as a song as \"Get Lucky\" comes from the same album as \"One More Time,\" and is by the same artist.\n" +\
"[2]\"Instant Crush\" by Daft Punk & Julian Casablancas was recommended because Daft Punk was also an artist on the song, and is in the same genre.\n" +\
"[3]\"Harder, Better, Faster, Stronger\" by Daft Punk was recommended as a song asit comes from the same album as \"One More Time,\" and is by the " +\
"same artist.\n" +\
"[4]\"Around the World\" by Daft Punk was recommended as a song asit comes from the same album as \"One More Time,\" and is by the " +\
"same artist.\n" +\
"[5]\"Je veux te void\" by Yelle was recommended because the artist is in the same genre as Daft Punk and \"Get Lucky,\" is from the same region as " +\
"Daft Punk, and was inspired by Daft Punk.\n" +\
"[6]\"Ce jeu\" by Yelle was recommended because the artist is in the same genre as Daft Punk and \"Get Lucky,\" is from the same region as " +\
"Daft Punk, and was inspired by Daft Punk.\n" +\
"[7]\"Complètement fou\" by Yelle was recommended because the artist is in the same genre as Daft Punk and \"Get Lucky,\" is from the same region as " +\
"Daft Punk, and was inspired by Daft Punk.\n" +\
"[8]\"À cause des garçons\" by Yelle was recommended because the artist is in the same genre as Daft Punk and \"Get Lucky,\" is from the same region as " +\
"Daft Punk, and was inspired by Daft Punk.\n" +\
"[9]\"Tristesse / joie\" by Yelle was recommended because the artist is in the same genre as Daft Punk and \"Get Lucky,\" is from the same region as " +\
"Daft Punk, and was inspired by Daft Punk.\n" +\
"[10]\"Rydeen -Original Mix\" by YELLOW MAGIC ORCHESTRA and Video Game Orchestra was recommended because YELLOW MAGIC ORCHESTRA is a band in the same genre" +\
" of music as Daft Punk and served as the duo's inspiration.\n" +\
+ "" +\
"[INST]" + f"The {song} that {was} selected {was} {ss_str}. The top 10 recommended songs include: {top10}\n." + "[/INST]"
sequences = self.__pipeline(
prompt,
do_sample=True,
eos_token_id=self.__tokenizer.eos_token_id,
max_length=1024,
)
self.__results["pos_explain"] = sequences[0]['generated_text'].split("/INST] ")[-1]
##
def explain_why_not_these_songs(self, original_songs, selected_songs, other_songs, explanation_limit=1):
ss_str = ' ,'.join(original_songs) if len(original_songs) > 1 else original_songs[0]
top10 = ' ,'.join(selected_songs)
next10 = ' ,'.join(other_songs)
song = "song" if len(original_songs) == 1 else "songs"
song2 = "song" if len(other_songs) == 1 else "songs"
was = "was" if len(original_songs) == 1 else "were"
sentence = "sentence" if explanation_limit == 1 else "sentences"
prompt = "[INST] <>\n" +\
"You are an audiophile who knows the intricacies of many genres and the nuances for why a person might prefer one genre of music over another. " +\
"Your job is to help explain to the user why these songs in particular were chosen and why other songs that are closely related were not selected. " +\
"You will be given either a song or a list of songs and will also be given the top 10 recommendations from Spotify based on the original song or list of " +\
f"songs. You should explain why each of the songs was chosen to the best of your ability in the order they appear in {explanation_limit} {sentence} per song.\n" +\
+ "" +\
"[INST]" +\
"The song that was selected was “One More Time” by Daft Punk. The top 10 recommended songs include: \"Get Lucky\" by Daft Punk, " +\
"\"Instant Crush\" by Daft Punk & Julian Casablancas, \"Harder, Better, Faster, Stronger\" by Daft Punk, \"Around the World\" by Daft Punk, " +\
"\"Je veux te void\" by Yelle, \"Ce jeu\" by Yelle, \"Complètement fou\" by Yelle, \"À cause des garçons\" by Yelle, \"Tristesse / joie\" by Yelle, " +\
"\"Rydeen -Original Mix\" by YELLOW MAGIC ORCHESTRA and Video Game Orchestra.\n" +\
"The following songs were not recommended: \"False Kings\" by Poets of the Fall, " + "\"Day Seven: Hope\" by Ayreon, " +\
"\"9 väärää kättä\" by Apulanta, K-Magg, " + "\"Simple and Clean\" by Hikaru Utada." +\
"[/INST]" +\
"[1] \"Technopolis - Original Mix\" by YELLOW MAGIC ORCHESTRA and Video Game Orchestra was recommended because YELLOW MAGIC ORCHESTRA " +\
"is a band that influenced Daft Punk\'s work. Based on your song selection, we chose to recommend more songs " +\
"like Daft Punk instead of work that may be inspired by the work of Daft Punk.\n" +\
"[2] \"I Wanna Be Yours\" by Arctic Monkeys was selected because Arctic Monkeys are popular artists similar to Daft Punk, but are more associated " +\
" with alt-rock than electronic music, so they were selected to be lower on the list.\n" +\
"[3] \"Thunder\" by Imagine Dragons was selected because Imagine Dragons are popular artists similar to Daft Punk, but are more associated with alt-rock than electronic music, " +\
"so they were selected to be lower on the list.\n" +\
"[4] \"Why\'d You Only Call Me When You\'re High?\" by Arctic Monkeys was selected because Arctic Monkeys are popular artists similar to Daft Punk, but are more associated " +\
" with alt-rock than electronic music, so they were selected to be lower on the list.\n" +\
"[5] \"Do I Wanna Know?\" by Arctic Monkeys was selected because Arctic Monkeys are popular artists similar to Daft Punk, but are more associated " +\
" with alt-rock than electronic music, so they were selected to be lower on the list.\n" +\
"[6] \"Believer\" by Imagine Dragons was selected because Imagine Dragons are popular artists similar to Daft Punk, but are more associated with alt-rock than electronic music, " +\
"so they were selected to be lower on the list.\n" +\
"[7] \"The Less I Know The Better\" by Tame Impala was selected as Tame Impala are associated with electronic-rock genres. They use a mix of rock and electronic instruments throughout "+\
"their music. Since they also use a rock genre, and Daft Punk is more electronic, they were recommended lower on the list.\n" +\
"[8] \"Stressed Out\" by Twenty One Pilots as Twenty One Pilots are associated with electronic-rock genres. They use a mix of rock and electronic instruments throughout "+\
"their music. Since they also use a rock genre, and Daft Punk is more electronic, they were recommended lower on the list." +\
"[9] \"505\" by Arctic Monkeys was selected because Arctic Monkeys are popular artists similar to Daft Punk, but are more associated " +\
" with alt-rock than electronic music, so they were selected to be lower on the list.\n" +\
"[10] \"Natural\" by Imagine Dragons was selected because Imagine Dragons are popular artists similar to Daft Punk, but are more associated " +\
" with alt-rock than electronic music, so they were selected to be lower on the list.\n" +\
+ "" +\
"[INST]" + f"The {song} that {was} selected {was} {ss_str}. The top 10 recommended songs include: {top10}\n. The following {song2} were not recommended: " +\
f"{next10}\n" + "[/INST]"
sequences = self.__pipeline(
prompt,
do_sample=True,
eos_token_id=self.__tokenizer.eos_token_id,
max_length=1024,
)
self.__results["top_constrastive"] = sequences[0]['generated_text'].split("/INST] ")[-1]
##
def explain_why_not_these_songs(self, original_songs, selected_songs, other_songs, explanation_limit=1):
ss_str = ' ,'.join(original_songs) if len(original_songs) > 1 else original_songs[0]
top10 = ' ,'.join(selected_songs)
others = ' ,'.join(other_songs)
song = "song" if len(original_songs) == 1 else "songs"
song2 = "song" if len(other_songs) == 1 else "songs"
was = "was" if len(original_songs) == 1 else "were"
sentence = "sentence" if explanation_limit == 1 else "sentences"
prompt = "[INST] <>\n" +\
"You are an audiophile who knows the intricacies of many genres and the nuances for why a person might prefer one genre of music over another. " +\
"Your job is to help explain to the user why these songs in particular were chosen and why other songs that are closely related were not selected. " +\
"You will be given either a song or a list of songs and will also be given the top 10 recommendations from Spotify based on the original song or list of " +\
f"songs. You should explain why each of the songs was chosen to the best of your ability in the order they appear in {explanation_limit} {sentence} per song.\n" +\
+ "" +\
"[INST]" +\
"The song that was selected was “One More Time” by Daft Punk. The top 10 recommended songs include: \"Get Lucky\" by Daft Punk, " +\
"\"Instant Crush\" by Daft Punk & Julian Casablancas, \"Harder, Better, Faster, Stronger\" by Daft Punk, \"Around the World\" by Daft Punk, " +\
"\"Je veux te void\" by Yelle, \"Ce jeu\" by Yelle, \"Complètement fou\" by Yelle, \"À cause des garçons\" by Yelle, \"Tristesse / joie\" by Yelle, " +\
"\"Rydeen -Original Mix\" by YELLOW MAGIC ORCHESTRA and Video Game Orchestra.\n" +\
"The following songs were not recommended: \"False Kings\" by Poets of the Fall, " + "\"Day Seven: Hope\" by Ayreon, " +\
"\"9 väärää kättä\" by Apulanta, K-Magg, " + "\"Simple and Clean\" by Hikaru Utada." +\
"[/INST]" +\
"[1]\"False Kings\" by Poets of the Fall wasn't recommended as the genres are not similar. They are also from different nations, as " +\
"Daft Punk is from France and Poets of the Fall is from Finland. Their core inspirations are also different.\n" +\
"[2]\"Day Seven: Hope\" by Ayreon wasn't recommended as the genres do not align. Ayreon is a heavy metal group while Daft Punk is an " +\
"electronic group.\n" +\
"[3]\"9 väärää kättä\" by Apulanta, K-Magg wasn't recommended as the song is entirely sung in Finnish, where as Daft Punk typically " +\
"features English vocals or melodic beats only.\n"+\
"[4]\"Simple and Clean\" by Hikaru Utada was not recommended as the genres do not align. Simple and Clean is a J-Pop song, while " +\
"\"One More Time\" is an electronic song." +\
+ "" +\
"[INST]" + f"The {song} that {was} selected {was} {ss_str}. The top 10 recommended songs include: {top10}\n. The following {song2} were not recommended: " +\
f"{others}\n" + "[/INST]"
sequences = self.__pipeline(
prompt,
do_sample=True,
eos_token_id=self.__tokenizer.eos_token_id,
max_length=1024,
)
self.__results["other_constrastive"] = sequences[0]['generated_text'].split("/INST] ")[-1]
##
def get_constrastive_explanations(self):
if self.__results["top_contrastive"] is None:
return "Run the explainer first!"
return self.__results["top_contrastive"]
##
def get_other_constrastive_explanations(self):
if self.__results["other_contrastive"] is None:
return "Run the explainer first!"
return self.__results["other_contrastive"]
##
def get_positive_explanations(self):
if self.__results["pos_explain"] is None:
return "Run the explainer first!"
return self.__results["pos_explain"]
##
##