Skip to content

Commit

Permalink
Merge branch 'develop' into chore/programming-exercises/improve-perfo…
Browse files Browse the repository at this point in the history
…rmance
  • Loading branch information
SimonEntholzer authored Dec 10, 2024
2 parents 06c290d + cae4fb5 commit fb4c947
Show file tree
Hide file tree
Showing 74 changed files with 2,139 additions and 308 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ spotless {
}
}
importOrderFile "artemis-spotless.importorder"
eclipse("4.28").configFile "artemis-spotless-style.xml"
eclipse("4.33").configFile "artemis-spotless-style.xml"

removeUnusedImports()
trimTrailingWhitespace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.core.repository.UserRepository;
import de.tum.cit.aet.artemis.iris.service.session.IrisCourseChatSessionService;
import de.tum.cit.aet.artemis.iris.service.pyris.PyrisEventService;
import de.tum.cit.aet.artemis.iris.service.pyris.event.CompetencyJolSetEvent;

/**
* Service Implementation for managing CompetencyJol.
Expand All @@ -44,15 +45,15 @@ public class CompetencyJolService {

private final UserRepository userRepository;

private final Optional<IrisCourseChatSessionService> irisCourseChatSessionService;
private final Optional<PyrisEventService> pyrisEventService;

public CompetencyJolService(CompetencyJolRepository competencyJolRepository, CompetencyRepository competencyRepository,
CompetencyProgressRepository competencyProgressRepository, UserRepository userRepository, Optional<IrisCourseChatSessionService> irisCourseChatSessionService) {
CompetencyProgressRepository competencyProgressRepository, UserRepository userRepository, Optional<PyrisEventService> pyrisEventService) {
this.competencyJolRepository = competencyJolRepository;
this.competencyRepository = competencyRepository;
this.competencyProgressRepository = competencyProgressRepository;
this.userRepository = userRepository;
this.irisCourseChatSessionService = irisCourseChatSessionService;
this.pyrisEventService = pyrisEventService;
}

/**
Expand Down Expand Up @@ -83,10 +84,10 @@ public void setJudgementOfLearning(long competencyId, long userId, short jolValu
final var jol = createCompetencyJol(competencyId, userId, jolValue, ZonedDateTime.now(), competencyProgress);
competencyJolRepository.save(jol);

irisCourseChatSessionService.ifPresent(service -> {
pyrisEventService.ifPresent(service -> {
// Inform Iris so it can send a message to the user
try {
service.onJudgementOfLearningSet(jol);
service.trigger(new CompetencyJolSetEvent(jol));
}
catch (Exception e) {
log.warn("Something went wrong while sending the judgement of learning to Iris", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ public interface SubmissionRepository extends ArtemisJpaRepository<Submission, L
@EntityGraph(type = LOAD, attributePaths = { "results", "results.assessor" })
List<Submission> findAllWithResultsAndAssessorByParticipationId(Long participationId);

/**
* Get all submissions of a participation and eagerly load results ordered by submission date in ascending order
*
* @param participationId the id of the participation
* @return a list of the participation's submissions
*/
@EntityGraph(type = LOAD, attributePaths = { "results" })
List<Submission> findAllWithResultsByParticipationIdOrderBySubmissionDateAsc(Long participationId);

