Conversation Memory Viz

An interactive visualisation of the sliding-window memory failure mode. Production LLMs that keep "the last N messages" don't forget gracefully — they drop facts the second their source message scrolls off. As 25 turns accumulate, six tracked entities (name, company, project, framework, database, auth provider) get extracted, then silently lost when their introducing message leaves the window.

Three modes:

  • Explore — step through one message at a time and watch the entity tracker degrade.
  • Predict — answer five "you are the model" questions where you can only see the window.
  • Challenge — four multiple-choice diagnostics on the window's failure modes.
A conversation begins. The model's context window holds the last 10 messages.
Conversation Timeline
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Press Step to begin the conversation
Entity Tracker
User name
Company
Project
Framework
Database
Auth provider

A conversation begins. The model's context window holds the last 10 messages.

Customize
Window
10

Installation

npx shadcn@latest add https://craftbits.dev/r/conversation-memory-viz.json

Usage

import { ConversationMemoryViz } from "@craft-bits/viz/conversation-memory-viz";
 
<ConversationMemoryViz />

Bring your own transcript and entities:

<ConversationMemoryViz
  messages={[
    { id: 1, role: "user", text: "I'm Vijay from Acme", entities: [{ key: "name", value: "Vijay" }] },
    { id: 2, role: "user", text: "Working on Project Aurora", entities: [{ key: "project", value: "Project Aurora" }] },
    /* … */
  ]}
  entities={[
    { key: "name", label: "User name", sourceMsg: 1, value: "Vijay" },
    { key: "project", label: "Project", sourceMsg: 2, value: "Project Aurora" },
  ]}
/>

Subscribe to score events:

<ConversationMemoryViz
  onModeComplete={({ mode, correct, total }) => {
    /* lift the new totals into an external chart */
  }}
/>

Understanding the component

  1. The timeline. A scrollable strip of 25 numbered bubbles. Squares are user turns, circles are bot turns. A translucent rectangle marks the model's current sliding window; the label window sits below it. The current step glows with a focus ring.
  2. The entity tracker. Six rows beneath the timeline track facts the model would extract: name, company, project, framework, database, auth provider. Each row shows a status dot — neutral before discovery, green while the source message is still in the window, red (with a strike-through value and shake animation) the moment that message slides out.
  3. Predict mode. You see only the window for one specific round and answer a question that requires resolving a fact stated earlier in the conversation. After checking your answer, the viz reveals the message that was lost (with a body-shake animation) and explains why the sliding window failed.
  4. Challenge mode. Pure multiple-choice diagnostics: "At message 15 with window 10, can the model greet the user by name? How would entity extraction fix this? In a 500-message conversation with window 20, how many of the first 100 messages survive?"
  5. Reduced motion. Under prefers-reduced-motion: reduce, every entrance, the window-shift spring, the entity shake on loss, and the mode crossfade collapse to instant transitions.

Props

PropTypeDefaultDescription
messagesreadonly ConversationMemoryVizMessage[]25-turn project-onboarding transcriptThe conversation. Each entry needs id, role, text, optional entities.
entitiesreadonly ConversationMemoryVizEntityDef[]6 entitiesFacts to track. Each needs key, label, sourceMsg, value.
windowSizenumber10Number of messages the sliding window can hold.
predictRoundsreadonly ConversationMemoryVizPredictRound[]5 rounds"You are the model" rounds for predict mode.
challengeRoundsreadonly ConversationMemoryVizChallengeRound[]4 roundsMultiple-choice rounds for challenge mode.
defaultMode"explore" | "predict" | "challenge""explore"Mode visible on first render.
transitionTransitionSPRINGS.snapOverride the spring for bubble entrances.
onStepChange(step: number) => voidFires when the explore-mode step changes.
onModeChange(mode) => voidFires when the user switches modes.
onModeComplete(score) => voidFires when a predict / challenge run finishes with { mode, correct, total, results }.
classNamestringMerged onto the root via cn().

Accessibility

  • The three mode buttons are a role="group" with aria-label="Visualization mode" and aria-pressed on the active one.
  • The conversation timeline is a scrollable role="region" with tabIndex={0} and an aria-label describing the window range. Every bubble carries an aria-label that includes the body text and whether the message is "in window" or "lost from window".
  • A polite live region (aria-live="polite") announces the current narration string on every step / mode change.
  • Mode switches focus the mode-content wrapper so screen readers re-read the new pane.
  • Each option button in predict / challenge has aria-pressed, a visible focus ring, and meets the 40×40 minimum hit area.
  • Colour is never the only signal — visible/lost counts are also spelled out in text, and lost entities use a strike-through plus a (msg N) label.
  • Motion respects prefers-reduced-motion: reduce — every entrance, the entity shake-on-loss, the lost-message shake reveal, and the mode crossfade collapse to instant transitions.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/systems/ConversationMemoryViz.tsx). The source was a lesson component wired to Widget / useWidgetHistory / ModeStrip / ChallengeBtn / FeedbackBadge / ScoreDots primitives in @/lessons/primitives/chrome/* and used per-track palette tokens (--color-accent-400, --color-fail-400, --color-success-400, --color-ink-*) plus CA-specific spring aliases (SPRINGS.snappy, SPRINGS.dramatic, STAGGER.tight, TIMING.wrong.shakeSpring). The craft-bits extract drops the lesson chrome (no widget shell, no undo/redo history — pure useState), re-keys every colour to the semantic --cb-* palette so consumer themes repaint freely, and routes every transition through the canonical SPRINGS.snap / SPRINGS.smooth / SPRINGS.bouncy / SPRINGS.slow from @craft-bits/core/motion. The mode strip, primary / secondary buttons, feedback badge, score dots, and option list are inlined as private sub-components that consume cb-* tokens. The hard-coded transcript, entities, predict rounds, and challenge rounds are now props with the original 25-turn project-onboarding scenario as the default. forwardRef + cn() + spread ...props were added to match the library's interactive-component API.