Skip to content
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
51d2688
Initial commit
luis-gasparschroeder Sep 20, 2025
5c8f4ab
Added tests
luis-gasparschroeder Sep 20, 2025
24f6f60
Implemented endpoint
luis-gasparschroeder Sep 20, 2025
d69d9c0
Merged HyperionRepositoryStructureService into HyperionProgrammingExe…
luis-gasparschroeder Sep 23, 2025
b6ed7ca
Removed service annotation
luis-gasparschroeder Sep 23, 2025
13fe6e5
Added Service suffix
luis-gasparschroeder Sep 23, 2025
2eced3f
Updated API
luis-gasparschroeder Sep 23, 2025
4e7a2ab
Using signal
luis-gasparschroeder Sep 23, 2025
40e8f35
Moved getExistingSolutionCode to cenralized class
luis-gasparschroeder Sep 23, 2025
da81272
Moved getExistingSolutionCode to cenralized class
luis-gasparschroeder Sep 23, 2025
236bbe0
Implemented module auto generation
luis-gasparschroeder Sep 24, 2025
8473a1d
Fixed signal bug
luis-gasparschroeder Sep 25, 2025
1e1dc1f
Added service defintions (required for discovery)
luis-gasparschroeder Sep 26, 2025
525510c
Adjusted prompt injection to adhere to HyperionPromptTemplateService
luis-gasparschroeder Sep 26, 2025
0c171c7
Added i18n localization
luis-gasparschroeder Sep 26, 2025
9667bb4
Added documentation
luis-gasparschroeder Sep 26, 2025
53ecb19
Removed generateSolutionPlan duplicate
luis-gasparschroeder Sep 26, 2025
c78609c
Dependency injecting beans
luis-gasparschroeder Sep 26, 2025
3884102
Fixed creation assistance button alignment
luis-gasparschroeder Sep 26, 2025
1ea753f
Merge branch 'develop' into feature/hyperion/code-generation-clean
luis-gasparschroeder Sep 29, 2025
beb8b29
Added code generation documentation
luis-gasparschroeder Sep 29, 2025
978e204
Modified code generation documentation
luis-gasparschroeder Sep 30, 2025
c91763a
Hide code generation button when hyperion is disabled
luis-gasparschroeder Sep 30, 2025
2cb1ca4
Merge branch 'develop' into feature/hyperion/code-generation-clean
FelixTJDietrich Sep 30, 2025
ea8f9f6
Fix constructor calls in Hyperion test files
luis-gasparschroeder Oct 2, 2025
620a048
Merge branch 'feature/hyperion/code-generation-clean' of github.com:l…
luis-gasparschroeder Oct 2, 2025
595252a
Fixed DTO naming conventions
luis-gasparschroeder Oct 2, 2025
3416a0f
Added docstring
luis-gasparschroeder Oct 2, 2025
f1a1316
Fixed tests
luis-gasparschroeder Oct 2, 2025
433d89c
Added additional tests to increase code coverage
luis-gasparschroeder Oct 2, 2025
c0637bc
Adjusted jest config
luis-gasparschroeder Oct 3, 2025
f0fc096
Merge branch 'develop' into feature/hyperion/code-generation-clean
luis-gasparschroeder Oct 6, 2025
47575dc
Removed old logic
luis-gasparschroeder Oct 6, 2025
020657a
Updated dependencies
luis-gasparschroeder Oct 6, 2025
2d63c25
Implemented tests to increase code coverage
luis-gasparschroeder Oct 6, 2025
e96dcae
Updated test naming
luis-gasparschroeder Oct 6, 2025
b9da96a
Removed duplicated tests
luis-gasparschroeder Oct 6, 2025
e795c98
Removed duplicated tests
luis-gasparschroeder Oct 6, 2025
0f10c11
Fixed architecture-related tests
luis-gasparschroeder Oct 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion docs/admin/setup/hyperion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,54 @@ Verifying the integration
3. Run a consistency check to ensure the LLM call succeeds. Inspect the server logs for ``Hyperion`` entries
if the request fails; misconfigured credentials and missing network egress are the most common causes.

