Files
2026-07-13 10:48:06 +00:00

1070 lines
61 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- WEHUB_ZH_README -->
> [!NOTE]
> 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
> [English](./README.en.md) · [原始项目](https://github.com/spencermountain/compromise) · [上游 README](https://github.com/spencermountain/compromise/blob/HEAD/README.md)
> 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
<div align="center">
<img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div><b>compromise</b></div>
<img src="https://user-images.githubusercontent.com/399657/68222691-6597f180-ffb9-11e9-8a32-a7f38aa8bded.png"/>
<div>轻量自然语言处理</div>
<div><code>npm install compromise</code></div>
<div align="center">
<sub>
<a href="https://spencermounta.in/">Spencer Kelly</a> 和
<a href="https://github.com/spencermountain/compromise/graphs/contributors">
众多贡献者
</a>
</sub>
</div>
<img height="22px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
<div align="center">
<div>
<a href="https://npmjs.org/package/compromise">
<img src="https://img.shields.io/npm/v/compromise.svg?style=flat-square" />
</a>
<a href="https://codecov.io/gh/spencermountain/compromise">
<img src="https://codecov.io/gh/spencermountain/compromise/branch/master/graph/badge.svg" />
</a>
<a href="https://bundlephobia.com/result?p=compromise">
<img src="https://img.shields.io/bundlephobia/min/compromise"/>
<!-- <img src="https://badge-size.herokuapp.com/spencermountain/compromise/master/builds/compromise.min.js" /> -->
</a>
</div>
<div align="center">
<sub>
<a href="https://github.com/nlp-compromise/fr-compromise">法语</a> • <a href="https://github.com/nlp-compromise/de-compromise">德语</a> • <a href="https://github.com/nlp-compromise/it-compromise">意大利语</a> • <a href="https://github.com/nlp-compromise/es-compromise">西班牙语</a>
</sub>
</div>
</div>
<!-- spacer -->
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="left">
你不觉得奇怪吗,
<br/>
<ul>
<img height="2px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<sub>文本是多么容易<b>生成</b></sub>
<br/>
<img height="2px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
&nbsp;<i>↬<sub>ᔐᖜ</sub><b>↬</b></i> &nbsp; <sub></sub>
而实际上要<b>解析</b>并<i>使用</i>它却又多么困难?
</ul>
</div>
<!-- spacer -->
<img height="45px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="left">
<img height="10px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>compromise <i><a href="https://observablehq.com/@spencermountain/compromise-justification">尽力</a></i>将文本转换为数据。
<br/>
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>它做出有限且合理的决策。
<br/>
<sub >
<img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/> 它并没有你想象的那么聪明。
</sub>
<img height="45px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<!--
it is
<a href="https://docs.compromise.cool/compromise-filesize">small,
<a href="https://docs.compromise.cool/compromise-performance">quick</a>,
and often <i><a href="https://docs.compromise.cool/compromise-accuracy">good-enough</a></i>.
<br/> -->
</div>
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
```js
import nlp from 'compromise'
let doc = nlp('she sells seashells by the seashore.')
doc.verbs().toPastTense()
doc.text()
// 'she sold seashells by the seashore.'
```
<!-- spacer -->
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="left">
<i>完全不必花哨:</i>
</div>
```js
if (doc.has('simon says #Verb')) {
return true
}
```
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
<div align="left">
<i>提取文本中的部分:</i>
</div>
```js
let doc = nlp(entireNovel)
doc.match('the #Adjective of times').text()
// "the blurst of times?"
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-match">match 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221837-0d142480-ffb8-11e9-9d30-90669f1b897c.png"/>
</div>
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<i>并获取数据:</i>
```js
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"]
}]
}]
*/
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-json">json 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
避免脆弱解析器带来的问题:
```js
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..'
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-contractions">contraction 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
<!-- spacer -->
<img height="30" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
并像操作数据一样随意摆弄内容:
```js
let doc = nlp('ninety five thousand and fifty two')
doc.numbers().add(20)
doc.text()
// 'ninety five thousand and seventy two'
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-values">number 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221837-0d142480-ffb8-11e9-9d30-90669f1b897c.png"/>
</div>
<!-- spacer -->
<img height="30" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<sub>——因为它实际上就是数据——</sub>
```js
let doc = nlp('the purple dinosaur')
doc.nouns().toPlural()
doc.text()
// 'the purple dinosaurs'
```
<div align="right">
<a href="https://docs.compromise.cool/nouns">noun 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221731-e8b84800-ffb7-11e9-8453-6395e0e903fa.png"/>
</div>
<!-- spacer -->
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
在客户端使用:
```html
<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>
```
或者同样地:
```typescript
import nlp from 'compromise'
var doc = nlp('London is calling')
doc.verbs().toNegative()
// 'London is not calling'
```
<img height="75px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<!--
bragging graphs
-->
<!-- spacer -->
<img height="30" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
compromise 约为 **~250kb**minified):
<div align="center">
<!-- filesize -->
<a href="https://bundlephobia.com/result?p=compromise">
<img width="600" src="https://user-images.githubusercontent.com/399657/68234819-14dfc300-ffd0-11e9-8b30-cb8545707b29.png"/>
</a>
</div>
它相当快,可在按键时运行:
<div align="center">
<a href="https://observablehq.com/@spencermountain/compromise-performance">
<img width="600" src="https://user-images.githubusercontent.com/399657/159795115-ed62440a-be41-424c-baa4-8dd15c48377d.png"/>
</a>
</div>
它主要通过<a href="https://observablehq.com/@spencermountain/verbs">为基础词表做全部词形变化(conjugating all forms</a>来实现。
最终词库约为 <a href="https://observablehq.com/@spencermountain/compromise-lexicon">~14,000 words</a>
<div align="center">
<img width="600" src="https://user-images.githubusercontent.com/399657/68234805-0d201e80-ffd0-11e9-8dc6-f7a600352555.png"/>
</div>
你可以[在这里](https://observablehq.com/@spencermountain/compromise-internals). 了解更多工作原理——挺奇怪的。
<!-- spacer -->
<img height="75px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<!--
one/two/three parts
-->
<p align="left">
<sub>好吧 —</sub>
<h1>
<code>compromise/one</code>
</h1>
<p align="center">对单词、句子和标点进行 <code>tokenizer</code>(分词器)。</p>
<img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<p>
```js
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" },
...
]
}]
*/
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-tokenization">tokenizer 文档</a>
</div>
<b>compromise/one</b> 会把文本拆分,并封装为便捷的 API,
<ul>
<sub>除此之外不做其他事 —</sub>
</ul>
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<b>/one</b> 很快——大多数句子只需十分之一毫秒。
它每秒可处理 <b>~1mb</b> 文本——相当于 10 个 Wikipedia 页面。
<i>Infinite jest</i> 需要 3 秒。
<div align="right">
你也可以并行处理,或通过 <a href="https://github.com/spencermountain/compromise/tree/master/plugins/speed">compromise-speed</a> 向其流式输入文本。
</div>
<!-- spacer -->
<img height="60px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<!-- two -->
<p align="center">
<h1 align="left">
<code>compromise/two</code>
</h1>
<p align="center"><code>part-of-speech</code>(词性)标注器与语法解释器。</p>
<img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<p>
```js
import nlp from 'compromise/two'
let doc = nlp("Wayne's World, party time")
let str = doc.match('#Possessive #Noun').text()
// "Wayne's World"
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-tagger">tagger 文档</a>
</div>
<p>
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</p>
<b>compromise/two</b> 会自动计算每个词的最基础语法。
<sub>这有时比人们意识到的更有用。</sub>
轻量语法有助于你编写更清晰的模板,并更接近信息本身。
<!-- Part-of-speech tagging is profoundly-difficult task to get 100% on. It is also a profoundly easy task to get 85% on. -->
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
compromise 拥有 <b>83 tags</b>,排列在 <a href="https://observablehq.com/@spencermountain/compromise-tags">一张美观的图谱</a>中。
<b>#FirstName</b> → <b>#Person</b> → <b>#ProperNoun</b> → <b>#Noun</b>
运行 `doc.debug()` 即可查看每个词的语法
使用 `nlp.verbose('tagger')` 可查看每个标签的推理过程。
如果你更喜欢 <a href="https://www.ling.upenn.edu/courses/Fall_2003/ling001/penn_treebank_pos.html"><i>Penn tags</i></a>,可以这样派生:
```js
let doc = nlp('welcome thrillho')
doc.compute('penn')
doc.json()
```
<img height="60px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<!-- three -->
<p align="center">
<h1 align="left">
<code>compromise/three</code>
</h1>
<p align="center"><code>Phrase</code> 与句子工具集。</p>
<img height="15px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<p>
```js
import nlp from 'compromise/three'
let doc = nlp("Wayne's World, party time")
let str = doc.people().normalize().text()
// "wayne"
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-selections">selection 文档</a>
</div>
<b>compromise/three</b> 是一套用于<i>聚焦</i>文本片段并进行操作的工具。
例如,`.numbers()` 会抓取文档中的所有数字,并通过 `.subtract()` 等方法进行扩展。
当你有一个短语或词组时,可用 `.json()` 查看其附加元数据
```js
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 }
}
]*/
```
```js
let doc = nlp('$4.09CAD')
doc.money().json()
/*[{
text: '$4.09CAD',
terms: [ [Object] ],
number: { prefix: '$', num: 4.09, suffix: 'cad'}
}
]*/
```
<img height="80px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
## API
### Compromise/one
##### 输出
- **[.text()](https://observablehq.com/@spencermountain/compromise-text)** - 以文本形式返回文档
- **[.json()](https://observablehq.com/@spencermountain/compromise-json)** - 以数据形式返回文档
- **[.debug()](https://observablehq.com/@spencermountain/compromise-output)** - 漂亮打印已解析的文档
- **[.out()](https://observablehq.com/@spencermountain/compromise-output)** - 具名或自定义输出
- **[.html({})](https://observablehq.com/@spencermountain/compromise-html)** - 为匹配项输出自定义 HTML 标签
- **[.wrap({})](https://observablehq.com/@spencermountain/compromise-output)** - 为文档匹配项生成自定义输出
##### 工具
- **[.found](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - 该文档是否为空?
- **[.docs](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ 以 json 形式获取 term 对象
- **[.length](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - 统计文档中的字符数(字符串长度)
- **[.isView](https://observablehq.com/@spencermountain/compromise-utils)** _[getter]_ - 识别 compromise 对象
- **[.compute()](https://observablehq.com/@spencermountain/compromise-compute)** - 对文档运行具名分析
- **[.clone()](https://observablehq.com/@spencermountain/compromise-utils)** - 深拷贝文档,使不留任何引用
- **[.termList()](https://observablehq.com/@spencermountain/compromise-accessors)** - 返回匹配中所有 Term 对象的扁平列表
- **[.cache({})](https://observablehq.com/@spencermountain/compromise-cache)** - 冻结文档当前状态,以提升速度
- **[.uncache()](https://observablehq.com/@spencermountain/compromise-cache)** - 解冻文档当前状态,以便可继续变换
- **[.freeze({})](https://observablehq.com/@spencermountain/compromise-freeze)** - 阻止这些 term 上的任何标签被移除
- **[.unfreeze({})](https://observablehq.com/@spencermountain/compromise-freeze)** - 恢复默认,允许标签再次变更
##### 访问器(Accessors
- **[.all()](https://observablehq.com/@spencermountain/compromise-utils)** - 返回完整原始文档('zoom out'
- **[.terms()](https://observablehq.com/@spencermountain/compromise-selections)** - 按每个单独词项拆分结果
- **[.first(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - 仅使用第一个(前几个)结果
- **[.last(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - 仅使用最后一个(后几个)结果
- **[.slice(n,n)](https://observablehq.com/@spencermountain/compromise-accessors)** - 获取结果的子集
- **[.eq(n)](https://observablehq.com/@spencermountain/compromise-accessors)** - 仅使用第 n 个结果
- **[.firstTerms()](https://observablehq.com/@spencermountain/compromise-accessors)** - 获取每个匹配中的第一个词
- **[.lastTerms()](https://observablehq.com/@spencermountain/compromise-accessors)** - 获取每个匹配中的最后一个词
- **[.fullSentences()](https://observablehq.com/@spencermountain/compromise-accessors)** - 获取每个匹配所在的完整句子
- **[.groups()](https://observablehq.com/@spencermountain/compromise-accessors)** - 从匹配中提取所有命名捕获组(named capture-groups
- **[.wordCount()](https://observablehq.com/@spencermountain/compromise-utils)** - 统计文档中的词项数量
- **[.confidence()](https://observablehq.com/@spencermountain/compromise-utils)** - 词性标注(POS tag)解释的平均置信度分数
##### 匹配(Match
_(匹配方法使用 [match-syntax](https://docs.compromise.cool/compromise-match-syntax).)_
- **[.match('')](https://observablehq.com/@spencermountain/compromise-match)** - 返回一个新的 Doc,并以当前文档作为父文档
- **[.not('')](https://observablehq.com/@spencermountain/compromise-match)** - 返回除此匹配外的所有结果
- **[.matchOne('')](https://observablehq.com/@spencermountain/compromise-match)** - 仅返回第一个匹配
- **[.if('')](https://observablehq.com/@spencermountain/compromise-match)** - 仅当当前短语包含此匹配时才返回该短语('only'
- **[.ifNo('')](https://observablehq.com/@spencermountain/compromise-match)** - 过滤掉包含此匹配的所有当前短语('notIf'
- **[.has('')](https://observablehq.com/@spencermountain/compromise-match)** - 若存在此匹配则返回布尔值
- **[.before('')](https://observablehq.com/@spencermountain/compromise-match)** - 返回每个短语中匹配之前的所有词项
- **[.after('')](https://observablehq.com/@spencermountain/compromise-match)** - 返回每个短语中匹配之后的所有词项
- **[.union()](https://observablehq.com/@spencermountain/compromise-set)** - 返回合并后的匹配,不含重复项
- **[.intersection()](https://observablehq.com/@spencermountain/compromise-set)** - 仅返回重复的匹配
- **[.complement()](https://observablehq.com/@spencermountain/compromise-set)** - 获取不在另一匹配中的所有内容
- **[.settle()](https://observablehq.com/@spencermountain/compromise-set)** - 从匹配中移除重叠部分
- **[.growRight('')](https://observablehq.com/@spencermountain/compromise-match)** - 在每个匹配之后立即添加任何匹配的词项
- **[.growLeft('')](https://observablehq.com/@spencermountain/compromise-match)** - 在每个匹配之前立即添加任何匹配的词项
- **[.grow('')](https://observablehq.com/@spencermountain/compromise-match)** - 在每个匹配之前或之后添加任何匹配的词项
- **[.sweep(net)](https://observablehq.com/@spencermountain/compromise-sweep)** - 将一系列匹配对象应用于文档
- **[.splitOn('')](https://observablehq.com/@spencermountain/compromise-split)** - 为每个匹配返回包含三部分的 Document'splitOn'
- **[.splitBefore('')](https://observablehq.com/@spencermountain/compromise-split)** - 在每个匹配片段之前分割短语
- **[.splitAfter('')](https://observablehq.com/@spencermountain/compromise-split)** - 在每个匹配片段之后分割短语
- **[.join()](https://observablehq.com/@spencermountain/compromise-split)** - 合并每个匹配中所有相邻的词项
- **[.joinIf(leftMatch, rightMatch)](https://observablehq.com/@spencermountain/compromise-split)** - 在给定条件下合并相邻词项
- **[.lookup([])](https://observablehq.com/@spencermountain/compromise-match)** - 快速查找字符串匹配数组
- **[.autoFill()](https://observablehq.com/@spencermountain/compromise-typeahead)** - 在文档上创建自动补全(type-ahead)假设
##### 标注(Tag
- **[.tag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - 为所有词项赋予给定标签
- **[.tagSafe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - 仅当与当前标签一致时才将标签应用于词项
- **[.unTag('')](https://observablehq.com/@spencermountain/compromise-tagger)** - 从给定词项中移除此词项
- **[.canBe('')](https://observablehq.com/@spencermountain/compromise-tagger)** - 仅返回可以具有此标签的词项
##### 大小写(Case
- **[.toLowerCase()](https://observablehq.com/@spencermountain/compromise-case)** - 将每个词项的每个字母转为小写
- **[.toUpperCase()](https://observablehq.com/@spencermountain/compromise-case)** - 将每个词项的每个字母转为大写
- **[.toTitleCase()](https://observablehq.com/@spencermountain/compromise-case)** - 将每个词项的首字母大写
- **[.toCamelCase()](https://observablehq.com/@spencermountain/compromise-case)** - 移除空白并将每个词项转为标题大小写(title-case)
##### 空白(Whitespace
- **[.pre('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - 在每个匹配之前添加此标点或空白
- **[.post('')](https://observablehq.com/@spencermountain/compromise-whitespace)** - 在每个匹配之后添加此标点或空白
- **[.trim()](https://observablehq.com/@spencermountain/compromise-whitespace)** - 移除首尾空白
- **[.hyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - 用连字符连接单词并移除空白
- **[.dehyphenate()](https://observablehq.com/@spencermountain/compromise-whitespace)** - 移除单词之间的连字符并设置空白
- **[.toQuotations()](https://observablehq.com/@spencermountain/compromise-whitespace)** - 在这些匹配周围添加引号
- **[.toParentheses()](https://observablehq.com/@spencermountain/compromise-whitespace)** - 在这些匹配周围添加括号
##### 循环(Loops
- **[.map(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 对每个短语运行函数并创建新文档
- **[.forEach(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 将每个短语作为独立文档对其运行函数
- **[.filter(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 仅返回结果为 true 的短语
- **[.find(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 返回仅包含第一个匹配短语的文档
- **[.some(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 若存在一个匹配短语则返回 true 或 false
- **[.random(fn)](https://observablehq.com/@spencermountain/compromise-loops)** - 对结果子集进行抽样
##### 插入(Insert
- **[.replace(match, replace)](https://observablehq.com/@spencermountain/compromise-insert)** - 搜索并用新内容替换匹配
- **[.replaceWith(replace)](https://observablehq.com/@spencermountain/compromise-insert)** - 替换为新文本
- **[.remove()](https://observablehq.com/@spencermountain/compromise-insert)** - 从文档中完全移除这些词项
- **[.insertBefore(str)](https://observablehq.com/@spencermountain/compromise-insert)** - 将这些新词项添加到每个匹配的前面(prepend)
- **[.insertAfter(str)](https://observablehq.com/@spencermountain/compromise-insert)** - 将这些新词项添加到每个匹配的末尾(append)
- **[.concat()](https://observablehq.com/@spencermountain/compromise-insert)** - 将这些新内容添加到末尾
- **[.swap(fromLemma, toLemma)](https://observablehq.com/@spencermountain/compromise-root)** - 智能替换词根,并使用正确的词形变化
##### Transform
- **[.sort('method')](https://observablehq.com/@spencermountain/compromise-sorting)** - 原地重新排列匹配项的顺序
- **[.reverse()](https://observablehq.com/@spencermountain/compromise-sorting)** - 反转匹配项的顺序,但不反转词语
- **[.unique()](https://observablehq.com/@spencermountain/compromise-sorting)** - 移除所有重复的匹配项
##### Lib
_(这些方法位于主 `nlp` 对象上)_
- **[nlp.tokenize(str)](https://observablehq.com/@spencermountain/compromise-tokenization)** - 解析文本,但不进行词性标注(POS-tagging
- **[nlp.lazy(str, match)](https://observablehq.com/@spencermountain/compromise-performance)** - 以最小分析量扫描文本
- **[nlp.plugin({})](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 混入 compromise-plugin
- **[nlp.parseMatch(str)](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 预先将匹配语句解析为 json
- **[nlp.world()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 获取或修改库内部结构
- **[nlp.model()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 获取所有当前语言数据
- **[nlp.methods()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 获取或修改内部方法
- **[nlp.hooks()](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 查看哪些计算方法会自动运行
- **[nlp.verbose(mode)](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 记录决策过程以便调试
- **[nlp.version](https://observablehq.com/@spencermountain/compromise-constructor-methods)** - 库的当前 semver 版本
- **[nlp.addWords(obj, isFrozen?)](https://observablehq.com/@spencermountain/compromise-plugin)** - 向词表添加新词
- **[nlp.addTags(obj)](https://observablehq.com/@spencermountain/compromise-plugin)** - 向 tagSet 添加新标签
- **[nlp.typeahead(arr)](https://observablehq.com/@spencermountain/compromise-typeahead)** - 向自动填充词典添加词语
- **[nlp.buildTrie(arr)](https://observablehq.com/@spencermountain/compromise-lookup)** - 将词列表编译为快速查找形式
- **[nlp.buildNet(arr)](https://observablehq.com/@spencermountain/compromise-sweep)** - 将匹配列表编译为快速匹配形式
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### compromise/two:
##### Contractions
- **[.contractions()](https://observablehq.com/@spencermountain/compromise-contractions)** - 如 "didn't" 这类缩略形式
- **[.contractions().expand()](https://observablehq.com/@spencermountain/compromise-contractions)** - 如 "didn't" 这类缩略形式
- **[.contract()](https://observablehq.com/@spencermountain/compromise-contractions)** - 如 "didn't" 这类缩略形式
<!-- spacer -->
<img height="30px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
### compromise/three:
- **[.normalize({})](https://observablehq.com/@spencermountain/compromise-normalization)** - 以各种方式清理文本
##### Nouns
- **[.nouns()](https://observablehq.com/@spencermountain/nouns)** - 返回后续被标注为 Noun 的词语
- **[.nouns().json()](https://observablehq.com/@spencermountain/nouns)** - 附带名词元数据的增强输出
- **[.nouns().parse()](https://observablehq.com/@spencermountain/nouns)** - 获取分词后的名词短语
- **[.nouns().isPlural()](https://observablehq.com/@spencermountain/nouns)** - 仅返回复数名词
- **[.nouns().isSingular()](https://observablehq.com/@spencermountain/nouns)** - 仅返回单数名词
- **[.nouns().toPlural()](https://observablehq.com/@spencermountain/nouns)** - `'football captain' → 'football captains'`
- **[.nouns().toSingular()](https://observablehq.com/@spencermountain/nouns)** - `'turnovers' → 'turnover'`
- **[.nouns().adjectives()](https://observablehq.com/@spencermountain/nouns)** - 获取描述该名词的形容词
##### Verbs
- **[.verbs()](https://observablehq.com/@spencermountain/verbs)** - 返回后续被标注为 Verb 的词语
- **[.verbs().json()](https://observablehq.com/@spencermountain/verbs)** - 附带动词元数据的增强输出
- **[.verbs().parse()](https://observablehq.com/@spencermountain/verbs)** - 获取分词后的动词短语
- **[.verbs().subjects()](https://observablehq.com/@spencermountain/verbs)** - 执行该动词动作的主体
- **[.verbs().adverbs()](https://observablehq.com/@spencermountain/verbs)** - 返回描述该动词的副词
- **[.verbs().isSingular()](https://observablehq.com/@spencermountain/verbs)** - 返回单数动词,如 'spencer walks'
- **[.verbs().isPlural()](https://observablehq.com/@spencermountain/verbs)** - 返回复数动词,如 'we walk'
- **[.verbs().isImperative()](https://observablehq.com/@spencermountain/verbs)** - 仅返回祈使动词,如 'eat it!'
- **[.verbs().toPastTense()](https://observablehq.com/@spencermountain/verbs)** - `'will go' → 'went'`
- **[.verbs().toPresentTense()](https://observablehq.com/@spencermountain/verbs)** - `'walked' → 'walks'`
- **[.verbs().toFutureTense()](https://observablehq.com/@spencermountain/verbs)** - `'walked' → 'will walk'`
- **[.verbs().toInfinitive()](https://observablehq.com/@spencermountain/verbs)** - `'walks' → 'walk'`
- **[.verbs().toGerund()](https://observablehq.com/@spencermountain/verbs)** - `'walks' → 'walking'`
- **[.verbs().toPastParticiple()](https://observablehq.com/@spencermountain/verbs)** - `'drive' → 'had driven'`
- **[.verbs().conjugate()](https://observablehq.com/@spencermountain/verbs)** - 返回这些动词的所有变位形式
- **[.verbs().isNegative()](https://observablehq.com/@spencermountain/verbs)** - 返回含 'not'、'never' 或 'no' 的动词
- **[.verbs().isPositive()](https://observablehq.com/@spencermountain/verbs)** - 仅返回不含 'not'、'never' 或 'no' 的动词
- **[.verbs().toNegative()](https://observablehq.com/@spencermountain/verbs)** - `'went' → 'did not go'`
- **[.verbs().toPositive()](https://observablehq.com/@spencermountain/verbs)** - `"didn't study" → 'studied'`
##### Numbers
- **[.numbers()](https://observablehq.com/@spencermountain/compromise-values)** - 获取所有文字形式和数值形式的数字
- **[.numbers().parse()](https://observablehq.com/@spencermountain/compromise-values)** - 获取分词后的数字短语
- **[.numbers().get()](https://observablehq.com/@spencermountain/compromise-values)** - 获取简单的 JavaScript 数字
- **[.numbers().json()](https://observablehq.com/@spencermountain/compromise-values)** - 附带数字元数据的增强输出
- **[.numbers().toNumber()](https://observablehq.com/@spencermountain/compromise-values)** - 将 'five' 转换为 `5`
- **[.numbers().toLocaleString()](https://observablehq.com/@spencermountain/compromise-values)** - 为数字添加逗号或更美观的格式
- **[.numbers().toText()](https://observablehq.com/@spencermountain/compromise-values)** - 将 '5' 转换为 `five`
- **[.numbers().toOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - 将 'five' 转换为 `fifth``5th`
- **[.numbers().toCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - 将 'fifth' 转换为 `five``5`
- **[.numbers().isOrdinal()](https://observablehq.com/@spencermountain/compromise-values)** - 仅返回序数
- **[.numbers().isCardinal()](https://observablehq.com/@spencermountain/compromise-values)** - 仅返回基数
- **[.numbers().isEqual(n)](https://observablehq.com/@spencermountain/compromise-values)** - 返回等于该值的数字
- **[.numbers().greaterThan(min)](https://observablehq.com/@spencermountain/compromise-values)** - 返回大于 n 的数字
- **[.numbers().lessThan(max)](https://observablehq.com/@spencermountain/compromise-values)** - 返回小于 n 的数字
- **[.numbers().between(min, max)](https://observablehq.com/@spencermountain/compromise-values)** - 返回 min 与 max 之间的数字
- **[.numbers().isUnit(unit)](https://observablehq.com/@spencermountain/compromise-values)** - 仅返回指定单位的数字,如 'km'
- **[.numbers().set(n)](https://observablehq.com/@spencermountain/compromise-values)** - 将数字设为 n
- **[.numbers().add(n)](https://observablehq.com/@spencermountain/compromise-values)** - 将数字增加 n
- **[.numbers().subtract(n)](https://observablehq.com/@spencermountain/compromise-values)** - 将数字减少 n
- **[.numbers().increment()](https://observablehq.com/@spencermountain/compromise-values)** - 将数字加 1
- **[.numbers().decrement()](https://observablehq.com/@spencermountain/compromise-values)** - 将数字减 1
- **[.money()](https://observablehq.com/@spencermountain/compromise-values)** - 如 `'$2.50'` 这类金额
- **[.money().get()](https://observablehq.com/@spencermountain/compromise-values)** - 获取解析后的金额
- **[.money().json()](https://observablehq.com/@spencermountain/compromise-values)** - 货币与数字信息
- **[.money().currency()](https://observablehq.com/@spencermountain/compromise-values)** - 金额所使用的货币
- **[.fractions()](https://observablehq.com/@spencermountain/compromise-values)** - 如 '2/3rds' 或 'one out of five'
- **[.fractions().parse()](https://observablehq.com/@spencermountain/compromise-values)** - 获取分词后的分数
- **[.fractions().get()](https://observablehq.com/@spencermountain/compromise-values)** - 简单的分子、分母数据
- **[.fractions().json()](https://observablehq.com/@spencermountain/compromise-values)** - 附带分数数据的增强 json 输出
- **[.fractions().toDecimal()](https://observablehq.com/@spencermountain/compromise-values)** - '2/3' -> '0.66'
- **[.fractions().normalize()](https://observablehq.com/@spencermountain/compromise-values)** - 'four out of 10' -> '4/10'
- **[.fractions().toText()](https://observablehq.com/@spencermountain/compromise-values)** - '4/10' -> 'four tenths'
- **[.fractions().toPercentage()](https://observablehq.com/@spencermountain/compromise-values)** - '4/10' -> '40%'
- **[.percentages()](https://observablehq.com/@spencermountain/compromise-values)** - 如 '2.5%'
- **[.percentages().get()](https://observablehq.com/@spencermountain/compromise-values)** - 返回百分比数值除以 100
- **[.percentages().json()](https://observablehq.com/@spencermountain/compromise-values)** - 附带百分比信息的增强 json 输出
- **[.percentages().toFraction()](https://observablehq.com/@spencermountain/compromise-values)** - '80%' -> '8/10'
##### 句子
- **[.sentences()](https://observablehq.com/@spencermountain/compromise-sentences)** - 返回带有附加方法的句子类
- **[.sentences().json()](https://observablehq.com/@spencermountain/compromise-sentences)** - 附带句子元数据的增强输出
<!-- - **[.sentences().subjects()](https://observablehq.com/@spencermountain/compromise-sentences)** - 返回每个句子的主要名词 -->
- **[.sentences().toPastTense()](https://observablehq.com/@spencermountain/compromise-sentences)** - `he walks` -> `he walked`
- **[.sentences().toPresentTense()](https://observablehq.com/@spencermountain/compromise-sentences)** - `he walked` -> `he walks`
- **[.sentences().toFutureTense()](https://observablehq.com/@spencermountain/compromise-sentences)** -- `he walks` -> `he will walk`
- **[.sentences().toInfinitive()](https://observablehq.com/@spencermountain/compromise-sentences)** -- verb root-form `he walks` -> `he walk`
- **[.sentences().toNegative()](https://observablehq.com/@spencermountain/compromise-sentences)** - - `he walks` -> `he didn't walk`
- **[.sentences().isQuestion()](https://observablehq.com/@spencermountain/compromise-sentences)** - 返回带 `?` 的疑问句
- **[.sentences().isExclamation()](https://observablehq.com/@spencermountain/compromise-sentences)** - 返回带 `!` 的感叹句
- **[.sentences().isStatement()](https://observablehq.com/@spencermountain/compromise-sentences)** - 返回不含 `?``!` 的陈述句
##### 形容词
- **[.adjectives()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'quick'` 之类的词
- **[.adjectives().json()](https://observablehq.com/@spencermountain/compromise-selections)** - 获取形容词元数据
- **[.adjectives().conjugate()](https://observablehq.com/@spencermountain/compromise-selections)** - 返回这些形容词的所有词形变化
- **[.adjectives().adverbs()](https://observablehq.com/@spencermountain/compromise-selections)** - 获取描述该形容词的副词
- **[.adjectives().toComparative()](https://observablehq.com/@spencermountain/compromise-selections)** - 'quick' -> 'quicker'
- **[.adjectives().toSuperlative()](https://observablehq.com/@spencermountain/compromise-selections)** - 'quick' -> 'quickest'
- **[.adjectives().toAdverb()](https://observablehq.com/@spencermountain/compromise-selections)** - 'quick' -> 'quickly'
- **[.adjectives().toNoun()](https://observablehq.com/@spencermountain/compromise-selections)** - 'quick' -> 'quickness'
##### 其他选择项
- **[.clauses()](https://observablehq.com/@spencermountain/compromise-selections)** - 将句子拆分为多词短语
- **[.chunks()](https://observablehq.com/@spencermountain/compromise-selections)** - 将句子拆分为名词短语和动词短语
- **[.hyphenated()](https://observablehq.com/@spencermountain/compromise-selections)** - 所有以连字符或破折号连接的词项,例如 `'wash-out'`
- **[.phoneNumbers()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'(939) 555-0113'` 之类的内容
- **[.hashTags()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'#nlp'` 之类的内容
- **[.emails()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'hi@compromise.cool'` 之类的内容
- **[.emoticons()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `:)` 之类的内容
- **[.emojis()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `💋` 之类的内容
- **[.atMentions()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'@nlp_compromise'` 之类的内容
- **[.urls()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'compromise.cool'` 之类的内容
- **[.pronouns()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'he'` 之类的内容
- **[.conjunctions()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'but'` 之类的内容
- **[.prepositions()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'of'` 之类的内容
- **[.abbreviations()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'Mrs.'` 之类的内容
- **[.people()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - 诸如 'John F. Kennedy' 之类的姓名
- **[.people().json()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - 获取人名元数据
- **[.people().parse()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - 获取人名解析结果
- **[.places()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - 例如 'Paris, France'
- **[.organizations()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - 例如 'Google, Inc'
- **[.topics()](https://observablehq.com/@spencermountain/topics-named-entity-recognition)** - `people()` + `places()` + `organizations()`
- **[.adverbs()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'quickly'` 之类的词
- **[.adverbs().json()](https://observablehq.com/@spencermountain/compromise-selections)** - 获取副词元数据
- **[.acronyms()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `'FBI'` 之类的内容
- **[.acronyms().strip()](https://observablehq.com/@spencermountain/compromise-selections)** - 移除缩写词中的句点
- **[.acronyms().addPeriods()](https://observablehq.com/@spencermountain/compromise-selections)** - 为缩写词添加句点
- **[.parentheses()](https://observablehq.com/@spencermountain/compromise-selections)** - 返回括号内的任何内容
- **[.parentheses().strip()](https://observablehq.com/@spencermountain/compromise-selections)** - 移除括号
- **[.possessives()](https://observablehq.com/@spencermountain/compromise-selections)** - 诸如 `"Spencer's"` 之类的内容
- **[.possessives().strip()](https://observablehq.com/@spencermountain/compromise-selections)** - "Spencer's" -> "Spencer"
- **[.quotations()](https://observablehq.com/@spencermountain/compromise-selections)** - 返回成对引号内的任何词项
- **[.quotations().strip()](https://observablehq.com/@spencermountain/compromise-selections)** - 移除引号
- **[.slashes()](https://observablehq.com/@spencermountain/compromise-selections)** - 返回以斜杠分组的任何词项
- **[.slashes().split()](https://observablehq.com/@spencermountain/compromise-selections)** - 将 'love/hate' 转换为 'love hate'
<p>
<img height="85px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</p>
<div align="center">
<img src="https://user-images.githubusercontent.com/399657/68221814-05ed1680-ffb8-11e9-8b6b-c7528d163871.png"/>
</div>
### .extend():
本库内置了一套体贴且符合常识的英语语法基线。
你可以随意修改,甚至彻底推翻任何设置——这其实也是乐趣所在。
最简单的做法是为任意给定词语建议标签:
```js
let myWords = {
kermit: 'FirstName',
fozzie: 'FirstName',
}
let doc = nlp(muppetText, myWords)
```
或者通过 [compromise-plugin](https://observablehq.com/@spencermountain/compromise-plugins). 进行更大幅度的修改
```js
import nlp from 'compromise'
nlp.extend({
// add new tags
tags: {
Character: {
isA: 'Person',
notA: 'Adjective',
},
},
// add or change words in the lexicon
words: {
kermit: 'Character',
gonzo: 'Character',
},
// change inflections
irregulars: {
get: {
pastTense: 'gotten',
gerund: 'gettin',
},
},
// add new methods to compromise
api: View => {
View.prototype.kermitVoice = function () {
this.sentences().prepend('well,')
this.match('i [(am|was)]').prepend('um,')
return this
}
},
})
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-plugins">.plugin() 文档</a>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221848-11404200-ffb8-11e9-90cd-3adee8d8564f.png"/>
</div>
<!-- spacer -->
<div >
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
### 文档:
##### 入门导读:
- **[#1) 输入 → 输出](https://docs.compromise.cool/tutorial-1)**
- **[#2) 匹配与转换](https://docs.compromise.cool/compromise-tutorial-2)**
- **[#3) 制作聊天机器人](https://docs.compromise.cool/compromise-making-a-bot)**
<!-- * **[Tutorial #4]()** - Making a plugin -->
<div >
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
##### 文档:
| 概念 | API | 插件 |
| ------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------: | -------------------------------------------------------------------------------------: |
| [准确度 (Accuracy)](https://observablehq.com/@spencermountain/compromise-accuracy) | [Accessors](https://observablehq.com/@spencermountain/compromise-accessors) | [Adjectives](https://observablehq.com/@spencermountain/compromise-adjectives) |
| [缓存 (Caching)](https://observablehq.com/@spencermountain/compromise-cache) | [Constructor-methods](https://observablehq.com/@spencermountain/compromise-constructor-methods) | [Dates](https://observablehq.com/@spencermountain/compromise-dates) |
| [大小写 (Case)](https://observablehq.com/@spencermountain/compromise-case) | [Contractions](https://observablehq.com/@spencermountain/compromise-contractions) | [Export](https://observablehq.com/@spencermountain/compromise-export) |
| [文件大小 (Filesize)](https://observablehq.com/@spencermountain/compromise-filesize) | [Insert](https://observablehq.com/@spencermountain/compromise-insert) | [Hash](https://observablehq.com/@spencermountain/compromise-hash) |
| [内部机制 (Internals)](https://observablehq.com/@spencermountain/compromise-internals) | [Json](https://observablehq.com/@spencermountain/compromise-json) | [Html](https://observablehq.com/@spencermountain/compromise-html) |
| [对齐 (Justification)](https://observablehq.com/@spencermountain/compromise-justification) | [Character Offsets](https://observablehq.com/@spencermountain/compromise-offsets) | [Keypress](https://observablehq.com/@spencermountain/compromise-keypress) |
| [词典 (Lexicon)](https://observablehq.com/@spencermountain/compromise-lexicon) | [Loops](https://observablehq.com/@spencermountain/compromise-loops) | [Ngrams](https://observablehq.com/@spencermountain/compromise-ngram) |
| [匹配语法 (Match-syntax)](https://observablehq.com/@spencermountain/compromise-match-syntax) | [Match](https://observablehq.com/@spencermountain/compromise-match) | [Numbers](https://observablehq.com/@spencermountain/compromise-values) |
| [性能 (Performance)](https://observablehq.com/@spencermountain/compromise-performance) | [Nouns](https://observablehq.com/@spencermountain/nouns) | [Paragraphs](https://observablehq.com/@spencermountain/compromise-paragraphs) |
| [插件 (Plugins)](https://observablehq.com/@spencermountain/compromise-plugins) | [Output](https://observablehq.com/@spencermountain/compromise-output) | [Scan](https://observablehq.com/@spencermountain/compromise-scan) |
| [项目 (Projects)](https://observablehq.com/@spencermountain/compromise-projects) | [Selections](https://observablehq.com/@spencermountain/compromise-selections) | [Sentences](https://observablehq.com/@spencermountain/compromise-sentences) |
| [标注器 (Tagger)](https://observablehq.com/@spencermountain/compromise-tagger) | [Sorting](https://observablehq.com/@spencermountain/compromise-sorting) | [Syllables](https://observablehq.com/@spencermountain/compromise-syllables) |
| [标签 (Tags)](https://observablehq.com/@spencermountain/compromise-tags) | [Split](https://observablehq.com/@spencermountain/compromise-split) | [Pronounce](https://observablehq.com/@spencermountain/compromise-pronounce) |
| [分词 (Tokenization)](https://observablehq.com/@spencermountain/compromise-tokenization) | [Text](https://observablehq.com/@spencermountain/compromise-text) | [Strict](https://observablehq.com/@spencermountain/compromise-strict) |
| [命名实体 (Named-Entities)](https://observablehq.com/@spencermountain/topics-named-entity-recognition) | [Utils](https://observablehq.com/@spencermountain/compromise-utils) | [Penn-tags](https://observablehq.com/@spencermountain/compromise-penn-tags) |
| [空白字符 (Whitespace)](https://observablehq.com/@spencermountain/compromise-whitespace) | [Verbs](https://observablehq.com/@spencermountain/verbs) | [Typeahead](https://observablehq.com/@spencermountain/compromise/compromise-typeahead) |
| [世界数据 (World data)](https://observablehq.com/@spencermountain/compromise-world) | [Normalization](https://observablehq.com/@spencermountain/compromise-normalization) | [Sweep](https://observablehq.com/@spencermountain/compromise-sweep) |
| [模糊匹配 (Fuzzy-matching)](https://observablehq.com/@spencermountain/compromise-fuzzy-matching) | [Typescript](https://observablehq.com/@spencermountain/compromise-typescript) | [Mutation](https://observablehq.com/@spencermountain/compromise-mutation) |
| [词根形式 (Root-forms)](https://observablehq.com/@spencermountain/compromise-root) |
<div >
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
##### 演讲:
- **[语言即界面 (Language as an Interface)](https://www.youtube.com/watch?v=WuPVS2tCg8s)** - 作者 Spencer Kelly
- **[编写聊天机器人 (Coding Chat Bots)](https://www.youtube.com/watch?v=c_hmwFwvO0U)** - 作者 KahWee Teng
- **[关于打字与数据 (On Typing and data)](https://vimeo.com/496095722)** - 作者 Spencer Kelly
##### 文章:
- **[使用 NLP 与 JavaScript 对社交对话进行地理编码](http://compromise.cool)** - 作者 Microsoft
- **[微服务配方 (Microservice Recipe)](https://eventn.com/recipes/text-parsing-with-nlp-compromise)** - 作者 Eventn
- **[使用 Compromise 解析冒险游戏句子](https://killalldefects.com/2020/02/20/adventure-game-sentence-parsing-with-compromise/)**
- **[构建基于文本的游戏 (Building Text-Based Games)](https://killalldefects.com/2019/09/24/building-text-based-games-with-compromise-nlp/)** - 作者 Matt Eland
- **[BigQuery 中的 JavaScript 乐趣](https://medium.com/@hoffa/new-in-bigquery-persistent-udfs-c9ea4100fd83#6e09)** - 作者 Felipe Hoffa
- **[自然语言处理……在浏览器中?](https://dev.to/charlesdlandau/natural-language-processing-in-the-browser-52hj)** - 作者 Charles Landau
##### 一些有趣的应用:
- **[自动化 Bechdel 测试 (Automated Bechdel Test)](https://github.com/guardian/bechdel-test)** - 作者 The Guardian
- **[故事生成框架 (Story generation framework)](https://perchance.org/welcome)** - 作者 Jose Phrocca
- **[列表 Tumblr 博客 (Tumbler blog of lists)](https://leanstooneside.tumblr.com/)** - 类似 horse-ebooks 的列表 - 作者 Michael Paulukonis
- **[基于转录文本的视频编辑 (Video Editing from Transcription)](https://newtheory.io/)** - 作者 New Theory
- **[浏览器扩展事实核查 (Browser extension Fact-checking)](https://github.com/AlexanderKidd/FactoidL)** - 作者 Alexander Kidd
- **[Siri 快捷指令 (Siri shortcut)](https://routinehub.co/shortcut/3260)** - 作者 Michael Byrns
- **[Amazon Skill](https://github.com/tajddin/voiceplay)** - 作者 Tajddin Maghni
- **[任务型 Slack 机器人 (Tasking Slack-bot)](https://github.com/kevinsuh/toki)** - 作者 Kevin Suh
[[查看更多]](https://observablehq.com/@spencermountain/compromise-projects)
##### 对比
- [Compromise 与 Spacy](https://observablehq.com/@spencermountain/compromise-and-spacy)
- [Compromise 与 NLTK](https://observablehq.com/@spencermountain/compromise-and-nltk)
<!-- spacer -->
<div align="center">
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<hr/>
</div>
<div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221632-b9094000-ffb7-11e9-99e0-b48edd6cdf8a.png"/>
</div>
<!-- <div align="center">
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221824-09809d80-ffb8-11e9-9ef0-6ed3574b0ce8.png"/>
</div> -->
### 插件:
以下是一些实用的扩展:
##### 日期
`npm install compromise-dates`
- **[.dates()](https://observablehq.com/@spencermountain/compromise-dates)** - 查找诸如 `June 8th``03/03/18` 的日期
- **[.dates().get()](https://observablehq.com/@spencermountain/compromise-dates)** - 返回简单的起止 JSON 结果
- **[.dates().json()](https://observablehq.com/@spencermountain/compromise-dates)** - 带日期元数据的富输出
- **[.dates().format('')](https://observablehq.com/@spencermountain/compromise-dates)** - 将日期转换为指定格式
- **[.dates().toShortForm()](https://observablehq.com/@spencermountain/compromise-dates)** - 将 'Wednesday' 转为 'Wed' 等
- **[.dates().toLongForm()](https://observablehq.com/@spencermountain/compromise-dates)** - 将 'Feb' 转为 'February' 等
- **[.durations()](https://observablehq.com/@spencermountain/compromise-dates)** - `2 weeks``5mins`
- **[.durations().get()](https://observablehq.com/@spencermountain/compromise-dates)** - 返回时长的简单 JSON
- **[.durations().json()](https://observablehq.com/@spencermountain/compromise-dates)** - 带时长元数据的富输出
- **[.times()](https://observablehq.com/@spencermountain/compromise-dates)** - `4:30pm``half past five`
- **[.times().get()](https://observablehq.com/@spencermountain/compromise-dates)** - 返回时间的简单 JSON
- **[.times().json()](https://observablehq.com/@spencermountain/compromise-dates)** - 带时间元数据的富输出
##### 统计
`npm install compromise-stats`
- **[.tfidf({})](https://observablehq.com/@spencermountain/compromise-tfidf)** - 按词频与独特性对词语排序
- **[.ngrams({})](https://observablehq.com/@spencermountain/compromise-ngram)** - 按词数列出所有重复的子短语
- **[.unigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 一词 n-gram
- **[.bigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 两词 n-gram
- **[.trigrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 三词 n-gram
- **[.startgrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 包含短语首词的 n-gram
- **[.endgrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 包含短语末词的 n-gram
- **[.edgegrams()](https://observablehq.com/@spencermountain/compromise-ngram)** - 包含短语首词或末词的 n-gram
##### 语音
`npm install compromise-syllables`
- **[.syllables()](https://observablehq.com/@spencermountain/compromise-syllables)** - 按典型发音拆分每个词
- **[.soundsLike()](https://observablehq.com/@spencermountain/compromise-soundsLike)** - 生成估计的发音
##### Wikipedia
`npm install compromise-wikipedia`
- **[.wikipedia()](https://observablehq.com/@spencermountain/compromise-wikipedia)** - 压缩版文章对齐
<!-- spacer -->
<div >
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<hr/>
</div>
### Typescript
我们致力于支持 TypeScript/Deno,主库与官方插件均提供支持:
```ts
import nlp from 'compromise'
import stats from 'compromise-stats'
const nlpEx = nlp.extend(stats)
nlpEx('This is type safe!').ngrams({ min: 1 })
```
<div align="right">
<a href="https://docs.compromise.cool/compromise-typescript">TypeScript 文档</a>
</div>
<div >
<img height="50px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
</div>
#### 局限性:
- **slash-support**
我们目前会像处理连字符一样,将斜杠拆成不同的词,因此像下面这样的情况无法正常工作:
<code>nlp('the koala eats/shoots/leaves').has('koala leaves') //false</code>
- **inter-sentence match**
默认情况下,句子是顶层抽象单元。
若无 <a href="https://github.com/spencermountain/compromise/tree/master/plugins/paragraphs">插件</a>,则不支持跨句或多句匹配:
<code>nlp("that's it. Back to Winnipeg!").has('it back')//false</code>
- **nested match syntax**
正则表达式的<s>危险</s>之美在于可以无限递归。
我们的匹配语法要弱得多。像下面这样的情况尚<i>(尚未)</i>支持:
<code>doc.match('(modern (major|minor))? general')</code>
复杂匹配必须通过连续的 **.match()** 调用来实现。
- **dependency parsing**
正确的句子变换需要理解句子的 [syntax tree](https://en.wikipedia.org/wiki/Parse_tree),我们目前尚未实现。
我们应当支持!欢迎在此方面提供帮助。
##### 常见问题
<ul align="left">
<p>
<details>
<summary>☂️ JavaScript 是不是太……</summary>
<p></p>
<ul>
没错,确实如此!
<br/>
它并非为与 NLTK 竞争而构建,也未必适合所有项目。
<br/>
字符串处理也是同步的,并行化 Node 进程也颇为别扭。
<br/>
有关速度与性能的信息请见 <a href="https://observablehq.com/@spencermountain/compromise-performance">此处</a>,项目动机请见
<a href="https://observablehq.com/@spencermountain/compromise-justification">此处</a>
</ul>
<p></p>
</details>
</p>
<p>
<details>
<summary>💃 能在我的 Arduino 手表上运行吗?</summary>
<p></p>
<ul>
除非它防水!
<br/>
请阅读 <a href="https://observablehq.com/@spencermountain/compromise-quickstart">快速入门</a>,了解如何在 Worker、移动应用等各种有趣环境中运行 compromise。
</ul>
<p></p>
</details>
</p>
<p>
<details>
<summary>🌎 其他语言的 Compromise</summary>
<p></p>
<ul>
我们已有遵循同一理念的 <a href="https://github.com/nlp-compromise/de-compromise">德语</a>、<a href="https://github.com/nlp-compromise/fr-compromise">法语</a>、<a href="https://github.com/nlp-compromise/es-compromise">西班牙语</a> 和 <a href="https://github.com/nlp-compromise/it-compromise">意大利语</a> 分支,仍在开发中。
<br/>
同时也需要一些帮助。
</ul>
<p></p>
</details>
</p>
<p>
<details>
<summary>✨ 部分构建?</summary>
<p></p>
<ul>
我们确实提供 <a href="https://observablehq.com/@spencermountain/compromise-filesize">仅分词</a> 构建,其中 POS 标注器已被移除。
<br/>
但除此之外,compromise 不易进行 tree-shaking。
<br/>
标注方法彼此竞争且呈贪婪式,因此不建议剥离部分功能。
<br/>
请注意,若没有完整的 POS 标注,缩略形式解析器将无法完美工作。(<i>(spencer's cool)</i> 与 <i>(spencer's house)</i>
<br/>
建议完整运行该库。
</ul>
<p></p>
</details>
</p>
</ul>
<div align="center">
<img src="https://user-images.githubusercontent.com/399657/68221731-e8b84800-ffb7-11e9-8453-6395e0e903fa.png"/>
</div>
#### 另请参阅:
- &nbsp; **[en-pos](https://github.com/finnlp/en-pos)** - 非常精巧的 JavaScript POS 标注器 _by [Alex Corvi](https://github.com/alexcorvi)_
- &nbsp; **[naturalNode](https://github.com/NaturalNode/natural)** - JavaScript 中更精致的统计 NLP
- &nbsp; **[winkJS](https://winkjs.org/)** - JavaScript 中的 POS 标注器、分词器与机器学习
- &nbsp; **[dariusk/pos-js ](https://github.com/dariusk/pos-js)** - JavaScript 版 fastTag 分支
- &nbsp; **[compendium-js](https://github.com/Ulflander/compendium-js)** - JavaScript 中的 POS 与情感分析
- &nbsp; **[nodeBox linguistics](https://www.nodebox.net/code/index.php/Linguistics)** - JavaScript 中的词形变化与屈折
- &nbsp; **[reText](https://github.com/wooorm/retext)** - JavaScript 中令人印象深刻的 [text utilities](https://github.com/wooorm/retext/blob/master/doc/plugins.md)
- &nbsp; **[superScript](https://github.com/superscriptjs/superscript)** - JavaScript 对话引擎
- &nbsp; **[jsPos](https://code.google.com/archive/p/jspos/)** - 久经考验的 Brill 标注器的 JavaScript 构建版
- &nbsp; **[spaCy](https://spacy.io/)** - C/Python 实现的快速多语言标注器(tagger)
- &nbsp; **[Prose](https://github.com/jdkato/prose/)** - Joseph Kato 用 Go 编写的快速标注器
- &nbsp; **[TextBlob](https://github.com/sloria/TextBlob)** - Python 标注器
<img height="25px" src="https://user-images.githubusercontent.com/399657/68221862-17ceb980-ffb8-11e9-87d4-7b30b6488f16.png"/>
<b>MIT</b>