Skip to content

[Feat] OllamaClient 연동 - #69

Merged
kangcheolung merged 5 commits into
developfrom
feature/67
Jul 28, 2026
Merged

[Feat] OllamaClient 연동#69
kangcheolung merged 5 commits into
developfrom
feature/67

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 28, 2026

Copy link
Copy Markdown
Member

🔍️작업 내용

✨ 상세 설명

RAG 블록 Issue 2(F-RAG-02) 구현입니다. Issue 1(#65)에서 만든 PromptBuilder가 조립한 프롬프트를 실제로 Ollama(qwen2.5:3b)에 전달해 답변을 받아오는 HTTP 클라이언트입니다.

  • RAG_SERVICE_UNAVAILABLE 에러코드 추가, ollama.model 설정값 외부화 (모델 교체 시 코드 변경 없이 대응)
  • OllamaServerConfig: EmbeddingServerConfig와 동일 패턴의 RestClient Bean (connectTimeout 5s / readTimeout 30s — LLM 생성이 임베딩보다 오래 걸리는 점 고려)
  • OllamaGenerateRequest/OllamaGenerateResponse/OllamaGenerateResult DTO — Ollama 응답(prompt_eval_count, eval_count 등)을 우리 서비스가 쓰는 형태로 변환
  • OllamaClient: /api/generate 호출, 실패 시 RestClientException → DocGridException(RAG_SERVICE_UNAVAILABLE, 503) 변환
  • NO_CONTEXT 판단은 포함하지 않음 — 순수 HTTP 클라이언트로 유지, 호출 여부 판단은 Issue 5의 RagFacade 책임

로컬 Ollama에 curl로 실제 /api/generate 호출해 응답 필드(response/prompt_eval_count/eval_count)가 DTO 매핑과 정확히 일치함을 확인했습니다.

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

  • Issue 3: 이 결과(OllamaGenerateResult)를 rag_responses에 저장
  • Issue 4: response_citations 저장
  • Issue 5: SearchFacade/SearchController와 연결해 실제 POST /search 응답에 answer 포함

📸 스크린샷 (선택)

N/A

💬 리뷰 요구사항

  • readTimeout을 30초로 잡은 게 적절한지 (NFR상 전체 응답 목표는 5초지만, 하드 타임아웃으로 조기 503 처리되는 것을 피하려는 의도)
  • 모델명을 하드코딩 대신 application.yml 설정값(ollama.model)으로 뺀 설계가 적절한지
  • OllamaGenerateResponse → OllamaGenerateResult로 한 번 더 감싸는 계층 분리가 과한 추상화는 아닌지

Summary by CodeRabbit

  • 새 기능

    • Ollama 기반 AI 응답 생성 기능을 추가했습니다.
    • 생성 결과에 답변, 토큰 사용량, 처리 시간을 제공합니다.
    • 사용할 모델을 환경 변수로 설정할 수 있으며 기본 모델을 지원합니다.
  • 오류 처리

    • AI 서버에 연결할 수 없는 경우 서비스 이용 불가 오류를 반환합니다.
    • 서버 요청에 연결 및 응답 시간 제한을 적용했습니다.
  • 테스트

    • 정상 응답과 AI 서버 연결 실패 상황을 검증하는 테스트를 추가했습니다.

Ollama 서버 호출 실패 시 사용할 에러코드와, 모델명을 하드코딩하지 않고
설정값(ollama.model)으로 외부화해 향후 모델 교체(3b→7b 등)에 대응한다.
EmbeddingServerConfig와 동일 패턴. LLM 텍스트 생성이 임베딩 변환보다
오래 걸리는 점을 고려해 readTimeout을 30초로 여유있게 설정한다.
PromptBuilder가 조립한 프롬프트를 Ollama /api/generate로 전송해 답변을
생성한다. QueryEmbeddingService와 동일하게 RestClientException을
DocGridException(RAG_SERVICE_UNAVAILABLE)으로 변환한다.
NO_CONTEXT 판단은 포함하지 않는다 — 순수 HTTP 클라이언트로 유지.
정상 케이스(답변/토큰수 반환)와 서버 장애 케이스(RAG_SERVICE_UNAVAILABLE)를
QueryEmbeddingServiceTest와 동일한 RestClient mocking 패턴으로 검증한다.
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kangcheolung, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 05d76cec-fc43-4026-b4ad-21f22730c304

📥 Commits

Reviewing files that changed from the base of the PR and between 27a2475 and 1d35352.

📒 Files selected for processing (2)
  • src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java
  • src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java
📝 Walkthrough

Walkthrough

Ollama 요청·응답 DTO와 결과 DTO를 추가하고, 타임아웃이 적용된 RestClient 및 모델 설정을 구성했다. OllamaClient는 /api/generate를 호출해 결과와 지연 시간을 반환하며, 연결 오류를 RAG 서비스 불가 예외로 변환한다.

Changes

Ollama 클라이언트 연동

Layer / File(s) Summary
Ollama 계약과 연결 설정
src/main/java/com/opensource/docgrid/domain/rag/dto/..., src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java, src/main/java/com/opensource/docgrid/global/exception/ErrorCode.java, src/main/resources/application.yml
Ollama 생성 요청·응답·결과 record를 정의하고, 모델 설정과 5초 연결·30초 읽기 타임아웃의 ollamaRestClient bean 및 RAG_SERVICE_UNAVAILABLE 오류 코드를 추가한다.
생성 요청과 결과 변환
src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java
/api/generate에 비스트리밍 요청을 전송하고 응답 텍스트·토큰 수·지연 시간을 OllamaGenerateResult로 반환하며, RestClientExceptionDocGridException으로 변환한다.
생성 성공과 장애 테스트
src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java
생성 결과 매핑과 응답 조회 중 RAG_SERVICE_UNAVAILABLE 예외 변환을 Mockito 기반 단위 테스트로 검증한다.

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

Sequence Diagram(s)

sequenceDiagram
  participant OllamaClient
  participant RestClient
  participant OllamaServer
  OllamaClient->>RestClient: POST /api/generate
  RestClient->>OllamaServer: OllamaGenerateRequest
  OllamaServer-->>RestClient: OllamaGenerateResponse
  RestClient-->>OllamaClient: 응답 역직렬화
  OllamaClient-->>OllamaClient: OllamaGenerateResult 생성
Loading

Suggested labels: ✨ Feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 OllamaClient 연동이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 작업 내용, 상세 설명, 추후 계획, 리뷰 요구사항이 템플릿 구조에 맞게 모두 포함됩니다.
Linked Issues check ✅ Passed #67의 RestClient 등록, /api/generate 호출, 503 예외 변환, 얇은 클라이언트 유지 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 요구사항과 무관한 변경은 보이지 않으며, 설정 외부화와 테스트 추가도 본 기능 범위 안에 있습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/67

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

🧹 Nitpick comments (3)
src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java (1)

43-51: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

HTTP 요청 계약을 검증하는 테스트를 추가하세요.

현재 테스트는 ResponseSpec.body(...)만 stub하므로 /api/generate URI, 설정된 model, 원본 prompt, stream=false가 실제로 전달되는지 검증하지 않습니다. uri("/api/generate")body(...)를 verify하고 OllamaGenerateRequest를 캡처해 네 필드를 assertion해야 잘못된 외부 계약 변경을 잡을 수 있습니다.

As per path instructions, 테스트 파일에서는 커버리지와 mock 사용법을 확인해야 합니다.

🤖 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/OllamaClientTest.java`
around lines 43 - 51, Update the generate_success test around
OllamaClient.generate to verify the HTTP request contract: verify
uri("/api/generate") and the request body invocation, capture the
OllamaGenerateRequest passed to body, and assert its model, original prompt, and
stream=false fields. Preserve the existing response and result assertions while
using the established mock verification style.

Source: Path instructions

src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java (1)

20-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

순차 실행 흐름의 단계 주석을 일관되게 추가하세요.

  • src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java#L20-L29: HttpClient 생성 → timeout 적용 → RestClient bean 생성 단계를 주석으로 구분합니다.
  • src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java#L38-L56: 호출 시작 → /api/generate 요청 → 응답 검증 및 결과 변환 단계를 주석으로 구분합니다.

As per coding guidelines, sequential execution flow에는 1., 2., 3. 형식의 단계 주석을 추가해야 합니다.

🤖 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/global/config/OllamaServerConfig.java`
around lines 20 - 29, Sequential execution steps lack consistent numbered
comments. In
src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java lines
20-29, add 1., 2., and 3. comments separating HttpClient creation, timeout
configuration, and RestClient bean creation; in
src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java lines
38-56, add the same style of comments for call initiation, the /api/generate
request, and response validation/result conversion.

Source: Coding guidelines

src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java (1)

3-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

신규 production type들의 역할·경계 주석이 누락되었습니다.

각 신규 record/class 위에 해당 타입의 책임과 외부 경계를 설명하는 짧은 Javadoc을 추가하세요.

  • src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java#L3-L4: Ollama generate 요청 payload임을 설명합니다.
  • src/main/java/com/opensource/docgrid/domain/rag/dto/response/OllamaGenerateResponse.java#L5-L11: Ollama 응답 매핑 DTO임을 설명합니다.
  • src/main/java/com/opensource/docgrid/domain/rag/dto/OllamaGenerateResult.java#L3-L9: 서비스 계층 결과 DTO임을 설명합니다.
  • src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java#L12-L13: Ollama 전용 RestClient와 timeout 설정의 경계를 설명합니다.

As per coding guidelines, 신규 class/interface/record에는 역할·책임·경계를 설명하는 class-level comment가 필요합니다.

🤖 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/dto/request/OllamaGenerateRequest.java`
around lines 3 - 4, 각 신규 production type에 역할과 외부 경계를 설명하는 간결한 class-level
Javadoc을 추가하세요:
src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java의
3-4행에는 Ollama generate 요청 payload임을,
src/main/java/com/opensource/docgrid/domain/rag/dto/response/OllamaGenerateResponse.java의
5-11행에는 Ollama 응답 매핑 DTO임을,
src/main/java/com/opensource/docgrid/domain/rag/dto/OllamaGenerateResult.java의
3-9행에는 서비스 계층 결과 DTO임을,
src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java의
12-13행에는 Ollama 전용 RestClient와 timeout 설정의 경계임을 명시하세요.

Source: Coding guidelines

🤖 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/dto/request/OllamaGenerateRequest.java`:
- Around line 3-4: OllamaGenerateRequest의 model과 prompt가 null 또는 blank로 생성되지 않도록
실제 호출 경계에서 검증을 추가하세요. compact constructor에서 불변식을 보장하거나 OllamaClient의 generate 호출
직전에 검증하고, 호출부가 항상 유효한 값을 보장하는 계약이라면 해당 동작을 테스트로 명시하세요.

In `@src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java`:
- Around line 41-56: Validate the result from the Ollama request in the method
containing the `/api/generate` call before accessing it. When `response` is null
or `response.response()` is null, throw `DocGridException` with
`ErrorCode.RAG_SERVICE_UNAVAILABLE`; otherwise preserve the existing
`OllamaGenerateResult` construction.

---

Nitpick comments:
In
`@src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java`:
- Around line 3-4: 각 신규 production type에 역할과 외부 경계를 설명하는 간결한 class-level
Javadoc을 추가하세요:
src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java의
3-4행에는 Ollama generate 요청 payload임을,
src/main/java/com/opensource/docgrid/domain/rag/dto/response/OllamaGenerateResponse.java의
5-11행에는 Ollama 응답 매핑 DTO임을,
src/main/java/com/opensource/docgrid/domain/rag/dto/OllamaGenerateResult.java의
3-9행에는 서비스 계층 결과 DTO임을,
src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java의
12-13행에는 Ollama 전용 RestClient와 timeout 설정의 경계임을 명시하세요.

In `@src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java`:
- Around line 20-29: Sequential execution steps lack consistent numbered
comments. In
src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java lines
20-29, add 1., 2., and 3. comments separating HttpClient creation, timeout
configuration, and RestClient bean creation; in
src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java lines
38-56, add the same style of comments for call initiation, the /api/generate
request, and response validation/result conversion.

In
`@src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java`:
- Around line 43-51: Update the generate_success test around
OllamaClient.generate to verify the HTTP request contract: verify
uri("/api/generate") and the request body invocation, capture the
OllamaGenerateRequest passed to body, and assert its model, original prompt, and
stream=false fields. Preserve the existing response and result assertions while
using the established mock verification style.
🪄 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: b816b272-89f3-4ff9-b8a2-3414f6ed0211

📥 Commits

Reviewing files that changed from the base of the PR and between 9ad3c34 and 27a2475.

📒 Files selected for processing (8)
  • src/main/java/com/opensource/docgrid/domain/rag/dto/OllamaGenerateResult.java
  • src/main/java/com/opensource/docgrid/domain/rag/dto/request/OllamaGenerateRequest.java
  • src/main/java/com/opensource/docgrid/domain/rag/dto/response/OllamaGenerateResponse.java
  • src/main/java/com/opensource/docgrid/domain/rag/service/OllamaClient.java
  • src/main/java/com/opensource/docgrid/global/config/OllamaServerConfig.java
  • src/main/java/com/opensource/docgrid/global/exception/ErrorCode.java
  • src/main/resources/application.yml
  • src/test/java/com/opensource/docgrid/domain/rag/service/OllamaClientTest.java

Comment on lines +3 to +4
public record OllamaGenerateRequest(String model, String prompt, boolean stream) {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

요청 입력을 호출 경계에서 검증하세요.

generate가 null/blank 입력을 받을 수 있다는 가정에서 현재 DTO는 이를 그대로 직렬화합니다. 이 record에 @NotBlank만 추가해도 @Valid 경로가 없으므로 자동 검증되지 않으니, OllamaClient 또는 compact constructor에서 modelprompt의 유효성을 실제로 보장하세요. 호출부가 항상 유효한 값을 보장한다면 그 계약을 테스트로 명시해야 합니다.

As per path instructions, DTO의 validation 누락 여부를 확인해야 합니다.

🤖 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/dto/request/OllamaGenerateRequest.java`
around lines 3 - 4, OllamaGenerateRequest의 model과 prompt가 null 또는 blank로 생성되지
않도록 실제 호출 경계에서 검증을 추가하세요. compact constructor에서 불변식을 보장하거나 OllamaClient의
generate 호출 직전에 검증하고, 호출부가 항상 유효한 값을 보장하는 계약이라면 해당 동작을 테스트로 명시하세요.

Source: Path instructions

RestClient가 null 응답이나 response 필드가 없는 응답을 반환할 경우
NullPointerException이 그대로 전파되던 문제를 RAG_SERVICE_UNAVAILABLE로
변환하도록 수정한다. QueryEmbeddingService.embed()의 null 체크 패턴과 동일.
@kangcheolung
kangcheolung merged commit d15e1af 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] OllamaClient 연동

1 participant