Skip to content

Commit

Permalink
#3944 - Ability to use recommenders as curator
Browse files Browse the repository at this point in the history
- Towards separating the context owner from the data owner
  • Loading branch information
reckart committed Apr 15, 2023
1 parent 6b4ddc2 commit 5723a03
Show file tree
Hide file tree
Showing 28 changed files with 563 additions and 405 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ private void actionStartSession(AjaxRequestTarget aTarget, Form<?> form)

recommendationService.setPredictForAllDocuments(userName, project, true);
recommendationService.triggerPrediction(userName, "ActionStartActiveLearningSession",
state.getDocument());
state.getDocument(), state.getUser().getUsername());

// Start new session
alState.setSessionActive(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

import de.tudarmstadt.ukp.clarin.webanno.api.CasProvider;
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.clarin.webanno.support.wicket.AjaxComponentRespondListener;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
Expand All @@ -66,6 +67,7 @@ public abstract class AnnotationEditorBase
private @SpringBean AnnotationEditorExtensionRegistry extensionRegistry;
private @SpringBean AnnotationSchemaService annotationService;
private @SpringBean ColoringService coloringService;
private @SpringBean UserDao userService;
private @SpringBean RenderingPipeline renderingPipeline;

private final AnnotationActionHandler actionHandler;
Expand Down Expand Up @@ -194,6 +196,7 @@ protected <T> T render(CAS aCas, int aWindowBeginOffset, int aWindowEndOffset,
.withState(getModelObject()) //
.withWindow(aWindowBeginOffset, aWindowEndOffset) //
.withCas(aCas) //
.withSessionOwner(userService.getCurrentUser()) //
.withVisibleLayers(getLayersToRender(getModelObject())) //
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class RenderRequest
private final AnnotatorState state;
private final SourceDocument sourceDocument;
private final User annotationUser;
private final User sessionOwner;
private final int windowBeginOffset;
private final int windowEndOffset;
private final boolean includeText;
Expand All @@ -56,6 +57,7 @@ private RenderRequest(Builder builder)
this.allLayers = builder.allLayers;
this.visibleLayers = builder.visibleLayers;
this.coloringStrategyOverride = builder.coloringStrategyOverride;
this.sessionOwner = builder.sessionOwner;
}

public Optional<ColoringStrategy> getColoringStrategyOverride()
Expand Down Expand Up @@ -125,6 +127,11 @@ public AnnotatorState getState()
return state;
}

public User getSessionOwner()
{
return sessionOwner;
}

public static Builder builder()
{
return new Builder();
Expand All @@ -139,6 +146,7 @@ public static final class Builder
private AnnotatorState state;
private SourceDocument sourceDocument;
private User annotationUser;
private User sessionOwner;
private CAS cas;
private List<AnnotationLayer> allLayers;
private List<AnnotationLayer> visibleLayers;
Expand All @@ -155,6 +163,12 @@ public Builder withCas(CAS aCas)
return this;
}

public Builder withSessionOwner(User aSessionOwner)
{
sessionOwner = aSessionOwner;
return this;
}

/**
* @deprecated See {@link RenderRequest#getState}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ List<AnnotationDocument> createOrGetAnnotationDocuments(Collection<SourceDocumen
* the user for whom documents should be returned.
* @return documents.
*/
Map<SourceDocument, AnnotationDocument> listAllDocuments(Project aProject, User aUser);
Map<SourceDocument, AnnotationDocument> listAllDocuments(Project aProject, String aUser);

AnnotationDocumentState setAnnotationDocumentState(AnnotationDocument aDocument,
AnnotationDocumentState aState, AnnotationDocumentStateChangeFlag... aFlags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.wicket.request.Request;
import org.springframework.core.annotation.Order;

import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.inception.diam.editor.config.DiamAutoConfig;
import de.tudarmstadt.ukp.inception.diam.model.ajax.AjaxResponse;
import de.tudarmstadt.ukp.inception.diam.model.ajax.DefaultAjaxResponse;
Expand Down Expand Up @@ -55,12 +56,15 @@ public class LoadAnnotationsHandler

private final RenderingPipeline renderingPipeline;
private final VDocumentSerializerExtensionPoint vDocumentSerializerExtensionPoint;
private final UserDao userService;

public LoadAnnotationsHandler(RenderingPipeline aRenderingPipeline,
VDocumentSerializerExtensionPoint aVDocumentSerializerExtensionPoint)
VDocumentSerializerExtensionPoint aVDocumentSerializerExtensionPoint,
UserDao aUserService)
{
renderingPipeline = aRenderingPipeline;
vDocumentSerializerExtensionPoint = aVDocumentSerializerExtensionPoint;
userService = aUserService;
}

