what-2-watch-ai

AI-powered Discord bot for movie recommendations

Recommends movies by reading user ratings, querying OpenAI's API, and returning conversational suggestions in real time. Built as a capstone for AIML9342 (University of Toronto & Circuit Stream), it demonstrates API integration, async workflows, and educational-to-production tradeoffs.

image


1. CONCEPT

Most recommenders score silently and return ranked lists. This one explains why—it reads your tastes and reasons conversationally about them based on movie metadata (such as actors, director, transcript, title, etc).


2. SYSTEM ARCHITECTURE

image

Fixed Commands (!hi, !bye, !roll, !flip, !rpsR/P/S) are instant, deterministic, with no API calls.

AI Commands (!recommend) read CSV → format data → create OpenAI thread → poll response → send to Discord.


3. COMMAND DISPATCH SYSTEM

Command Type Handler Response Time
!hi Fixed greeting() Instant
!bye Fixed farewell() Instant
!roll Fixed roll() Instant
!flip Fixed flip() Instant
!rpsR / !rpsP / !rpsS Fixed rps_rock() / rps_paper() / rps_scissors() Instant
!recommend AI ask_assistant() ~3-10 seconds

Dictionary dispatch is cleaner than if-elif chains and scales better:

commands = {
    '!hi': greeting(),
    '!bye': farewell(),
    '!roll': roll(),
    '!flip': flip(),
    '!rpsR': rps_rock(),
    '!rpsP': rps_paper(),
    '!rpsS': rps_scissors(),
}

4. AI INTEGRATION PIPELINE

The recommendation flow is the heart of the project. It demonstrates three key technical challenges:

Challenge 1: Data Cleaning

movie_string = movie_string.replace("['', '0'], ","")
movie_string = movie_string.replace("'","")

String replacement works but is fragile. The Fix?: Pandas + schema validation.

Challenge 2: Non-Blocking Waits

async def wait_for_response(thread_id):
    for i in range(30):
        await asyncio.sleep(1)
        messages = ai.beta.threads.messages.list(thread_id=thread_id)
        if len(messages.data) > 1:
            return messages.data[0].content[0].text.value

Polls every 1s for ≤30s. Production would use webhooks; polling works for small bots.

Challenge 3: Prompt Quality

Simple prompt → generic results. Add genres, mood, tone, constraints for better output. 300-token limit forces brevity over detail.


5. LIMITATIONS

Data: Single hard-coded CSV. No validation. String concat overflows. → Solution: SQLite + schema validation.

Scalability: Single file. Hard-coded paths. No multi-user support. → Modularize; use pathlib.


TLDR

  • Discord bot that reads movie ratings (CSV) → queries OpenAI API → returns conversational recommendations in real time
  • Strengths: Real API calls, secure credential handling, clean command dispatch, async patterns, error handling
  • Limitations: Single hard-coded CSV (no multi-user), fragile string cleaning, single-file architecture, 300-token limit on responses
  • Key Technical Challenge: Making non-blocking API calls work in Discord's event loop without freezing the connection
  • Production Gap: Educational simplicity (polling, string-based parsing) vs. production-ready (webhooks, schema validation, databases)

view on github