Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General: Track token usage of LLM service requests #9455

Merged
merged 34 commits into from
Oct 23, 2024

Conversation

alexjoham
Copy link
Member

@alexjoham alexjoham commented Oct 11, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I documented the Java code using JavaDoc style.

Motivation and Context

This PR fixes parts of an open Feature request: Issue
The feature request also includes a graphical interface, but this will be implemented in a follow-up.

Description

I worked with Pyris and Athena to implement the requested feature for both LLM services. Pyris now sends tokens with a status message if tokens were used. Those tokens are of a new Type called PyrisLLMCostDTO that saves input and output tokens, the used LLM and also the service that used those tokens:

public record LLMRequest(String model, int numInputTokens, float costPerMillionInputToken, int numOutputTokens, float costPerMillionOutputToken, String pipelineId) {
}

If Artemis receives those tokens it saves them using the LLMTokenUsageService in two new table called llm_token_usage_request grouped by llm_token_usage_trace. Those tables contains all the information related to the LLM call: model, number and cost of input and output tokens, the course, exercise, user and IrisMessage Id and a trace. The trace is used to group calls that were made for one message.

Steps for Testing

Prerequisites:

Prerequisite:

  • Local setup since you need DB access
  • Iris or Athena setup

Testing with Iris

  1. Run Artemis with Pyris running with the branch feature/track-usage-of-iris-requests (related PR).
  2. Check if the new llm_token_usage_request and llm_token_usage_trace tables exist.
  3. Activate Iris for the course
  4. Activate Iris for an exercise
  5. Chat with Iris
  6. Check the database if the tokens are logged correctly into the tables

Testing with Athena

  1. Run Artemis with Athena running (develop of Athena)
  2. Check if the new llm_token_usage_request and llm_token_usage_trace tables exist.
  3. Create an exercise with Athena enabled for feedback
  4. Request feedback from Athena (either request preliminary AI feedback as a student during working time, or after the deadline as a tutor by opening a submission to assess)
  5. Check the database if the tokens are logged correctly into the tables

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Server

Class/File Line Coverage Confirmation (assert/expect)
ResponseMetaDTO.java 0%
AthenaFeedbackSuggestionsService.java 83%
LLMRequest.java 100%
LLMServiceType.java 100%
LLMTokenUsageRequest.java 94%
LLMTokenUsageTrace.java 83%
LLMTokenUsageRequestRepository.java not found (added)
LLMTokenUsageTraceRepository.java not found (added)
LLMTokenUsageService.java 83%
IrisChatWebsocketDTO.java 93%
IrisCompetencyGenerationService.java 82%
PyrisStatusUpdateService.java 76%
PyrisChatStatusUpdateDTO.java 100%
PyrisCompetencyStatusUpdateDTO.java 100%
PyrisLLMCostDTO.java 0%
CompetencyExtractionJob.java 63%
CourseChatJob.java 52%
ExerciseChatJob.java 51%
SessionBasedPyrisJob.java not found (added)
AbstractIrisChatSessionService.java 85%
IrisCourseChatSessionService.java 17%
IrisExerciseChatSessionService.java 88%
IrisChatWebsocketService.java 100%

Summary by CodeRabbit

  • New Features

    • Introduced new service types for LLM functionalities, including IRIS_LECTURE_RETRIEVAL_PIPELINE and IRIS_LECTURE_INGESTION.
    • Added classes for managing token usage requests and traces, enhancing tracking of LLM interactions.
    • Integrated token usage tracking into various chat session services and feedback suggestion services.
    • New ResponseMetaDTO for encapsulating response metadata from the Athena service.
    • Implemented a new interface TrackedSessionBasedPyrisJob for managing jobs requiring session tracking and LLM usage tracing.
  • Bug Fixes

    • Improved handling of job status updates and token tracking across multiple services.
  • Tests

    • Added integration tests for token tracking in chat sessions to ensure accurate data recording and error handling.

@alexjoham alexjoham self-assigned this Oct 11, 2024
@alexjoham alexjoham linked an issue Oct 11, 2024 that may be closed by this pull request
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. core Pull requests that affect the corresponding module iris Pull requests that affect the corresponding module labels Oct 11, 2024
@alexjoham alexjoham changed the title Iris: Feature/track usage of iris requests Iris: Track usage of iris requests Oct 11, 2024
@alexjoham alexjoham changed the title Iris: Track usage of iris requests Iris: Track token usage of iris requests Oct 11, 2024
Copy link
Contributor

@FelixTJDietrich FelixTJDietrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some comments for consideration on the proposed LLMTokenUsage table.

@alexjoham alexjoham marked this pull request as ready for review October 12, 2024 11:26
@alexjoham alexjoham requested a review from a team as a code owner October 12, 2024 11:26
Copy link

coderabbitai bot commented Oct 12, 2024

Walkthrough

The changes introduced in this pull request encompass the addition of new classes and modifications to existing ones within the Artemis application. Key updates include the introduction of LLMTokenUsageRequest and LLMTokenUsageTrace classes, enhancements to the LLMServiceType enumeration, and the integration of token usage tracking into various services. Additionally, several methods have been updated to accommodate new parameters and functionalities, particularly around handling job statuses and tracking LLM token usage.

Changes

File Path Change Summary
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java Updated LLMServiceType enum to include new constants: IRIS_LECTURE_RETRIEVAL_PIPELINE, IRIS_LECTURE_INGESTION, IRIS, ATHENA.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageRequest.java Added new class LLMTokenUsageRequest with fields for token usage request attributes and methods for data access.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsageTrace.java Added new class LLMTokenUsageTrace with fields for token usage tracing and a relationship to LLMTokenUsageRequest.
src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageTraceRepository.java Introduced new interface LLMTokenUsageTraceRepository extending ArtemisJpaRepository for managing LLMTokenUsageTrace entities.
src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java Updated service class to manage token usage data, including methods for saving and appending requests to traces.
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java Modified to include new dependencies and updated methods for handling competency extraction and status updates.
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisCourseChatSessionService.java Added LLMTokenUsageService dependency and replaced handleStatusUpdate with setLLMTokenUsageParameters.
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java Similar updates as IrisCourseChatSessionService, integrating LLMTokenUsageService and replacing handleStatusUpdate.
src/test/java/de/tum/cit/aet/artemis/iris/IrisChatTokenTrackingIntegrationTest.java Implemented integration tests for token tracking functionality in chat sessions.
src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRequestRepository.java Introduced new interface LLMTokenUsageRequestRepository for managing LLMTokenUsageRequest entities.
src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java Updated to include new fields and methods for managing token usage and websocket interactions.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CompetencyExtractionJob.java Updated CompetencyExtractionJob to replace userLogin with userId.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CourseChatJob.java Modified to implement TrackedSessionBasedPyrisJob and added traceId field.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/ExerciseChatJob.java Similar updates as CourseChatJob, implementing TrackedSessionBasedPyrisJob and adding traceId.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisJobService.java Updated job management methods to include new parameters and added methods for job removal and updating.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java Modified methods to handle TrackedSessionBasedPyrisJob and updated logic for job termination and updates.
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/TrackedSessionBasedPyrisJob.java Introduced new interface for managing jobs requiring session tracking and LLM usage tracing.
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java Updated handleStatusUpdate to return TextExerciseChatJob and modified internal logic for message handling.
src/main/java/de/tum/cit/aet/artemis/athena/dto/ResponseMetaDTO.java Added new DTO ResponseMetaDTO for encapsulating response metadata.
src/main/java/de/tum/cit/aet/artemis/athena/service/AthenaFeedbackSuggestionsService.java Modified to include LLMTokenUsageService and updated response handling to track token usage.
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMRequest.java Introduced new record LLMRequest for encapsulating LLM token usage information.

