Skip to content

feat: 인터뷰 세션 기능 추가 및 코드 구조 개선#1641

Merged
jaeyeonling merged 17 commits intomainfrom
feature/qna-helper
Apr 14, 2025
Merged

feat: 인터뷰 세션 기능 추가 및 코드 구조 개선#1641
jaeyeonling merged 17 commits intomainfrom
feature/qna-helper

Conversation

@jaeyeonling
Copy link
Contributor

이 풀 리퀘스트는 인터뷰 세션 기능 강화를 위한 백엔드의 주요 변경 사항을 포함하고 있으며, 전체적인 코드 구조 개선도 함께 이루어졌습니다. 주요 변경 사항은 다음과 같습니다:

인터뷰 세션 기능 향상:

  • InterviewService 클래스 추가: 인터뷰 세션 생성 및 답변 처리를 담당 (backend/src/main/java/wooteco/prolog/interview/application/InterviewService.java)
  • InterviewSessionMapper 도입: 인터뷰 세션 엔티티를 응답 객체로 매핑 (backend/src/main/java/wooteco/prolog/interview/application/InterviewSessionMapper.java)
  • 인터뷰 세션 및 메시지 요청/응답용 클래스 추가
    (InterviewSessionRequest.java, InterviewSessionResponse.java, InterviewMessageResponse.java)
  • 인터뷰 메시지 관리를 위한 InterviewMessageInterviewMessages 클래스 생성
    (backend/src/main/java/wooteco/prolog/interview/domain/InterviewMessage.java,
    InterviewMessages.java)

의존성 업데이트:

  • spring-ai-openai, spring-ai-azure-openai-spring-boot-starter 제거 후
    spring-ai-starter-model-azure-openai로 교체 (backend/build.gradle)

인수 테스트:

  • 질문 관련 기능 테스트 스텝 추가 (QuestionStepDefinitions.java)
  • 세션 생성 스텝 추가 (SessionStepDefinitions.java)
  • 질문 관련 시나리오 피처 파일 추가 (question.feature)

코드 구조 개선:

  • AuditingEntityCreateAuditingEntity로 이름 변경 후
    AuditingEntity 클래스 생성 (AuditingEntity.java, CreateAuditingEntity.java)
  • AI 응답 처리 중 발생하는 예외를 처리하기 위한 AiResponseProcessingException 클래스 추가

이번 변경으로 인터뷰 세션 처리 기능이 강화되었고, 의존성 관리가 간소화되었으며, 코드 유지보수성 또한 향상되었습니다.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @jaeyeonling, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

This pull request introduces the interview session feature, enhances the backend functionality, and improves the overall code structure. It includes the addition of the InterviewService class, InterviewSessionMapper, and related request/response classes for managing interview sessions and messages. The dependencies have been updated, replacing spring-ai-openai and spring-ai-azure-openai-spring-boot-starter with spring-ai-starter-model-azure-openai. Acceptance tests have been added for questions and sessions. Code structure improvements include renaming AuditingEntity to CreateAuditingEntity and creating a new AuditingEntity class, along with the addition of AiResponseProcessingException for handling AI response exceptions.

Highlights

  • Interview Session Feature: Introduces core components for managing interview sessions, including session creation, answering, and message handling.
  • Dependency Update: Simplifies AI-related dependencies by replacing older libraries with spring-ai-starter-model-azure-openai.
  • Code Structure Improvement: Refactors auditing entities and adds a specific exception for handling AI response processing errors.
  • Acceptance Tests: Adds new acceptance tests to cover question creation/retrieval and session creation scenarios.

Changelog

