Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from scripts.recommender import load_data, recommend_movies | |
| from agent import generate_retention_tip | |
| st.set_page_config(page_title="StreamWiseAI", layout="wide") | |
| st.title("π¬ StreamWiseAI β Personalized Movie Recommender & Retention Coach") | |
| st.caption("π€ Powered by AI Agents Β· π― Smart Search Β· π§ AI Insights") | |
| # Load data | |
| movies, embeddings = load_data() | |
| # Initialize watch history | |
| if "watch_history" not in st.session_state: | |
| st.session_state["watch_history"] = [] | |
| # Search input | |
| movie_input = st.text_input("Enter a movie you liked", placeholder="e.g. Toy Story") | |
| show_tip = st.checkbox("π‘ Show retention insight from AI coach?", value=True) | |
| if movie_input: | |
| with st.spinner("Finding great recommendations..."): | |
| recommendations = recommend_movies(movie_input, movies, embeddings) | |
| if not recommendations: | |
| st.error("β Movie not found. Please try another title.") | |
| else: | |
| st.subheader(f"π½οΈ Recommendations for **{recommendations['input_title']}**") | |
| if recommendations["input_title"] not in st.session_state["watch_history"]: | |
| st.session_state["watch_history"].append(recommendations["input_title"]) | |
| cols = st.columns(2) | |
| for idx, rec in enumerate(recommendations["results"]): | |
| with cols[idx % 2]: | |
| with st.container(): | |
| st.markdown("#### π¬ " + rec['title'] + f" ({rec['release_year']})") | |
| # Fallback-safe image | |
| if rec['poster_path']: | |
| st.image(f"https://image.tmdb.org/t/p/w200{rec['poster_path']}", width=150) | |
| else: | |
| st.image("https://via.placeholder.com/150x225.png?text=No+Image", width=150) | |
| st.markdown(f"**π Genre(s):** {rec['genres']}") | |
| st.markdown(f"**π§ Similarity Score:** {rec['similarity']:.2f}") | |
| # Truncate overview if too long | |
| short_overview = rec['overview'] | |
| if len(short_overview) > 250: | |
| short_overview = short_overview[:250] + "..." | |
| st.markdown(f"_{short_overview}_") | |
| st.markdown("---") | |
| if show_tip: | |
| with st.spinner("π€ Retention Coach is analyzing your taste..."): | |
| tip = generate_retention_tip(movie_input, recommendations["results"], st.session_state.get("watch_history", [])) | |
| if tip and not tip.startswith("β οΈ"): | |
| st.markdown("### π‘ Retention Coach Suggests:") | |
| st.markdown(f""" | |
| <div style="background-color:#f0f8ff; padding:15px; border-radius:10px; border-left:5px solid #1f77b4;"> | |
| <span style="font-size:16px;">{tip}</span> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| else: | |
| st.warning("Couldn't generate tip at the moment.") | |
| with st.sidebar: | |
| st.markdown("## π¬ **About StreamWiseAI**") | |
| st.markdown(""" | |
| <span style='color:#6c63ff'><strong>StreamWiseAI</strong></span> is a personalized movie discovery engine designed for modern streaming platforms. | |
| Built to impress recruiters and mimic real-world production use cases, it features: | |
| π <span style='color:#FFA500'><strong>Semantic Search</strong></span> β understands meaning, not just keywords | |
| π§ <span style='color:#00BFFF'><strong>AI Retention Coach</strong></span> β LLM agent gives viewing tips | |
| ποΈ <span style='color:#32CD32'><strong>Watch History Memory</strong></span> β tracks user session dynamically | |
| π <span style='color:#FF69B4'><strong>Built for Showcase</strong></span> β Fast, deployable & free | |
| --- | |
| <small><i>Tech stack: Sentence Transformers Β· Streamlit Β· OpenRouter LLM API Β· Fuzzy Matching Β· Vector Index</i></small> | |
| """, unsafe_allow_html=True) | |
| if st.session_state["watch_history"]: | |
| st.divider() | |
| with st.expander("π Recently Searched"): | |
| st.markdown("π Hereβs a list of your recent searches:") | |
| st.markdown("\n".join(f"- {title}" for title in st.session_state["watch_history"])) | |
| st.markdown("---") | |
| st.markdown( | |
| "<small>π Built by Rajesh Marudhachalam</small>", | |
| unsafe_allow_html=True | |
| ) |