Suggested labels

priority:critical, small, atlas

Suggested reviewers

  • MaximilianAnzinger

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 25

🧹 Outside diff range comments (2)
src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java (1)

Line range hint 62-65: Update equals method to include the new tokens field.

The equals method has not been updated to include the new tokens field. This could lead to inconsistent behavior when comparing IrisChatWebsocketDTO objects.

Please update the equals method to include the tokens field in the comparison. Here's a suggested implementation:

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    IrisChatWebsocketDTO that = (IrisChatWebsocketDTO) o;
    return type == that.type && 
           Objects.equals(message, that.message) && 
           Objects.equals(rateLimitInfo, that.rateLimitInfo) && 
           Objects.equals(stages, that.stages) &&
           Objects.equals(suggestions, that.suggestions) &&
           Objects.equals(tokens, that.tokens);
}

Also, consider overriding the hashCode method to maintain consistency with the updated equals method.

src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java (1)

Line range hint 37-85: Test method adheres well to coding guidelines. Consider minor enhancements.

The test method generateCompetencies_asEditor_shouldSucceed generally follows the provided coding guidelines:

  • Descriptive naming
  • Small, specific test case
  • Use of fixed data
  • JUnit 5 features
  • assertThat for assertions
  • Avoidance of direct DB access
  • Use of mocking

Consider the following enhancements:

  1. Add explicit DB query count tracking if relevant to this test case.
  2. Ensure ArchUnit is used elsewhere to enforce package rules if not applicable here.
  3. If possible, add a comment or mechanism to address context restart minimization.

These suggestions aim to fully align the test with all aspects of the provided coding guidelines.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 607e8f7 and 188ff22.

