Skip to content

[Feature] Import a document to seed personalization #3

Description

@ryleydotmp3

The ability to point TabType at a document (notes, a style guide, a glossary, past writing) and have it seed personalization immediately, instead of waiting for typing history to accumulate.

To be clear on scope: this is not fine-tuning. The MLX path here is inference-only, so this is corpus seeding, not training.

The pipeline already exists. TypingHistoryStore feeds three consumers:

  • PhraseMemory.ingest() for verbatim phrase recall
  • contextSamples(budget:) for the <recently_written_by_author> block
  • topWords(limit:) for the persona line

Importing a document would mean parsing it to text and feeding that same pipeline, so most of the work is already done.

How does Cotypist or another tool handle it? (optional)

Not aware of an equivalent, this would be new ground.

Anything else

Parsing needs no new dependencies: NSAttributedString reads .docx/.rtf/.html, PDFKit reads .pdf, .txt/.md are free, and String.enumerateSubstrings(options: .bySentences) chunks it.

Two design questions I'd want your ruling on before writing anything:

  1. How the document reaches the prompt. A stable <reference> block costs prefill once and fits the volatility ordering in PromptBuilder. Retrieving relevant chunks per keystroke would give better quality but would invalidate the KV prefix cache constantly, which works against the design in Predictor.swift. I'd default to the stable block unless you'd rather have retrieval.

  2. Storage. TypingHistoryStore caps at maxEntries = 500 with FIFO eviction, so writing document chunks into entries would flush real typing history out. I'd add docChunks: [String]? to the existing Snapshot so it stays inside the same AES-GCM encrypted file rather than a plaintext sidecar. There's already legacy-decode handling at TypingHistoryStore.swift:189, so an optional field should stay backward compatible.

One trap worth flagging: PhraseMemory.minCount = 2 means a continuation has to recur twice before it's suggested. A document ingested once gives every trigram a count of 1, so continuation() returns nothing and the feature would look like it does nothing at all. Would need an ingest(_:weight:) parameter or similar.

This would pair well with the custom dictionary idea (other issue), since document import could harvest rare capitalised terms straight into that word list. Happy to do them as two separate PRs in that order.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions