
Java SDK para construir pipelines de análise que processam e enriquecem dados de texto não estruturados com anotações, sistemas de tipos e motores de análise modulares.
[Apache UIMA][UIMA] ajuda você a gerenciar dados não estruturados (como textos) que são enriquecidos com informações úteis. Por exemplo, se você deseja identificar uma menção a uma entidade em um texto ou possivelmente vincular essa entidade a um conjunto de dados de referência, o Apache UIMA fornece:
Observe que o Apache UIMA Java SDK fornece apenas uma estrutura para construir análises, mas não fornece nenhuma análise. No entanto, existem vários terceiros que constroem sobre o Apache UIMA e fornecem coleções de componentes de análise ou soluções prontas.
Apache UIMA v3.6.0 e posteriores exigem Java versão 17 ou superior.
Executar o plugin Eclipse para UIMA requer iniciar o Eclipse 4.25 (2022-09) ou posterior usando um Java 17 ou superior.
Executar a ferramenta de migração em arquivos de classe requer executar com um Java JDK, não um Java JRE.
As plataformas suportadas são: Windows, Linux e macOS. Outras implementações da plataforma Java devem funcionar, mas não foram significativamente testadas.
Muitos dos scripts no diretório /bin invocam Java. Eles usam o valor da variável de ambiente JAVA_HOME para localizar o Java a ser usado; se não estiver definida, eles invocam java esperando encontrar um Java apropriado na sua variável PATH.
Você pode adicionar o Apache UIMA Java SDK ao seu projeto facilmente na maioria das ferramentas de build importando-o do [Maven Central][MAVEN-CENTRAL]. Por exemplo, se você usa Maven, pode adicionar a seguinte dependência ao seu projeto:
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimaj-core</artifactId>
<version>3.6.0</version>
</dependency>
A seguir, damos alguns breves exemplos de como usar o Apache UIMA Java SDK e a biblioteca Apache uimaFIT. Apache uimaFIT é uma dependência separada que você pode adicionar:
<dependency>
<groupId>org.apache.uima</groupId>
<artifactId>uimafit-core</artifactId>
<version>3.6.0</version>
</dependency>
O sistema de tipos define o tipo de informação que queremos anexar à informação não estruturada (aqui um documento de texto). Em nosso exemplo, queremos identificar menções de entidades, então definimos um tipo my.Entity com um recurso category que pode ser usado para armazenar a categoria à qual a entidade pertence.
Para ilustrar a informação que a UIMA mantém internamente sobre o esquema de anotação, escrevemos o esquema gerado como XML na tela.
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);
Agora criamos um objeto Common Analysis Structure (CAS) no qual armazenamos o texto que queremos analisar.
Novamente, para ilustrar a informação que a UIMA armazena internamente no objeto CAS, escrevemos uma representação XML do objeto na tela.
var cas = CasFactory.createCas(tsd);
cas.setDocumentText("Welcome to Apache UIMA.");
cas.setDocumentLanguage("en");
CasIOUtils.save(cas, System.out, SerialFormat.XMI_PRETTY);
Agora, criamos uma anotação do tipo my.Entity para identificar a menção de Apache UIMA no texto de exemplo.
Finalmente, iteramos sobre todas as anotações na CAS e as imprimimos na tela. Isso inclui a DocumentAnnotation padrão que é sempre criada pela UIMA, bem como a anotação my.Entity que criamos nós mesmos.
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());
}
Para organizar diferentes tipos de análise em etapas, geralmente os empacotamos em motores de análise individuais. Ilustramos agora como esses componentes podem ser construídos e como podem ser executados como um pipeline de análise.
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());
}