Skip to content

[Feat] rag_responses 저장 - #72

Merged
kangcheolung merged 6 commits into
developfrom
feature/71
Jul 28, 2026
Merged

[Feat] rag_responses 저장#72
kangcheolung merged 6 commits into
developfrom
feature/71

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 28, 2026

Copy link
Copy Markdown
Member

🔍️ 작업 내용

✨ 상세 설명

RAG 블록 Issue 3(F-RAG-03) 구현입니다. Issue 2(#67)에서 OllamaClient가 만든 답변 생성 결과(성공/실패)를 rag_responses 테이블에 실제로 저장합니다.

  • RagResponseRepository, RagResponseCommandService 신규 구현
  • createSuccess() / createFailed() — SearchQuery와 달리 단일 호출로 성공/실패가 갈리므로 PROCESSING 중간 상태 없이 한 번에 저장
  • answer_text NOT NULL 제약 때문에 실패 시에도 고정 문구("답변 생성에 실패했습니다.")를 저장하고, 실제 사유는 error_message에 담음
  • FAILED 기록은 SearchQueryCommandService.markFailed()와 동일하게 @Transactional(propagation = REQUIRES_NEW)로 상위 트랜잭션 롤백과 무관하게 저장되도록 함
  • OllamaGenerateResponse/OllamaGenerateResult(Issue 2 산출물)에 model 필드 추가 — rag_responses.llm_model_name을 별도 설정값 재조회 없이 Ollama 응답에서 그대로 채우기 위함

상세 설계 배경은 docs/design/kangcheolung-#71-rag-response-save.md 참고해주세요.

🛠️ 추후 리팩토링 및 고도화 계획

  • Issue 4: response_citations 저장 — search_result_id 연결은 SearchResultCommandService.saveAll()이 저장된 엔티티를 반환하지 않아(void) 이번 이슈 단독으로는 어려움, Issue 5에서 검토 필요
  • Issue 5: RagFacade로 SearchFacade/SearchController와 실제 연결

📸 스크린샷 (선택)

N/A

💬 리뷰 요구사항

  • OllamaGenerateResult에 model 필드를 추가해 "실제 응답 모델명"을 Ollama 응답에서 그대로 가져오는 방식이 적절한지 (대안: RagFacade가 ollama.model 설정값을 별도로 재주입받는 방식)
  • 실패 시 answer_text에 고정 문구를 넣는 방식이 적절한지 (마이그레이션 NOT NULL 제약 우회)
  • createFailed()의 REQUIRES_NEW 적용이 적절한지

Summary by CodeRabbit

  • 새 기능

    • RAG 생성 결과를 성공 또는 실패 상태로 저장합니다.
    • 실패 시 안내 문구와 실제 오류 사유를 구분해 기록합니다.
    • 생성에 사용된 모델명과 토큰 사용량, 처리 시간을 저장합니다.
  • 문서

    • RAG 응답 저장 흐름과 오류 처리 및 트랜잭션 정책을 문서화했습니다.
  • 테스트

    • 성공·실패 응답 저장과 모델 정보 반환에 대한 검증을 추가했습니다.

rag_responses.llm_model_name을 별도 설정값 재조회 없이, Ollama가 실제로
응답을 생성한 모델명(응답의 model 필드)에서 그대로 가져오도록 한다.
OllamaGenerateResponse 생성자에 model 인자가 추가된 것을 테스트 mocking에
반영하고, 정상 케이스에 result.model() 검증을 추가한다.
OllamaClient 호출 결과(성공/실패)를 rag_responses에 저장한다.
SearchQuery와 달리 단일 호출로 성공/실패가 갈리므로 PROCESSING 중간 상태
없이 createSuccess/createFailed로 한 번에 저장한다.
answer_text NOT NULL 제약 때문에 FAILED 시에도 고정 문구를 저장하고,
실제 실패 사유는 error_message에 담는다. FAILED 기록은
SearchQueryCommandService.markFailed와 동일하게 REQUIRES_NEW로 상위
트랜잭션 롤백과 무관하게 저장되도록 한다.
createSuccess/createFailed가 저장하려는 RagResponse 필드가 기대한 값과
일치하는지 ArgumentCaptor로 검증한다.
코드 작성이 끝났다고 바로 커밋/PR을 진행하지 않고, 사용자가 결과를
확인하고 명시적으로 승인한 뒤에만 실행하도록 git-conventions.md에 명시한다.
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Ollama 응답 DTO에 모델 정보를 추가하고, RAG 생성 결과를 성공·실패 상태로 rag_responses에 저장하는 Repository와 CommandService 및 테스트·설계 문서를 추가했습니다. 실패 저장에는 REQUIRES_NEW를 적용했습니다.

Changes

RAG 응답 저장

Layer / File(s) Summary
Ollama 결과 모델 정보 전달
src/main/java/.../rag/dto/*, src/main/java/.../rag/service/OllamaClient.java, src/test/java/.../OllamaClientTest.java
Ollama 응답과 생성 결과에 model 필드를 추가하고, 클라이언트가 이를 결과에 전달하도록 변경했으며 테스트에서 검증합니다.
RAG 응답 저장 경로
src/main/java/.../rag/repository/RagResponseRepository.java, src/main/java/.../rag/service/command/RagResponseCommandService.java, docs/design/...
성공 결과는 생성 정보와 함께 SUCCESS로 저장하고, 실패 결과는 고정 답변과 오류 메시지를 FAILED로 저장합니다. 실패 저장에는 REQUIRES_NEW를 적용합니다.
저장 매핑 검증
src/test/java/.../RagResponseCommandServiceTest.java, docs/design/...
성공·실패 저장 필드 매핑을 단위 테스트로 검증하고 테스트 및 빌드 실행 기록을 문서화합니다.

개발 작업 규칙

Layer / File(s) Summary
커밋·PR 확인 규칙
.claude/rules/git-conventions.md
커밋과 PR 생성을 사용자의 명시적 확인 이후에만 수행하도록 규칙을 추가합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant OllamaClient
  participant RagResponseCommandService
  participant RagResponseRepository
  OllamaClient->>RagResponseCommandService: 생성 결과 또는 오류 전달
  RagResponseCommandService->>RagResponseRepository: SUCCESS/FAILED 응답 저장
  RagResponseRepository-->>RagResponseCommandService: 저장 결과 반환
Loading

Possibly related PRs

  • DocGrid/backend#69: OllamaClient와 관련 DTO의 초기 통합을 추가했으며, 이번 변경이 동일 DTO와 클라이언트의 model 필드를 확장합니다.

Suggested labels: ✨ Feature, 📃 Docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning .claude/rules/git-conventions.md의 커밋·PR 규칙 변경은 rag_responses 저장과 무관해 범위를 벗어납니다. 해당 변경을 별도 PR로 분리하거나 제거하고, rag_responses 저장 관련 코드와 테스트만 포함하세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 rag_responses 저장이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 필수 섹션과 Closes #71, 상세 설명, 추후 계획, 리뷰 요구사항이 모두 포함되어 있습니다.
Linked Issues check ✅ Passed RagResponseRepository, RagResponseCommandService, SUCCESS/FAILED 저장, REQUIRES_NEW가 모두 구현되어 요구사항을 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/71

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/opensource/docgrid/domain/rag/repository/RagResponseRepository.java`:
- Around line 7-8: RagResponseRepository에 class-level Javadoc를 추가해 RagResponse의
영속화와 Spring Data가 제공하는 기본 CRUD만 담당하며 그 외 비즈니스 로직은 포함하지 않는다는 역할과 경계를 간략히 설명하세요.

In
`@src/test/java/com/opensource/docgrid/domain/rag/service/command/RagResponseCommandServiceTest.java`:
- Around line 24-32: RagResponseCommandServiceTest의 Mockito 단위 테스트만으로는
createFailed()의 REQUIRES_NEW 경계를 검증할 수 없으므로, Spring/JPA 컨텍스트를 사용하는 별도 통합 테스트를
추가하세요. 상위 트랜잭션에서 롤백이 발생하는 시나리오를 구성한 뒤에도 createFailed()의 FAILED 저장 호출이 진행되고 결과가
실제로 커밋되는지 검증하며, `@InjectMocks` 기반 테스트와 구분해 Spring 프록시를 통해 서비스를 호출하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d9aab5e6-37a2-4f0c-960a-6b8876380b12

📥 Commits

Reviewing files that changed from the base of the PR and between 992a91f and 42a9983.

📒 Files selected for processing (9)
  • .claude/rules/git-conventions.md
  • docs/design/kangcheolung-#71-rag-response-save.md
  • src/main/java/com/opensource/docgrid/domain/rag/dto/OllamaGenerateResult.java
  • src/main/java/com/opensource/docgrid/domain/rag/dto/response/OllamaGenerateResponse.java
  • src/main/java/com/opensource/docgrid/domain/rag/repository/RagResponseRepository.java
  • src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java
  • src/main/java/com/opensource/docgrid/domain/rag/service/command/RagResponseCommandService.java
  • src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java
  • src/test/java/com/opensource/docgrid/domain/rag/service/command/RagResponseCommandServiceTest.java

Comment on lines +7 to +8
public interface RagResponseRepository extends JpaRepository<RagResponse, Long> {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

새 인터페이스에 역할과 경계를 설명하는 주석을 추가해 주세요.

새로 생성된 RagResponseRepository에 class-level Javadoc가 없습니다. RagResponse의 영속화와 Spring Data 기본 CRUD만 담당한다는 역할을 짧게 명시해 주세요.

코딩 가이드의 “Every newly created class, interface, or record must have a class-level comment explaining its role, responsibility, and boundary.” 규칙에 따릅니다.

제안
+/**
+ * RAG 응답 엔티티의 영속화와 기본 CRUD를 담당하는 저장소.
+ */
 public interface RagResponseRepository extends JpaRepository<RagResponse, Long> {
📝 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.

Suggested change
public interface RagResponseRepository extends JpaRepository<RagResponse, Long> {
}
/**
* RAG 응답 엔티티의 영속화와 기본 CRUD를 담당하는 저장소.
*/
public interface RagResponseRepository extends JpaRepository<RagResponse, Long> {
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/opensource/docgrid/domain/rag/repository/RagResponseRepository.java`
around lines 7 - 8, RagResponseRepository에 class-level Javadoc를 추가해 RagResponse의
영속화와 Spring Data가 제공하는 기본 CRUD만 담당하며 그 외 비즈니스 로직은 포함하지 않는다는 역할과 경계를 간략히 설명하세요.

Source: Coding guidelines

Comment on lines +24 to +32
@ExtendWith(MockitoExtension.class)
@DisplayName("RagResponseCommandService 단위 테스트")
class RagResponseCommandServiceTest {

@InjectMocks
private RagResponseCommandService ragResponseCommandService;

@Mock
private RagResponseRepository ragResponseRepository;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
fd -a 'RagResponseCommandServiceTest.java|RagResponseCommandService.java|RagResponseRepository.java' . || true

echo "== test outline/contents =="
for f in $(fd 'RagResponseCommandServiceTest.java' .); do
  echo "--- $f"
  wc -l "$f"
  cat -n "$f"
done

echo "== service outline/contents =="
for f in $(fd 'RagResponseCommandService.java' .); do
  echo "--- $f"
  wc -l "$f"
  rg -n "`@Transactional`|createFailed|class RagResponseCommandService|REQUIRES_NEW" "$f" -C 3 || true
done

Repository: DocGrid/backend

Length of output: 5751


REQUIRES_NEW 트랜잭션 경계를 Spring/JPA 통합 테스트로 보완하세요.

@InjectMocks 단위는 Spring 프록시를 bypass하므로 createFailed()@Transactional(propagation = REQUIRES_NEW)이 현재 커버되지 않습니다. 별도 통합 테스트에서 상위 트랜잭션이 롤백되어도 FAILED 저장 호출이 진행됨을 어설션으로 보증해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/rag/service/command/RagResponseCommandServiceTest.java`
around lines 24 - 32, RagResponseCommandServiceTest의 Mockito 단위 테스트만으로는
createFailed()의 REQUIRES_NEW 경계를 검증할 수 없으므로, Spring/JPA 컨텍스트를 사용하는 별도 통합 테스트를
추가하세요. 상위 트랜잭션에서 롤백이 발생하는 시나리오를 구성한 뒤에도 createFailed()의 FAILED 저장 호출이 진행되고 결과가
실제로 커밋되는지 검증하며, `@InjectMocks` 기반 테스트와 구분해 Spring 프록시를 통해 서비스를 호출하세요.

Source: Path instructions

@kangcheolung
kangcheolung merged commit 1602454 into develop Jul 28, 2026
1 check passed
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.

[Feat] rag_responses 저장

1 participant