Skip to content

Signals, the recommender ​

Experimental

Signals is at version 0.0.1. Its contract with Server and its algorithms can still change.

TypeType Signals is the optional service that holds the home page algorithms. This page explains how it fits with Server and how an algorithm is written. For what users see, read Choosing your algorithm; to run it, read Recommender.

Who does what ​

TypeType-ServerSignals
Accounts, sessions, user dataOwns themHas none: a request never names a user
Talking to YouTubeFetches every video, through its extraction and cacheNever does
Blocking, family filtersApplies them to whatever comes backCannot bypass them
Choosing and ordering videosFalls back to its built-in home pageOwns the algorithms
What is keptChoices, corrections, opinions, built pagesPublic title vectors and a public video catalogue; temporary keyed history snapshots

Server is the only caller of the service. If the service is absent, slow or failing, Server serves its built-in home page, so a home page never breaks.

One home page, step by step ​

text
browser ── GET /recommendations/home ─▶ Server
Server  ── POST /v1/history (once, when the history changed) ─▶ Signals
Server  ── POST /v1/plan (snapshot) ─▶ Signals
Server  ◀─ the sources to fetch ───── Signals
Server:    fetches those sources, filters the candidates
Server  ── POST /v1/rank (plan id, candidates) ─▶ Signals
Server  ◀─ rows, reasons, trace ───── Signals
Server:    filters the rows again, keeps the page, serves it in slices
browser ◀─ rows ───────────────────── Server
  1. Snapshot. Server describes the person without naming them: the algorithm they chose and its settings, the hour and language, their subscriptions, and only the data categories the algorithm lists and the person allows. A long history is sent once under a key and named by that key afterwards.
  2. Plan. The algorithm answers with the sources it wants: the subscription feed, the videos next to a given video, a channel's videos, a search, trending, or exact videos to resume. Each source carries the reason it was asked for.
  3. Fetch. Server fetches the sources, through its shared cache, and counts every video it has to open at the provider against the instance's limit.
  4. Rank. The algorithm scores the candidates and arranges them in rows. Rows name videos by URL only: the service cannot put a video on screen that Server did not fetch and filter.
  5. Second filter. Server applies blocking and family filters to the rows again. A bug in an algorithm cannot show a blocked video.

A page that is not ready within Server's deadline is replaced by the built-in home page for that visit, and keeps being built for the next one.

Routes of the service ​

Every route but /health requires the X-Internal-Token header, the secret shared with Server.

RoutePurpose
GET /healthLiveness and version
GET /versionVersion, revision and build time, as every TypeType service gives them
GET /v1/algorithmsThe algorithms, their texts, the data each reads and every setting with its bounds and default. The interface is built from this answer: a new algorithm needs no frontend change.
POST /v1/historyA history and likes under a key chosen by Server, in one call or in parts
POST /v1/planSnapshot in, sources to fetch out
POST /v1/rankCandidates in, rows with reasons out, and the trace when asked
POST /v1/profileWhat the algorithm concludes from a snapshot: interests, channels, recent watches
POST /v1/topicsFor a list of titles, the interest each belongs to

A plan or a history the service no longer holds is answered 409; Server then sends it again. The exact shapes are the models in recommender/contract.py and the contract_*.py files beside it.

Rules every algorithm follows ​

  1. It says what it reads. An algorithm lists the data categories it uses, and the engine removes the others from the snapshot before calling it. "Never reads your history" is true by construction.
  2. Every setting is exposed. Each weight, threshold, cap and decay time is declared with its type, bounds and default, and shown to the user.
  3. Every row has a reason. A row carries the kind of reason and the item or conclusion behind it; every video carries what brought it.
  4. Conclusions are shown. What was deduced (interests, channels, recent watches) comes out of the same code that ranks, with where each conclusion comes from.
  5. The user's decisions win. Hidden and pinned interests, ignored channels and excluded items are honoured by every algorithm.
  6. Randomness is declared. An algorithm that draws says so and takes a seed: the same seed and the same data give the same page.
  7. One code path. The profile and the trace a user sees come from the run that built their page. There is no separate explanation.

Write an algorithm ​

An algorithm is one file in recommender/algorithms/. It declares its name and texts, the data it reads, its settings, and implements two steps: plan the sources, then rank the candidates into rows. Register it in recommender/registry.py.

Start from subscriptions.py, the smallest one, and read CONTRIBUTING.md first: it says how the code is written and how to prove that a change did not alter a single page.

sh
docker compose up -d --build
uv run pytest

The first command starts the service on port 8190 with its own database and cache. The tests use a word-hashing stand-in for the language model, so they need no download.

How Signals reads a history ​

The Signals family (Signals, channels, videos, mix) shares one reading of the history:

  • Channels. A channel counts by the different videos watched from it, fading by half every 30 days. Minutes watched do not count.
  • Interests. Titles of videos watched through are compared by meaning with a multilingual sentence model, and grouped when they are close enough on average. A group is named after the words its titles share. Titles that say nothing about a subject are left out.
  • Recent watches. A video just watched steers the page at once; its effect halves over time and stops after a few hours.

Shorts are tracked apart and do not steer regular-video recommendations by default. In the Signals family, Let Shorts shape the home page is off by default; turning it on lets Shorts also influence the regular videos in the feed.

The model runs locally in the service, on CPU. It is downloaded once on first start and nothing is sent to a third party afterwards.

Versions ​

Signals follows semantic versioning. A patch changes no page, a minor version may change what pages show or add settings, a major version changes the contract with Server. While the number starts with 0, anything may still change. The version running on an instance is shown on its About page.

The service is licensed under the GNU Affero General Public License, version 3.

Source references ​