需求概述
调研方案主要满足以下需求:
○ 英文单词拼写检查
○ 英文语句语法检查
○ 中文词汇正确性检查
○ 中文语法正确性检查
功能范围
单词拼写/词汇使用 | 语句语法 | |
---|---|---|
中文 | 1. 是否拼写正确 2. 返回最佳纠正结果 3. 返回所有纠正结果列表 4. 自定义词库 | 1. 语法修正原因 2. 语法修正结果 3. 是否有语法错误 4. 自定义纠错规则 |
英文 | 1. 是否拼写正确 2. 返回最佳纠正结果 3. 返回所有纠正结果列表 4. 自定义词库 | 1. 语法修正原因 2. 语法修正结果 3. 是否有语法错误 4. 自定义纠错规则 |
其他 | 1. 中英文混合长文本分词纠错 2. 内置8W+英文词库,扩展需自定义增加 | 基础语法包包含Chinese,English, English (US), English (GB), English (Australian), English (Canadian), English (New Zealand), English (South African),Italian,Polish等 |
模块包 | |
---|---|
单词拼写/词汇使用 | word-checker:0.1.0 |
语句语法 | ● language-en:6.0 ● language-zh:6.0 ● languagetool-core:6.0 |
根据实际输入输出结果展示word-checker的单词纠错能力以及languagetool的语法纠正能力
word-checker英文单词拼写检查支持的使用方式如下:
核心 api 在 EnWordCheckers 工具类下。
功能 | 方法 | 参数 | 返回值 | 备注 |
---|---|---|---|---|
判断单词拼写是否正确 | isCorrect(string) | 待检测的单词 | boolean | |
返回最佳纠正结果 | correct(string) | 待检测的单词 | String | 如果没有找到可以纠正的单词,则返回其本身 |
判断单词拼写是否正确 | correctList(string) | 待检测的单词 | List | 返回所有匹配的纠正列表 |
判断单词拼写是否正确 | correctList(string, int limit) | 待检测的单词, 返回列表的大小 | 返回指定大小的的纠正列表 | 列表大小 <= limit |
测试语句输入:
String testString = "Hi lets see fi iti cahn check miy seplling";
EnWordCheckers工具类仅支持单个单词的拼写纠正,目前word-checker-0.1.0版本支持中英文混合长文本自动分词纠正,以下输出结果可使用WordCheckers工具类直接输出。
测试输出结果:
单词:Hi,输出是否拼写正确:true,输出最佳纠正结果in,输出匹配纠正列表[in, is, i, it, if, ii, id, hi]
--------
单词:lets,输出是否拼写正确:true,输出最佳纠正结果lets,输出匹配纠正列表[lets]
--------
单词:see,输出是否拼写正确:true,输出最佳纠正结果see,输出匹配纠正列表[see]
--------
单词:fi,输出是否拼写正确:false,输出最佳纠正结果of,输出匹配纠正列表[of, in, is, i, it, if, ii, id, fri, fit, fix, fig, fin, fir, fid, fib, fie, hi]
--------
单词:iti,输出是否拼写正确:false,输出最佳纠正结果it,输出匹配纠正列表[it, its, ii, bit, kit, iii, int, hit, fit, tip, tim, sit, tie, tit, tin, vii, pit, lit, til, wit, tai, xii, tia, cit, tic, dit, git, ito, ait, lii, nit, rit, tui, twi, inti, zit, tiu, tiv, titi, ziti, wii]
--------
单词:cahn,输出是否拼写正确:false,输出最佳纠正结果can,输出匹配纠正列表[can, cash, scan, cant, clan, chen, chan, chin, cane, cans, cyan, cain, hahn, kahn, cath, cana, caen, chon, canc, icahn]
--------
单词:check,输出是否拼写正确:true,输出最佳纠正结果check,输出匹配纠正列表[check]
--------
单词:miy,输出是否拼写正确:false,输出最佳纠正结果my,输出匹配纠正列表[my, may, min, mid, mix, amy, mil, mic, mai, mia, ivy, mir, ami, moi, icy, mig, mim, mys, miry]
--------
单词:seplling,输出是否拼写正确:false,输出最佳纠正结果selling,输出匹配纠正列表[selling, spelling, swelling, smelling, spilling, shelling]
优点 | 缺点 | 处理方案 | |
---|---|---|---|
响应时间 | ● 单个单词保持在1MS上下响应结果 ● 长文本保持在19~100MS内 | 初次调用工具类时间1S | |
单词覆盖 | ● 基础词库8W+,覆盖基本常用单词 ● 可自定义词库 | ● 英文单词总数60W左右,无全面覆盖 | 如需增加单词使用自定义词库 |
纠错结果 | ● 可判断单词拼写正确与否 ● 可返回纠正单词列表 ● 可返回最佳纠正结果 | ● 拼写非常杂乱的单词无法纠正及判断对错,将会返回输入本身 ● 最佳纠正结果可能并不是最有效结果 ● 纠正单词列表内单词很多 ● 类似于my输入错误成miy,最佳结果会是may,根据字数有限判断 ● 无法在单词衔接及语法上给出建议,仅单独的单词拼写纠错 | 需要在代码内对返回结果再做处理 |
其他 | ● 长文本中英混合模式可自动分词纠错 ● 2核1G资源可用,每次需占用1核资源 | ● 偶现抛错,出现在大量杂乱单词的长文本纠错模式下 | 针对抛错需要捕获 |
目前最新版本为0.1.0
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>word-checker</artifactId>
<version>0.1.0</version>
</dependency>
自定义词库
项目资源目录创建文件 resources/data/define_word_checker_en.txt
内容如下:
my-long-long-define-word,2
my-long-long-define-word-two
不同的词独立一行。
每一行第一列代表单词,第二列代表出现的次数,二者用逗号 , 隔开。
次数越大,在纠正的时候返回优先级就越高,默认值为 1。
用户自定义的词库优先级高于系统内置词库。
示例:
final String word = "my-long-long-define-word";
final String word2 = "my-long-long-define-word-two";
System.out.println(EnWordCheckers.isCorrect(word));
System.out.println(EnWordCheckers.isCorrect(word2));
//输出:
//true
//true
word-checker中文词语拼写检查支持的使用方式与英文一致
测试语句1输入:
String right = "正确";
String error = "万变不离其中";
System.out.println(ZhWordCheckers.isCorrect(right));
System.out.println(ZhWordCheckers.isCorrect(error));
System.out.println(ZhWordCheckers.correct(error));
测试1输出结果:
true
false
万变不离其宗
测试语句2输入:
String testStringOne = "以毒功毒"; System.out.println(ZhWordCheckers.isCorrect(testStringOne));
System.out.println(ZhWordCheckers.correct(testStringOne));
String testStringTwo = "错中复杂"; System.out.println(ZhWordCheckers.isCorrect(testStringTwo));
System.out.println(ZhWordCheckers.correct(testStringTwo));
测试2输出结果:
false
以毒攻毒
true
错中复杂
测试语句3输入:
String right = "你好,以毒功毒,每天都吃玉米但是吃不报,but i waut";
System.out.println(WordCheckers.isCorrect(right));
System.out.println(WordCheckers.correctMap(right));
测试3输出结果:
false
{你=[你], but=[but], =[ ], 吃=[吃], 报=[报], 但=[但], 天=[天], 玉=[玉], i=[i], ,=[,], 不=[不], 每=[每], 是=[是], 米=[米], 以毒功毒=[以毒攻毒], 好=[好], 都=[都], waut=[want, wait, watt, walt, wat, wart, taut, wast, waft, naut]}
优点 | 缺点 | 处理方案 | |
---|---|---|---|
响应时间 | ● 单个词语10MS~20MS ● 长文本保持在19~100MS内 | 初次调用工具类时间1S | |
单词覆盖 | ● 可自定义词库 | ● 大量中文词汇、相近字、同音字、同型字无法覆盖,基础词库覆盖性差 | 如需使用,会大量使用到自定义词库 |
纠错结果 | ● 可以判断词语正确与否 ● 可返回纠正词语 ● 可返回最佳纠正结果 ● 可结合英文长文本判断 | ● 大量词汇无法纠错 ● 长文本下会出现分词不准确 ● 大量同音字无法判断错误,大量乱词类似"正确""正去"等无法区分对错 ● 中文无主语也可认为通顺,该情况也无法判断 | |
其他 | ● 长文本中英混合模式可自动分词纠错 ● 2核1G资源可用,每次需占用1核资源 |
自定义词库
项目资源目录创建文件 resources/data/define_word_checker_zh.txt
内容如下:
吃不报 吃不饱
使用英文空格分隔,前面是错误,后面是正确。
示例:
String right = "你好,以毒功毒,每天都吃玉米但是吃不报,but i waut";
System.out.println(WordCheckers.isCorrect(right));
System.out.println(WordCheckers.correctMap(right));
//false
//{你=[你], but=[but], =[ ], 吃=[吃], 但=[但], 天=[天], 玉=[玉], i=[i], ,=[,], 每=[每], 是=[是], 米=[米], 以毒功毒=[以毒攻毒], 好=[好], 都=[都], 吃不报=[吃不饱], waut=[want, wait, watt, walt, wat, wart, taut, wast, waft, naut]}
WordCheckers 工具类提供了长文本中英文混合的自动纠正功能。
功能 | 方法 | 参数 | 返回值 | 备注 |
---|---|---|---|---|
文本拼写是否正确 | isCorrect(string) | 待检测的文本 | boolean | 全部正确,才会返回 true |
返回最佳纠正结果 | correct(string) | 待检测的单词 | String | 如果没有找到可以纠正的文本,则返回其本身 |
判断文本拼写是否正确 | correctMap(string) | 待检测的单词 | Map<String, List | 返回所有匹配的纠正列表 |
判断文本拼写是否正确 | correctMap(string, int limit) | 待检测的文本, 返回列表的大小 | 返回指定大小的的纠正列表 | 列表大小 <= limit |
languagetool可支持的语言及语法规则数量
语言 | 规则数量 |
---|---|
Arabic | 520 |
Asturian | 61 |
Belarusian | 8 |
Breton | 675 |
CatalanVariants for: Valencian | 5306 |
Chinese | 1863 |
Danish | 78 |
DutchVariants for: Belgium | 3374 |
EnglishVariants for: Australian, Canadian, GB, New Zealand, South African, US | 5727 |
Esperanto | 422 |
French | 7263 |
Galician | 308 |
GermanVariants for: Austria, Germany, Swiss | 4724 |
Greek | 55 |
Irish | 1663 |
Japanese | 734 |
Italian | 139 |
Khmer | 33 |
Persian | 283 |
Polish | 1728 |
PortugueseVariants for: Angola preAO, Brazil, Moçambique preAO, Portugal | 2732 |
Romanian | 457 |
Russian | 878 |
Slovak | 170 |
Slovenian | 86 |
SpanishVariants for: voseo | 1430 |
Swedish | 26 |
Tagalog | 44 |
Tamil | 210 |
Ukrainian | 1038 |
测试语句1输入:
JLanguageTool lt = new JLanguageTool(new AmericanEnglish());
String input = "Hi lets see fi iti cahn check miy seplling";
List<RuleMatch> result = lt.check(input);
if (result !=null && !result.isEmpty()){
System.out.println("有错误");
}else {
System.out.println("无错误");
}
for (RuleMatch ruleMatch : result) {
System.out.println(" " + ruleMatch);
}
测试1结果输出:
有错误
Checking 'Hi lets see fi iti cahn check miy seplling' with Chinese:
MORFOLOGIK_RULE_EN_US:12-14:Possible spelling mistake found.
MORFOLOGIK_RULE_EN_US:15-18:Possible spelling mistake found.
MORFOLOGIK_RULE_EN_US:19-23:Possible spelling mistake found.
MORFOLOGIK_RULE_EN_US:30-33:Possible spelling mistake found.
MORFOLOGIK_RULE_EN_US:34-42:Possible spelling mistake found.
//单词拼写错误
测试语句2输入:
JLanguageTool lt = new JLanguageTool(new AmericanEnglish());
String input = "who are you you";
List<RuleMatch> result = lt.check(input);
if (result !=null && !result.isEmpty()){
System.out.println("有错误");
}else {
System.out.println("无错误");
}
for (RuleMatch ruleMatch : result) {
System.out.println(" " + ruleMatch);
}
测试2输出:
有错误
UPPERCASE_SENTENCE_START:0-3:This sentence does not start with an uppercase letter.
//语句开头单词没有大写
ENGLISH_WORD_REPEAT_RULE:8-15:Possible typo: you repeated a word
//you单词重复了
测试3对比文本输入:
JLanguageTool lt = new JLanguageTool(new AmericanEnglish());
String input = "I hope an world peace";
List<RuleMatch> result = lt.check(input);
if (result !=null && !result.isEmpty()){
System.out.println("有错误");
}else {
System.out.println("无错误");
}
for (RuleMatch ruleMatch : result) {
System.out.println(" " + ruleMatch);
}
String input2 = "I hope for world peace";
List<RuleMatch> result2 = lt.check(input2);
if (result2 !=null && !result2.isEmpty()){
System.out.println("有错误");
}else {
System.out.println("无错误");
}
for (RuleMatch ruleMatch : result2) {
System.out.println(" " + ruleMatch);
}
测试3对比输出:
有错误
EN_A_VS_AN:7-9:Use <suggestion>a</suggestion> instead of 'an' if the following word doesn't start with a vowel sound, e.g. 'a sentence', 'a university'.
无错误
优点 | 缺点 | 处理方案 | |
---|---|---|---|
响应时间 | ● 单个句子语法检查在10~30MS上下 | 初次工具类调用需要3.6S | 代码结构处理 |
语法覆盖 | ● 可自定义规则 ● 包含基础规则xml英语规则5727个 ● 包含多种风格英语规则包 | ● 无法完全覆盖所有英文语法规范 | 如有需要可以自定义加入规则 |
纠错结果 | ● 可以判断多种语法错误 ● 可根据使用需要灵活切换规则包及语言 ● 可以给出详细出错的字数位置及详细错误信息 | ● 单词拼写错误无法给出纠正结果 | |
其他 | ● 基于错误模式匹配,降低文本纠正难度 ● 规则可配置,检验规则灵活。 ● 可积累复用的规则文件。 | ● 各个语法规则包判断标准不一样需要自行判断所需包 ● 扫描匹配的资源消耗巨大。目前测试每次扫描需要1G内存以及大量CPU资源,需要大于3核2G的资源可运行 ● 自定义匹配规则配置复杂 | 可根据需要加入规则类以及配置 |
<dependency>
<groupId>org.languagetool</groupId>
<artifactId>language-en</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.languagetool</groupId>
<artifactId>languagetool-core</artifactId>
<version>6.0</version>
</dependency>
语言包选择:
创建META-INF/org/languagetool/language-module.properties 。
该文件如下所示:
languageClasses=org.languagetool.language.Italian
languageClasses=org.languagetool.language.Polish
languageClasses=org.languagetool.language.English,org.languagetool.language.AmericanEnglish
注: 该类JLanguageTool不是线程安全的。JLanguageTool 每个线程创建一个实例,但只创建一次语言(例如new BritishEnglish())并将其用于所有实例JLanguageTool。对于它也是如此 MultiThreadedJLanguageTool——它的名字指的是它在内部使用线程,但它本身不是线程安全的。
测试语句1输入:
JLanguageTool langTool = new JLanguageTool(new Chinese());
System.out.println(langTool.getAllActiveRules());
List<RuleMatch> matches = langTool.check("我和她去吃了二顿饭。");
System.out.println(matches);
for (RuleMatch match : matches) {
System.out.println("可能拼写错误 " +
match.getFromPos() + "-" + match.getToPos() + ": " +
match.getMessage());
System.out.println("建议修正(s): " +
match.getSuggestedReplacements());
}
测试1输出结果:
[wa5[5]:6-8:若非古汉语,则量词“二”可能使用错误,您的意思是否是:<suggestion>两顿</suggestion>?]
可能拼写错误 6-8: 若非古汉语,则量词“二”可能使用错误,您的意思是否是:<suggestion>两顿</suggestion>?
建议修正(s): [两顿]
测试语句2输入:
JLanguageTool langTool = new JLanguageTool(new Chinese());
System.out.println(langTool.getAllActiveRules());
List<RuleMatch> matches = langTool.check("消毁一个人,我没有计性,我天每三顿饭吃我");
System.out.println(matches);
for (RuleMatch match : matches) {
System.out.println("可能拼写错误 " +
match.getFromPos() + "-" + match.getToPos() + ": " +
match.getMessage());
System.out.println("建议修正(s): " +
match.getSuggestedReplacements());
}
测试2输出结果:
[XIAO1_XIAO2[1]:0-2:您的意思是"<suggestion>销毁</suggestion>"吗?, JI31_JI32[5]:9-10:您的意思是"<suggestion>记</suggestion>性"吗?]
可能拼写错误 0-2: 您的意思是"<suggestion>销毁</suggestion>"吗?
建议修正(s): [销毁]
可能拼写错误 9-10: 您的意思是"<suggestion>记</suggestion>性"吗?
建议修正(s): [记]
测试语句3输入:
JLanguageTool langTool = new JLanguageTool(new Chinese());
System.out.println(langTool.getAllActiveRules());
List<RuleMatch> matches = langTool.check("后歌开了会唱演,险保买我");
System.out.println(matches);
for (RuleMatch match : matches) {
System.out.println("可能拼写错误 " +
match.getFromPos() + "-" + match.getToPos() + ": " +
match.getMessage());
System.out.println("建议修正(s): " +
match.getSuggestedReplacements());
}
测试3输出结果:
[]
优点 | 缺点 | 处理方案 | |
---|---|---|---|
响应时间 | ● 单个句子语法检查在10~30MS上下 | 初次工具类调用需要3.6S | 代码结构处理 |
语法覆盖 | ● 可自定义规则 | ● 自定义规则配置复杂 ● 中文语言规则仅1863项,且大多数不是语法错误,都是成语及词语相近词错误,中文规则数量庞大,完全无法覆盖 | |
纠错结果 | ● 可以给出详细出错的字数位置及详细错误信息 | ● 大部分无纠错结果,与语法覆盖有关,影响使用 | |
其他 | ● 基于错误模式匹配,降低文本纠正难度 ● 规则可配置,检验规则灵活。 ● 可积累复用的规则文件。 | ● 各个语法规则包判断标准不一样需要自行判断所需包 ● 扫描匹配的资源消耗巨大。目前测试每次扫描需要1G内存以及大量CPU资源,需要大于3核2G的资源可运行 ● 中文规则包过于小 ● 中文中的量词包含阿拉伯数字、中文大小写数字等,数词的筛选很困难,找出统一的判断规则配置的难度极大。 ● 以错误的匹配规则检查语法的方式,难以做到高度抽象,无法涵盖到不同的语法情况,就需要通过具体的字词匹配,才能满足改错的精确性。 ● 一些不常用的词语和隐性的表达方式,难以用规则涵盖,使用LT提供的XML系统也难以进行统一规格化描述,不得不为每一种“隐性错误”进行区别对待,单独编写规则。 ● 标点符号的类别多样,目前 LT 所使用的 ICTCLAS 分词系统,对大部分符号的支持度都不高,甚至会对一些符号进行断句处理,这样就无法通过规则匹配出大部分符号使用错误的语法规则。 |
<dependency>
<groupId>org.languagetool</groupId>
<artifactId>language-zh</artifactId>
<version>6.0</version>
</dependency>
languagetool | word-checker | 可用性分析 | |
---|---|---|---|
中文词语检查 | 可检查词语错误与正确,可以根据规则给出纠正,配置复杂,覆盖面小,需要大量自填规则,基础规则基本不可用 | 可以检查词语错误与正确,可以给出是否准确词语,覆盖面小,需要大量自定义词库 | 中文词语检查覆盖面太小,中文本身词语就过多,针对日常对话词语可用性差 |
英文单词检查 | 可以检查单词拼写正确与错误,但无法给出纠正单词推荐 | 可以检查单词拼写正确错误,可以给出纠正单词推荐以及最佳纠正结果 | word-checker基本可用于英文单词拼写检查,效果比languagetool要好,单个单词拼写上效率高且资源占用小,占用约2核1G |
中文语法检查 | 可以根据规则检查语法,但规则太小,基本无法覆盖日常语言的语法,很多说错主语的句子也无法纠正。另中文组合错误不好判断 | 仅可以检查单词,无法进行语法检查 | 只有languagetool可以支持语法检查,但是中文语法规则配置复杂,基础规则覆盖面太小,可用性非常差 |
英文语法检查 | 可以检查英文的多个语法错误,长文本中多个语法错误都可以返回,规则包覆盖面较广,但资源占用较大 | 仅可检查单词,无长文本上下文连接,无法检查语法错误 | languagetool在英文语法检查上表现良好,目前基础规则包覆盖面较广,可以检查大部分的英文语法,但资源占用较大,需要至少4核2G的空闲资源机器可运行 |