AI Presentation Generator is a chatbot that builds Google Slides from natural language. A LangChain / DeepAgents backend uses OpenAI (gpt-4o-mini) for reasoning, Tavily for web search and image URLs, and the Google Slides and Drive APIs to edit decks. Chat history and sessions live in Supabase. The UI is React (Vite) and talks to a FastAPI backend.
| Credential / service | Purpose |
|---|---|
| OpenAI API key | LLM for the slide agent |
| Tavily API key | TavilySearchResults tool (facts + image URLs) |
| Google Cloud OAuth (Desktop client) | User OAuth for Slides + Drive (path to client JSON via env) |
| Supabase | SUPABASE_URL + SUPABASE_KEY for messages/sessions |
Optional: GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI only if you use the separate web OAuth routes under backend/googleauth/ (not required for the main chat + SlideAgent flow).
- Python 3.12+ (CI uses 3.12)
- Node.js and npm
- Git
git clone https://github.com/Anay-jo/SlidesAgent.git
cd Team-26.028- Sign in at the OpenAI Platform.
- Go to API keys and create a new secret key.
- Add billing / credits if your account requires it.
Add to backend/.env:
OPEN_AI_API_KEY=sk-...The backend reads OPEN_AI_API_KEY (with underscores as shown)—see backend/agents/slide_agent.py.
- Create an account at Tavily.
- Open the developer/API dashboard and create an API key.
The Tavily client used by LangChain expects:
TAVILY_API_KEY=tvly-...The chat endpoint loads user OAuth credentials with the Desktop app flow (InstalledAppFlow in backend/api/v1/users.py). You do not paste a bare “client id” string for that path; you download Google’s OAuth client JSON, which contains client_id and client_secret inside the file.
- Open Google Cloud Console and select or create a project.
- Enable Google Slides API and Google Drive API for that project.
- Open APIs & Services → OAuth consent screen, configure it (External or Internal as appropriate), and add these scopes:
https://www.googleapis.com/auth/presentationshttps://www.googleapis.com/auth/drive.file
- Go to APIs & Services → Credentials.
- Create credentials → OAuth client ID.
- Application type: Desktop app.
- Create, then download the JSON (often named like
client_secret_….json).
Put the downloaded file in backend/secrets/ (create the folder if it doesn't exist — it's gitignored), then point to it in backend/.env:
GOOGLE_OAUTH_CREDENTIAL=secrets/client_secret_....jsonOptional: where to store the refreshed user token (default shown below):
GOOGLE_OAUTH_TOKEN_PATH=secrets/google_oauth_token.jsonPath gotcha: both of these are resolved as plain relative paths (via Python's
open()), relative to whatever directory you actually launch the server from — not relative tobackend/.envor to the source file that reads them. As long as you always start the server withcd backendfirst (see Run locally),secrets/...resolves correctly. If you ever runuvicorn/python main.pyfrom a different working directory, use an absolute path instead.
The first time the backend needs Google access, a browser window opens for consent; after that, the token file is reused and refreshed when possible. If you ever see a RefreshError: invalid_grant, the cached token has expired or was tied to an old/rotated OAuth client — delete backend/secrets/google_oauth_token.json and retry to re-run the consent flow.
GOOGLE_SLIDES_PARENT_FOLDER_ID=your_drive_folder_idIf you use backend/googleauth/’s web callback flow, create a Web application OAuth client in the same Google project and set:
GOOGLE_CLIENT_ID=your_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=...
GOOGLE_REDIRECT_URI=http://localhost:8000/auth/googleThese are separate from the Desktop JSON used by GOOGLE_OAUTH_CREDENTIAL for the slide agent.
- Create a project at Supabase.
- Under Project Settings → API, copy the Project URL and a secret key (often the
service_rolekey for a trusted local backend).
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_KEY=your_supabase_secret_keyThe code in backend/db/client.py expects tables including sessions, messages, and memory compatible with that client (UUID session_id, message rows with role / content, etc.). Align RLS and keys with your team schema.
Create backend/.env (gitignored):
# OpenAI (required)
OPEN_AI_API_KEY=sk-...
# Tavily (required for search tool)
TAVILY_API_KEY=tvly-...
# Supabase (required)
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_KEY=your_supabase_secret_key
# Google — Desktop OAuth JSON path (required for slide generation)
GOOGLE_OAUTH_CREDENTIAL=/absolute/path/to/client_secret_....json
# GOOGLE_OAUTH_TOKEN_PATH=secrets/google_oauth_token.json
# GOOGLE_SLIDES_PARENT_FOLDER_ID=
# Optional — web OAuth only (googleauth routes)
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# GOOGLE_REDIRECT_URI=http://localhost:8000/auth/googlePytest uses a separate Supabase test project when configured:
TEST_SUPABASE_URL=https://yyyy.supabase.co
TEST_SUPABASE_KEY=your_test_keyRESPAN_API_KEY appears in .github/workflows/ci.yml secrets but is not read by application code; omit locally unless you add usage.
cd backend
python3 -m venv venv && source venv/bin/activate # or use conda / your preferred env manager
pip install -r requirements.txt
python main.pyAPI default: http://localhost:8000 (see backend/main.py). Always launch this from inside backend/ — the code uses flat imports (from db.client import ..., from agents.slide_agent import ...) that only resolve correctly when backend/ itself is the working directory.
cd frontend
npm install
npm run devUse the URL Vite prints (usually http://localhost:5173). The chat UI calls:
POST http://localhost:8000/api/v1/users/requestGET http://localhost:8000/api/v1/messages/history?session_id=...
CORS gotcha:
backend/main.pyhardcodesallow_origins=["http://localhost:5173"]. If another project's Vite dev server is already running on your machine and occupying port 5173, Vite will silently bump this frontend to the next free port (5174, 5175, ...) — the browser tab will still load, but every API request will fail preflight with a400 Bad Request("Disallowed CORS origin"), since the actual origin no longer matches. Check the port Vite printed in your terminal matches5173, or updateallow_originsinbackend/main.pyto match whatever port you're actually on.
cd backend
pytestbackend/conftest.py adds backend/ to sys.path so the flat imports resolve the same way they do at runtime.
- Start backend and frontend.
- Complete Google consent when the local OAuth flow opens (first run).
- Ask for a deck (topic, audience, slide count, style). The assistant reply should include presentation details and a link when generation finishes.
- Chat UI with session history
- Agent-driven Slides generation with Tavily-backed research
- Supabase-backed persistence
- Full-stack layout for demos and coursework