Queuei

Project Documentation

Queuei Handbook

A self-hosted intelligence platform. It ingests YouTube playlists, distils each video into structured intelligence with Gemini, stores everything in a searchable vector store, and surfaces it through a terminal-style dashboard — plus a generic scheduled-LLM feed engine you can point at anything.

Django PostgreSQL + MongoDB Gemini APScheduler Alpine + Tailwind

Overview

Queuei turns a stream of long-form video into a queryable knowledge base. Every video in a monitored playlist flows through a pipeline that fetches a transcript, runs a configurable Gemini prompt, generates a 3072-dimension embedding, and writes one document to MongoDB. The dashboard reads those documents back as browsable Stacks, powers semantic Intel Chat, and renders relationship graphs.

Beyond video, the same machinery is generalised: define a prompt, attach a schedule, and Queuei runs it every morning and paints the result as its own dashboard tab. That is how the built-in NASDAQ stock analysis and any custom Dashboard Feed work.

Dual database

Postgres for config & auth, MongoDB for content & vectors.

LLM-native

Gemini for summarisation, embeddings, and transcript fallback.

Schedule anything

Cron-driven pipelines & feeds, editable from the UI.

Architecture

Two Django apps sit on top of two databases.

Two apps

  • records — the user-facing frontend: auth, dashboard, Intel Chat, Nexus graph, Command Center, Settings, Cron manager, and this documentation portal.
  • tasks — the ingestion & scheduling backend: the YouTube pipeline, stock & feed pipelines, the APScheduler runtime, and utility endpoints.

Two databases

StoreAccessHolds
PostgreSQL (Neon) Django ORM Users & groups, TaskConfiguration, GlobalSetting, CronJob, DashboardFeed, TranscriptCache.
MongoDB (Atlas) pymongo (no ORM) All content records, transcripts, LLM outputs, entity annotations, and embedding vectors for search.

MongoDB connections are raw pymongo. get_db_collection() in records/views.py opens a fresh connection per request; the pipeline shares a module-level client from tasks/config.py. There is deliberately no ORM over Mongo.

The Pipeline

Every video runs through YouTubeLLMPipeline (tasks/script_custom/youtube_llm_pipeline.py). One document out per video in.

  1. 1

    Discover

    yt-dlp lists recent videos from every playlist in YOUTUBE_PLAYLIST_IDS, up to PLAYLIST_FETCH_LIMIT each. Already-processed IDs are skipped.

  2. 2

    Transcript

    Tries the local cache, then the source chain (see Transcript Sources). Successful pulls are written to TranscriptCache so retries never re-fetch.

  3. 3

    LLM action

    The task's prompt_template is formatted with {transcript} and sent to Gemini. The response is the intelligence body.

  4. 4

    Embed

    The LLM output is embedded with gemini-embedding-001 into a 3072-dim vector.

  5. 5

    Persist

    A document — metadata + LLM result + embedding + any EXTRA_DOCUMENT_ARGS — is inserted into the task's target collection in MongoDB.

Concurrency is bounded by EXECUTOR_WORKERS with an INBETWEEN_TASK_SLEEP pause between batches — the throttle that keeps Gemini rate limits happy. Trigger a run with POST /tasks/queuei/<task_key>/.

Transcript Sources

Transcripts are fetched through a fallback chain — the first source that returns text wins, and the result is cached.

1

youtube_transcript_api

Fast and free. Blocked on datacenter IPs (Render, cloud hosts) — often fails in production.

2

Gemini (server-side fetch)

Gemini reads the YouTube URL from Google's own infrastructure, bypassing datacenter-IP blocks. The reliable cloud path. Public videos only.

3

RapidAPI

Third-party transcript API. Paid, quota-limited.

4

Supadata

Second paid fallback.

On cloud hosts the library step almost always fails; Gemini is the workhorse. Because video ingestion is token-heavy, large backfills can hit Gemini rate limits — throttle via EXECUTOR_WORKERS / INBETWEEN_TASK_SLEEP.

Dashboard Features

Stacks

Video intelligence grouped by playlist. Drill into a stack to browse per-video reports; transcripts are excluded from the list query for speed.

Stocks

NASDAQ-100 analysis refreshed every morning by a scheduled pipeline, stored in the stock_results collection and rendered as its own tab.

Feeds

Generic scheduled-LLM tabs. Each run is appended as a new sub-tab (history), so a feed reads like a Stack of daily editions.

Intel Chat

RAG over your corpus: your question is embedded, a $vectorSearch on vector_index pulls the top-5 documents, and Gemini answers grounded in them.