@Override
Expand Down Expand Up @@ -100,6 +104,7 @@ private RenderRequest prepareRenderRequest(Request aRequest) throws IOException

RenderRequest request = RenderRequest.builder() //
.withState(state) //
.withSessionOwner(userService.getCurrentUser()) //
.withCas(page.getEditorCas()) //
.withWindow(begin, end) //
.withText(includeText) //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.inception.diam.editor.actions.CreateRelationAnnotationHandler;
import de.tudarmstadt.ukp.inception.diam.editor.actions.CreateSpanAnnotationHandler;
import de.tudarmstadt.ukp.inception.diam.editor.actions.DeleteAnnotationHandler;
Expand Down Expand Up @@ -145,9 +146,11 @@ public LazyDetailsLookupService lazyDetailsLookupService(

@Bean
public LoadAnnotationsHandler loadAnnotationsHandler(RenderingPipeline aRenderingPipeline,
VDocumentSerializerExtensionPoint aVDocumentSerializerExtensionPoint)
VDocumentSerializerExtensionPoint aVDocumentSerializerExtensionPoint,
UserDao aUserService)
{
return new LoadAnnotationsHandler(aRenderingPipeline, aVDocumentSerializerExtensionPoint);
return new LoadAnnotationsHandler(aRenderingPipeline, aVDocumentSerializerExtensionPoint,
aUserService);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@
import java.io.IOException;
import java.security.Principal;
import java.time.Duration;
import java.util.List;

import javax.persistence.NoResultException;

import org.apache.uima.cas.CAS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
Expand Down Expand Up @@ -68,7 +66,6 @@
import de.tudarmstadt.ukp.clarin.webanno.model.AnnotationLayer;
import de.tudarmstadt.ukp.clarin.webanno.model.Mode;
import de.tudarmstadt.ukp.clarin.webanno.model.Project;
import de.tudarmstadt.ukp.clarin.webanno.model.SourceDocument;
import de.tudarmstadt.ukp.clarin.webanno.security.UserDao;
import de.tudarmstadt.ukp.clarin.webanno.security.model.User;
import de.tudarmstadt.ukp.clarin.webanno.support.JSONUtil;
Expand All @@ -77,10 +74,8 @@
import de.tudarmstadt.ukp.inception.diam.messages.MViewportUpdate;
import de.tudarmstadt.ukp.inception.diam.model.websocket.ViewportDefinition;
import de.tudarmstadt.ukp.inception.diam.model.websocket.ViewportState;
import de.tudarmstadt.ukp.inception.rendering.editorstate.AnnotationPreference;
import de.tudarmstadt.ukp.inception.rendering.pipeline.RenderingPipeline;
import de.tudarmstadt.ukp.inception.rendering.request.RenderRequest;
import de.tudarmstadt.ukp.inception.rendering.vmodel.VDocument;
import de.tudarmstadt.ukp.inception.rendering.vmodel.serialization.VDocumentSerializerExtensionPoint;
import de.tudarmstadt.ukp.inception.schema.AnnotationSchemaService;

Expand Down Expand Up @@ -280,27 +275,28 @@ private JsonNode render(Project aProject, long aDocumentId, String aUser, int aV
int aViewportEnd, String aFormat)
throws IOException
{
SourceDocument doc = documentService.getSourceDocument(aProject.getId(), aDocumentId);
User user = userRepository.getUserOrCurationUser(aUser);
var doc = documentService.getSourceDocument(aProject.getId(), aDocumentId);
var user = userRepository.getUserOrCurationUser(aUser);

CAS cas = documentService.readAnnotationCas(doc, aUser);
var cas = documentService.readAnnotationCas(doc, aUser);

AnnotationPreference prefs = userPreferencesService.loadPreferences(doc.getProject(),
user.getUsername(), Mode.ANNOTATION);
var prefs = userPreferencesService.loadPreferences(doc.getProject(), user.getUsername(),
Mode.ANNOTATION);

List<AnnotationLayer> layers = schemaService.listSupportedLayers(aProject).stream()
var layers = schemaService.listSupportedLayers(aProject).stream()
.filter(AnnotationLayer::isEnabled) //
.filter(l -> !prefs.getHiddenAnnotationLayerIds().contains(l.getId()))
.collect(toList());

RenderRequest request = RenderRequest.builder() //
var request = RenderRequest.builder() //
.withSessionOwner(userRepository.getCurrentUser()) //
.withDocument(doc, user) //
.withWindow(aViewportBegin, aViewportEnd) //
.withCas(cas) //
.withVisibleLayers(layers) //
.build();

VDocument vdoc = renderingPipeline.render(request);
var vdoc = renderingPipeline.render(request);

if (FORMAT_LEGACY.equals(aFormat)) {
return JSONUtil.getObjectMapper().valueToTree(new MViewportInit(vdoc));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -1215,9 +1214,9 @@ public List<AnnotationDocument> listAllAnnotationDocuments(SourceDocument aDocum
public Map<SourceDocument, AnnotationDocument> listAnnotatableDocuments(Project aProject,
User aUser)
{
Map<SourceDocument, AnnotationDocument> map = listAllDocuments(aProject, aUser);
var map = listAllDocuments(aProject, aUser.getUsername());

Iterator<Entry<SourceDocument, AnnotationDocument>> i = map.entrySet().iterator();
var i = map.entrySet().iterator();
while (i.hasNext()) {
Entry<SourceDocument, AnnotationDocument> e = i.next();
if (e.getValue() != null && IGNORE == e.getValue().getState()) {
Expand All @@ -1230,7 +1229,7 @@ public Map<SourceDocument, AnnotationDocument> listAnnotatableDocuments(Project

@Override
@Transactional(noRollbackFor = NoResultException.class)
public Map<SourceDocument, AnnotationDocument> listAllDocuments(Project aProject, User aUser)
public Map<SourceDocument, AnnotationDocument> listAllDocuments(Project aProject, String aUser)
{
// First get the source documents
var sourceDocsQuery = "FROM SourceDocument WHERE project = (:project)";
Expand All @@ -1243,8 +1242,7 @@ public Map<SourceDocument, AnnotationDocument> listAllDocuments(Project aProject
// documents which are IGNOREed for given users.
var annDocsQuery = "FROM AnnotationDocument WHERE user = (:username) AND project = (:project)";
List<AnnotationDocument> annotationDocuments = entityManager
.createQuery(annDocsQuery, AnnotationDocument.class)
.setParameter("username", aUser.getUsername()) //
.createQuery(annDocsQuery, AnnotationDocument.class).setParameter("username", aUser) //
.setParameter("project", aProject) //
.getResultList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,53 +98,54 @@ public interface RecommendationService
*/
Optional<RecommendationEngineFactory<?>> getRecommenderFactory(Recommender aRecommender);

boolean hasActiveRecommenders(String aUser, Project aProject);
boolean hasActiveRecommenders(String aSessionOwner, Project aProject);

List<EvaluatedRecommender> getActiveRecommenders(User aUser, Project aProject);
List<EvaluatedRecommender> getActiveRecommenders(User aSessionOwner, Project aProject);

void setEvaluatedRecommenders(User aUser, AnnotationLayer layer,
void setEvaluatedRecommenders(User aSessionOwner, AnnotationLayer layer,
List<EvaluatedRecommender> selectedClassificationTools);

List<EvaluatedRecommender> getEvaluatedRecommenders(User aUser, AnnotationLayer aLayer);
List<EvaluatedRecommender> getEvaluatedRecommenders(User aSessionOwner, AnnotationLayer aLayer);

Optional<EvaluatedRecommender> getEvaluatedRecommender(User aUser, Recommender aRecommender);
Optional<EvaluatedRecommender> getEvaluatedRecommender(User aSessionOwner,
Recommender aRecommender);

List<EvaluatedRecommender> getActiveRecommenders(User aUser, AnnotationLayer aLayer);
List<EvaluatedRecommender> getActiveRecommenders(User aSessionOwner, AnnotationLayer aLayer);

void setPreferences(User aUser, Project aProject, Preferences aPreferences);
void setPreferences(User aSessionOwner, Project aProject, Preferences aPreferences);

Preferences getPreferences(User aUser, Project aProject);
Preferences getPreferences(User aSessionOwner, Project aProject);

Predictions getPredictions(User aUser, Project aProject);
Predictions getPredictions(User aSessionOwner, Project aProject);

Predictions getIncomingPredictions(User aUser, Project aProject);
Predictions getIncomingPredictions(User aSessionOwner, Project aProject);

void putIncomingPredictions(User aUser, Project aProject, Predictions aPredictions);
void putIncomingPredictions(User aSessionOwner, Project aProject, Predictions aPredictions);

boolean switchPredictions(User aUser, Project aProject);
boolean switchPredictions(String aSessionOwner, Project aProject);

/**
* Returns the {@code RecommenderContext} for the given recommender if it exists.
*
* @param aUser
* @param aSessionOwner
* The owner of the context
* @param aRecommender
* The recommender to which the desired context belongs
* @return The context of the given recommender if there is one, or an empty one
*/
Optional<RecommenderContext> getContext(User aUser, Recommender aRecommender);
Optional<RecommenderContext> getContext(String aSessionOwner, Recommender aRecommender);

/**
* Publishes a new context for the given recommender.
*
* @param aUser
* @param aSessionOwner
* The owner of the context.
* @param aRecommender
* The recommender to which the desired context belongs.
* @param aContext
* The new active context of the given recommender.
*/
void putContext(User aUser, Recommender aRecommender, RecommenderContext aContext);
void putContext(User aSessionOwner, Recommender aRecommender, RecommenderContext aContext);

/**
* Uses the given annotation suggestion to create a new annotation or to update a feature in an
Expand Down Expand Up @@ -182,20 +183,21 @@ int upsertRelationFeature(SourceDocument aDocument, String aUsername, CAS aCas,
/**
* Compute predictions.
*
* @param aUser
* @param aSessionOwner
* the user to compute the predictions for.
* @param aProject
* the project to compute the predictions for.
* @param aDocuments
* the documents to compute the predictions for.
* @return the new predictions.
*/
Predictions computePredictions(User aUser, Project aProject, List<SourceDocument> aDocuments);
Predictions computePredictions(User aSessionOwner, Project aProject,
List<SourceDocument> aDocuments, String aDataOwner);

/**
* Compute predictions.
*
* @param aUser
* @param aSessionOwner
* the user to compute the predictions for.
* @param aProject
* the project to compute the predictions for.
Expand All @@ -209,8 +211,9 @@ int upsertRelationFeature(SourceDocument aDocument, String aUsername, CAS aCas,
* end of the prediction range (negative to predict until the end of the document)
* @return the new predictions.
*/
Predictions computePredictions(User aUser, Project aProject, SourceDocument aCurrentDocument,
List<SourceDocument> aInherit, int aPredictionBegin, int aPredictionEnd);
Predictions computePredictions(User aSessionOwner, Project aProject,
SourceDocument aCurrentDocument, String aDataOwner, List<SourceDocument> aInherit,
int aPredictionBegin, int aPredictionEnd);

void calculateSpanSuggestionVisibility(SourceDocument aDocument, CAS aCas, String aUser,
AnnotationLayer aLayer, Collection<SuggestionGroup<SpanSuggestion>> aRecommendations,
Expand All @@ -220,26 +223,28 @@ void calculateRelationSuggestionVisibility(CAS aCas, String aUser, AnnotationLay
Collection<SuggestionGroup<RelationSuggestion>> aRecommendations, int aWindowBegin,
int aWindowEnd);

void clearState(String aUsername);
void clearState(String aSessionOwner);

void triggerPrediction(String aUsername, String aEventName, SourceDocument aDocument);
void triggerPrediction(String aSessionOwner, String aEventName, SourceDocument aDocument,
String aDataOwner);

void triggerTrainingAndPrediction(String aUser, Project aProject, String aEventName,
SourceDocument aCurrentDocument);
void triggerTrainingAndPrediction(String aSessionOwner, Project aProject, String aEventName,
SourceDocument aCurrentDocument, String aDataOwner);

void triggerSelectionTrainingAndPrediction(String aUser, Project aProject, String aEventName,
SourceDocument aCurrentDocument);
void triggerSelectionTrainingAndPrediction(String aSessionOwner, Project aProject,
String aEventName, SourceDocument aCurrentDocument, String aDataOwner);

boolean isPredictForAllDocuments(String aUser, Project aProject);
boolean isPredictForAllDocuments(String aSessionOwner, Project aProject);

void setPredictForAllDocuments(String aUser, Project aProject, boolean aPredictForAllDocuments);
void setPredictForAllDocuments(String aSessionOwner, Project aProject,
boolean aPredictForAllDocuments);

List<LogMessageGroup> getLog(String aUser, Project aProject);
List<LogMessageGroup> getLog(String aSessionOwner, Project aProject);

/**
* @return the total amount of enabled recommenders
*/
long countEnabledRecommenders();

Progress getProgressTowardsNextEvaluation(User aUser, Project aProject);
Progress getProgressTowardsNextEvaluation(User aSessionOwner, Project aProject);
}

0 comments on commit 5723a03

Please sign in to comment.