VerbalSentimentAnalysis / streamlit_app.py
Vlad Bastina
changes
ca22ee2
import streamlit as st
import time
from sentiment_analysis import get_analysis
from PIL import Image
import os
import json
from pathlib import Path
def load_css(file_name):
"""Loads a CSS file and injects it into the Streamlit app."""
try:
css_path = Path(__file__).parent / file_name
with open(css_path) as f:
st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
# st.info(f"Loaded CSS: {file_name}") # Optional: uncomment for debugging
except FileNotFoundError:
st.error(f"CSS file not found: {file_name}. Make sure it's in the same directory as app.py.")
except Exception as e:
st.error(f"Error loading CSS file {file_name}: {e}")
st.markdown("""
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:ital,wght@0,100..900;1,100..900&family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
""", unsafe_allow_html=True)
load_css("style.css")
os.environ['GOOGLE_API_KEY'] = st.secrets['GOOGLE_API_KEY']
google_credentials_dict = json.loads(st.secrets["GOOGLE_APPLICATION_CREDENTIALS"])
google_credentials_json = json.dumps(google_credentials_dict)
# Write the credentials to a temporary file
temp_file = "gcp_credentials.json"
with open(temp_file, "w") as f:
f.write(google_credentials_json)
# Set the environment variable to point to the temporary file
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = temp_file
def display_message(role, content, image_path=None):
"""Displays the messages on the screen along with the plots"""
if role == "user":
st.chat_message(role).markdown(f"**User:** {content}")
elif role == "ai":
st.chat_message(role).markdown(f"**Ai:** {content}")
if image_path:
# Display the image if it exists
try:
img = Image.open(image_path)
st.image(img, caption="Generated Image", use_container_width=True)
except Exception as e:
st.error(f"Error loading image: {e}")
def main():
"""Main function that loops and can record audio and dispaly the messages from gemini"""
st.title("Verbal Sentiment Tracker")
st.write("This demo lets you upload an audio file, automatically transcribes the audio, and analyzes the emotional tone of your words over time. By generating a histogram of sentiment evolution, it helps uncover how feelings shift throughout a conversation—useful for scenarios like customer calls, where ending on a positive note can make all the difference.")
if "messages" not in st.session_state:
st.session_state.messages = []
uploaded_file = st.file_uploader("Upload an audio file", type=["wav", "mp3"])
if uploaded_file is not None:
# Saving the uploaded audio to a temporary file
save_path = "uploaded_audio.wav"
with open(save_path, "wb") as f:
f.write(uploaded_file.getbuffer())
time.sleep(0.1)
with st.spinner('Fetching response from Ai...'):
user_message, gemini_response = get_analysis(save_path)
st.session_state.messages.append({"role": "user", "content": user_message})
st.session_state.messages.append({"role": "ai", "content": gemini_response, "image_url": "plot.png"})
# Display the chat history
for msg in st.session_state.messages:
# Check if the message is from Gemini and display the image accordingly
if msg["role"] == "user":
display_message(msg["role"], msg["content"])
elif msg["role"] == "ai":
display_message(msg["role"], msg["content"], msg.get("image_url"))
time.sleep(0.1)
import streamlit.components.v1 as components
components.html(
"""
<script>
function sendHeightWhenReady() {
const el = window.parent.document.getElementsByClassName('stMain')[0];
if (el) {
const height = el.scrollHeight;
console.log("Sending height to parent:", height);
window.parent.parent.postMessage({ type: 'setHeight', height: height }, '*');
} else {
// Retry in 100ms until the element appears
setTimeout(sendHeightWhenReady, 1000);
}
}
window.onload = sendHeightWhenReady;
window.addEventListener('resize', sendHeightWhenReady);
setInterval(sendHeightWhenReady, 1000);
</script>
"""
,height=0)
if __name__ == "__main__":
main()