Click here to see the changelog
  • backend/build.gradle
    • Replaced spring-ai-openai and spring-ai-azure-openai-spring-boot-starter with spring-ai-starter-model-azure-openai to simplify dependencies.
  • backend/src/acceptanceTest/java/wooteco/prolog/steps/QuestionStepDefinitions.java
    • Added Cucumber step definitions for creating and retrieving questions.
  • backend/src/acceptanceTest/java/wooteco/prolog/steps/SessionStepDefinitions.java
    • Added a Given annotation on line 22 to the existing 강의 생성 step definition.
  • backend/src/acceptanceTest/resources/wooteco/prolog/question.feature
    • Created a feature file with scenarios for question creation and retrieval.
  • backend/src/main/java/wooteco/prolog/DataLoaderApplicationListener.java
    • Modified the shouldSkip method on line 108 to check the number of members instead of checking for a specific username.
  • backend/src/main/java/wooteco/prolog/common/entity/AuditingEntity.java
    • Created a new AuditingEntity class extending CreateAuditingEntity to include updatedAt.
  • backend/src/main/java/wooteco/prolog/common/entity/CreateAuditingEntity.java
    • Renamed AuditingEntity to CreateAuditingEntity and moved createdAt field to this class.
  • backend/src/main/java/wooteco/prolog/common/exception/AiResponseProcessingException.java
    • Added a new exception class AiResponseProcessingException to handle invalid AI response formats.
  • backend/src/main/java/wooteco/prolog/common/exception/BadRequestCode.java
    • Added QUESTION_NOT_FOUND and INTERVIEW_SESSION_NOT_FOUND error codes.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewAnswerRequest.java
    • Created a record InterviewAnswerRequest for handling interview answer requests.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewMessageResponse.java
    • Created a record InterviewMessageResponse for representing interview message responses.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewService.java
    • Created InterviewService to handle interview session creation and answering logic.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewSessionMapper.java
    • Created InterviewSessionMapper to map InterviewSession entities to response objects.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewSessionRequest.java
    • Created a record InterviewSessionRequest for handling interview session requests.
  • backend/src/main/java/wooteco/prolog/interview/application/InterviewSessionResponse.java
    • Created a record InterviewSessionResponse for representing interview session responses.
  • backend/src/main/java/wooteco/prolog/interview/domain/FollowUpQuestion.java
    • Created a record FollowUpQuestion for representing follow-up questions.
  • backend/src/main/java/wooteco/prolog/interview/domain/InterviewMessage.java
    • Created InterviewMessage enum and class to represent interview messages with sender and type information.
  • backend/src/main/java/wooteco/prolog/interview/domain/InterviewMessages.java
    • Created InterviewMessages class to manage a collection of InterviewMessage objects.
  • backend/src/main/java/wooteco/prolog/interview/domain/InterviewSession.java
    • Created InterviewSession entity to represent an interview session.
  • backend/src/main/java/wooteco/prolog/interview/domain/Interviewer.java
    • Created Interviewer interface to define the behavior of an interviewer.
  • backend/src/main/java/wooteco/prolog/interview/domain/repository/InterviewSessionRepository.java
    • Created InterviewSessionRepository interface for managing InterviewSession entities in the database.
  • backend/src/main/java/wooteco/prolog/interview/infrastructure/AzureOpenAiInterviewer.java
    • Created AzureOpenAiInterviewer class implementing the Interviewer interface using Azure OpenAI.
  • backend/src/main/java/wooteco/prolog/interview/infrastructure/FakeInterviewer.java
    • Created FakeInterviewer class implementing the Interviewer interface for local and test environments.
  • backend/src/main/java/wooteco/prolog/interview/ui/InterviewController.java
    • Created InterviewController to handle interview-related HTTP requests.
  • backend/src/main/java/wooteco/prolog/levellogs/domain/LevelLog.java
    • Changed the import from wooteco.prolog.common.AuditingEntity to wooteco.prolog.common.entity.AuditingEntity.
  • backend/src/main/java/wooteco/prolog/roadmap/domain/EssayAnswer.java
    • Changed the import from wooteco.prolog.common.AuditingEntity to wooteco.prolog.common.entity.AuditingEntity.
  • backend/src/main/java/wooteco/prolog/session/application/QuestionService.java
    • Added methods to create and find questions, including transactional annotations and exception handling.
  • backend/src/main/java/wooteco/prolog/session/application/dto/QuestionRequest.java
    • Created a record QuestionRequest for handling question creation requests.
  • backend/src/main/java/wooteco/prolog/session/infrastructure/AzureOpenAiFeedbackProvider.java
    • Replaced RuntimeJsonProcessingException with AiResponseProcessingException for exception handling.
  • backend/src/main/java/wooteco/prolog/session/ui/QuestionController.java
    • Added endpoints for creating and retrieving questions.
  • backend/src/main/java/wooteco/prolog/studylog/domain/Comment.java
    • Changed the import from wooteco.prolog.common.AuditingEntity to wooteco.prolog.common.entity.AuditingEntity.
  • backend/src/main/java/wooteco/prolog/studylog/domain/PopularStudylog.java
    • Changed the import from wooteco.prolog.common.AuditingEntity to wooteco.prolog.common.entity.AuditingEntity.
  • backend/src/main/java/wooteco/prolog/studylog/domain/Studylog.java
    • Changed the import from wooteco.prolog.common.AuditingEntity to wooteco.prolog.common.entity.AuditingEntity.
  • backend/src/main/resources/application-local.yml
    • Excluded several AzureOpenAiAutoConfiguration classes.
  • backend/src/main/resources/application-test.yml
    • Excluded several AzureOpenAiAutoConfiguration classes.
  • backend/src/main/resources/db/migration/prod/V15__create_table_interview.sql
    • Created tables for interview sessions and messages.
  • backend/src/main/resources/prompts/qna-feedback.st
    • Removed the line ## 당신의 역할: 소프트웨어 엔지니어링 교육 코치 and added the line - 답변은 한글로 작성합니다.
  • backend/src/test/java/wooteco/prolog/interview/application/InterviewServiceTest.java
    • Added tests for interview session creation, answering, and completion.
  • backend/src/test/java/wooteco/prolog/interview/domain/InterviewMessagesTest.java
    • Added tests for the InterviewMessages domain.
  • backend/src/test/java/wooteco/prolog/session/infrastructure/AzureOpenAiFeedbackProviderTest.java
    • Modified the AzureOpenAiChatModel instantiation to use the builder pattern.
  • backend/src/test/java/wooteco/prolog/studylog/application/StudylogServiceTest.java
    • Modified the field retrieval to get the createdAt field.
  • frontend/src/components/Controls/SelectBox.tsx
    • Removed the selectedSessionId prop from the SelectBoxProps interface.
  • frontend/src/components/StudylogEditor/Sidebar.tsx
    • Modified the missionOptions and sessionOptions and selectedSession to use id instead of sessionId.
  • frontend/src/components/StudylogEditor/StudylogEditor.tsx
    • Modified the sessionId to use id instead of sessionId.
  • frontend/src/models/Studylogs.ts
    • Modified the Session interface to use id instead of sessionId.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


