Apache OpenNLP 2.5.12 构建并运行示例应用指南
Apache OpenNLP 2.5.12 构建并运行示例应用指南(Java API 使用示例):从零创建 Maven 工程、阿里云镜像配置、完整 pom.xml 与示例源码(TokenizerME 分词 / POSTaggerME 词性标注 / TokenNameFinder 命名实体识别)、编译运行命令与真实回显,含 JVM 堆限制与 FAQ,全程实测。
Apache OpenNLP 2.5.12 构建并运行示例应用指南
目标:从零构建并运行一个基于 Apache OpenNLP 2.5.12 的 Java 示例应用(Maven 工程 + Java API),串联完成分词(TokenizerME)、词性标注(POSTaggerME)、命名实体识别(TokenNameFinder)三类 NLP 任务。给出 Maven 镜像配置、完整 pom.xml、示例 Java 源码、编译与运行命令及真实回显。所有命令与输出均在 Ubuntu 22.04.5 + JDK 17 + OpenNLP 2.5.12 环境实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(jammy)
- Java:OpenJDK 17.0.20.1
- 构建工具:Apache Maven 3.6.3
- OpenNLP 版本:2.5.12(依赖
org.apache.opennlp:opennlp-tools:2.5.12) - 示例工程目录:
/root/opennlp-demo/ - 模型目录:
/opt/opennlp/models/(en-token.bin、opennlp-en-ud-ewt-pos-1.3-2.5.4.bin、en-ner-person.bin) - 演示账号:root
二、前置条件
已按《Ubuntu 22.04 安装 Apache OpenNLP 2.5.12 指南》完成安装:
- JDK 17 与 Maven 3.6.3 可用(
java -version、mvn -version正常回显); - OpenNLP 2.5.12 安装于
/opt/opennlp-2.5.12; - 模型文件已下载至
/opt/opennlp/models/。
验证命令:
java -version
mvn -version
ls -l /opt/opennlp/models/en-token.bin /opt/opennlp/models/opennlp-en-ud-ewt-pos-1.3-2.5.4.bin /opt/opennlp/models/en-ner-person.bin
三、工程结构
标准 Maven 布局,仅一个 pom 与一个主类:
opennlp-demo/
├── pom.xml
└── src/main/java/demo/OpenNlpDemo.java
mkdir -p /root/opennlp-demo/src/main/java/demo
四、Maven 镜像配置
国内网络环境为加速依赖下载,在 ~/.m2/settings.xml 配置阿里云公共镜像(实测依赖下载走该镜像):
mkdir -p /root/.m2
cat > /root/.m2/settings.xml <<'EOF'
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
EOF
五、完整 pom.xml
pom 声明 opennlp-tools 2.5.12 依赖,并通过 exec-maven-plugin 执行主类:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>opennlp-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.opennlp</groupId>
<artifactId>opennlp-tools</artifactId>
<version>2.5.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>demo.OpenNlpDemo</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
六、示例源码
创建 /root/opennlp-demo/src/main/java/demo/OpenNlpDemo.java,完成三步:TokenizerME 分词 → POSTaggerME 词性标注 → TokenNameFinder 命名实体识别:
package demo;
import opennlp.tools.namefind.NameFinderME;
import opennlp.tools.namefind.TokenNameFinderModel;
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
import opennlp.tools.tokenize.TokenizerME;
import opennlp.tools.tokenize.TokenizerModel;
import opennlp.tools.util.Span;
import java.io.FileInputStream;
import java.util.Arrays;
public class OpenNlpDemo {
public static void main(String[] args) throws Exception {
String text = "Pierre Vinken, 61 years old, will join the board as a nonexecutive director on November 29. Mr. Vinken is chairman of Elsevier N.V., the Dutch publishing group. Alice Smith works at Google in New York.";
// 1) TokenizerME:学习型分词器(模型 en-token.bin)
TokenizerModel tokenModel = new TokenizerModel(new FileInputStream("/opt/opennlp/models/en-token.bin"));
TokenizerME tokenizer = new TokenizerME(tokenModel);
String[] tokens = tokenizer.tokenize(text);
System.out.println("=== TokenizerME 分词结果 ===");
System.out.println(String.join(" | ", tokens));
// 2) POSTaggerME:词性标注(输出 token_TAG,模型为 UD 词性模型)
POSModel posModel = new POSModel(new FileInputStream("/opt/opennlp/models/opennlp-en-ud-ewt-pos-1.3-2.5.4.bin"));
POSTaggerME tagger = new POSTaggerME(posModel);
String[] tags = tagger.tag(tokens);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tokens.length; i++) {
if (i > 0) {
sb.append(' ');
}
sb.append(tokens[i]).append('_').append(tags[i]);
}
System.out.println("=== POSTaggerME 词性标注(token_TAG)===");
System.out.println(sb);
// 3) TokenNameFinder:命名实体识别(人名 person,模型 en-ner-person.bin)
TokenNameFinderModel nerModel = new TokenNameFinderModel(new FileInputStream("/opt/opennlp/models/en-ner-person.bin"));
NameFinderME finder = new NameFinderME(nerModel);
Span[] spans = finder.find(tokens);
double[] probs = finder.probs(spans);
System.out.println("=== TokenNameFinder 人名识别 ===");
for (int i = 0; i < spans.length; i++) {
Span span = spans[i];
String entity = String.join(" ", Arrays.copyOfRange(tokens, span.getStart(), span.getEnd()));
System.out.println("类型=" + span.getType() + " 概率=" + probs[i] + " 实体=" + entity);
}
}
}
💡 说明:三个模型分别来自安装指南中的传统 demo 模型站(en-token.bin、en-ner-person.bin)与 Apache 官方 UD 模型(opennlp-en-ud-ewt-pos-1.3-2.5.4.bin);词性标注输出为 UD 标签集(PROPN/NOUN/AUX 等)。
七、编译与运行
编译(实测成功,退出码 0,无任何输出):
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
cd /root/opennlp-demo
mvn -q clean compile
运行(UTF-8 环境,限制示例 JVM 堆为 256 MB):
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 MAVEN_OPTS="-Xms256m -Xmx256m"
cd /root/opennlp-demo
mvn -q exec:java
八、运行结果解读
程序真实输出(退出码 0):
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
=== TokenizerME 分词结果 ===
Pierre | Vinken | , | 61 | years | old | , | will | join | the | board | as | a | nonexecutive | director | on | November | 29 | . | Mr. | Vinken | is | chairman | of | Elsevier | N.V. | , | the | Dutch | publishing | group | . | Alice | Smith | works | at | Google | in | New | York | .
=== POSTaggerME 词性标注(token_TAG)===
Pierre_PROPN Vinken_PROPN ,_PUNCT 61_NUM years_NOUN old_ADJ ,_PUNCT will_AUX join_VERB the_DET board_NOUN as_ADP a_DET nonexecutive_ADJ director_NOUN on_ADP November_PROPN 29_NUM ._PUNCT Mr._PROPN Vinken_PROPN is_AUX chairman_NOUN of_ADP Elsevier_ADJ N.V._PROPN ,_PUNCT the_DET Dutch_PROPN publishing_VERB group_NOUN ._PUNCT Alice_PROPN Smith_PROPN works_VERB at_ADP Google_PROPN in_ADP New_ADJ York_PROPN ._PUNCT
=== TokenNameFinder 人名识别 ===
类型=person 概率=0.9445758431440533 实体=Pierre Vinken
类型=person 概率=0.9593189992179502 实体=Alice Smith
结果解读:
- TokenizerME:把整句切成 41 个 token;
Mr.、N.V.等含缩写点的词被保留为单个 token(与 SimpleTokenizer 的切法不同,详见《Apache OpenNLP 2.5.12 常用工具与 API 详解》篇)。 - POSTaggerME:为每个 token 标注 UD 词性——PROPN(专有名词)、NOUN(名词)、VERB(动词)、AUX(助动词)、DET(限定词)、ADP(介词)、ADJ(形容词)、NUM(数词)、PUNCT(标点)。
- TokenNameFinder:识别出 2 个人名实体——Pierre Vinken(person,概率 0.945)、Alice Smith(person,概率 0.959)。
- 首行三条
SLF4J(W)仅表示 classpath 未绑定 SLF4J 日志实现(NOP logger),不影响任何功能。
九、注意事项
⚠️ 注意:
- 示例进程堆内存用
MAVEN_OPTS="-Xms256m -Xmx256m"限制;生产环境按内存规划调整。- 词性标注模型与分词模型来自不同模型站(UD 与传统 demo),标签体系不同不影响示例运行,但训练/评测时须保持标签集一致。
- 模型文件用绝对路径加载(
new TokenizerModel(new FileInputStream(...))即上文源码中的用法);更多 API 类与用法见《Apache OpenNLP 2.5.12 常用工具与 API 详解》篇。
十、常见问题
Q1:mvn 下载依赖失败 / 超时?
检查 /root/.m2/settings.xml 的阿里云镜像是否生效(mirrorOf 为 central);必要时删除 ~/.m2/repository 重新拉取。
Q2:运行报 FileNotFoundException?
模型路径不存在。确认 /opt/opennlp/models/ 下存在 en-token.bin、opennlp-en-ud-ewt-pos-1.3-2.5.4.bin、en-ner-person.bin 三个文件。
Q3:输出中文乱码?
OpenNLP 模型面向英文。运行前 export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8,保证管道与终端 UTF-8。
Q4:内存占用偏高?
示例已用 MAVEN_OPTS="-Xms256m -Xmx256m" 限制 JVM 堆;如需复核实际生效堆参数,另开终端执行 ps -ef | grep [j]ava | grep -o "\-Xmx[^ ]*",应看到 -Xmx256m(⚠️ 说明:MAVEN_OPTS 注入为实测运行方式,ps 抓取为通用核对命令,本次未单独保存该场景回显)。
Q5:SLF4J 告警影响使用吗?
不影响。SLF4J(W): No SLF4J providers were found. 表示未绑定日志实现,程序照常运行;如需日志输出可引入 slf4j-simple 等实现。
十一、参考链接
- Apache OpenNLP 官方文档:
https://opennlp.apache.org/docs/ - opennlp-tools 依赖坐标:
org.apache.opennlp:opennlp-tools:2.5.12(Maven Central) - Apache OpenNLP 下载目录:
https://dlcdn.apache.org/opennlp/ - demo 模型站:
https://opennlp.sourceforge.net/models-1.5/