Skip to content

Analytics

The web dashboard exposes an /analytics page that surfaces shape-of-corpus signals derived from the local index. Start the server (txi serve) and open http://127.0.0.1:8765/analytics, or use the top navbar to switch between Browse and Analytics.

The page is one server-rendered view with five panels:

  • Activity: a GitHub-style calendar heatmap of conversations per day, rendered with cal-heatmap. The grid shows the trailing twelve months with weekday rows and month labels; empty days render as light cells so gaps in activity are visible. Hovering a cell shows the exact date and conversation count, and clicking a populated cell links back to Browse filtered to that day (/?since=…&until=…).
  • Top speakers — horizontal bar chart of the most active resolved speakers. Clicks deep-link to Browse filtered to that speaker. An "unresolved turns" badge surfaces turns that have no person_id.
  • Length distribution — histograms of turns-per-conversation and conversation duration, with bucket boundaries chosen automatically by numpy.histogram_bin_edges(..., bins="auto").
  • Embedding map — 2D projection of chunk embeddings. The method dropdown selects between PCA (linear, preserves global geometry) and PCA → UMAP (PCA to 50 dims, then UMAP with cosine metric — better at separating local neighborhoods of related conversations). The granularity dropdown switches between one dot per conversation (mean-of-chunks, default) and one dot per chunk. The color dropdown overlays a color encoding by speaker, by date, or by conversation title. Speaker and title are categorical: the top fifteen groups get distinct colors, the rest collapse into a grey "other" bucket, and the legend doubles as a toggle. Date uses a sequential gradient (purple for oldest, yellow for newest) with a gradient legend below the controls; points with no date are drawn in faint grey. Clicks open the corresponding conversation.
  • Data quality — counts and drill-downs for unresolved speakers, conversations with no resolved participants, and embedding coverage. The unresolved-speakers list suggests the txi people alias command needed to fix each entry.

Requirements

  • uv sync --extra web for the page itself.
  • txi sync to populate conversations and turns. The activity, speakers, length, and data-quality panels work as soon as sync has run.
  • txi embed (and uv sync --extra embed) to populate the embedding map. The scatter shows an empty state when no embeddings exist.

Caching

The embedding projection is cached in the analytics_projections table keyed by (method, granularity), so switching methods or granularities re-uses prior results when the underlying embeddings haven't changed. The cache is invalidated by a fingerprint over the current state of chunk_embeddings, so re-running txi embed causes the next page load to recompute the projection. The cache lives in the same SQLite file as the rest of the index; deleting it is safe — it will be rebuilt on the next request.

UMAP is non-deterministic across hardware but is seeded (random_state=0) so repeated runs on the same machine produce the same layout. With fewer than four points it falls back to plain PCA.

Out of scope

  • t-SNE projection.
  • Per-person topic fingerprinting / similarity matrices.
  • Time-range filters on analytics panels — use Browse for filtering.