| import streamlit as st |
| from streamlit_js_eval import streamlit_js_eval |
| import choosingdata as choice |
| from dotenv import load_dotenv |
| from langchain.text_splitter import CharacterTextSplitter |
| from langchain_community.embeddings import HuggingFaceInstructEmbeddings |
| from langchain_community.vectorstores import FAISS |
| from langchain_openai import ChatOpenAI |
| from langchain_openai import OpenAIEmbeddings |
| from langchain.memory import ConversationBufferMemory |
| from langchain.chains import ConversationalRetrievalChain |
| from langchain_community.llms import HuggingFaceHub |
|
|
|
|
| def get_text_chunks(text): |
| """ |
| Splits the given text into chunks based on specified character settings. |
| |
| Parameters: |
| - text (str): The text to be split into chunks. |
| |
| Returns: |
| - list: A list of text chunks. |
| """ |
| text_splitter = CharacterTextSplitter( |
| separator="\n", chunk_size=1000, chunk_overlap=200, length_function=len |
| ) |
| chunks = text_splitter.split_text(text) |
| return chunks |
|
|
|
|
| def get_vectorstore(text_chunks): |
| """ |
| Generates a vector store from a list of text chunks using specified embeddings. |
| |
| Parameters: |
| - text_chunks (list of str): Text segments to convert into vector embeddings. |
| |
| Returns: |
| - FAISS: A FAISS vector store containing the embeddings of the text chunks. |
| """ |
| embeddings = OpenAIEmbeddings() |
| vectorstore = FAISS.from_texts(texts=text_chunks, embedding=embeddings) |
| return vectorstore |
|
|
|
|
| def get_conversation_chain(vectorstore): |
| """ |
| Initializes a conversational retrieval chain that uses a large language model |
| for generating responses based on the provided vector store. |
| |
| Parameters: |
| - vectorstore (FAISS): A vector store to be used for retrieving relevant content. |
| |
| Returns: |
| - ConversationalRetrievalChain: An initialized conversational chain object. |
| """ |
| llm = ChatOpenAI( |
| model_name="gpt-4-1106-preview", |
| ) |
|
|
| memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) |
| conversation_chain = ConversationalRetrievalChain.from_llm( |
| llm=llm, retriever=vectorstore.as_retriever(), memory=memory |
| ) |
| return conversation_chain |
|
|
|
|
| def set_prompt(text_block): |
| """ |
| Callback function that sets the chosen prompt in the session state. |
| |
| Parameters: |
| - text_block (str): The prompt text selected by the user. |
| """ |
| st.session_state["messages"].append({"role": "user", "content": text_block}) |
| st.session_state["prompts"] = text_block |
|
|
|
|
| def prompts(): |
| """ |
| Renders clickable buttons for predefined prompts in the Streamlit application, |
| allowing the user to select a prompt to send to the conversation chain. |
| """ |
| potential_prompts = [ |
| f"What is the meaning of the song {st.session_state['title']} by {st.session_state['artist']}?", |
| f"What is the most difficult English grammar point in the song {st.session_state['title']} by {st.session_state['artist']}? Can you explain it?", |
| f"What is the most common English word in the song {st.session_state['title']} by {st.session_state['artist']} (excluding stopwords)? Can you give some example sentences using that word?", |
| f"What is the most worth learning English phrase in the song {st.session_state['title']} by {st.session_state['artist']}? Can you explain it and provide practical example using the phrase?", |
| ] |
| chosen_prompt = None |
| for index, text_block in enumerate(potential_prompts): |
| st.button( |
| f"Prompt {index + 1}: {text_block}", on_click=set_prompt, args=(text_block,) |
| ) |
|
|
|
|
| def get_lyrics(): |
| """ |
| Retrieves the lyrics stored in the session state. |
| |
| Returns: |
| - str: The lyrics of the currently selected song. |
| """ |
| lyrics = st.session_state["lyrics"] |
| return lyrics |
|
|
|
|
| def page_title(): |
| """ |
| Sets the title of the Streamlit page based on the selected song and artist. |
| """ |
| if st.session_state["title"] and st.session_state["artist"]: |
| st.title( |
| f'🎵 English Music Recommender 💬 ({st.session_state["title"]} by {st.session_state["artist"]})' |
| ) |
| else: |
| st.title("🎵 English Music Recommender 💬") |
|
|
|
|
| def chat_sidebar(): |
| """ |
| Renders the sidebar in the Streamlit application for selecting music preferences |
| and handling song recommendations. |
| """ |
| with st.sidebar: |
| st.title("💚 Music Preferences") |
|
|
| user_difficulty = st.sidebar.radio( |
| "Choose a difficulty level:", ("Easy", "Medium", "Hard") |
| ) |
|
|
| user_danceability = st.sidebar.radio( |
| "How much do you want to dance?", ("Low", "Medium", "High") |
| ) |
|
|
| user_valence = st.sidebar.radio( |
| "What energy are you feeling?", ("Negative", "Neutral", "Positive") |
| ) |
|
|
| if not st.session_state["song_bool"]: |
|
|
| if st.sidebar.button("Submit"): |
| df = choice.process_data("data.json") |
| recommendations = choice.recommendation( |
| df, |
| dance_choice=user_danceability, |
| valence_choice=user_valence, |
| difficulty_choice=user_difficulty, |
| ) |
|
|
| st.session_state["title"] = recommendations["title"].values[0] |
| st.session_state["artist"] = recommendations["artist"].values[0] |
| st.session_state["lyrics"] = recommendations["lyrics"].values[0] |
| st.session_state["id"] = ( |
| f'https://open.spotify.com/track/{recommendations["id"].values[0]}' |
| ) |
| st.session_state["song_bool"] = True |
|
|
| st.rerun() |
|
|
| else: |
| if st.session_state["song_bool"]: |
|
|
| st.write("### We would recommend you...") |
| st.write(f"## {st.session_state['title']}") |
| st.write(f" by {st.session_state['artist']}") |
| st.markdown( |
| f'<a href="{st.session_state["id"]}"><img src="{st.session_state["icon"]}" alt="Clickable image" style="height:60px;"></a>', |
| unsafe_allow_html=True, |
| ) |
| st.write("Please refresh the page for a new recommendation.") |
| if st.button("Reload page"): |
| streamlit_js_eval(js_expressions="parent.window.location.reload()") |
|
|
|
|
| def chat(): |
| """ |
| Manages the chat interface in the Streamlit application, handling the conversation |
| flow and displaying the chat history. |
| """ |
| if st.session_state["lyrics"]: |
|
|
| text_chunks = get_text_chunks(get_lyrics()) |
| vectorstore = get_vectorstore(text_chunks) |
| st.session_state.conversation = get_conversation_chain(vectorstore) |
|
|
| if len(st.session_state.messages) == 1: |
| message = st.session_state.messages[0] |
| with st.chat_message(message["role"]): |
| st.write(message["content"]) |
| prompts() |
|
|
| else: |
| for message in st.session_state.messages: |
| with st.chat_message(message["role"]): |
| st.write(message["content"]) |
|
|
| |
| if prompt := st.chat_input(): |
| st.session_state.messages.append({"role": "user", "content": prompt}) |
| st.session_state.prompts = prompt |
| with st.chat_message("user"): |
| st.write(prompt) |
|
|
| if st.session_state.messages[-1]["role"] != "system": |
|
|
| with st.chat_message("system"): |
| with st.spinner("Generating response..."): |
| response = st.session_state.conversation.invoke( |
| {"question": st.session_state.prompts} |
| ) |
| st.session_state.chat_history = response["chat_history"] |
| message = st.session_state.chat_history[-1] |
| st.write(message.content) |
| message = {"role": "system", "content": message.content} |
| st.session_state.messages.append(message) |
|
|
| else: |
| st.write("You can chat with GPT once a song has been recommended to you!") |
|
|
|
|
| def init(): |
| """ |
| Initializes the session state variables used in the Streamlit application and |
| loads environment variables. |
| """ |
| load_dotenv() |
|
|
| if "title" not in st.session_state: |
| st.session_state["title"] = "" |
| if "artist" not in st.session_state: |
| st.session_state["artist"] = "" |
| if "icon" not in st.session_state: |
| st.session_state["icon"] = ( |
| "https://thereceptionist.com/wp-content/uploads/2021/02/Podcast-Listen-On-Spotify-1.png" |
| ) |
| if "id" not in st.session_state: |
| st.session_state["id"] = "" |
| if "song_bool" not in st.session_state: |
| st.session_state["song_bool"] = False |
| if "messages" not in st.session_state.keys(): |
| st.session_state.messages = [ |
| { |
| "role": "system", |
| "content": "What do you want to learn about? Here are some suggested prompts: ", |
| } |
| ] |
| if "conversation" not in st.session_state: |
| st.session_state.conversation = None |
| if "chat_history" not in st.session_state: |
| st.session_state.chat_history = None |
| if "lyrics" not in st.session_state: |
| st.session_state["lyrics"] = "" |
| if "prompts" not in st.session_state: |
| st.session_state["prompts"] = "" |
|
|