Skip to content

Latest commit

 

History

History
113 lines (81 loc) · 4.61 KB

File metadata and controls

113 lines (81 loc) · 4.61 KB

Compromise — core concepts

A 5-minute mental model. Read this before writing compromise code.

What it is

compromise is a rule-based NLP library for English. It tokenizes text, tags each word with its part-of-speech, and lets you find and transform parts of the text. It is fast, runs offline in the browser or node, has no dependencies, and makes "good-enough" decisions — it is not a neural/LLM model and does not call out to one.

import nlp from 'compromise'

let doc = nlp('she sells seashells by the seashore.')
doc.verbs().toPastTense()
doc.text()
// 'she sold seashells by the seashore.'

The three objects

Object What it is
Document the whole parsed text, held internally as Term[][] (sentences of terms).
View a selection of terms within a document — the thing every method returns. nlp(text) returns a View of the whole document; .match('#Verb') returns a smaller View. A View still knows about its whole document (.all() zooms back out).
Term a single tokenized word, with .text, .pre/.post (surrounding whitespace/punctuation), .normal, and a Set of tags.

Almost every method is called on a View and returns a new View, so calls chain:

nlp(text).match('#Person+').first().text()

Mutability — the #1 gotcha

A View points at the underlying document. Transform methods mutate that shared document in place, even though they also return a View:

let doc = nlp('I walk to work')
doc.verbs().toPastTense()       // mutates doc, even though we didn't reassign
doc.text()                      // 'I walked to work'  ← doc changed
  • Read-only methods (.match, .if, .found, .text, .json, .has, accessors) do not change the document.
  • Transform methods (.toPastTense, .replace, .remove, .tag, .normalize, case/whitespace methods …) do.
  • To work on a copy without touching the original, call .clone() first:
let past = doc.clone().verbs().toPastTense().text()   // doc is untouched

Sentences are the top-level unit

Matching does not cross sentence boundaries by default.

nlp("that's it. Back to Winnipeg!").has('it back')   // false

For multi-sentence / paragraph matching use the compromise-paragraphs plugin.

Build tiers (one / two / three)

The default import is the full library. Smaller builds exist for size/speed:

Import Includes Use when
compromise (= compromise/three) tokenize + tags + all selections (.nouns(), .verbs(), .people(), .numbers() …) default — what you almost always want
compromise/two tokenize + POS tags + contractions you only need tags + .match(), not the named selections
compromise/one (= compromise/tokenize) tokenize only, no tags you only need words/sentences split up; #Tag patterns won't work
import nlp from 'compromise'          // full (recommended)
import nlp from 'compromise/two'      // tags, no selections
import nlp from 'compromise/tokenize' // tokens only

There is no meaningful tree-shaking beyond these tiers — the tagger is greedy and competitive, so pulling individual pieces out is not recommended. Run the full library unless size is critical.

Getting data out

doc.text()            // a string
doc.out('array')      // array of strings, one per match
doc.json()            // rich data: terms, tags, offsets, etc.
doc.debug()           // pretty-print the tagging to the console (great for debugging)

Customising

Three escalating ways to teach compromise new things — see recipes.md and the .extend() section of the README:

  1. A lexicon object at parse time: nlp(text, { kermit: 'FirstName' })
  2. nlp.addWords({...}) / nlp.addTags({...}) globally.
  3. nlp.plugin({...}) / nlp.extend({...}) — add words, tags, new methods, and post-processing.

Known limitations

  • No nested match syntax'(modern (major|minor))? general' is not supported. Chain successive .match() calls instead.
  • No inter-sentence matching without the paragraphs plugin (see above).
  • Slashes split into separate wordsnlp('eats/shoots/leaves').has('koala leaves') is false.
  • No dependency/parse tree — transformations are heuristic, not grammar-tree based.

See also