1070 lines
61 KiB
Markdown
1070 lines
61 KiB
Markdown
<!-- 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"/>
|
||
|
||
<i>↬<sub>ᔐᖜ</sub><b>↬</b></i> <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>
|
||
|
||
#### 另请参阅:
|
||
|
||
- **[en-pos](https://github.com/finnlp/en-pos)** - 非常精巧的 JavaScript POS 标注器 _by [Alex Corvi](https://github.com/alexcorvi)_
|
||
- **[naturalNode](https://github.com/NaturalNode/natural)** - JavaScript 中更精致的统计 NLP
|
||
- **[winkJS](https://winkjs.org/)** - JavaScript 中的 POS 标注器、分词器与机器学习
|
||
- **[dariusk/pos-js ](https://github.com/dariusk/pos-js)** - JavaScript 版 fastTag 分支
|
||
- **[compendium-js](https://github.com/Ulflander/compendium-js)** - JavaScript 中的 POS 与情感分析
|
||
- **[nodeBox linguistics](https://www.nodebox.net/code/index.php/Linguistics)** - JavaScript 中的词形变化与屈折
|
||
- **[reText](https://github.com/wooorm/retext)** - JavaScript 中令人印象深刻的 [text utilities](https://github.com/wooorm/retext/blob/master/doc/plugins.md)
|
||
- **[superScript](https://github.com/superscriptjs/superscript)** - JavaScript 对话引擎
|
||
- **[jsPos](https://code.google.com/archive/p/jspos/)** - 久经考验的 Brill 标注器的 JavaScript 构建版
|
||
|
||
- **[spaCy](https://spacy.io/)** - C/Python 实现的快速多语言标注器(tagger)
|
||
- **[Prose](https://github.com/jdkato/prose/)** - Joseph Kato 用 Go 编写的快速标注器
|
||
- **[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>
|