Skip to content

- Web Application (Frontend)

The frontend is a Streamlit web application that allows users to interactively receive movie recommendations based on Our Model or Google's Gemini AI.


- Access URLs

Users can:

  • Enter a movie description
  • Select recommendation mode
  • Filter by genres
  • View detailed suggestions with posters, ratings, and summaries

- Features

  • Two Recommendation Modes:
  • Our Model: Uses hybrid semantic and genre-based filtering from FastAPI backend
  • Gemini AI: Uses Google Generative AI to creatively suggest matching movies

  • Genre Filtering:

  • Choose strict or relaxed filtering when selecting genres

  • Preview Mode:

  • Shows the movie title, rating, top actors, duration, and synopsis chunks

- Docker Service

The frontend is deployed as a container and connects with backend (FastAPI) to request movie recommendations and displays results:

- Dockerfile

FROM python:3.10-slim-bullseye

RUN apt-get update && apt-get install -y \
    build-essential \
    libfreetype6-dev libpng-dev libjpeg-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /front

ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1

COPY requirements.txt .

RUN pip3 install --upgrade pip \
 && pip3 install --no-cache-dir --force-reinstall numpy pandas \
 && pip3 install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8501

CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.headless=true", "--server.runOnSave=true", "--server.address=0.0.0.0"]

custom_model_recommendation(query, num_recs, use_filter, selected_genres, filtering_mode)

Fetches movie recommendations from a custom backend model.

Parameters:

Name Type Description Default
query str

The input query describing the type of story or movie.

required
num_recs int

The number of movie recommendations to generate.

required
use_filter bool

Whether to apply genre-based filtering.

required
selected_genres list

List of genres to filter the recommendations by.

required
filtering_mode str

The filtering mode ('strict' or 'relaxed').

required

Returns:

Name Type Description
dict dict

The JSON response from the backend containing movie recommendations.

Source code in app/front/recommend.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def custom_model_recommendation(query: str, num_recs: int, use_filter: bool,
                                selected_genres: list, filtering_mode: str) -> dict:
    """
    Fetches movie recommendations from a custom backend model.

    Args:
        query (str): The input query describing the type of story or movie.
        num_recs (int): The number of movie recommendations to generate.
        use_filter (bool): Whether to apply genre-based filtering.
        selected_genres (list): List of genres to filter the recommendations by.
        filtering_mode (str): The filtering mode ('strict' or 'relaxed').

    Returns:
        dict: The JSON response from the backend containing movie recommendations.
    """
    payload = {
        "query": query,
        "use_genre_filter": use_filter,
        "selected_genres": selected_genres,
        "filtering_mode": filtering_mode,
        "num_recs": num_recs
    }

    response = requests.post(f"{BACKEND_URL}/recommend_movies", json=payload)
    return response.json()

display_movie(movie)

Displays movie details in a Streamlit app with emojis and clean formatting.

Parameters:

Name Type Description Default
movie dict

A dictionary containing movie details such as title, year, genres, IMDb rating, age rating, duration, top actors, poster URL, and preview chunks.

required

Returns:

Type Description
None

None

Source code in app/front/recommend.py
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
def display_movie(movie: dict) -> None:
    """
    Displays movie details in a Streamlit app with emojis and clean formatting.

    Args:
        movie (dict): A dictionary containing movie details such as title, year, genres,
                      IMDb rating, age rating, duration, top actors, poster URL, and preview chunks.

    Returns:
        None
    """
    st.markdown(f"### 🎬 {movie.get('title', 'Unknown')} ({movie.get('year', 'N/A')})")
    st.markdown(f"**Genres:** {', '.join(movie.get('genres', []))}")

    imdb = movie.get("imdb_rating", "N/A")
    rating = movie.get("age_rating", "N/A")
    runtime = format_runtime(movie.get("duration", ""))

    st.markdown(f"⭐️ IMDb: {imdb}     🔞 Rating: {rating}     🕒 Runtime: {runtime}")

    # Actor list cleanup
    raw_actors = movie.get("top_actors", [])
    try:
        if isinstance(raw_actors, str):
            actors = ast.literal_eval(raw_actors)
        else:
            actors = raw_actors
        actor_str = ", ".join(actors)
    except Exception:
        actor_str = "N/A"
    st.markdown(f"🎭 Top Actors: {actor_str}")

    if movie.get("poster_url"):
        st.image(movie["poster_url"], width=150)

    st.markdown("📖 **Preview:**")
    for chunk in movie.get("preview_chunks", []):
        st.markdown(f"*({chunk.get('type', 'N/A')})* {chunk.get('text', '')}")

    st.markdown("---")

format_runtime(runtime_str)

Formats a runtime string by normalizing 'hours' and 'minutes' into a consistent format.

Parameters:

Name Type Description Default
runtime_str str

The runtime string to format.

required

Returns:

Name Type Description
str

The formatted runtime string, or 'N/A' if the input is empty or not a string.

Source code in app/front/recommend.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def format_runtime(runtime_str):
    """
    Formats a runtime string by normalizing 'hours' and 'minutes' into a consistent format.

    Args:
        runtime_str (str): The runtime string to format.

    Returns:
        str: The formatted runtime string, or 'N/A' if the input is empty or not a string.
    """
    if not runtime_str or not isinstance(runtime_str, str):
        return "N/A"

    # Normalize both "hour" and "hours" into one consistent format
    runtime_str = re.sub(r"(\d+)\s*hours?", r"\1 hours ", runtime_str)
    runtime_str = re.sub(r"(\d+)\s*minutes?", r"\1 minutes ", runtime_str)

    return runtime_str.strip()

gemini_recommendation(query, num_recs)

Generates movie recommendations using the Gemini Generative AI model.

Parameters:

Name Type Description Default
query str

The input query describing the type of story or movie.

required
num_recs int

The number of movie recommendations to generate.

required

Returns:

Name Type Description
str str

The generated text containing movie recommendations.

Source code in app/front/recommend.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def gemini_recommendation(query: str, num_recs: int) -> str:
    """
    Generates movie recommendations using the Gemini Generative AI model.

    Args:
        query (str): The input query describing the type of story or movie.
        num_recs (int): The number of movie recommendations to generate.

    Returns:
        str: The generated text containing movie recommendations.
    """
    genai.configure(api_key=GEMINI_API_KEY)
    model = genai.GenerativeModel("gemini-1.5-flash")
    prompt = f"Suggest {num_recs} movies that match this kind of story:\n{query}"
    response = model.generate_content(prompt)
    return response.text