⛔ Files ignored due to path filters (2)
  • src/main/resources/config/liquibase/changelog/20241012125003_changelog.xml is excluded by !**/*.xml
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (16)
  • src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsage.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/chat/PyrisChatStatusUpdateDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/competency/PyrisCompetencyStatusUpdateDTO.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/data/PyrisLLMCostDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisCourseChatSessionService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (4 hunks)
  • src/main/webapp/app/entities/iris/iris-message.model.ts (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/iris/IrisChatMessageIntegrationTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/iris/IrisChatWebsocketTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMTokenUsage.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRepository.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/chat/PyrisChatStatusUpdateDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/competency/PyrisCompetencyStatusUpdateDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/data/PyrisLLMCostDTO.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisCourseChatSessionService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisExerciseChatSessionService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/webapp/app/entities/iris/iris-message.model.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

src/test/java/de/tum/cit/aet/artemis/iris/IrisChatMessageIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

src/test/java/de/tum/cit/aet/artemis/iris/IrisChatWebsocketTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

📓 Learnings (2)
src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (2)
Learnt from: Hialus
PR: ls1intum/Artemis#8286
File: src/main/java/de/tum/in/www1/artemis/service/iris/websocket/IrisChatWebsocketService.java:48-0
Timestamp: 2024-10-08T15:35:42.972Z
Learning: In the `IrisChatWebsocketService.java` file, the `sendMessage` method is designed to allow exceptions to propagate without specific handling, as this is an intentional part of the error handling strategy.
Learnt from: Hialus
PR: ls1intum/Artemis#8286
File: src/main/java/de/tum/in/www1/artemis/service/iris/websocket/IrisChatWebsocketService.java:48-0
Timestamp: 2024-10-08T15:35:52.595Z
Learning: In the `IrisChatWebsocketService.java` file, the `sendMessage` method is designed to allow exceptions to propagate without specific handling, as this is an intentional part of the error handling strategy.
src/test/java/de/tum/cit/aet/artemis/iris/IrisCompetencyGenerationIntegrationTest.java (2)
Learnt from: julian-christl
PR: ls1intum/Artemis#8052
File: src/test/java/de/tum/in/www1/artemis/lecture/CompetencyIntegrationTest.java:310-310
Timestamp: 2024-02-23T00:03:06.365Z
Learning: Modifications to parameters in `competencyProgressUtilService.createCompetencyProgress` for debugging purposes are considered irrelevant to the test outcomes but helpful for clarity during debugging.
Learnt from: julian-christl
PR: ls1intum/Artemis#8052
File: src/test/java/de/tum/in/www1/artemis/lecture/CompetencyIntegrationTest.java:310-310
Timestamp: 2024-10-08T15:35:52.595Z
Learning: Modifications to parameters in `competencyProgressUtilService.createCompetencyProgress` for debugging purposes are considered irrelevant to the test outcomes but helpful for clarity during debugging.
🔇 Additional comments (31)
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/data/PyrisLLMCostDTO.java (3)

1-1: LGTM: Package declaration is correct.

The package declaration follows the standard Java naming conventions and aligns with the project structure.


3-3: LGTM: Import statement is appropriate.

The import statement is specific and imports only the necessary LLMServiceType enum, which is used in the record declaration. This adheres to the guideline of avoiding star imports.


1-6: Overall, well-structured DTO with minor naming convention issue.

This new PyrisLLMCostDTO record is well-designed and adheres to most of our coding guidelines:

  • It follows the single responsibility principle.
  • Uses Java records for DTOs as recommended.
  • Promotes immutability.
  • Uses primitive types where appropriate.
  • Captures necessary information without redundancy.

The only improvement needed is to adjust the field names to follow Java's camelCase convention. Once this is addressed, the file will fully comply with our coding standards.

src/main/java/de/tum/cit/aet/artemis/core/domain/LLMServiceType.java (2)

1-1: LGTM: Package declaration is correct.

The package declaration follows the expected naming convention and structure.


4-5: Past review comment has been addressed.

The distinction between ATHENA_PRELIMINARY_FEEDBACK and ATHENA_FEEDBACK_SUGGESTION suggested in the past review comment has been implemented in the current version of the enum.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/chat/PyrisChatStatusUpdateDTO.java (2)

7-7: LGTM: New import added correctly

The import for PyrisLLMCostDTO is correctly added, which is necessary for the new tokens field in the record. This change aligns with the PR objectives of tracking token usage.


11-11: LGTM: Record updated to include token usage tracking

The PyrisChatStatusUpdateDTO record has been correctly updated to include the new tokens field of type List<PyrisLLMCostDTO>. This change:

  1. Aligns with the PR objectives of tracking token usage in Iris requests.
  2. Uses Java records, which is in line with the coding guidelines for DTOs.
  3. Follows the naming convention of CamelCase.
  4. Adheres to the principle of minimal DTOs by only adding the necessary field for token usage tracking.

The use of a List for tokens allows for multiple token usage entries per chat status update, which provides flexibility in tracking token usage across different stages or components of a chat interaction.

src/main/java/de/tum/cit/aet/artemis/core/repository/LLMTokenUsageRepository.java (5)

1-1: LGTM: Package declaration follows conventions.

The package declaration adheres to Java naming conventions and follows the project's structure.


3-9: LGTM: Imports are well-organized and follow guidelines.

The import statements are properly organized, grouped logically, and avoid wildcard imports as per the coding guidelines.


11-12: LGTM: Annotations are appropriate and align with project requirements.

The @Repository annotation correctly identifies this as a Spring Data repository, and the @Profile(PROFILE_IRIS) annotation ensures that this repository is only active when the Iris profile is in use, which aligns with the PR objectives.


13-14: LGTM: Interface declaration follows best practices and coding guidelines.

The LLMTokenUsageRepository interface:

  • Follows CamelCase naming convention.
  • Extends the appropriate base repository (ArtemisJpaRepository).
  • Adheres to the single responsibility principle.
  • Correctly uses generics to specify the entity type (LLMTokenUsage) and ID type (Long).

The empty interface is appropriate as it inherits necessary methods from the base repository.


1-14: Overall: Excellent implementation of the LLMTokenUsageRepository.

This new repository interface is well-designed and aligns perfectly with the PR objectives for tracking token usage in the Iris service. It adheres to all relevant coding guidelines, including:

  1. Proper package structure and naming conventions.
  2. Correct use of imports without wildcards.
  3. Appropriate use of Spring annotations (@repository and @Profile).
  4. Following the single responsibility principle and extending the correct base repository.

The empty interface is sufficient as it inherits all necessary methods from ArtemisJpaRepository. This implementation provides a solid foundation for managing LLMTokenUsage entities within the Artemis application.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/dto/competency/PyrisCompetencyStatusUpdateDTO.java (2)

7-7: LGTM: New import added for PyrisLLMCostDTO

The import for PyrisLLMCostDTO is correctly added to support the new parameter in the record.


19-19: LGTM: Record updated to include token information

The PyrisCompetencyStatusUpdateDTO record has been correctly updated to include the List<PyrisLLMCostDTO> tokens parameter. This change aligns with the PR objectives to track token usage in Iris requests.

A few observations:

  1. The naming convention follows CamelCase as required.
  2. The record adheres to the single responsibility principle, focusing on competency status updates.
  3. The use of List for all parameters suggests consistency in data structure.
  4. The record uses Java records, which aligns with the DTO guidelines.
src/main/webapp/app/entities/iris/iris-message.model.ts (1)

Line range hint 1-31: Overall structure and changes look good

The overall structure of the file and the changes made align well with the PR objective of tracking token usage. The file adheres to most of the coding guidelines, including:

  • Using single quotes for strings
  • Using PascalCase for enums and types
  • Following the Angular style guide

Once the property naming is adjusted to camelCase as suggested in the previous comments, the file will fully comply with the coding guidelines.

src/main/java/de/tum/cit/aet/artemis/iris/dto/IrisChatWebsocketDTO.java (3)

12-12: LGTM: Import statement added correctly.

The new import for PyrisLLMCostDTO is necessary for the added tokens field and follows the Java import guidelines.


25-26: LGTM: Record declaration updated appropriately.

The addition of the List<PyrisLLMCostDTO> tokens parameter to the record declaration is consistent with the PR objectives and follows coding guidelines. It maintains the single responsibility principle for this DTO.


Line range hint 1-73: Overall, the changes effectively implement token usage tracking.

The modifications to IrisChatWebsocketDTO successfully incorporate the new tokens field for tracking LLM token usage. The changes are consistent and adhere to coding guidelines. Minor improvements have been suggested for documentation and object comparison. Once these are addressed, the implementation will be robust and aligned with the PR objectives.

src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisCourseChatSessionService.java (3)

22-22: LGTM: Import statement added correctly.

The import for LLMTokenUsageService is properly placed and follows the coding guideline of avoiding star imports.


47-48: LGTM: Field added correctly following best practices.

The llmTokenUsageService field is properly declared as private and final, adhering to the principle of least access. The use of constructor injection for this dependency is in line with best practices for dependency injection.


Line range hint 1-238: Consider adding documentation and improving error handling.

The changes for incorporating token usage tracking have been implemented well and align with the PR objectives. To further improve the code:

  1. Add JavaDoc comments to the new llmTokenUsageService field and the modified handleStatusUpdate method to explain their purpose and any important details about token usage tracking.

  2. Consider adding error handling for the token usage saving operations. For example:

try {
    llmTokenUsageService.saveTokenUsage(...);
} catch (Exception e) {
    // Log the error and possibly notify an admin
    log.error("Failed to save token usage", e);
}
  1. Ensure that the LLMTokenUsageService is properly configured and tested. You might want to add integration tests for the token usage tracking functionality.

To verify the proper configuration of LLMTokenUsageService, please run the following command:

This will help ensure that the new service is properly set up in the application context.

src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (2)

63-64: Ensure handling when user is null

The code sets userId only if user is not null:

if (user != null) {
    llmTokenUsage.setUserId(user.getId());
}

Is it acceptable for userId to be null in LLMTokenUsage? If userId is a non-nullable field in the database, this may cause issues.

If userId must not be null, consider throwing an exception or handling this case appropriately.


66-70: Check for potential null values in PyrisLLMCostDTO properties

When accessing properties of PyrisLLMCostDTO, such as num_input_tokens(), cost_per_input_token(), etc., there's no check for null values. If any of these methods can return null, it could lead to NullPointerException.

Confirm whether the properties of PyrisLLMCostDTO are guaranteed to be non-null. If they can be null, add checks or default values.

src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (3)

11-11: Import LLMTokenUsageService added correctly

The import statement for LLMTokenUsageService has been appropriately added, ensuring the class is recognized within this file.


29-29: Declaration of llmTokenUsageService aligns with best practices

The llmTokenUsageService is declared as a private final field, adhering to the principles of immutability and least access. This follows the best practice for dependency injection.


35-40: Constructor updated with new dependency

The constructor has been correctly updated to include LLMTokenUsageService llmTokenUsageService, and the assignment this.llmTokenUsageService = llmTokenUsageService; has been added. This aligns with the dependency injection via constructor injection guideline.

src/main/java/de/tum/cit/aet/artemis/iris/service/websocket/IrisChatWebsocketService.java (5)

14-14: Addition of PyrisLLMCostDTO import is appropriate

The import of PyrisLLMCostDTO is necessary for handling token cost data in the updated methods.


45-45: Ensure IrisChatWebsocketDTO handles null values safely

When constructing IrisChatWebsocketDTO with null values for suggestions and tokens, verify that the class handles null inputs appropriately to prevent potential NullPointerException issues.


56-56: Method overloading maintains backward compatibility

The sendStatusUpdate method now delegates to the overloaded method with additional parameters. This approach maintains backward compatibility and promotes code reuse.


70-70: Handle potential null values in payload

When constructing the payload with null for irisMessage, ensure that the IrisChatWebsocketDTO class and its consumers handle null values correctly to prevent unexpected behaviors.


66-66: ⚠️ Potential issue

Changing public method signature may introduce breaking changes

The sendStatusUpdate method signature has been updated to include suggestions and tokens. This could potentially break existing code that calls this method with the old signature. Ensure that all external callers have been updated to match the new method signature to prevent runtime errors.

Run the following script to identify any usages of sendStatusUpdate that may need updating:

✅ Verification successful

Verification Successful: No usages of sendStatusUpdate with the old signature found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to `sendStatusUpdate` with the old signature.

# Test: Search for method calls to `sendStatusUpdate` with three arguments (excluding 'this' pointer).
# Expect: No instances should be found; all calls should use the new signature with four arguments.

ast-grep --lang java --pattern '$_.sendStatusUpdate($_, $_, $_)' --ignore 'IrisChatWebsocketService.java'

Length of output: 326


Script:

#!/bin/bash
# Description: Find all calls to `sendStatusUpdate` with the old signature, excluding IrisChatWebsocketService.java.

# Using fd to list all Java files excluding IrisChatWebsocketService.java and passing them to ast-grep
fd --extension java --exclude 'IrisChatWebsocketService.java' | xargs ast-grep --lang java --pattern '$_.sendStatusUpdate($_, $_, $_)'

Length of output: 258


Script:

#!/bin/bash
# Description: Find all calls to `sendStatusUpdate` with the old signature, excluding IrisChatWebsocketService.java and EncodingISO_8559_1.java.

# Using fd to list all Java files excluding the specified problematic files and passing them to ast-grep
fd --extension java --exclude 'IrisChatWebsocketService.java' --exclude 'EncodingISO_8559_1.java' | xargs ast-grep --lang java --pattern '$_.sendStatusUpdate($_, $_, $_)' 2>/dev/null

Length of output: 168

@alexjoham alexjoham changed the title Iris: Track token usage of iris requests Iris: Track token usage of iris requests Oct 12, 2024
Copy link
Member

@Hialus Hialus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through the server code and left some comments.
A general feedback point would be to please add server tests for your feature.

@ls1intum ls1intum deleted a comment from coderabbitai bot Oct 23, 2024
@ls1intum ls1intum deleted a comment from coderabbitai bot Oct 23, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 23, 2024
@ls1intum ls1intum deleted a comment from github-actions bot Oct 23, 2024
krusche
krusche previously approved these changes Oct 23, 2024
Copy link
Member

@krusche krusche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good to me 👍 In case the feature works as expected, I suggest we merge the PR now so we can use it on production. We can still improve small aspects in follow-up PRs.

Copy link
Contributor

@FelixTJDietrich FelixTJDietrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also verified that it works locally for Athena.

dmytropolityka
dmytropolityka previously approved these changes Oct 23, 2024
Copy link
Contributor

@dmytropolityka dmytropolityka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works as expected for Athena

@bassner bassner force-pushed the feature/track-usage-of-iris-requests branch from 8671e35 to 79b1b88 Compare October 23, 2024 17:42
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (12)
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/TrackedSessionBasedPyrisJob.java (2)

3-6: Consider enhancing JavaDoc documentation.

While the documentation is clear, consider adding:

  • @since tag for version tracking
  • Documentation about the relationship with PyrisJob interface
 /**
  * A Pyris job that has a session id and stored its own LLM usage tracing ID.
  * This is used for chat jobs where we need to reference the trace ID later after chat suggestions have been generated.
+ * 
+ * @since 1.0.0
+ * @see PyrisJob The parent interface that this extends
  */

