compromise README

The project's README from github.com/spencermountain/compromise. As one markdown file: README.md.

compromise
modest natural language processing
npm install compromise
by Spencer Kelly and many contributors
french • german • italian • spanish
don't you find it strange,
    how easy text is to make,

     ↬ᔐᖜ↬   and how hard it is to actually parse and use?

compromise tries its best to turn text into data.
it makes limited and sensible decisions.
it's not as smart as you'd think.
import nlp from 'compromise'

let doc = nlp('she sells seashells by the seashore.')
doc.verbs().toPastTense()
doc.text()
// 'she sold seashells by the seashore.'
don't be fancy, at all:
if (doc.has('simon says #Verb')) {
  return true
}
grab parts of the text:
let doc = nlp(entireNovel)
doc.match('the #Adjective of times').text()
// "the blurst of times?"
match docs

and get data:

import plg from 'compromise-speech'
nlp.extend(plg)

let doc = nlp('Milwaukee has certainly had its share of visitors..')
doc.compute('syllables')
doc.places().json()
/*
[{
  "text": "Milwaukee",
  "terms": [{
    "normal": "milwaukee",
    "syllables": ["mil", "wau", "kee"]
  }]
}]
*/
json docs

avoid the problems of brittle parsers:

let doc = nlp("we're not gonna take it..")

doc.has('gonna') // true
doc.has('going to') // true (implicit)

// transform
doc.contractions().expand()
doc.text()
// 'we are not going to take it..'
contraction docs

and whip stuff around like it's data:

let doc = nlp('ninety five thousand and fifty two')
doc.numbers().add(20)
doc.text()
// 'ninety five thousand and seventy two'
number docs

-because it actually is-

let doc = nlp('the purple dinosaur')
doc.nouns().toPlural()
doc.text()
// 'the purple dinosaurs'
noun docs

Use it on the client-side:

<script src="https://unpkg.com/compromise"></script>
<script>
  var doc = nlp('two bottles of beer')
  doc.numbers().minus(1)
  document.body.innerHTML = doc.text()
  // 'one bottle of beer'
</script>

or likewise:

import nlp from 'compromise'

var doc = nlp('London is calling')
doc.verbs().toNegative()
// 'London is not calling'

compromise is ~250kb (minified):

it's pretty fast. It can run on keypress:

it works mainly by conjugating all forms of a basic word list.

The final lexicon is ~14,000 words:

you can read more about how it works, here. it's weird.

okay -

compromise/one

A tokenizer of words, sentences, and punctuation.

import nlp from 'compromise/one'

let doc = nlp("Wayne's World, party time")
let data = doc.json()
/* [{
  normal:"wayne's world party time",
    terms:[{ text: "Wayne's", normal: "wayne" },
      ...
      ]
  }]
*/
tokenizer docs

compromise/one splits your text up, wraps it in a handy API,

/one is quick - most sentences take a 10th of a millisecond.

It can do ~1mb of text a second - or 10 wikipedia pages.

Infinite jest takes 3s.

You can also parallelize, or stream text to it with compromise-speed.

compromise/two

A part-of-speech tagger, and grammar-interpreter.

import nlp from 'compromise/two'

let doc = nlp("Wayne's World, party time")
let str = doc.match('#Possessive #Noun').text()
// "Wayne's World"
tagger docs

compromise/two automatically calculates the very basic grammar of each word.

this is more useful than people sometimes realize.

Light grammar helps you write cleaner templates, and get closer to the information.

compromise has 83 tags, arranged in a handsome graph.

#FirstName → #Person → #ProperNoun → #Noun

you can see the grammar of each word by running doc.debug()

you can see the reasoning for each tag with nlp.verbose('tagger').

if you prefer Penn tags, you can derive them with:

let doc = nlp('welcome thrillho')
doc.compute('penn')
doc.json()

compromise/three

Phrase and sentence tooling.

import nlp from 'compromise/three'

let doc = nlp("Wayne's World, party time")
let str = doc.people().normalize().text()
// "wayne"
selection docs

compromise/three is a set of tooling to zoom into and operate on parts of a text.

.numbers() grabs all the numbers in a document, for example - and extends it with new methods, like .subtract().

When you have a phrase, or group of words, you can see additional metadata about it with .json()

let doc = nlp('four out of five dentists')
console.log(doc.fractions().json())
/*[{
    text: 'four out of five',
    terms: [ [Object], [Object], [Object], [Object] ],
    fraction: { numerator: 4, denominator: 5, decimal: 0.8 }
  }
]*/
let doc = nlp('$4.09CAD')
doc.money().json()
/*[{
    text: '$4.09CAD',
    terms: [ [Object] ],
    number: { prefix: '$', num: 4.09, suffix: 'cad'}
  }
]*/

🤖 For AI agents & LLMs

Plain-text, copy-paste docs that render without JavaScript live in this repo:

API

Compromise/one

Output
Utils
Accessors
Match

(match methods use the match-syntax.)

compromise (spencermountain/compromise)

Searching Database…

这是什么?Compromise 是一个轻量级的 JavaScript 自然语言处理库,可以把文本解析成结构化数据:包括分词(词语和句子)、词性标注,以及按数字、人名、日期等类型查询短语。
它是框架还是库?它是一个可以导入 JS 项目的库,由三个分层的部分组成:'one' 负责分词,'two' 负责词性标注和语法分析,'three' 负责短语和句子的处理工具。
怎么把它添加到项目里?用 npm 安装,然后调用 nlp(text) 获取一个文档对象,就可以对它进行查询和转换。
我需要先安装 Python 或其他运行环境吗?不需要。它是纯 JavaScript 编写的,只依赖几个小型 npm 包(efrt、grad-school、suffix-thumb);如果在服务端使用,需要 Node 12 或更高版本。
词性标注准确吗,还是只是个粗略的启发式方法?它依赖基础词表和轻量级的启发式规则,而不是经过训练的模型,所以标注速度快,但结果只是近似的;你可以用 .confidence() 查看置信度,或用 doc.debug() 进行调试。
它能在浏览器里运行,还是只能在 Node 中运行?只要有 JavaScript 运行的地方都能用,包括在浏览器里响应按键事件,因为它没有任何原生依赖。
它有多快?compromise/one 每秒大约可以分词 1MB 文本(相当于约 10 个维基百科页面),大多数句子的解析时间在十分之一毫秒左右;《无尽的玩笑》(Infinite Jest)大约需要 3 秒。
语法标注是怎么工作的?compromise/two 会为每个词分配 83 种词性标签之一,这些标签按层级组织(例如 #FirstName → #Person → #ProperNoun → #Noun),有助于从文本中提取干净的数据。
我能从文本中提取数字或日期之类的特定内容吗?可以。compromise/three 提供了短语级别的工具,例如用 .numbers() 获取文档中的所有数字,还有 .subtract() 和 .json() 等方法,用于获取匹配短语的元数据。
Size
62.9 MB
Stars
12.2K
Age
15y
Commits · 90 Days