Operational considerations
Code Generation Process
^^^^^^^^^^^^^^^^^^^^^^^

Hyperion can automatically generate complete programming exercise repositories (solution, template, and test code)
using a structured AI-driven approach. The generation process consists of a 4-step pipeline with iterative
improvement based on compilation feedback.

4-Step Generation Pipeline
""""""""""""""""""""""""""

Each repository component follows a systematic generation process:

1. **Solution Planning**: Creates a high-level algorithmic approach and identifies key components needed
2. **File Structure Definition**: Organizes the code into appropriate files and packages
3. **Class and Method Headers**: Generates class definitions, method signatures, and documentation
4. **Core Logic Implementation**: Produces the complete functional implementation

Iterative Compilation Feedback
"""""""""""""""""""""""""""""""

For each repository component, Hyperion automatically:

- Generates code using the 4-step pipeline
- Commits changes and triggers a CI build
- Waits for compilation results
- If compilation fails, uses build logs as feedback for the next iteration
- Retries up to 3 times (default value) per component, incorporating error messages to improve the code
- Stores the final generated code in the repository, even if compilation ultimately fails

This feedback loop enables Hyperion to self-correct common issues like syntax errors, missing imports,
or incorrect API usage.

Cost Considerations
"""""""""""""""""""

Average code generation costs depend on the LLM model and number of components (solution, template, or test repository):

**Per Component Costs** (with up to 3 iterations):

- **GPT-5**: ~$0.05 per repository component
- **GPT-5-mini**: ~$0.01 per repository component

**Full Assignment Costs** (solution + template + test repositories):

- **GPT-5**: ~$0.15 total
- **GPT-5-mini**: ~$0.03 total

Operational considerations
^^^^^^^^^^^^^^^^^^^^^^^^^^

- **Cost control:** Define usage policies and rate limits with your provider. Hyperion requests can process the
Expand Down
40 changes: 40 additions & 0 deletions openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,26 @@ paths:
content:
application/json:
schema: {$ref: '#/components/schemas/ProblemStatementRewriteResponse'}
/api/hyperion/programming-exercises/{exerciseId}/generate-code:
post:
tags: [hyperion-code-generation]
operationId: generateCode
parameters:
- name: exerciseId
in: path
required: true
schema: {type: integer, format: int64}
requestBody:
content:
application/json:
schema: {$ref: '#/components/schemas/CodeGenerationRequestDTO'}
required: true
responses:
'200':
description: OK
content:
application/json:
schema: {$ref: '#/components/schemas/CodeGenerationResultDTO'}
/api/tutorialgroup/tutorial-groups/{tutorialGroupId}/title:
get:
tags: [tutorial-group]
Expand Down Expand Up @@ -478,3 +498,23 @@ components:
registrationNumber: {type: string}
firstName: {type: string}
lastName: {type: string}
CodeGenerationRequestDTO:
type: object
description: Request DTO for code generation
properties:
repositoryType:
type: string
description: Type of repository to generate code for
enum: [TEMPLATE, SOLUTION, TESTS]
example: SOLUTION
CodeGenerationResultDTO:
type: object
description: Response DTO for code generation result
properties:
success: {type: boolean, description: Whether the code generation was successful,
example: true}
message: {type: string, description: Result message describing the outcome,
example: Solution code generated successfully and compiles without errors.}
attempts: {type: integer, format: int32, description: Number of generation
attempts made, example: 1}
required: [success, message, attempts]
62 changes: 58 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@
"stylelint-config-standard": "39.0.0",
"stylelint-config-standard-scss": "16.0.0",
"stylelint-scss": "6.12.1",
"typescript": "5.9.3",
"ts-morph": "27.0.0",
"typescript": "5.9.2",
"typescript-eslint": "8.45.0"
},
"engines": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,37 @@ private void addDirectory(String containerId, String directoryName, boolean crea
}