7-14: Consider addressing type consistency and documentation.

  1. Type consistency: sessionId() returns primitive long while traceId() returns wrapper Long. Consider using consistent types unless there's a specific reason for nullable trace IDs.

  2. Missing method documentation: Add JavaDoc for each method explaining:

    • Parameters
    • Return values
    • Nullable conditions
    • Any validation requirements
 public interface TrackedSessionBasedPyrisJob extends PyrisJob {
 
+    /**
+     * Gets the session ID associated with this job.
+     *
+     * @return the session ID
+     */
     long sessionId();
 
+    /**
+     * Gets the trace ID used for LLM usage tracking.
+     *
+     * @return the trace ID, may be null if not yet assigned
+     */
     Long traceId();
 
+    /**
+     * Creates a new instance of this job with the specified trace ID.
+     *
+     * @param traceId the trace ID to assign
+     * @return a new instance with the specified trace ID
+     */
     TrackedSessionBasedPyrisJob withTraceId(long traceId);
 }
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/ExerciseChatJob.java (1)

25-28: Consider adding traceId validation.

The implementation correctly follows immutable pattern and KISS principle. However, consider validating the traceId parameter to prevent potential issues with negative values.

 @Override
 public TrackedSessionBasedPyrisJob withTraceId(long traceId) {
+    if (traceId <= 0) {
+        throw new IllegalArgumentException("Trace ID must be positive");
+    }
     return new ExerciseChatJob(jobId, courseId, exerciseId, sessionId, traceId);
 }
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (2)

32-41: Consider grouping related fields together

For better code organization and readability, consider grouping related fields together. For example, group repositories together and services together.

Apply this diff to improve field organization:

    private final PyrisPipelineService pyrisPipelineService;
    private final LLMTokenUsageService llmTokenUsageService;
-   private final CourseRepository courseRepository;
    private final IrisWebsocketService websocketService;
    private final PyrisJobService pyrisJobService;
+   private final CourseRepository courseRepository;
    private final UserRepository userRepository;

78-87: Consider removing unnecessary return value

The method returns the unmodified job object, which doesn't provide any additional value to the caller.

Consider changing the method signature to void since the job object isn't modified:

