Skip to content

Commit

Permalink
#2696 - Document-level recommendations
Browse files Browse the repository at this point in the history
- Fix suggestion registry class name
- Wrote a very few words of documentation
- Bit of cleaning
  • Loading branch information
reckart committed Dec 26, 2023
1 parent 5ec948d commit abe46f2
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,15 @@ public <T extends AnnotationSuggestion> void calculateSuggestionVisibility(Strin
{
LOG.trace("calculateSuggestionVisibility() for layer {} on document {}", aLayer, aDocument);

var type = aCas.getTypeSystem().getType(aLayer.getName());
if (type == null) {
var predictedType = aCas.getTypeSystem().getType(aLayer.getName());
if (predictedType == null) {
// The type does not exist in the type system of the CAS. Probably it has not
// been upgraded to the latest version of the type system yet. If this is the case,
// we'll just skip.
return;
}

var annotations = aCas.<AnnotationBase> select(type).asList();
var annotations = aCas.<AnnotationBase> select(predictedType).asList();

var suggestionsForLayer = aRecommendations.stream()
// Only suggestions for the given layer
Expand All @@ -194,7 +194,7 @@ public <T extends AnnotationSuggestion> void calculateSuggestionVisibility(Strin
var adapter = schemaService.getAdapter(aLayer);
var traits = adapter.getTraits(DocumentMetadataLayerTraits.class).get();
for (var feature : schemaService.listSupportedFeatures(aLayer)) {
var feat = type.getFeatureByBaseName(feature.getName());
var feat = predictedType.getFeatureByBaseName(feature.getName());

if (feat == null) {
// The feature does not exist in the type system of the CAS. Probably it has not
Expand Down Expand Up @@ -267,14 +267,16 @@ static void hideSuggestionsRejectedOrSkipped(MetadataSuggestion aSuggestion,
}

@Override
public LearningRecord toLearningRecord(SourceDocument aDocument, String aUsername,
public LearningRecord toLearningRecord(SourceDocument aDocument, String aDataOwner,
AnnotationSuggestion aSuggestion, AnnotationFeature aFeature,
LearningRecordUserAction aUserAction, LearningRecordChangeLocation aLocation)
{
var record = new LearningRecord();
record.setUser(aUsername);
record.setUser(aDataOwner);
record.setSourceDocument(aDocument);
record.setUserAction(aUserAction);
record.setOffsetBegin(-1);
record.setOffsetEnd(-1);
record.setOffsetBegin2(-1);
record.setOffsetEnd2(-1);
record.setAnnotation(aSuggestion.getLabel());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,70 @@
public interface SuggestionSupport
extends Extension<Recommender>
{
/**
* @param aCtx
* the extraction context containing all important information.
* @return the suggestions extracted from the prediction CAS provided in the context.
*/
List<AnnotationSuggestion> extractSuggestions(ExtractionContext aCtx);

/**
* @return the renderer used to render suggestions provided by this suggestion support.
*/
Optional<SuggestionRenderer> getRenderer();

/**
* Calculate the visibility for the given suggestions. The suggestions must have been produced
* by this suggestion support. Also, they must all be from the same layer - be sure to process
* one layer at a time. The suggestions may come from different recommenders though.
*/
<T extends AnnotationSuggestion> void calculateSuggestionVisibility(String aSessionOwner,
SourceDocument aDocument, CAS aCas, String aDataOwner, AnnotationLayer aLayer,
Collection<SuggestionGroup<T>> aRecommendations, int aWindowBegin, int aWindowEnd);

/**
* Accept the given suggestion.
*
* @param aSuggestion
* the suggestion to accept.
* @return the annotation created from the suggestion.
* @throws AnnotationException
* if there was a problem creating the annotation.
*/
AnnotationBaseFS acceptSuggestion(String aSessionOwner, SourceDocument aDocument,
String aDataOwner, CAS aCas, TypeAdapter aAdapter, AnnotationFeature aFeature,
AnnotationSuggestion aSuggestion, LearningRecordChangeLocation aLocation,
LearningRecordUserAction aAction)
throws AnnotationException;

/**
* Reject the given suggestion.
*
* @param aSuggestion
* the suggestion to reject.
* @throws AnnotationException
* if there was a problem rejecting the annotation.
*/
void rejectSuggestion(String aSessionOwner, SourceDocument aDocument, String aDataOwner,
AnnotationSuggestion suggestion, LearningRecordChangeLocation aAction)
AnnotationSuggestion aSuggestion, LearningRecordChangeLocation aAction)
throws AnnotationException;

/**
* Skip the given suggestion.
*
* @param aSuggestion
* the suggestion to skip.
* @throws AnnotationException
* if there was a problem skipping the annotation.
*/
void skipSuggestion(String aSessionOwner, SourceDocument aDocument, String aDataOwner,
AnnotationSuggestion suggestion, LearningRecordChangeLocation aAction)
AnnotationSuggestion aSuggestion, LearningRecordChangeLocation aAction)
throws AnnotationException;

<T extends AnnotationSuggestion> void calculateSuggestionVisibility(String aSessionOwner,
SourceDocument aDocument, CAS aCas, String aDataOwner, AnnotationLayer aLayer,
Collection<SuggestionGroup<T>> aRecommendations, int aWindowBegin, int aWindowEnd);

LearningRecord toLearningRecord(SourceDocument aDocument, String aUsername,
/**
* Create a learning record from the given suggestion.
*/
LearningRecord toLearningRecord(SourceDocument aDocument, String aDataOwner,
AnnotationSuggestion aSuggestion, AnnotationFeature aFeature,
LearningRecordUserAction aUserAction, LearningRecordChangeLocation aLocation);

Optional<SuggestionRenderer> getRenderer();

List<AnnotationSuggestion> extractSuggestions(ExtractionContext aCtx);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
import de.tudarmstadt.ukp.inception.recommendation.project.RecommenderProjectSettingsPanelFactory;
import de.tudarmstadt.ukp.inception.recommendation.relation.RelationSuggestionSupport;
import de.tudarmstadt.ukp.inception.recommendation.render.RecommendationRenderer;
import de.tudarmstadt.ukp.inception.recommendation.service.LayerRecommendtionSupportRegistryImpl;
import de.tudarmstadt.ukp.inception.recommendation.service.SuggestionSupportRegistryImpl;
import de.tudarmstadt.ukp.inception.recommendation.service.RecommendationServiceImpl;
import de.tudarmstadt.ukp.inception.recommendation.service.RecommenderFactoryRegistryImpl;
import de.tudarmstadt.ukp.inception.recommendation.sidebar.RecommendationSidebarFactory;
Expand Down Expand Up @@ -232,6 +232,6 @@ public RelationSuggestionSupport relationRecommendationSupport(
public SuggestionSupportRegistry layerRecommendtionSupportRegistry(
@Lazy @Autowired(required = false) List<SuggestionSupport> aExtensions)
{
return new LayerRecommendtionSupportRegistryImpl(aExtensions);
return new SuggestionSupportRegistryImpl(aExtensions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ public List<AnnotationSuggestion> extractSuggestions(ExtractionContext ctx)
.withId(RelationSuggestion.NEW_ID) //
.withGeneration(ctx.getGeneration()) //
.withRecommender(ctx.getRecommender()) //
.withDocumentName(ctx.getDocument().getName()) //
.withDocument(ctx.getDocument()) //
.withPosition(position) //
.withLabel(label) //
.withUiLabel(label) //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1831,7 +1831,7 @@ static ReconciliationResult reconcile(Predictions aActivePredictions, SourceDocu
s.getScore() == newSuggestion.getScore() && //
Objects.equals(s.getScoreExplanation(),
newSuggestion.getScoreExplanation()))
.collect(toList());
.toList();

if (existingSuggestions.isEmpty()) {
addedSuggestions.add(newSuggestion);
Expand Down Expand Up @@ -1864,8 +1864,10 @@ public <T extends AnnotationSuggestion> void calculateSuggestionVisibility(Strin
SourceDocument aDocument, CAS aCas, String aDataOwner, AnnotationLayer aLayer,
Collection<SuggestionGroup<T>> aRecommendations, int aWindowBegin, int aWindowEnd)
{
var maybeSuggestion = aRecommendations.stream().filter(group -> !group.isEmpty())
.flatMap(group -> group.stream()).findAny();
var maybeSuggestion = aRecommendations.stream() //
.filter(group -> !group.isEmpty()) //
.flatMap(group -> group.stream()) //
.findAny();

if (maybeSuggestion.isEmpty()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
import de.tudarmstadt.ukp.inception.recommendation.api.model.Recommender;
import de.tudarmstadt.ukp.inception.support.extensionpoint.ExtensionPoint_ImplBase;

public class LayerRecommendtionSupportRegistryImpl
public class SuggestionSupportRegistryImpl
extends ExtensionPoint_ImplBase<Recommender, SuggestionSupport>
implements SuggestionSupportRegistry
{
@Autowired
public LayerRecommendtionSupportRegistryImpl(
public SuggestionSupportRegistryImpl(
@Lazy @Autowired(required = false) List<SuggestionSupport> aExtensions)
{
super(aExtensions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,13 +441,13 @@ static void hideSuggestionsRejectedOrSkipped(SpanSuggestion aSuggestion,
}

@Override
public LearningRecord toLearningRecord(SourceDocument aDocument, String aUsername,
public LearningRecord toLearningRecord(SourceDocument aDocument, String aDataOwner,
AnnotationSuggestion aSuggestion, AnnotationFeature aFeature,
LearningRecordUserAction aUserAction, LearningRecordChangeLocation aLocation)
{
var pos = ((SpanSuggestion) aSuggestion).getPosition();
var record = new LearningRecord();
record.setUser(aUsername);
record.setUser(aDataOwner);
record.setSourceDocument(aDocument);
record.setUserAction(aUserAction);
record.setOffsetBegin(pos.getBegin());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// limitations under the License.

[[sect_recommendation]]
= Recommendation
= Recommenders system

For information on the different recommenders, please refer to <<user-guide.adoc#sect_projects_recommendation,user guide>>.

Expand All @@ -31,3 +31,26 @@ For information on the different recommenders, please refer to <<user-guide.adoc
//
// DocumentService -- LearningRecordService : AfterDocuemntResetEvent
// ....

== Recommenders

Recommenders provide the ability to generate annotation suggestions. Optionally, they can be trained based on existing annotations. Also optionally, they can be evaluated.

* The `RecommendationEngineFactory` interface provides the API for implementing recommender types.
* The `RecommendationEngine` interface provides the API for the actual recommenders produced by the factory.
* The `RecommenderFactoryRegistry` interface and its default implementation `RecommenderFactoryRegistryImpl` serve as an access point to the different recommender types.

== Suggestion supports

Suggestion supports provide everything necessary to handle annotation suggestions. This includes:

* extracting suggestions from the predicted annotations that the recommenders
* rendering these suggestions
* handling actions like accepting/correting, rejecting, or skipping suggestions

The subsystem is made up of the following main APIs:

* The `SuggestionSupport` interface provides the API for handling different kinds of suggestions.
* The `SuggestionSupportRegistry` interface and its default implementation `SuggestionSupportRegistryImpl` serve as an access point to the different recommender types.
* The `SuggestionRenderer` interface provides the API for rendering suggestions into a `VDoc`.

Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public class RecommendationServiceImplIntegrationTest
private RecommendationServiceImpl sut;

private FeatureSupportRegistryImpl featureSupportRegistry;
private LayerRecommendtionSupportRegistryImpl layerRecommendtionSupportRegistry;
private SuggestionSupportRegistryImpl layerRecommendtionSupportRegistry;
private Project project;
private AnnotationLayer spanLayer;
private Recommender spanLayerRecommender;
Expand All @@ -115,7 +115,7 @@ public class RecommendationServiceImplIntegrationTest
@BeforeEach
public void setUp() throws Exception
{
layerRecommendtionSupportRegistry = new LayerRecommendtionSupportRegistryImpl(asList( //
layerRecommendtionSupportRegistry = new SuggestionSupportRegistryImpl(asList( //
new SpanSuggestionSupport(sut, sut, null, schemaService, null, null),
new RelationSuggestionSupport(sut, sut, null, schemaService, null)));
layerRecommendtionSupportRegistry.init();
Expand Down

0 comments on commit abe46f2

Please sign in to comment.