赞
踩
我们的系统应用,总离不开留言和评论功能,甚至是Im即时通讯,也就产生了审核的需求。如果全部依赖人工来做,显然不现实。在当今chatgpt火爆的时候,如果我们连静态的分词都还做不到,实是惭愧万分。
我们不要求做到ai机器人那么强大,还需要去理解用户的上下文,只需要根据输入的一段文本,进行语义上的拆分(即分词)。经过选型,我们选择了一款免费版的hanlp工具,当然你也可以选择市面上的其他工具,如网易易盾、微盾、Jieba等等。(这里就不说一些大厂的在线服务了)
我们有一个硬核需求,就是要自定义单词,相对方便灵活。因为敏感词的变化太快了~~
这里不建议你使用portable-1.8.4,区别是portable-1.8.4包含了data目录。而我们一般是将data目录放置在jar包的外部,这也是我不推荐你引用portable-1.8.4包的原因,使用轻量级的1.8.4就够了。
<dependency>
<groupId>com.hankcs</groupId>
<artifactId>hanlp</artifactId>
<version>1.8.4</version>
<!-- <version>portable-1.8.4</version>-->
</dependency>
下面我截图以对比二者,但是你如果直接使用1.8.4,会发现远程仓库没有该包,需要你手动下载然后上传至你自己的私有仓库中。
先手工下载jar和配置文件:hanlp-release.zip
下载至本地,把jar和source包先后upload至nexus等私有仓库中。
该包还有一个hanlp.properties文件,你需要修改配置root=你自己的HanLP数据包的目录
只需要修改这一项,其他的保持不变。
root=/Users/xxx/Desktop/data-for-1.7.5/
# hanlp自定义单词
hanlp:
define:
wordlist: 傻逼,杂种细胞
import cn.hutool.core.date.DateUtil; import com.xxx.ws.test.hanlp.HanlpService; import io.swagger.annotations.Api; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; /** * hanlp的测试入口类. */ @Api(tags = "hanlp") @RestController @RequiredArgsConstructor public class HanlpApiController { private final HanlpService hanlpService; @PatchMapping("/hanlp/add/{word}") public ResponseEntity<?> add(@PathVariable String word) { hanlpService.add(word); return ResponseEntity.ok(DateUtil.now()); } @DeleteMapping("/hanlp/remove/{word}") public ResponseEntity<?> remove(@PathVariable String word) { hanlpService.remove(word); return ResponseEntity.ok(DateUtil.now()); } @PostMapping("/hanlp/split") public ResponseEntity<?> split(@RequestBody String content) { return ResponseEntity.ok(hanlpService.segmentWord(content)); } }
import com.google.common.collect.Lists; import com.hankcs.hanlp.HanLP; import com.hankcs.hanlp.dictionary.CustomDictionary; import com.hankcs.hanlp.seg.common.Term; import com.hankcs.hanlp.utility.Predefine; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service public class HanlpService { // 多个单词之间使用逗号隔开 @Value("#{'${hanlp.define.wordlist:}'.split(',')}") private List<String> myDefineWordList; @PostConstruct public void init() { // 从环境变量里读取 Predefine.HANLP_PROPERTIES_PATH = System.getProperty("hanlp_properties_path"); // 将自定义的单词加入到自定义词典 myDefineWordList.stream().forEach(word -> { this.add(word); }); } public List<String> segmentWord(String content) { if (StringUtils.isEmpty(content)) { return Lists.newArrayList(); } List<Term> termList = HanLP.segment(content); List<String> words = termList.stream().map(term -> term.word).collect(Collectors.toList()); return words; } public void add(String word) { CustomDictionary.add(word); } public void remove(String word) { CustomDictionary.remove(word); } }
curl -X POST -H “Accept:/” -H “Content-Type:application/json” -d “你是个傻逼还是杂种细胞呢” “http://localhost:8085/hanlp/split”
返回结果是:[
“你”,
“是”,
“个”,
“傻逼”,
“还是”,
“杂种细胞”,
“呢”
]
证明自定义的单词生效了。
curl -X DELETE -H “Accept:/” -H “Content-Type:application/x-www-form-urlencoded” “http://localhost:8085/hanlp/remove/”
再去切割上一句话,则是如下结果
再新增自定义单词
curl -X PATCH -H “Accept:/” -H “Content-Type:application/x-www-form-urlencoded” “http://localhost:8085/hanlp/add/”
这里就不赘述,第一次切割单词"杂种细胞"为两个单词"杂种"和"细胞",第二步新增单词"杂种细胞"后,就不会拆分成两个单词,第三步删除自定义单词"杂种细胞",效果又回到第一次。
Predefine.HANLP_PROPERTIES_PATH,你需要在程序启动的过程中,对它进行赋值,为hanlp.properties文件所在的目录。比如 Predefine.HANLP_PROPERTIES_PATH = “/Users//Desktop/data-for-1.7.5/hanlp.properties”;
本文花费比较多的地方截图和补充说明在准备工作,环境配置相对可能是一个坑。因为我们的需求是需要自定义单词。(如果你不需要自定义单词,你可以直接使用portable-1.8.4,压根都没有这么多步骤)
话说回来,如果你对接的是分词需求,而且是离线版的hanlp,自定义的需求就是我们的硬核需求,不可或缺。(否则你直接使用rest版本的即可)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。