Skip to content

Add Memory Title Generation to Enrichment Pipeline

System Intent

This plan adds automatic title generation for memories to improve user comprehension and memory discoverability. During enrichment, the system will use an LLM to generate concise, descriptive titles from memory transcripts. The backend will persist titles in the memory ORM, and the frontend will display titles with graceful fallback to default behavior if titles are unavailable.

Mermaid Diagram

graph LR
    A[Enrichment Pipeline] -->|Transcript| B[LLM Title Generator]
    B -->|Generated Title| C[Memory ORM]
    C -->|Store Title Field| D[Database]
    C -->|Query with Title| E[Frontend]
    E -->|Display Title or Fallback| F[User Interface]
    D -->|Retrieve Title| C

    style A fill:#e1f5ff
    style B fill:#fff3e0
    style C fill:#f3e5f5
    style D fill:#e8f5e9
    style E fill:#fce4ec
    style F fill:#f1f8e9

Black-Box Input/Output Contracts

System-Level Contract

Input

  • Enriched Memory Object — Memory with populated transcript field
  • Type: Memory object (ORM entity)
  • Required fields: id, transcript, created_at
  • Optional fields: existing title (null or string)

Output (Success)

  • Memory with Title — Memory object persisted with generated title
  • Type: Memory object
  • Fields: all input fields + title (non-null string, 50–150 characters)
  • Behavior: Title summarizes key content from transcript for quick recognition

Output (Failure)

  • Memory without Title — Memory persists without generated title
  • Type: Memory object
  • Fields: all input fields with title = null
  • Behavior: Frontend falls back to default display (e.g., timestamp or "Untitled Memory")
  • Trigger: LLM call timeout, API error, rate limit exceeded

Contracts by Flow

Flow: Generate Title from Transcript

Component Input Output Validation Updated
LLM Service Transcript text (string, max 4000 chars) Title (string, 50–150 chars) Title length within bounds; no empty strings Y
Enrichment Processor Memory object with transcript Memory object with title field populated Title field is non-null; ORM save succeeds Y
Error Handling LLM timeout or API error Memory with title=null, error logged Error logged; memory persists regardless Y

Flow: Persist Title to ORM

Component Input Output Validation Updated
Memory ORM Title value (string or null) Database row with title field Foreign key integrity; title field accepts null Y
Database Schema Title column (nullable VARCHAR) Persisted title row Column type allows null; index on title for search Y

Flow: Display Title in Frontend

Component Input Output Validation Updated
Frontend API Query memory with title field Title (or null) API returns title field; null is valid Y
UI Component Memory object with title (or null) Rendered title or fallback text If title exists, show it; else show default label Y

Acceptance Criteria and Test Flows

Test Flow 1: Generate and Persist Title (Happy Path)

Inputs: - Memory object with transcript = "I went to the park today. The weather was sunny. I saw my friends."

Pass Criteria: 1. LLM generates a title (e.g., "Park Visit with Friends") 2. Title length is between 50 and 150 characters 3. Title is persisted to database in memory.title field 4. Memory object returned by ORM includes title field populated 5. No errors logged

Fail Criteria: - Title is empty or exceeds length bounds - Database save fails - ORM does not return title field in response

Test Flow 2: Handle LLM Timeout (Error Path)

Inputs: - Memory object with transcript - LLM service timeout occurs (simulated)

Pass Criteria: 1. Title generation attempt fails with timeout error 2. Error is logged with memory ID and timestamp 3. Memory is persisted to database with title=null 4. Memory object returned includes title=null 5. Enrichment pipeline continues (does not halt)

Fail Criteria: - Memory is not persisted when LLM fails - Error is not logged - Enrichment pipeline halts

Test Flow 3: Frontend Displays Title (Happy Path)

Inputs: - API query returns memory object with title = "Park Visit with Friends"

Pass Criteria: 1. Frontend receives title in API response 2. UI component renders title in memory card 3. Title is clickable/searchable if applicable 4. No console errors

Fail Criteria: - Title is not rendered - UI breaks if title is missing

Test Flow 4: Frontend Fallback when Title is Null (Edge Case)

Inputs: - API query returns memory object with title=null

Pass Criteria: 1. Frontend receives title=null 2. UI component displays fallback text (e.g., "Untitled Memory" or timestamp) 3. Memory is still usable (clickable, selectable) 4. No console errors

Fail Criteria: - UI breaks or shows "null"/"undefined" - Memory becomes unusable

  1. Batch Title Generation — Verify enrichment handles multiple memories in a single run without rate-limit errors
  2. Title Uniqueness — Verify two different transcripts produce different titles (no copy-paste errors from LLM)
  3. Search Integration — Verify titles are indexed and searchable (if applicable to feature scope)
  4. Concurrent Updates — Verify database handles concurrent title updates without race conditions
  5. Empty Transcript — Verify graceful fallback when transcript is empty or very short

Pseudocode

Enrichment Processor: generate_title_for_memory

function enrich_memory_with_title(memory):
    if memory.transcript is empty or too short:
        memory.title = null
        return memory

    try:
        # Call LLM to generate title
        title = llm.generate_title(
            transcript=memory.transcript,
            max_length=150,
            min_length=50,
            context="User memory from wearable AI system"
        )

        # Validate title
        if title is None or len(title) < 50 or len(title) > 150:
            log_error(f"Title validation failed for memory {memory.id}: {title}")
            memory.title = null
        else:
            memory.title = title

    except TimeoutError:
        log_error(f"LLM timeout for memory {memory.id}")
        memory.title = null

    except RateLimitError:
        log_error(f"LLM rate limit for memory {memory.id}")
        memory.title = null

    except Exception as e:
        log_error(f"Unexpected error generating title for memory {memory.id}: {e}")
        memory.title = null

    finally:
        # Always persist memory, with or without title
        memory.save()
        return memory

Frontend: MemoryCard Component

function MemoryCard(memory):
    title_display = memory.title if memory.title else "Untitled Memory"
    timestamp_display = format_time(memory.created_at)

    render:
        <div class="memory-card">
            <h3 class="memory-title">{title_display}</h3>
            <p class="memory-time">{timestamp_display}</p>
            <p class="memory-preview">{memory.transcript[:100]}...</p>
        </div>

Status

Draft — Awaiting approval of system intent, diagram, contracts, and acceptance criteria before implementation.

Files to Create/Modify

  • src/backend/enrichment/title_generator.py — LLM title generation service
  • src/backend/enrichment/enrichment_processor.py — Update to call title generator
  • src/backend/orm/models.py — Add nullable title field to Memory model
  • src/backend/db/migrations/ — Add title column to memories table
  • src/frontend/components/MemoryCard.tsx — Update to display title with fallback
  • tests/backend/test_enrichment_titles.py — Unit and integration tests
  • tests/frontend/MemoryCard.test.tsx — Frontend component tests