private void copyToContainer(Path sourcePath, String containerId) {
try (final var uploadStream = new ByteArrayInputStream(createTarArchive(sourcePath).toByteArray());
final var copyToContainerCommand = buildAgentConfiguration.getDockerClient().copyArchiveToContainerCmd(containerId)
.withRemotePath(LOCAL_CI_DOCKER_CONTAINER_WORKING_DIRECTORY).withTarInputStream(uploadStream)) {
copyToContainerCommand.exec();
}
catch (IOException e) {
throw new LocalCIException("Could not copy to container " + containerId, e);
final int maxRetries = 3;
final long retryDelayMs = 1000;

/*
* Retry mechanism is essential for Docker container operations due to potential transient failures:
* - Docker daemon may be temporarily overloaded or unresponsive
* - Network connectivity issues between client and Docker daemon
* - Container filesystem may be temporarily locked or busy
* - Resource contention during concurrent build operations
* This improves reliability in CI/CD environments where multiple builds run simultaneously.
*/
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try (final var uploadStream = new ByteArrayInputStream(createTarArchive(sourcePath).toByteArray());
final var copyToContainerCommand = buildAgentConfiguration.getDockerClient().copyArchiveToContainerCmd(containerId)
.withRemotePath(LOCAL_CI_DOCKER_CONTAINER_WORKING_DIRECTORY).withTarInputStream(uploadStream)) {
copyToContainerCommand.exec();
return;
}
catch (Exception e) {
if (attempt == maxRetries) {
throw new LocalCIException("Could not copy to container " + containerId + " after " + maxRetries + " attempts", e);
}
log.warn("Attempt {} failed to copy to container {}: {}. Retrying in {} ms...", attempt, containerId, e.getMessage(), retryDelayMs);
try {
Thread.sleep(retryDelayMs);
}
catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new LocalCIException("Interrupted while retrying copy to container " + containerId, ie);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
@Schema(description = "Location information for artifacts")
public record ArtifactLocationDTO(

@NotNull @Schema(description = "Type of artifact", example = "PROBLEM_STATEMENT") ArtifactType type,
@NotNull @Schema(description = "Type of artifact", example = "PROBLEM_STATEMENT") ArtifactTypeDTO type,

@NotNull @Schema(description = "Path to file, empty or problem_statement.md for problem statement", example = "src/main/java/Main.java") String filePath,

Expand Down

This file was deleted.

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

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Enum for artifact types in consistency checks.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public enum ArtifactTypeDTO {

PROBLEM_STATEMENT("PROBLEM_STATEMENT"), TEMPLATE_REPOSITORY("TEMPLATE_REPOSITORY"), SOLUTION_REPOSITORY("SOLUTION_REPOSITORY"), TESTS_REPOSITORY("TESTS_REPOSITORY");

private final String value;

ArtifactTypeDTO(String value) {
this.value = value;
}

@JsonValue
public String getValue() {
return value;
}

@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import jakarta.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonInclude;

import de.tum.cit.aet.artemis.programming.domain.RepositoryType;

/**
* DTO for requesting code generation for a programming exercise.
* Contains the repository type to determine which generation strategy to use.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationRequestDTO(@NotNull RepositoryType repositoryType) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;

/**
* DTO for internal code generation response.
* Contains the generated content from AI service calls.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationResponseDTO(
/**
* The solution plan as a string
*/
String solutionPlan,

/**
* List of generated files with path and content
*/
List<GeneratedFileDTO> files) {

public String getSolutionPlan() {
return solutionPlan;
}

public List<GeneratedFileDTO> getFiles() {
return files;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.tum.cit.aet.artemis.hyperion.dto;

import com.fasterxml.jackson.annotation.JsonInclude;

/**
* DTO for REST API code generation result.
* Contains the result of the code generation and compilation process.
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CodeGenerationResultDTO(
/**
* Whether the code generation and compilation was successful
*/
boolean success,

/**
* Descriptive message about the generation result
*/
String message,

/**
* Number of attempts made during the generation process
*/
int attempts) {
}
Loading
Loading