
Java SDK для создания конвейеров аналитики, которые обрабатывают и обогащают неструктурированные текстовые данные с помощью аннотаций, систем типов и модульных механизмов анализа.
[Apache UIMA][UIMA] помогает вам управлять неструктурированными данными (например, текстами), которые обогащаются полезной информацией. Например, если вы хотите идентифицировать упоминание сущности в тексте или связать эту сущность с эталонным набором данных, Apache UIMA предоставляет:
Обратите внимание: Apache UIMA Java SDK предоставляет только платформу для создания аналитики, но не предоставляет саму аналитику. Однако существуют различные сторонние проекты, которые основаны на Apache UIMA и предоставляют наборы компонентов анализа или готовые решения.
Apache UIMA v3.6.0 и более поздние версии требуют Java версии 17 или новее.
Для запуска инструментов плагина Eclipse для UIMA требуется Eclipse 4.25 (2022-09) или новее, использующий Java 17 или новее.
Для запуска инструмента миграции для class-файлов требуется Java JDK, а не Java JRE.
Поддерживаемые платформы: Windows, Linux и macOS. Другие реализации платформы Java должны работать, но не были тщательно протестированы.
Многие скрипты в каталоге /bin вызывают Java. Они используют значение переменной окружения JAVA_HOME для поиска используемой Java; если она не задана, они вызывают java, ожидая найти подходящую Java в вашей переменной PATH.
Вы можете легко добавить Apache UIMA Java SDK в свой проект в большинстве инструментов сборки, импортировав его из [Maven Central][MAVEN-CENTRAL]. Например, если вы используете Maven, вы можете добавить следующую зависимость в свой проект:
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-core</artifactId>
<version>3.6.0</version>
</dependency>
Далее мы приведём несколько кратких примеров использования Apache UIMA Java SDK и библиотеки Apache uimaFIT. Apache uimaFIT — это отдельная зависимость, которую вы можете добавить:
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimafit-core</artifactId>
<version>3.6.0</version>
</dependency>
Система типов определяет тип информации, которую мы хотим прикрепить к неструктурированной информации (здесь — текстовому документу). В нашем примере мы хотим идентифицировать упоминания сущностей, поэтому мы определяем тип my.Entity с признаком category, который можно использовать для хранения категории, к которой принадлежит сущность.
Чтобы проиллюстрировать информацию, которую UIMA внутренне хранит о схеме аннотаций, мы выводим сгенерированную схему в виде XML на экран.
String TYPE_NAME_ENTITY = "my.Entity";
String TYPE_NAME_TOKEN = "my.Token";
String FEAT_NAME_CATEGORY = "category";
var tsd = UIMAFramework.getResourceSpecifierFactory().createTypeSystemDescription();
tsd.addType(TYPE_NAME_TOKEN, "", CAS.TYPE_NAME_ANNOTATION);
var entityTypeDesc = tsd.addType(TYPE_NAME_ENTITY, "", CAS.TYPE_NAME_ANNOTATION);
entityTypeDesc.addFeature(FEAT_NAME_CATEGORY, "", CAS.TYPE_NAME_STRING);
tsd.toXML(System.out);
Теперь мы создаём объект Common Analysis Structure (CAS), в который сохраняем текст, который хотим проанализировать.
Опять же, чтобы проиллюстрировать информацию, которую UIMA внутренне хранит в объекте CAS, мы выводим XML-представление объекта на экран.
var cas = CasFactory.createCas(tsd);
cas.setDocumentText("Welcome to Apache UIMA.");
cas.setDocumentLanguage("en");
CasIOUtils.save(cas, System.out, SerialFormat.XMI_PRETTY);
Теперь мы создаём аннотацию типа my.Entity, чтобы идентифицировать упоминание Apache UIMA в примере текста.
Наконец, мы перебираем все аннотации в CAS и выводим их на экран. Это включает стандартную аннотацию DocumentAnnotation, которая всегда создаётся UIMA, а также аннотацию my.Entity, которую мы создали сами.
var entityType = cas.getTypeSystem().getType(TYPE_NAME_ENTITY);
var entity = cas.createAnnotation(entityType, 11, 22);
cas.addFsToIndexes(entity);
for (var anno : cas.<Annotation>select(entityType)) {
System.out.printf("%s: [%s]%n", anno.getType().getName(), anno.getCoveredText());
}
Чтобы организовать различные типы анализа в виде шагов, мы обычно упаковываем их в отдельные аналитические движки. Теперь мы покажем, как такие компоненты можно создавать и как их можно запускать в виде конвейера анализа.
class TokenAnnotator extends CasAnnotator_ImplBase {
public void process(CAS cas) throws AnalysisEngineProcessException {
var tokenType = cas.getTypeSystem().getType(TYPE_NAME_TOKEN);
var bi = BreakIterator.getWordInstance();
bi.setText(cas.getDocumentText());
int begin = bi.first();
int end;
for (end = bi.next(); end != BreakIterator.DONE; end = bi.next()) {
var token = cas.createAnnotation(tokenType, begin, end);
cas.addFsToIndexes(token);
begin = end;
}
}
}
class EntityAnnotator extends CasAnnotator_ImplBase {
public void process(CAS cas) throws AnalysisEngineProcessException {
var tokenType = cas.getTypeSystem().getType(TYPE_NAME_TOKEN);
var entityType = cas.getTypeSystem().getType(TYPE_NAME_ENTITY);
for (var token : cas.<Annotation>select(tokenType)) {
if (Character.isUpperCase(token.getCoveredText().charAt(0))) {
var entity = cas.createAnnotation(entityType, token.getBegin(), token.getEnd());
cas.addFsToIndexes(entity);
}
}
}
}
cas = CasFactory.createCas(tsd);
cas.setDocumentText("John likes Apache UIMA.");
cas.setDocumentLanguage("en");
var pipeline = AnalysisEngineFactory.createEngineDescription(
AnalysisEngineFactory.createEngineDescription(TokenAnnotator.class),
AnalysisEngineFactory.createEngineDescription(EntityAnnotator.class));
SimplePipeline.runPipeline(cas, pipeline);
for (var anno : cas.<Annotation>select(entityType)) {
System.out.printf("%s: [%s]%n", anno.getType().getName(), anno.getCoveredText());
}