Nexus Graph

A force-directed graph built from entity annotations on documents — people, orgs, and tickers linked across the corpus.

Command Center

Supervisor CRUD over TaskConfiguration — create tasks and edit their prompts and target collections inline.

Configuration Layers

Runtime behaviour lives in PostgreSQL, editable from the UI — no redeploy to change how the pipeline runs.

TaskConfiguration Command Center (/command-center/)

Defines what a task does: its prompt_template (with {transcript}) and target_collection. Adding a row makes /tasks/queuei/<task_key>/ live immediately.

GlobalSetting Settings (/settings/, superuser)

Defines how the pipeline runs: playlist IDs, fetch limit, AI model, workers, sleep, extra document fields. Seeded from env vars on first visit, then the DB value wins. Read fresh on every run.

CronJob Cron manager (/cron/, superuser)

Schedules a pipeline or an internal endpoint on a 5-part cron expression. APScheduler hot-reloads on change.

DashboardFeed Command Center / admin

A scheduled-LLM feed: a prompt, a render type (markdown or table), an optional model, and an icon. A CronJob hitting /tasks/feed/<key>/ refreshes it.

Scheduling

A single APScheduler BackgroundScheduler (UTC) reads CronJob rows and fires them. Two job types:

  • pipeline — invokes a Python pipeline class directly (e.g. the YouTube or stock pipeline).
  • endpoint — dispatches an internal request to a relative URL with the task secret header (used by feeds).

Timezone note

The scheduler runs in UTC. 9:00 AM IST is 30 3 * * *. Convert your local time to UTC before entering a cron expression.

Data Models (Postgres)

TaskConfiguration

task_key · display_name · prompt_template · target_collection · is_active

GlobalSetting

key · value · description

CronJob

name · job_type · task_key · endpoint_url · cron_expression · is_active · last_run_at · created_at

DashboardFeed

key · title · icon · prompt · render_type · ai_model · is_active · created_at

TranscriptCache

video_id · transcript · cached_at

MongoDB documents are schemaless; a record typically carries video metadata, the LLM result, entity annotations, and a 3072-dim embedding.

Endpoint Reference

MethodPathPurpose
GET / Dashboard (Analyst/Supervisor)
GET /intel-chat/ RAG chat over the corpus
GET /nexus-data/ Entity force-graph JSON
GET /stocks-data/ Latest stock analysis JSON
ALL /command-center/ TaskConfiguration CRUD (Supervisor)
ALL /settings/ GlobalSetting editor (superuser)
ALL /cron/ CronJob manager (superuser)
GET /doc/ This documentation portal
POST /tasks/queuei/<task_key>/ Run the YouTube pipeline for a task
POST /tasks/feed/<feed_key>/ Refresh a Dashboard Feed
POST /tasks/stocks_refresh/ Refresh NASDAQ analysis
POST /tasks/alert/ Send a Slack webhook alert
POST /tasks/backfill_entities/ Backfill entity annotations

Environment Variables

Secrets and infrastructure config live in .env, never in the database.

DATABASE_URL — Neon PostgreSQL connection string
DB_USER / DB_PASSWORD / DB_URL — MongoDB Atlas credentials
MONGO_DB_NAME — Mongo database (default queuei)
GOOGLE_API_KEY / GEN_AI_API_KEY — Gemini API key
SLACK_WEBHOOK_URL — Incoming webhook for alerts
RAPID_API_KEY / _HOST / _URL — RapidAPI transcript fallback
SUPADATA_API_KEY — Supadata transcript fallback
DJANGO_SECRET_KEY — Django cryptographic secret
ALLOWED_HOSTS — Comma-separated allowed hostnames

Pipeline-behaviour vars (playlist IDs, fetch limit, AI model, workers, sleep, extra args) are only seeds — once the Settings page runs, the DB value takes over.

Access Control

New signups are is_active=False until a supervisor approves them. Authorisation is by Django group plus the superuser flag.

AreaWho
Dashboard, Chat, DocsAnalyst or Supervisor
Command CenterSupervisor or superuser
Settings, CronSuperuser only

Unauthorised authenticated users see access_denied.html rather than a redirect.

Deployment

Local development:

# run the app
python manage.py migrate
python manage.py runserver

# after model changes
python manage.py makemigrations

# build & run the container (connects to production DBs)
./build.sh

The container entrypoint runs migrate then gunicorn on port 8000 with --env-file .env. The scheduler boots inside the web process and hot-loads cron jobs from the DB.