Metadata-Version: 2.4
Name: marquee-ai
Version: 1.0.2
Summary: Marquee -- Plex-style recommendation rows for a media server library
Author: KernelMedia
License: Apache-2.0
Project-URL: Homepage, https://huggingface.co/KernelMedia
Keywords: recommendations,media-server,plex,jellyfin,llm
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Video
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.24
Requires-Dist: requests>=2.31
Requires-Dist: sentence-transformers>=3.0
Provides-Extra: api
Requires-Dist: fastapi>=0.110; extra == "api"
Requires-Dist: uvicorn>=0.27; extra == "api"
Requires-Dist: pydantic>=2.6; extra == "api"
Provides-Extra: harvest
Requires-Dist: tqdm>=4.66; extra == "harvest"

# Marquee

Turns one item in a media library into Plex-style rows of other items in **that same
library**. Built for self-hosted media servers.

```
IN:  "The Sopranos"

OUT:
  Shows like The Sopranos      Gomorrah, Boardwalk Empire, The Wire, ZeroZeroZero
  More from Tim Van Patten     Game of Thrones, Black Mirror, Boardwalk Empire
  More with Edie Falco         Nurse Jackie, Oz
  Shot by Alik Sakharov        Game of Thrones, House of Cards
```

## Two halves, both required

A **retriever** decides what goes in the rows, by joining your library on shared cast,
crew and franchise and by embedding similarity. A small fine-tuned **model** decides
which rows are worth showing, their order, and what to call them.

The model never sees item ids — it answers with index references into candidates it was
handed, so it cannot invent a title that isn't in your library.

```bash
pip install marquee-ai
```

## Get the model

Weights live on Hugging Face: **[KernelMedia/marquee-ai](https://huggingface.co/KernelMedia/marquee-ai)**

```bash
pip install huggingface_hub
hf download KernelMedia/marquee-ai --local-dir marquee-model

cd marquee-model
ollama create marquee -f Modelfile     # 2.4 GB, needs ollama.com
cd ..
```

Do not edit the `Modelfile`'s `TEMPLATE` block or raise `temperature` -- both are
load-bearing, see [SETUP.md](https://huggingface.co/KernelMedia/marquee-ai/blob/main/SETUP.md).

## Quickstart

```bash
# metadata -- free TMDB key from themoviedb.org/settings/api
echo 'TMDB_API_KEY=your_key' >> .env
marquee harvest --out tmdb_full.jsonl        # ~55 min, ~120k titles

# join it to your server's library
marquee ingest --server library.jsonl --catalog tmdb_full.jsonl \
               --out lib.jsonl --mode requestable

# serve
marquee serve --library lib.jsonl --model marquee --port 8080
```

Your server exports one JSON object per line — only `tmdb_id` and `media_type` are
required:

```json
{"id": "myserver-04471", "tmdb_id": 335984, "media_type": "movie"}
```

Anything missing from the harvest is fetched from TMDB on demand at ingest, so coverage
is complete however you filtered.

## API

```bash
POST /recommend   {"seed_id": "myserver-04471", "row_size": 20}
GET  /search?q=Scorsese          # matches titles AND people
GET  /person?name=Roger%20Deakins
GET  /health
DELETE /cache                    # after a library rescan
```

`/search` and `/person` are pure index lookups — no model call, effectively instant.
Only `/recommend` uses the GPU.

Items carry an `owned` flag, so a UI can offer a Request button on anything not on the
server. Ambiguous titles return **409 with the candidates** rather than guessing —
`Godzilla` matches three films. Narrow with `year` and `media_type`, or write
`"Top Gun (1986)"` directly.

## Use it as a library

The HTTP API is optional. If your server is Python, skip it:

```python
from marquee import Library
from marquee.contract import messages, parse, repair, expand_rows

lib = Library.load("lib.jsonl")
lib.build_embeddings(cache=Path("lib.emb.npz"))     # once at startup

request = lib.build_request(seed_id, semantic_k=14, row_size=20)
raw = call_your_llm(messages(request))              # any OpenAI-compatible endpoint
rows = expand_rows(repair(parse(raw), request), request, 20)
```

## Requirements

| | |
|---|---|
| VRAM | ~3.5 GB (Q4_K_M). Runs on a 4 GB card, or CPU. |
| RAM | ~2.2 GB for a 120k-title catalog |
| Latency | ~1 s per request on an RTX 3060; cached responses are instant |

Full setup and troubleshooting: [SETUP.md](https://huggingface.co/KernelMedia/marquee-ai/blob/main/SETUP.md)

## Data

You harvest TMDB yourself with your own free key; no catalog is distributed. TMDB is
free for non-commercial use and requires attribution — commercial use needs a written
agreement with them.

This product uses the TMDB API but is not endorsed or certified by TMDB.

## Licence

Apache-2.0.