/**
* Get all submissions with their results by the submission ids
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public class IrisChatSubSettings extends IrisSubSettings {
@Convert(converter = IrisListConverter.class)
private SortedSet<String> enabledForCategories = new TreeSet<>();

@Column(name = "disabled_proactive_events", nullable = false)
@Convert(converter = IrisListConverter.class)
private SortedSet<String> disabledProactiveEvents = new TreeSet<>();

@Nullable
public Integer getRateLimit() {
return rateLimit;
Expand All @@ -57,4 +61,12 @@ public SortedSet<String> getEnabledForCategories() {
public void setEnabledForCategories(SortedSet<String> enabledForCategories) {
this.enabledForCategories = enabledForCategories;
}

public SortedSet<String> getDisabledProactiveEvents() {
return disabledProactiveEvents;
}

public void setDisabledProactiveEvents(SortedSet<String> disabledProactiveEvents) {
this.disabledProactiveEvents = disabledProactiveEvents;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.tum.cit.aet.artemis.iris.domain.settings;

import jakarta.annotation.Nullable;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;

import com.fasterxml.jackson.annotation.JsonInclude;

/**
* An {@link IrisSubSettings} implementation for course chat settings.
* Chat settings notably provide settings for the rate limit.
*/
@Entity
@DiscriminatorValue("COURSE_CHAT")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class IrisCourseChatSubSettings extends IrisSubSettings {

@Nullable
@Column(name = "rate_limit")
private Integer rateLimit;

@Nullable
@Column(name = "rate_limit_timeframe_hours")
private Integer rateLimitTimeframeHours;

@Nullable
public Integer getRateLimit() {
return rateLimit;
}

public void setRateLimit(@Nullable Integer rateLimit) {
this.rateLimit = rateLimit;
}

@Nullable
public Integer getRateLimitTimeframeHours() {
return rateLimitTimeframeHours;
}

public void setRateLimitTimeframeHours(@Nullable Integer rateLimitTimeframeHours) {
this.rateLimitTimeframeHours = rateLimitTimeframeHours;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public class IrisCourseSettings extends IrisSettings {
@JoinColumn(name = "iris_text_exercise_chat_settings_id")
private IrisTextExerciseChatSubSettings irisTextExerciseChatSettings;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "iris_course_chat_settings_id")
private IrisCourseChatSubSettings irisCourseChatSettings;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name = "iris_lecture_ingestion_settings_id")
private IrisLectureIngestionSubSettings irisLectureIngestionSettings;
Expand Down Expand Up @@ -78,6 +82,16 @@ public void setIrisTextExerciseChatSettings(IrisTextExerciseChatSubSettings iris
this.irisTextExerciseChatSettings = irisTextExerciseChatSettings;
}

@Override
public IrisCourseChatSubSettings getIrisCourseChatSettings() {
return irisCourseChatSettings;
}

@Override
public void setIrisCourseChatSettings(IrisCourseChatSubSettings irisCourseChatSettings) {
this.irisCourseChatSettings = irisCourseChatSettings;
}

@Override
public IrisCompetencyGenerationSubSettings getIrisCompetencyGenerationSettings() {
return irisCompetencyGenerationSettings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ public void setIrisTextExerciseChatSettings(IrisTextExerciseChatSubSettings iris
this.irisTextExerciseChatSettings = irisTextExerciseChatSettings;
}

@Override
public IrisCourseChatSubSettings getIrisCourseChatSettings() {
// Empty because exercises don't have course chat settings
return null;
}

@Override
public void setIrisCourseChatSettings(IrisCourseChatSubSettings irisCourseChatSettings) {
// Empty because exercises don't have course chat settings
}

@Override
public IrisCompetencyGenerationSubSettings getIrisCompetencyGenerationSettings() {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public class IrisGlobalSettings extends IrisSettings {
@JoinColumn(name = "iris_text_exercise_chat_settings_id")
private IrisTextExerciseChatSubSettings irisTextExerciseChatSettings;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "iris_course_chat_settings_id")
private IrisCourseChatSubSettings irisCourseChatSettings;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "iris_lecture_ingestion_settings_id")
private IrisLectureIngestionSubSettings irisLectureIngestionSettings;
Expand Down Expand Up @@ -65,6 +69,16 @@ public void setIrisTextExerciseChatSettings(IrisTextExerciseChatSubSettings iris
this.irisTextExerciseChatSettings = irisTextExerciseChatSettings;
}

@Override
public IrisCourseChatSubSettings getIrisCourseChatSettings() {
return irisCourseChatSettings;
}

@Override
public void setIrisCourseChatSettings(IrisCourseChatSubSettings irisCourseChatSettings) {
this.irisCourseChatSettings = irisCourseChatSettings;
}

@Override
public IrisCompetencyGenerationSubSettings getIrisCompetencyGenerationSettings() {
return irisCompetencyGenerationSettings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public abstract class IrisSettings extends DomainObject {

public abstract void setIrisTextExerciseChatSettings(IrisTextExerciseChatSubSettings irisTextExerciseChatSettings);

public abstract IrisCourseChatSubSettings getIrisCourseChatSettings();

public abstract void setIrisCourseChatSettings(IrisCourseChatSubSettings irisCourseChatSettings);

public abstract IrisLectureIngestionSubSettings getIrisLectureIngestionSettings();

public abstract void setIrisLectureIngestionSettings(IrisLectureIngestionSubSettings irisLectureIngestionSettings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
@JsonSubTypes({
@JsonSubTypes.Type(value = IrisChatSubSettings.class, name = "chat"),
@JsonSubTypes.Type(value = IrisTextExerciseChatSubSettings.class, name = "text-exercise-chat"),
@JsonSubTypes.Type(value = IrisCourseChatSubSettings.class, name = "course-chat"),
@JsonSubTypes.Type(value = IrisLectureIngestionSubSettings.class, name = "lecture-ingestion"),
@JsonSubTypes.Type(value = IrisCompetencyGenerationSubSettings.class, name = "competency-generation")
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.tum.cit.aet.artemis.iris.domain.settings;

public enum IrisSubSettingsType {
CHAT, // TODO: Split into PROGRAMMING_EXERCISE_CHAT and COURSE_CHAT
TEXT_EXERCISE_CHAT, COMPETENCY_GENERATION, LECTURE_INGESTION
CHAT, // TODO: Rename to PROGRAMMING_EXERCISE_CHAT
TEXT_EXERCISE_CHAT, COURSE_CHAT, COMPETENCY_GENERATION, LECTURE_INGESTION
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package de.tum.cit.aet.artemis.iris.domain.settings.event;

/**
* The type of event that can be triggered by the Iris system.
*/
public enum IrisEventType {

BUILD_FAILED, PROGRESS_STALLED, JOL
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record IrisCombinedChatSubSettingsDTO(boolean enabled, Integer rateLimit, Integer rateLimitTimeframeHours, @Nullable SortedSet<String> allowedVariants,
@Nullable String selectedVariant, @Nullable SortedSet<String> enabledForCategories) {
@Nullable String selectedVariant, @Nullable SortedSet<String> enabledForCategories, @Nullable SortedSet<String> disabledProactiveEvents) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.tum.cit.aet.artemis.iris.dto;

import java.util.SortedSet;

import jakarta.annotation.Nullable;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record IrisCombinedCourseChatSubSettingsDTO(boolean enabled, Integer rateLimit, Integer rateLimitTimeframeHours, @Nullable SortedSet<String> allowedVariants,
@Nullable String selectedVariant) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
public record IrisCombinedSettingsDTO(
IrisCombinedChatSubSettingsDTO irisChatSettings,
IrisCombinedTextExerciseChatSubSettingsDTO irisTextExerciseChatSettings,
IrisCombinedCourseChatSubSettingsDTO irisCourseChatSettings,
IrisCombinedLectureIngestionSubSettingsDTO irisLectureIngestionSettings,
IrisCombinedCompetencyGenerationSubSettingsDTO irisCompetencyGenerationSettings
) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_IRIS;

import java.util.Optional;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -62,6 +64,7 @@ public void executeCompetencyExtractionPipeline(User user, Course course, String
pyrisPipelineService.executePipeline(
"competency-extraction",
"default",
Optional.empty(),
pyrisJobService.createTokenForJob(token -> new CompetencyExtractionJob(token, course.getId(), user.getId())),
executionDto -> new PyrisCompetencyExtractionPipelineExecutionDTO(executionDto, courseDescription, currentCompetencies, CompetencyTaxonomy.values(), 5),
stages -> websocketService.send(user.getLogin(), websocketTopic(course.getId()), new PyrisCompetencyStatusUpdateDTO(stages, null, null))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -73,13 +74,13 @@ public List<PyrisVariantDTO> getOfferedVariants(IrisSubSettingsType feature) thr
try {
var response = restTemplate.getForEntity(pyrisUrl + "/api/v1/pipelines/" + feature.name() + "/variants", PyrisVariantDTO[].class);
if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) {
throw new PyrisConnectorException("Could not fetch offered models");
throw new PyrisConnectorException("Could not fetch offered variants");
}
return Arrays.asList(response.getBody());
}
catch (HttpStatusCodeException e) {
log.error("Failed to fetch offered models from Pyris", e);
throw new PyrisConnectorException("Could not fetch offered models");
log.error("Failed to fetch offered variants from Pyris", e);
throw new PyrisConnectorException("Could not fetch offered variants");
}
}

Expand All @@ -89,9 +90,12 @@ public List<PyrisVariantDTO> getOfferedVariants(IrisSubSettingsType feature) thr
* @param feature The feature name of the pipeline to execute
* @param variant The variant of the feature to execute
* @param executionDTO The DTO sent as a body for the execution
* @param event The event to be sent as a query parameter, if the pipeline is getting executed due to an event
*/
public void executePipeline(String feature, String variant, Object executionDTO) {
public void executePipeline(String feature, String variant, Object executionDTO, Optional<String> event) {
var endpoint = "/api/v1/pipelines/" + feature + "/" + variant + "/run";
// Add event query parameter if present
endpoint += event.map(e -> "?event=" + e).orElse("");
try {
restTemplate.postForEntity(pyrisUrl + endpoint, objectMapper.valueToTree(executionDTO), Void.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.tum.cit.aet.artemis.iris.service.pyris;

/**
* Exception thrown when an error occurs during Pyris event processing.
*/
public class PyrisEventProcessingException extends RuntimeException {

public PyrisEventProcessingException(String message) {
super(message);
}
}
Loading

0 comments on commit fb4c947

Please sign in to comment.