samedi 10 décembre 2011

Mise en correspondance de vues via un Aggregate pour interconnecter des composants UIMA (view et sofa name mapping)

Après avoir rappelé quelques notions (que le lecteur averti peut ne pas lire), le post expose brièvement le problème et présente avec un exemple la mise en oeuvre d'une solution de mise en correspondance de vues au sein d'un Aggregate.

Bref rappel de quelques notions
Les chapitres 5 et 6 de la documentation UIMA tutorials_and_users_guides [1;2] rappellent les définitions des notions d'Artifact, Sofa et View.
Brièvement l'Artifact est la chose non structurée que l'on souhaite analyser. Le Sofa (Subject of Analysis) est une représentation de l'Artifact (e.g. HTML). Une annotation metadata est de l'information associée à un Sofa particulier pour en décrire une sous région. La notion de View simplifie les choses quand plusieurs versions de l'Artifact sont nécessaire à différentes étapes de l'analyse (e.g. une version sans balise d'un document XML). Les notions de Sofa et de CAS View sont liées. Dans l'implémentation Apache actuelle (2.4), à chaque Sofa est associé une seule View et à chaque View un seul Sofa. Le nom qui désigne une vue particulière est Sofa name pour des raisons historiques mais cela s'applique indifféremment à View aussi.
L'analyse d'un composant UIMA (AE - Analysis Engine) porte toujours sur une vue. Il peut y en avoir plusieurs. L'AE peut en créer. Les résultats d'analyse peuvent être associés sur les vues traitées ou bien sur les vues créées.
Un AE qui travaille seulement sur une seule vue est appelée "single-view component" et dans le cas contraire "multi-view/multi-sofa component".
Par défaut, si rien n'est spécifié il y a qu'une seule view et celle-ci a le sofa name de "_InitialView".

Problème d'interopérabilité pour interconnecter des composants développés indépendamment
Le développeur d'AE est libre de choisir le nom qu'il souhaite pour désigner ses vues d'entrée et ses vues de sortie.
Cela conduit naturellement à quelques petits soucis lorsque l'on veut interconnecter des composants ayant des noms de vue différents.

Le mécanisme de mise en correspondance des vues au niveau d'un Aggregate
La section 6.4 de la documentation explique et présente différentes situations de mises en correspondance : au sein d'un Aggregate, d'un CPE, d'une application UIMA, pour des services distants. Je rapporte et illustre la solution au sein d'un AE Aggregate.

Pour cela, j'utilise deux composants : l'XmlDetagger présent dans les exemples fournis avec Apache UIMA [4] et le Whitespace Tokenizer des addons de la Sandbox d'Apache UIMA [5].

L'XmlDetagger est un composant multiple vues qui retire les balises d'un document XML. Il lit l'XML d'une vue input nommée "xmlDocument". Le contenu textuel est écrit dans une nouvelle vue output appelée "plainTextDocument".
Le Whitespace Tokenizer est un composant simple vue qui travaille sur la vue par défaut (i.e.  "_InitialView") et qui ajoute à celle-ci des annotations de phrases et de tokens.

Rapidement, je mets en place un projet Java sous Eclipse. J'y ajoute la UIMA Nature, déclare les répertoires desc et resources dans le build path ainsi que les bibliothèques de UIMA [6]. Je rajoute au  le build path les bibliothèques uima-examples [10] et addon whitespace tokenizer [9] qui vont servir pour notre chaîne.

Je crée un descripteur d'AE Aggregate [7] et j'y ajoute by name en pipeline : d'abord l'XmlDetagger  puis le Whitespace Tokenizer (je déclare les bons types à produire en output dans les capabilities).

A la sauvegarde le message suivant s'affiche
Error in AE Descriptor
The Descriptor is invalid for the following reason:
ResourceInitializationException: The output Sofa "plainTextDocument" in component "XmlDetagger" is not mapped to any output Sofa in its containing aggregate, "demoSofaNameMappingAAE". (Descriptor path ...) 

Ce n'est pas réellement une erreur si l'on sait ce que l'on fait. Une vue qui n'est pas utilisée par exemple n'a pas besoin d'être mise en correspondance dans l'Aggregate.
En l'état si on exécute cet AE avec le DocumentAnalyzer [8] sur un document XML quelconque, on obtiendra l'erreur suivante :
org.apache.uima.analysis_engine.AnalysisEngineProcessException: Annotator processing failed. Caused by: org.apache.uima.cas.CASRuntimeException: No sofaFS with name xmlDocument found. 
Vraissemblablement ici il y a des vues qui requièrent d'être mise en correspondance et cela va se faire au niveau de l'Aggregate.

La première chose à faire est d'indiquer que la vue sur laquelle travaille en entrée XmlDetagger, à savoir xmlDocument, correspond à _InitialView dans l'Aggregate. Autrement dit, la vue d'entrée par défaut de l'Aggregate,  _InitialView, doit être mise en correspondance avec la vue d'entrée, xmlDocument, de l'XmlDetagger.
Au sein du descripteur de l'Aggregate, c'est dans la section capabilities que l'on déclare les vues sur lesquelles on travaille (sous section component capabilities) et celles entre lesquelles on réalise des mises en correspondance (sous section sofaMappings).
On ajoute d'abord la vue xmlDocument comme input (entrée) en faisant un add sofa dans la component capabilities.
Ensuite on indique dans la sous section sofaMappings que pour le composant (componentKeyXmlDetagger sa vue (componentSofaNamexmlDocument correspond à la vue dans l'aggregate (aggregateSofaName_InitialView.
Par les éléments componentKey et componentSofaName on désigne le composant et la vue souhaitée chez celui-ci comme devant intervenir dans un mapping. L'élément aggregateSofaName est la clé partagée entre les éléments sofaMapping.
Cette dernière opération doit se faire pour partie à la main en éditant le source (personnellement je n'y arrive pas via l'éditeur du formulaire). Cela donne
<capability>
...
  <inputSofas>
    <sofaName>xmlDocument</sofaName>
  </inputSofas>
  ...
et
  <sofaMappings>
    <sofaMapping>
      <componentKey>XmlDetagger</componentKey>
      <componentSofaName>xmlDocument</componentSofaName>
      <aggregateSofaName>_InitialView</aggregateSofaName>
    </sofaMapping>
  </sofaMappings>
Si on réexécute l'AE on se rend compte que ce n'est pas encore l'idéal car le Whitespace Tokenizer travaille sur l'_InitialView par défaut et traite donc ce qui correspond à l'xmlDocument au lieu du plainTextDocument.
On rajoute dans l'élément inputSofas
<sofaName>_InitialView</sofaName>
et l'élément suivant
  <sofaMapping>
      <componentKey>WhitespaceTokenizer</componentKey>
      <componentSofaName>_InitialView</componentSofaName>
      <aggregateSofaName>plainTextDocument</aggregateSofaName>
    </sofaMapping>
La vue plainTextDocument du XmlDetagger n'a pas été redéfinie dans l'Aggregate, il n'y a pas d'ambiguité. Ce que produit le XmlDetagger au sein de sa vue output plainTextDocument est accessible sous ce même nom au sein de l'Aggregate qui le met en correspondance avec la vue input du
WhitespaceTokenizer.   
L'exécution fonctionne comme attendu finalement.  

Quelques commentaires supplémentaires

Au niveau de l'Aggregate après mise en correspondance, le nom de la vue du componentSofaName
sera renommé en le nom de la vue déclarée dans aggregateSofaName.
Les vues avec leur nom précédent ne seront plus accessibles. Une fois sérialisée en XMI, on constatera sela en cherchant la valeur de l'attribut sofaID.
Les composants d'Apache OpenNLP sont des composants multiples vues et requièrent en général l'usage de mises en correspondance.


Liens

[1] 5. Annotations, Artifacts & Sofas
[2] 6. Multiple CAS Views
[3] 6.4. Sofa Name Mapping
[4] UIMA_HOME/examples/descriptors/analysis_engine/XmlDetagger.xml
[5] http://uima.apache.org/sandbox.html#whitespace.tokenizer
[6] Créer un projet Eclipse pour le développement d'un composant UIMA
[7] Construire une chaîne de traitement UIMA à partir de composants existants
[8] Exécuter un traitement ou une chaîne de traitement sous UIMA (avec UIMAJ et en local)
[9] UIMA_HOME/addons/annotator/WhitespaceTokenizer/lib/uima-an-wst.jar
[10] UIMA_HOME/lib/uima-examples.jar

Aucun commentaire:

Enregistrer un commentaire