A session starts, questions arise,
AI guides with digital eyes,
Code evolves, answers flow,
Knowledge grows, as we all know,
In learning's realm, wisdom flies.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces interview session functionality and improves code structure. The changes include adding an InterviewService class, introducing InterviewSessionMapper, adding classes for interview session and message requests/responses, creating InterviewMessage and InterviewMessages classes, updating dependencies, adding 인수 tests, renaming AuditingEntity to CreateAuditingEntity and creating a new AuditingEntity class, and adding an AiResponseProcessingException class. Overall, the changes seem well-structured and contribute to enhancing the interview session feature.

Summary of Findings

  • Missing Foreign Key Constraint in SQL Migration: The member_id column in the interview_message table should have a foreign key constraint referencing the member table to ensure data integrity. This was not commented on due to review settings.
  • Potential NullPointerException in InterviewSessionMapper: The mapToResponse method in InterviewSessionMapper could throw a NullPointerException if interviewSession.getMessages() returns null. A null check should be added to prevent this. This was not commented on due to review settings.
  • Inconsistent use of final keyword: The final keyword is used inconsistently across the codebase. For example, InterviewSessionMapper is declared as final, but FakeInterviewer is also final but not consistently used in constructor parameters. Consider applying it consistently where appropriate to enhance immutability.
  • Missing Transactional Annotation: The createSession and answer methods in InterviewService should be annotated with @Transactional to ensure atomicity and consistency. This was not commented on due to review settings.

Merge Readiness

The pull request introduces significant new functionality and refactors existing code. While the changes appear to be well-structured, addressing the identified issues is crucial before merging. Specifically, the missing foreign key constraint in the SQL migration and the potential NullPointerException in InterviewSessionMapper should be resolved. I am unable to directly approve this pull request, and recommend that others review and approve this code before merging. Given the presence of a high severity issue, I recommend that this pull request not be merged until it is addressed.

Comment on lines +56 to +62
private FollowUpQuestion toFollowUpQuestion(final InterviewMessage message) {
try {
return objectMapper.readValue(message.getVisibleMessage(), FollowUpQuestion.class);
} catch (final JsonProcessingException e) {
throw new IllegalArgumentException("잘못된 형식의 메시지입니다.");
}
}

Choose a reason for hiding this comment

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

medium

The exception message is hardcoded. Consider using a constant or an enum for exception messages to improve maintainability.

private static final String INVALID_MESSAGE_FORMAT = "잘못된 형식의 메시지입니다.";

        try {
            return objectMapper.readValue(message.getVisibleMessage(), FollowUpQuestion.class);
        } catch (final JsonProcessingException e) {
            throw new IllegalArgumentException(INVALID_MESSAGE_FORMAT);

Comment on lines +148 to +150
void logging(final RuntimeException e, final QnaFeedbackRequest request) {
log.error("Failed to follow up [request={}]", request, e);
}

Choose a reason for hiding this comment

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

medium

The logging method is using QnaFeedbackRequest which doesn't seem relevant in the context of AzureOpenAiInterviewer. Consider using a more appropriate type or creating a specific DTO for logging purposes in this class.

Suggested change
void logging(final RuntimeException e, final QnaFeedbackRequest request) {
log.error("Failed to follow up [request={}]", request, e);
}
@Recover
void logging(final RuntimeException e, final InterviewMessages interviewMessages, final String answer) {
log.error("Failed to follow up [interviewMessages={}, answer={}]", interviewMessages, answer, e);
}

@jaeyeonling jaeyeonling merged commit 041bee1 into main Apr 14, 2025
1 check failed
@jaeyeonling jaeyeonling deleted the feature/qna-helper branch April 14, 2025 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants