diff --git a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java index 699d52b569d..6033a4254bc 100644 --- a/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java +++ b/inception/inception-active-learning/src/main/java/de/tudarmstadt/ukp/inception/active/learning/sidebar/ActiveLearningSidebar.java @@ -43,8 +43,6 @@ import java.util.Optional; import org.apache.uima.cas.CAS; -import org.apache.uima.cas.Feature; -import org.apache.uima.cas.Type; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.fit.util.CasUtil; import org.apache.wicket.Component; @@ -993,10 +991,11 @@ private void actionSelectHistoryItem(AjaxRequestTarget aTarget, LearningRecord a private Optional getMatchingAnnotation(CAS aCas, LearningRecord aRecord) { - Type type = CasUtil.getType(aCas, alStateModel.getObject().getLayer().getName()); - Feature feature = type.getFeatureByBaseName(aRecord.getAnnotationFeature().getName()); + var type = CasUtil.getType(aCas, alStateModel.getObject().getLayer().getName()); + var feature = type.getFeatureByBaseName(aRecord.getAnnotationFeature().getName()); return selectAt(aCas, type, aRecord.getOffsetBegin(), aRecord.getOffsetEnd()).stream() - .filter(fs -> aRecord.getAnnotation().equals(fs.getFeatureValueAsString(feature))) + .filter(fs -> Objects.equals(aRecord.getAnnotation(), + fs.getFeatureValueAsString(feature))) .findFirst(); } diff --git a/inception/inception-imls-stringmatch/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/stringmatch/relation/StringMatchingRelationRecommender.java b/inception/inception-imls-stringmatch/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/stringmatch/relation/StringMatchingRelationRecommender.java index 61420a4f07b..5aaf6a4571c 100644 --- a/inception/inception-imls-stringmatch/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/stringmatch/relation/StringMatchingRelationRecommender.java +++ b/inception/inception-imls-stringmatch/src/main/java/de/tudarmstadt/ukp/inception/recommendation/imls/stringmatch/relation/StringMatchingRelationRecommender.java @@ -30,7 +30,6 @@ import static org.apache.uima.fit.util.CasUtil.selectCovered; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Objects; @@ -84,7 +83,7 @@ public void train(RecommenderContext aContext, List aCasses) throws Recomme private MultiValuedMap, String> trainModel(List aData) { - MultiValuedMap, String> model = new ArrayListValuedHashMap<>(); + var model = new ArrayListValuedHashMap, String>(); for (var t : aData) { var key = Pair.of(t.governor, t.dependent); @@ -98,7 +97,7 @@ private MultiValuedMap, String> trainModel(List aDa public Range predict(PredictionContext aContext, CAS aCas, int aBegin, int aEnd) throws RecommendationException { - MultiValuedMap, String> model = aContext.get(KEY_MODEL).orElseThrow( + var model = aContext.get(KEY_MODEL).orElseThrow( () -> new RecommendationException("Key [" + KEY_MODEL + "] not found in context")); var sampleUnitType = getType(aCas, SAMPLE_UNIT); @@ -116,8 +115,13 @@ public Range predict(PredictionContext aContext, CAS aCas, int aBegin, int aEnd) // whole document for potential relations, we only need to look at those units that overlap // with the current prediction request area var units = selectOverlapping(aCas, sampleUnitType, aBegin, aEnd); + + if (model.isEmpty()) { + return Range.rangeCoveringAnnotations(units); + } + for (var sampleUnit : units) { - Collection baseAnnotations = selectCovered(attachType, sampleUnit); + var baseAnnotations = selectCovered(attachType, sampleUnit); for (var governor : baseAnnotations) { for (var dependent : baseAnnotations) { @@ -151,7 +155,7 @@ public Range predict(PredictionContext aContext, CAS aCas, int aBegin, int aEnd) } } - return new Range(units); + return Range.rangeCoveringAnnotations(units); } @Override @@ -218,22 +222,22 @@ public EvaluationResult evaluate(List aCasses, DataSplitter aDataSplitter) private List getTrainingData(List aCasses) { - List data = new ArrayList<>(); + var data = new ArrayList(); - for (CAS cas : aCasses) { - Type predictedType = getPredictedType(cas); - Feature governorFeature = predictedType.getFeatureByBaseName(FEAT_REL_SOURCE); - Feature dependentFeature = predictedType.getFeatureByBaseName(FEAT_REL_TARGET); - Feature predictedFeature = getPredictedFeature(cas); - Feature attachFeature = getAttachFeature(cas); + for (var cas : aCasses) { + var predictedType = getPredictedType(cas); + var governorFeature = predictedType.getFeatureByBaseName(FEAT_REL_SOURCE); + var dependentFeature = predictedType.getFeatureByBaseName(FEAT_REL_TARGET); + var predictedFeature = getPredictedFeature(cas); + var attachFeature = getAttachFeature(cas); - for (AnnotationFS relation : select(cas, predictedType)) { - AnnotationFS governor = (AnnotationFS) relation.getFeatureValue(governorFeature); - AnnotationFS dependent = (AnnotationFS) relation.getFeatureValue(dependentFeature); + for (var relation : select(cas, predictedType)) { + var governor = (AnnotationFS) relation.getFeatureValue(governorFeature); + var dependent = (AnnotationFS) relation.getFeatureValue(dependentFeature); - String relationLabel = relation.getStringValue(predictedFeature); - String governorLabel = governor.getStringValue(attachFeature); - String dependentLabel = dependent.getStringValue(attachFeature); + var relationLabel = relation.getStringValue(predictedFeature); + var governorLabel = governor.getStringValue(attachFeature); + var dependentLabel = dependent.getStringValue(attachFeature); if (isBlank(governorLabel) || isBlank(dependentLabel) || isBlank(relationLabel)) { continue; @@ -268,7 +272,7 @@ private Type getAttachType(CAS aCas) private Feature getAttachFeature(CAS aCas) { - Type attachType = getAttachType(aCas); + var attachType = getAttachType(aCas); return attachType.getFeatureByBaseName(traits.getAdjunctFeature()); } diff --git a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/SuggestionSupport_ImplBase.java b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/SuggestionSupport_ImplBase.java index b7c15fe3183..455e75f9f34 100644 --- a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/SuggestionSupport_ImplBase.java +++ b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/SuggestionSupport_ImplBase.java @@ -41,7 +41,6 @@ import de.tudarmstadt.ukp.inception.recommendation.api.model.AutoAcceptMode; import de.tudarmstadt.ukp.inception.recommendation.api.model.LearningRecordChangeLocation; import de.tudarmstadt.ukp.inception.recommendation.api.model.LearningRecordUserAction; -import de.tudarmstadt.ukp.inception.recommendation.api.model.SpanSuggestion; import de.tudarmstadt.ukp.inception.schema.api.AnnotationSchemaService; import de.tudarmstadt.ukp.inception.schema.api.adapter.AnnotationException; import de.tudarmstadt.ukp.inception.schema.api.adapter.TypeAdapter; @@ -146,7 +145,7 @@ public void rejectSuggestion(String aSessionOwner, SourceDocument aDocument, Str AnnotationSuggestion aSuggestion, LearningRecordChangeLocation aLocation) throws AnnotationException { - var suggestion = (SpanSuggestion) aSuggestion; + var suggestion = aSuggestion; // Hide the suggestion. This is faster than having to recalculate the visibility status // for the entire document or even for the part visible on screen. @@ -160,9 +159,8 @@ var record = toLearningRecord(aDocument, aDataOwner, aSuggestion, feature, REJEC learningRecordService.logRecord(aSessionOwner, record); // Send an application event that the suggestion has been rejected - applicationEventPublisher.publishEvent(new RecommendationRejectedEvent(this, aDocument, - aDataOwner, suggestion.getBegin(), suggestion.getEnd(), suggestion.getCoveredText(), - feature, suggestion.getLabel())); + applicationEventPublisher.publishEvent( + new RecommendationRejectedEvent(this, aDocument, aDataOwner, feature, suggestion)); } @Override diff --git a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/event/RecommendationRejectedEvent.java b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/event/RecommendationRejectedEvent.java index c60f9aa223a..ae2a2c688b7 100644 --- a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/event/RecommendationRejectedEvent.java +++ b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/event/RecommendationRejectedEvent.java @@ -21,6 +21,7 @@ import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationFeature; import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument; +import de.tudarmstadt.ukp.inception.recommendation.api.model.AnnotationSuggestion; public class RecommendationRejectedEvent extends ApplicationEvent @@ -30,31 +31,18 @@ public class RecommendationRejectedEvent private final SourceDocument document; private final String user; - private final int begin; - private final int end; - private final String text; + private final AnnotationSuggestion suggestion; private final AnnotationFeature feature; - private final Object recommendedValue; public RecommendationRejectedEvent(Object aSource, SourceDocument aDocument, String aUser, - AnnotationFeature aFeature, Object aRecommendedValue) - { - this(aSource, aDocument, aUser, -1, -1, null, aFeature, aRecommendedValue); - } - - public RecommendationRejectedEvent(Object aSource, SourceDocument aDocument, String aUser, - int aBegin, int aEnd, String aText, AnnotationFeature aFeature, - Object aRecommendedValue) + AnnotationFeature aFeature, AnnotationSuggestion aSuggestion) { super(aSource); document = aDocument; user = aUser; - begin = aBegin; - end = aEnd; - text = aText; feature = aFeature; - recommendedValue = aRecommendedValue; + suggestion = aSuggestion; } @Override @@ -69,19 +57,9 @@ public String getUser() return user; } - public int getBegin() - { - return begin; - } - - public int getEnd() + public AnnotationSuggestion getSuggestion() { - return end; - } - - public String getText() - { - return text; + return suggestion; } public AnnotationFeature getFeature() @@ -89,11 +67,6 @@ public AnnotationFeature getFeature() return feature; } - public Object getRecommendedValue() - { - return recommendedValue; - } - @Override public String toString() { @@ -106,16 +79,10 @@ public String toString() builder.append(user); builder.append(", "); } - builder.append("begin="); - builder.append(begin); - builder.append("end="); - builder.append(end); - builder.append("text="); - builder.append(text); builder.append(", feature="); builder.append(feature.getName()); - builder.append(", recommendedValue="); - builder.append(recommendedValue); + builder.append(", suggestion="); + builder.append(suggestion); builder.append("]"); return builder.toString(); } diff --git a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/ArcPosition_ImplBase.java b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/ArcPosition_ImplBase.java index 44f6e0583aa..336f221c5c4 100644 --- a/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/ArcPosition_ImplBase.java +++ b/inception/inception-recommendation-api/src/main/java/de/tudarmstadt/ukp/inception/recommendation/api/model/ArcPosition_ImplBase.java @@ -114,5 +114,4 @@ public int compareTo(T o) .append(getTargetBegin(), o.getTargetBegin()) // .append(getTargetEnd(), o.getTargetEnd()).toComparison(); } - } diff --git a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/log/RecommendationRejectedEventAdapter.java b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/log/RecommendationRejectedEventAdapter.java index 0f252083e32..6066bed399e 100644 --- a/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/log/RecommendationRejectedEventAdapter.java +++ b/inception/inception-recommendation/src/main/java/de/tudarmstadt/ukp/inception/recommendation/log/RecommendationRejectedEventAdapter.java @@ -23,6 +23,9 @@ import de.tudarmstadt.ukp.inception.log.model.AnnotationDetails; import de.tudarmstadt.ukp.inception.log.model.FeatureChangeDetails; import de.tudarmstadt.ukp.inception.recommendation.api.event.RecommendationRejectedEvent; +import de.tudarmstadt.ukp.inception.recommendation.api.model.LinkSuggestion; +import de.tudarmstadt.ukp.inception.recommendation.api.model.RelationSuggestion; +import de.tudarmstadt.ukp.inception.recommendation.api.model.SpanSuggestion; import de.tudarmstadt.ukp.inception.recommendation.config.RecommenderServiceAutoConfiguration; import de.tudarmstadt.ukp.inception.support.json.JSONUtil; @@ -62,15 +65,28 @@ public String getAnnotator(RecommendationRejectedEvent aEvent) @Override public String getDetails(RecommendationRejectedEvent aEvent) throws IOException { - AnnotationDetails annotation = new AnnotationDetails(); - annotation.setBegin(aEvent.getBegin()); - annotation.setEnd(aEvent.getEnd()); - annotation.setText(aEvent.getText()); + var suggestion = aEvent.getSuggestion(); + + var annotation = new AnnotationDetails(); annotation.setType(aEvent.getFeature().getLayer().getName()); - FeatureChangeDetails details = new FeatureChangeDetails(); + if (suggestion instanceof SpanSuggestion spanSuggestion) { + annotation.setBegin(spanSuggestion.getBegin()); + annotation.setEnd(spanSuggestion.getEnd()); + annotation.setText(spanSuggestion.getCoveredText()); + } + else if (suggestion instanceof RelationSuggestion relationSuggestion) { + annotation.setBegin(relationSuggestion.getPosition().getTargetBegin()); + annotation.setEnd(relationSuggestion.getPosition().getTargetEnd()); + } + else if (suggestion instanceof LinkSuggestion linkSuggestion) { + annotation.setBegin(linkSuggestion.getPosition().getTargetBegin()); + annotation.setEnd(linkSuggestion.getPosition().getTargetEnd()); + } + + var details = new FeatureChangeDetails(); details.setAnnotation(annotation); - details.setValue(aEvent.getRecommendedValue()); + details.setValue(suggestion.getLabel()); return JSONUtil.toJsonString(details); }