-    public CompetencyExtractionJob handleStatusUpdate(CompetencyExtractionJob job, PyrisCompetencyStatusUpdateDTO statusUpdate) {
+    public void handleStatusUpdate(CompetencyExtractionJob job, PyrisCompetencyStatusUpdateDTO statusUpdate) {
         // ... existing code ...
-        return job;
     }
src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (1)

117-117: Add JavaDoc for the abstract method.

The abstract method lacks documentation explaining its purpose and implementation requirements for subclasses.

Add JavaDoc:

/**
 * Sets specific parameters for LLM token usage tracking based on the session type.
 * Subclasses must implement this method to provide session-specific token usage parameters.
 *
 * @param builder The builder to configure with additional parameters
 * @param session The chat session containing context for the parameters
 * @return The configured builder
 */
protected abstract void setLLMTokenUsageParameters(LLMTokenUsageService.LLMTokenUsageBuilder builder, S session);
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisJobService.java (1)

110-122: Add parameter validation and improve documentation.

While the methods are concise and follow the single responsibility principle, they lack parameter validation and could benefit from more detailed documentation.

Consider these improvements:

     /**
      * Remove a job from the job map.
      *
      * @param job the job to remove
+     * @throws IllegalArgumentException if the job is null
      */
     public void removeJob(PyrisJob job) {
+        if (job == null) {
+            throw new IllegalArgumentException("Job cannot be null");
+        }
         jobMap.remove(job.jobId());
     }

     /**
      * Store a job in the job map.
      *
      * @param job the job to store
+     * @throws IllegalArgumentException if the job is null
      */
     public void updateJob(PyrisJob job) {
+        if (job == null) {
+            throw new IllegalArgumentException("Job cannot be null");
+        }
         jobMap.put(job.jobId(), job);
     }
src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java (3)

119-119: Update JavaDoc to reflect the return value.

The method signature change to return TextExerciseChatJob looks good, but the JavaDoc should be updated to document the return value.

Add the @return tag to the JavaDoc:

     /**
      * Handles the status update of a text exercise chat job.
      *
      * @param job          The job that is updated
      * @param statusUpdate The status update
+     * @return The updated job
      */

Also applies to: 132-132


Line range hint 120-131: Add error handling for external service calls.

The implementation looks good, but it's missing error handling for the external service calls (irisMessageService.saveMessage and irisChatWebsocketService.sendMessage). These operations could fail and throw exceptions.

Consider wrapping the external calls in try-catch blocks:

     if (statusUpdate.result() != null) {
         var message = session.newMessage();
         message.addContent(new IrisTextMessageContent(statusUpdate.result()));
-        IrisMessage savedMessage = irisMessageService.saveMessage(message, session, IrisMessageSender.LLM);
-        irisChatWebsocketService.sendMessage(session, savedMessage, statusUpdate.stages());
+        try {
+            IrisMessage savedMessage = irisMessageService.saveMessage(message, session, IrisMessageSender.LLM);
+            irisChatWebsocketService.sendMessage(session, savedMessage, statusUpdate.stages());
+        } catch (Exception e) {
+            // Log the error and potentially throw a custom exception
+            log.error("Failed to save or send message: {}", e.getMessage(), e);
+            throw new IrisMessageHandlingException("Failed to process status update", e);
+        }
     } else {
-        irisChatWebsocketService.sendMessage(session, null, statusUpdate.stages());
+        try {
+            irisChatWebsocketService.sendMessage(session, null, statusUpdate.stages());
+        } catch (Exception e) {
+            log.error("Failed to send message: {}", e.getMessage(), e);
+            throw new IrisMessageHandlingException("Failed to send status update", e);
+        }
     }
🧰 Tools
🪛 ast-grep

[warning] 123-123: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 123-123: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


120-120: Consider implementing the suggested inheritance refactoring.

The TODO comment suggests making this class a subclass of AbstractIrisChatSessionService. This refactoring could improve code reuse and standardize token tracking across different chat services.

Would you like me to help create a GitHub issue to track this refactoring task? I can provide a detailed plan for:

  1. Creating the abstract base class
  2. Moving common functionality
  3. Implementing token tracking consistently
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java (2)

57-58: Correct the grammatical error in the method documentation

The documentation should use "an exercise chat job" instead of "a exercise chat job".

Apply this diff to fix the typo:

 /**
- * Handles the status update of a exercise chat job and forwards it to
+ * Handles the status update of an exercise chat job and forwards it to
  * {@link IrisExerciseChatSessionService#handleStatusUpdate(TrackedSessionBasedPyrisJob, PyrisChatStatusUpdateDTO)}

135-137: Address the TODO comment in handleStatusUpdate for IngestionWebhookJob

There's a TODO comment indicating that this method should be updated to handle changes beyond logging. Consider implementing the required functionality.

Would you like assistance in generating the updated implementation or opening a GitHub issue to track this task?

🛑 Comments failed to post (8)
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CourseChatJob.java (1)

12-12: 🛠️ Refactor suggestion

Consider using primitive long instead of Long for traceId.

Since tracing is a core feature for token usage tracking, consider using the primitive long type instead of Long to:

  1. Prevent potential null pointer exceptions
  2. Reduce memory overhead
  3. Enforce mandatory tracing
-public record CourseChatJob(String jobId, long courseId, long sessionId, Long traceId) implements TrackedSessionBasedPyrisJob {
+public record CourseChatJob(String jobId, long courseId, long sessionId, long traceId) implements TrackedSessionBasedPyrisJob {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

public record CourseChatJob(String jobId, long courseId, long sessionId, long traceId) implements TrackedSessionBasedPyrisJob {
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (2)

79-82: 🛠️ Refactor suggestion

Optimize database query and simplify token check

The course is retrieved even when tokens might be null or empty. Also, the token check can be simplified.

Apply this diff to optimize the code:

-    Course course = courseRepository.findByIdForUpdateElseThrow(job.courseId());
-    if (statusUpdate.tokens() != null && !statusUpdate.tokens().isEmpty()) {
+    if (statusUpdate.tokens() != null && !statusUpdate.tokens().isEmpty()) {
+        Course course = courseRepository.findByIdForUpdateElseThrow(job.courseId());
         llmTokenUsageService.saveLLMTokenUsage(statusUpdate.tokens(), LLMServiceType.IRIS, 
             builder -> builder.withCourse(course.getId()).withUser(job.userId()));
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        if (statusUpdate.tokens() != null && !statusUpdate.tokens().isEmpty()) {
            Course course = courseRepository.findByIdForUpdateElseThrow(job.courseId());
            llmTokenUsageService.saveLLMTokenUsage(statusUpdate.tokens(), LLMServiceType.IRIS, builder -> builder.withCourse(course.getId()).withUser(job.userId()));
        }

84-84: ⚠️ Potential issue

Improve error handling for user retrieval

The current implementation might throw a generic NoSuchElementException. Consider providing a more specific error message.

Apply this diff:

-    var user = userRepository.findById(job.userId()).orElseThrow();
+    var user = userRepository.findById(job.userId())
+        .orElseThrow(() -> new IllegalStateException("User not found for job: " + job.userId()));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        var user = userRepository.findById(job.userId())
            .orElseThrow(() -> new IllegalStateException("User not found for job: " + job.userId()));
src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (2)

71-115: 🛠️ Refactor suggestion

Consider breaking down the handleStatusUpdate method.

The method is handling multiple responsibilities which makes it harder to maintain and test. Consider extracting the following into separate methods:

  1. Message handling logic
  2. Token usage tracking logic
  3. Trace management logic

Here's a suggested refactoring approach:

public TrackedSessionBasedPyrisJob handleStatusUpdate(TrackedSessionBasedPyrisJob job, PyrisChatStatusUpdateDTO statusUpdate) {
    var session = getAndValidateSession(job.sessionId());
    var savedMessage = handleMessageUpdate(session, statusUpdate);
    var updatedJob = handleTokenUsage(job, statusUpdate, session, savedMessage);
    updateLatestSuggestions(session, statusUpdate.suggestions());
    return updatedJob;
}

private S getAndValidateSession(String sessionId) {
    var session = (S) irisSessionRepository.findByIdWithMessagesAndContents(sessionId);
    if (session == null) {
        throw new IllegalStateException("Session not found with id: " + sessionId);
    }
    return session;
}

private IrisMessage handleMessageUpdate(S session, PyrisChatStatusUpdateDTO statusUpdate) {
    if (statusUpdate.result() != null) {
        var message = new IrisMessage();
        message.addContent(new IrisTextMessageContent(statusUpdate.result()));
        var savedMessage = irisMessageService.saveMessage(message, session, IrisMessageSender.LLM);
        irisChatWebsocketService.sendMessage(session, savedMessage, statusUpdate.stages());
        return savedMessage;
    }
    irisChatWebsocketService.sendStatusUpdate(session, statusUpdate.stages(), 
        statusUpdate.suggestions(), statusUpdate.tokens());
    return null;
}

private TrackedSessionBasedPyrisJob handleTokenUsage(TrackedSessionBasedPyrisJob job, 
    PyrisChatStatusUpdateDTO statusUpdate, S session, IrisMessage savedMessage) {
    if (statusUpdate.tokens() == null || statusUpdate.tokens().isEmpty()) {
        return job;
    }
    return savedMessage != null ? 
        handleNewTrace(job, statusUpdate, session, savedMessage) :
        handleExistingTrace(job, statusUpdate, session);
}
🧰 Tools
🪛 ast-grep

[warning] 75-75: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 75-75: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


71-73: ⚠️ Potential issue

Add null check for session retrieval.

The session retrieval could return null, but there's no null check before using it.

Add a null check:

 var session = (S) irisSessionRepository.findByIdWithMessagesAndContents(job.sessionId());
+if (session == null) {
+    throw new IllegalStateException("Session not found with id: " + job.sessionId());
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    public TrackedSessionBasedPyrisJob handleStatusUpdate(TrackedSessionBasedPyrisJob job, PyrisChatStatusUpdateDTO statusUpdate) {
        var session = (S) irisSessionRepository.findByIdWithMessagesAndContents(job.sessionId());
        if (session == null) {
            throw new IllegalStateException("Session not found with id: " + job.sessionId());
        }
        IrisMessage savedMessage;
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisJobService.java (2)

81-81: ⚠️ Potential issue

Update method signature and avoid passing null directly.

The code passes null directly to the ExerciseChatJob constructor, which is a code smell and could lead to NullPointerException. Additionally, the method signature hasn't been updated to match the constructor change.

Consider these improvements:

  1. Update the method signature to include the new parameter
  2. Add parameter validation
  3. Update JavaDoc
-    public String addExerciseChatJob(Long courseId, Long exerciseId, Long sessionId) {
+    /**
+     * Creates a new exercise chat job.
+     *
+     * @param courseId the ID of the course
+     * @param exerciseId the ID of the exercise
+     * @param sessionId the ID of the session
+     * @param tokenUsageData the token usage tracking data (can be null)
+     * @return the generated job token
+     */
+    public String addExerciseChatJob(Long courseId, Long exerciseId, Long sessionId, PyrisLLMCostDTO tokenUsageData) {
         var token = generateJobIdToken();
-        var job = new ExerciseChatJob(token, courseId, exerciseId, sessionId, null);
+        var job = new ExerciseChatJob(token, courseId, exerciseId, sessionId, tokenUsageData);
         jobMap.put(token, job);
         return token;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    /**
     * Creates a new exercise chat job.
     *
     * @param courseId the ID of the course
     * @param exerciseId the ID of the exercise
     * @param sessionId the ID of the session
     * @param tokenUsageData the token usage tracking data (can be null)
     * @return the generated job token
     */
    public String addExerciseChatJob(Long courseId, Long exerciseId, Long sessionId, PyrisLLMCostDTO tokenUsageData) {
        var token = generateJobIdToken();
        var job = new ExerciseChatJob(token, courseId, exerciseId, sessionId, tokenUsageData);
        jobMap.put(token, job);
        return token;
    }

88-88: ⚠️ Potential issue

Update method signature and avoid passing null directly.

Similar to addExerciseChatJob, this method passes null directly and needs signature updates.

Apply similar improvements:

-    public String addCourseChatJob(Long courseId, Long sessionId) {
+    /**
+     * Creates a new course chat job.
+     *
+     * @param courseId the ID of the course
+     * @param sessionId the ID of the session
+     * @param tokenUsageData the token usage tracking data (can be null)
+     * @return the generated job token
+     */
+    public String addCourseChatJob(Long courseId, Long sessionId, PyrisLLMCostDTO tokenUsageData) {
         var token = generateJobIdToken();
-        var job = new CourseChatJob(token, courseId, sessionId, null);
+        var job = new CourseChatJob(token, courseId, sessionId, tokenUsageData);
         jobMap.put(token, job);
         return token;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    /**
     * Creates a new course chat job.
     *
     * @param courseId the ID of the course
     * @param sessionId the ID of the session
     * @param tokenUsageData the token usage tracking data (can be null)
     * @return the generated job token
     */
    public String addCourseChatJob(Long courseId, Long sessionId, PyrisLLMCostDTO tokenUsageData) {
        var token = generateJobIdToken();
        var job = new CourseChatJob(token, courseId, sessionId, tokenUsageData);
        jobMap.put(token, job);
        return token;
    }
src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1)

99-141: 🛠️ Refactor suggestion

Standardize the Use of 'Id' in Variable and Method Names for Consistency

The code uses both ID and Id in variable and method names within the LLMTokenUsageBuilder class (e.g., courseID vs. courseId). According to Java naming conventions, Id is preferred over ID. For consistency and readability, consider standardizing all variable and method names to use Id.

Apply this diff to update the naming convention:

- private Optional<Long> courseID = Optional.empty();
+ private Optional<Long> courseId = Optional.empty();

- private Optional<Long> irisMessageID = Optional.empty();
+ private Optional<Long> irisMessageId = Optional.empty();

- private Optional<Long> exerciseID = Optional.empty();
+ private Optional<Long> exerciseId = Optional.empty();

- private Optional<Long> userID = Optional.empty();
+ private Optional<Long> userId = Optional.empty();

- public LLMTokenUsageBuilder withCourse(Long courseID) {
+ public LLMTokenUsageBuilder withCourse(Long courseId) {

- public LLMTokenUsageBuilder withIrisMessageID(Long irisMessageID) {
+ public LLMTokenUsageBuilder withIrisMessageId(Long irisMessageId) {

- public LLMTokenUsageBuilder withExercise(Long exerciseID) {
+ public LLMTokenUsageBuilder withExercise(Long exerciseId) {

- public LLMTokenUsageBuilder withUser(Long userID) {
+ public LLMTokenUsageBuilder withUser(Long userId) {

- public Optional<Long> getCourseID() {
+ public Optional<Long> getCourseId() {

- public Optional<Long> getIrisMessageID() {
+ public Optional<Long> getIrisMessageId() {

- public Optional<Long> getExerciseID() {
+ public Optional<Long> getExerciseId() {

- public Optional<Long> getUserID() {
+ public Optional<Long> getUserId() {

Also, ensure that all references to these variables and methods are updated accordingly throughout the codebase.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

        private Optional<Long> courseId = Optional.empty();

        private Optional<Long> irisMessageId = Optional.empty();

        private Optional<Long> exerciseId = Optional.empty();

        private Optional<Long> userId = Optional.empty();

        public LLMTokenUsageBuilder withCourse(Long courseId) {
            this.courseId = Optional.ofNullable(courseId);
            return this;
        }

        public LLMTokenUsageBuilder withIrisMessageId(Long irisMessageId) {
            this.irisMessageId = Optional.ofNullable(irisMessageId);
            return this;
        }

        public LLMTokenUsageBuilder withExercise(Long exerciseId) {
            this.exerciseId = Optional.ofNullable(exerciseId);
            return this;
        }

        public LLMTokenUsageBuilder withUser(Long userId) {
            this.userId = Optional.ofNullable(userId);
            return this;
        }

        public Optional<Long> getCourseId() {
            return courseId;
        }

        public Optional<Long> getIrisMessageId() {
            return irisMessageId;
        }

        public Optional<Long> getExerciseId() {
            return exerciseId;
        }

        public Optional<Long> getUserId() {
            return userId;
        }

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (7)
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (2)

42-50: Reorder field assignments to match constructor parameter order.

The field assignments in the constructor should follow the same order as the parameters for better readability and maintainability.

Apply this diff:

 public IrisCompetencyGenerationService(PyrisPipelineService pyrisPipelineService, LLMTokenUsageService llmTokenUsageService, CourseRepository courseRepository,
         IrisWebsocketService websocketService, PyrisJobService pyrisJobService, UserRepository userRepository) {
     this.pyrisPipelineService = pyrisPipelineService;
-    this.llmTokenUsageService = llmTokenUsageService;
-    this.courseRepository = courseRepository;
-    this.websocketService = websocketService;
-    this.pyrisJobService = pyrisJobService;
-    this.userRepository = userRepository;
+    this.llmTokenUsageService = llmTokenUsageService;
+    this.courseRepository = courseRepository;
+    this.websocketService = websocketService;
+    this.pyrisJobService = pyrisJobService;
+    this.userRepository = userRepository;
 }

84-84: Improve error handling for user lookup.

The orElseThrow() without a custom message makes debugging harder. Consider adding a descriptive error message.

Apply this diff:

-var user = userRepository.findById(job.userId()).orElseThrow();
+var user = userRepository.findById(job.userId())
+    .orElseThrow(() -> new IllegalStateException("User not found for ID: " + job.userId()));
src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java (4)

64-64: Consider adding final modifier to local variables.

The job handling logic is well-structured and consistent across all handlers. Consider making the local variables final for better immutability:

-var updatedJob = irisExerciseChatSessionService.handleStatusUpdate(job, statusUpdate);
+final var updatedJob = irisExerciseChatSessionService.handleStatusUpdate(job, statusUpdate);

Also applies to: 66-66, 77-77, 79-79, 90-90, 92-92, 103-103, 105-105


109-125: Consider extracting the terminal state check to a private method.

The method is well-documented and follows the single responsibility principle. To improve readability further, consider extracting the terminal state check:

 private void removeJobIfTerminatedElseUpdate(List<PyrisStageDTO> stages, PyrisJob job) {
-    var isDone = stages.stream().map(PyrisStageDTO::state).allMatch(PyrisStageState::isTerminal);
+    var isDone = isJobTerminated(stages);
     if (isDone) {
         pyrisJobService.removeJob(job);
     }
     else {
         pyrisJobService.updateJob(job);
     }
 }

+private boolean isJobTerminated(List<PyrisStageDTO> stages) {
+    return stages.stream()
+        .map(PyrisStageDTO::state)
+        .allMatch(PyrisStageState::isTerminal);
+}

137-137: Track the TODO comment for future implementation.

The method correctly uses the new job handling logic, but there's a TODO comment indicating that this method needs to be updated beyond logging.

Would you like me to create a GitHub issue to track the TODO for implementing the complete lecture ingestion handling?


Based on the verification results, I can now provide a final response:

TextExerciseChatJob needs to implement TrackedSessionBasedPyrisJob interface

The verification reveals inconsistencies in the implementation:

  • ExerciseChatJob and CourseChatJob correctly implement TrackedSessionBasedPyrisJob
  • TextExerciseChatJob only implements PyrisJob, despite being used in similar session-based contexts
  • CompetencyExtractionJob and IngestionWebhookJob correctly implement PyrisJob as they are not session-based

Required changes:

  • TextExerciseChatJob should implement TrackedSessionBasedPyrisJob interface
  • Add sessionId (already present) and traceId fields
  • Implement withTraceId method as required by the interface
🔗 Analysis chain

Line range hint 1-138: Verify consistent implementation of TrackedSessionBasedPyrisJob.

Let's verify that all relevant job types properly implement the new interface and maintain consistent patterns.


Let me generate new shell scripts with corrected syntax to verify the implementation.


Let me generate one final verification script to check the remaining job implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent implementation of TrackedSessionBasedPyrisJob interface

# Test 1: Check job implementations
echo "Checking job implementations..."
ast-grep --pattern 'class $_ implements TrackedSessionBasedPyrisJob {
  $$$
}'

# Test 2: Check for any remaining direct PyrisJob usage that should be TrackedSessionBasedPyrisJob
echo "Checking for potential missed conversions..."
rg "PyrisJob(?!.*TrackedSessionBasedPyrisJob)" -g "*.java"

Length of output: 690


Script:

#!/bin/bash
# Let's break this down into multiple checks

# 1. Find all files that mention TrackedSessionBasedPyrisJob
echo "=== Files referencing TrackedSessionBasedPyrisJob ==="
rg "TrackedSessionBasedPyrisJob" --type java

# 2. Find all job class definitions
echo -e "\n=== Job class definitions ==="
rg "class \w+(?:Chat|Extraction|Webhook)Job" --type java

# 3. Check PyrisJob interface/class definition
echo -e "\n=== PyrisJob definition ==="
rg "^(interface|class) PyrisJob" --type java -A 5

# 4. Check service implementations handling these jobs
echo -e "\n=== Service methods handling jobs ==="
rg "handleStatusUpdate.*Job" --type java -A 2

# 5. Check for job type usage in PyrisStatusUpdateService
echo -e "\n=== Job type usage in status service ==="
rg "(?:Chat|Extraction|Webhook)Job" src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java

Length of output: 10513


Script:

#!/bin/bash
# Check implementation details of remaining job types

# 1. Check TextExerciseChatJob implementation
echo "=== TextExerciseChatJob Implementation ==="
rg "record TextExerciseChatJob" --type java -A 5

# 2. Check CompetencyExtractionJob implementation
echo -e "\n=== CompetencyExtractionJob Implementation ==="
rg "record CompetencyExtractionJob" --type java -A 5

# 3. Check IngestionWebhookJob implementation
echo -e "\n=== IngestionWebhookJob Implementation ==="
rg "record IngestionWebhookJob" --type java -A 5

# 4. Check TrackedSessionBasedPyrisJob interface definition
echo -e "\n=== TrackedSessionBasedPyrisJob Interface Definition ==="
rg "interface TrackedSessionBasedPyrisJob" --type java -A 10

Length of output: 3730

src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1)

36-48: Enhance JavaDoc documentation

The JavaDoc could be improved for better clarity and completeness.

Add more detailed documentation:

     /**
      * Saves the token usage to the database.
      * This method records the usage of tokens by various LLM services in the system.
+     * The method executes asynchronously to prevent blocking the main operation flow.
      *
      * @param llmRequests     List of LLM requests containing details about the token usage.
      * @param serviceType     Type of the LLM service (e.g., IRIS, GPT-3).
      * @param builderFunction A function that takes an LLMTokenUsageBuilder and returns a modified LLMTokenUsageBuilder.
      *                            This function is used to set additional properties on the LLMTokenUsageTrace object, such as
      *                            the course ID, user ID, exercise ID, and Iris message ID.
      *                            Example usage:
-     *                            builder -> builder.withCourse(courseId).withUser(userId)
+     *                            builder -> builder.withCourse(courseId)
+     *                                             .withUser(userId)
+     *                                             .withMessageId(messageId)
+     *                                             .withExercise(exerciseId)
      * @return The saved LLMTokenUsageTrace object, which includes the details of the token usage.
+     * @throws IllegalArgumentException if llmRequests is null or empty
      */
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8671e35 and 79b1b88.

📒 Files selected for processing (9)
  • src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisJobService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CourseChatJob.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/ExerciseChatJob.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/TrackedSessionBasedPyrisJob.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisJobService.java
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/CourseChatJob.java
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/ExerciseChatJob.java
  • src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/job/TrackedSessionBasedPyrisJob.java
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java
🧰 Additional context used
📓 Path-based instructions (4)
src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🪛 ast-grep
src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java

[warning] 53-53: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new LLMTokenUsageBuilder())
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 53-53: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new LLMTokenUsageBuilder())
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java

[warning] 66-66: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (user.getLogin(), websocketTopic(course.getId()), new PyrisCompetencyStatusUpdateDTO(stages, null, null))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 66-66: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (user.getLogin(), websocketTopic(course.getId()), new PyrisCompetencyStatusUpdateDTO(stages, null, null))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java

[warning] 76-76: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 76-76: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (new IrisTextMessageContent(statusUpdate.result()))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

🔇 Additional comments (6)
src/main/java/de/tum/cit/aet/artemis/iris/service/session/AbstractIrisChatSessionService.java (3)

4-5: LGTM: Well-structured field declarations and imports.

The new fields follow proper encapsulation, immutability, and dependency injection principles. The imports are organized logically and avoid star imports as per coding guidelines.

Also applies to: 10-14, 17-20, 26-31


34-40: LGTM: Constructor properly implements dependency injection.

The constructor follows best practices by using constructor injection and properly initializing all fields.


118-118: LGTM: Well-designed abstract method.

The abstract method follows the template method pattern and has appropriate access level. The method name and parameters clearly convey its purpose.

src/main/java/de/tum/cit/aet/artemis/iris/service/pyris/PyrisStatusUpdateService.java (2)

23-23: LGTM: Import statements follow conventions.

The new imports are properly organized and follow the coding guidelines.

Also applies to: 25-25


57-58: LGTM: JavaDoc updates are accurate and well-maintained.

The documentation properly reflects the parameter type changes and maintains correct method references.

Also applies to: 84-84

src/main/java/de/tum/cit/aet/artemis/core/service/LLMTokenUsageService.java (1)

1-34: LGTM! Class structure follows Spring best practices.

The service is properly configured with constructor injection and appropriate annotations.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (2)

32-40: Consider reordering fields for better readability

The field declarations could be grouped more logically. Consider keeping related fields together:

  1. Pipeline-related: pyrisPipelineService
  2. Repository-related: courseRepository, userRepository
  3. Service-related: llmTokenUsageService, websocketService, pyrisJobService

79-83: Consider adding transaction management

The method performs multiple database operations (course and token usage). Consider adding transaction management to ensure data consistency:

+    @Transactional
     public CompetencyExtractionJob handleStatusUpdate(CompetencyExtractionJob job, PyrisCompetencyStatusUpdateDTO statusUpdate) {

This ensures that both the course retrieval and token usage saving are executed within the same transaction.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 79b1b88 and 5a2e92a.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/de/tum/cit/aet/artemis/iris/service/session/IrisTextExerciseChatSessionService.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🪛 ast-grep
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java

[warning] 66-66: Detected a cookie where the Secure flag is either missing or disabled. The Secure cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set the Secure flag to true so the cookie will only be sent over HTTPS.
Context: (user.getLogin(), websocketTopic(course.getId()), new PyrisCompetencyStatusUpdateDTO(stages, null, null))
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration


[warning] 66-66: Detected a cookie where the HttpOnly flag is either missing or disabled. The HttpOnly cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set the HttpOnly flag to true` in all other cases.
Context: (user.getLogin(), websocketTopic(course.getId()), new PyrisCompetencyStatusUpdateDTO(stages, null, null))
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration

🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/iris/service/IrisCompetencyGenerationService.java (1)

42-49: LGTM! Constructor follows best practices

The constructor properly uses dependency injection and correctly initializes all fields.

Copy link
Contributor

@FelixTJDietrich FelixTJDietrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good to me

@bassner bassner added this to the 7.6.2 milestone Oct 23, 2024
@bassner bassner merged commit dd96df5 into develop Oct 23, 2024
41 of 45 checks passed
@bassner bassner deleted the feature/track-usage-of-iris-requests branch October 23, 2024 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
athena Pull requests that affect the corresponding module core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. iris Pull requests that affect the corresponding module ready to merge server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

Iris: Track the token usage of requests
10 participants