-
Notifications
You must be signed in to change notification settings - Fork 6
[LLM] Qdrant 연결 오류 해결 #28
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
Changes from 8 commits
f3be76d
355ed3c
fac97d8
8f11ffa
0e02e2d
56add97
5fcb5c3
16a5d1e
a592fcb
c025e27
13cb65b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package io.github.petty.llm.controller; | ||
|
|
||
| import io.github.petty.llm.service.EmbeddingBatchService; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/embedding-batch") | ||
| @RequiredArgsConstructor | ||
| public class EmbeddingBatchController { | ||
| private final EmbeddingBatchService embeddingBatchService; | ||
|
|
||
| // 기본 저장 | ||
| @PostMapping("/run") | ||
| public String runBatch() { | ||
| embeddingBatchService.saveAllContentsInBatch(); | ||
| return "Vector DB 구성 완료"; | ||
| } | ||
|
|
||
| // 실패 ID 재저장 | ||
| // @PostMapping("/retry") | ||
| // public String retryFailedEmbeddings(@RequestBody List<Long> failedContentIds) { | ||
| // embeddingBatchService.retryFailedContents(failedContentIds); | ||
| // return "재시도 완료!"; | ||
| // } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package io.github.petty.llm.dto; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| // 추천 응답 반환 | ||
| public record RecommendResponseDTO ( | ||
| List<PlaceRecommend> recommend | ||
| ) { | ||
| public record PlaceRecommend ( | ||
| String contentId, | ||
| String title, | ||
| String addr, | ||
| String description, | ||
| String imageUrl, | ||
| String acmpyTypeCd, | ||
| String acmpyPsblCpam, | ||
| String acmpyNeedMtr ) {} | ||
| } |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,109 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package io.github.petty.llm.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.dto.DetailPetDto; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.entity.Content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.entity.ContentImage; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.repository.ContentImageRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.repository.ContentRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Optional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class ContentService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // content ID 받아서 추가 정보 받기 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ContentRepository contentRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ContentImageRepository contentImageRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String DEFAULT_IMAGE_URL = "/assets/noimg.png"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Optional<Content> findByContentId(String contentId){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long id = Long.parseLong(contentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return contentRepository.findById(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (NumberFormatException e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // contentid가 없을 때 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("Invalid contentId format: {}", contentId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Optional.empty(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String getImageUrl(String contentId){ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long id = Long.parseLong(contentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 1. Content 엔티티에서 이미지 확인 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Optional<Content> contentOpt = contentRepository.findById(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (contentOpt.isPresent()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Content content = contentOpt.get(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // firstimage 필드가 있다고 가정 (필드명은 실제 엔티티에 맞게 조정 필요) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| String contentImage = content.getFirstImage(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (contentImage != null && !contentImage.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return contentImage; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 2. ContentImageRepository에서 이미지 검색 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<ContentImage> images = contentImageRepository.findByContent_ContentId(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (images != null && !images.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 첫 번째 이미지의 URL 반환 (필드명은 실제 엔티티에 맞게 조정 필요) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return images.get(0).getOriginImgUrl(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 3. 이미지가 없는 경우 기본 이미지 반환 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return DEFAULT_IMAGE_URL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (NumberFormatException e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("Invalid contentId format: {}", contentId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return DEFAULT_IMAGE_URL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 코드 중복 제거 및 메소드 리팩토링 필요 이 메소드는 길이가 길고 contentId 파싱 로직이 다른 메소드와 중복됩니다. 파싱 로직을 추출하여 재사용하는 것이 좋습니다. 또한 이미지 검색 로직을 더 작은 메소드로 분리하면 가독성이 향상됩니다. +private Optional<Long> parseContentId(String contentId) {
+ try {
+ return Optional.of(Long.parseLong(contentId));
+ } catch (NumberFormatException e) {
+ log.error("컨텐츠 ID 형식이 유효하지 않습니다: {}", contentId, e);
+ return Optional.empty();
+ }
+}
public String getImageUrl(String contentId){
- try {
- Long id = Long.parseLong(contentId);
+ return parseContentId(contentId)
+ .map(id -> {
+ // 1. Content 엔티티에서 이미지 확인
+ return contentRepository.findById(id)
+ .map(content -> {
+ // firstimage 필드가 있으면 반환
+ String contentImage = content.getFirstImage();
+ if (contentImage != null && !contentImage.isEmpty()) {
+ return contentImage;
+ }
+
+ // 2. ContentImageRepository에서 이미지 검색
+ List<ContentImage> images = contentImageRepository.findByContent_ContentId(id);
+ if (images != null && !images.isEmpty()) {
+ return images.get(0).getOriginImgUrl();
+ }
+
+ // 3. 이미지가 없는 경우 기본 이미지 반환
+ return DEFAULT_IMAGE_URL;
+ })
+ .orElse(DEFAULT_IMAGE_URL);
+ })
+ .orElse(DEFAULT_IMAGE_URL);
- // 1. Content 엔티티에서 이미지 확인
- Optional<Content> contentOpt = contentRepository.findById(id);
- if (contentOpt.isPresent()) {
- Content content = contentOpt.get();
-
- // firstimage 필드가 있다고 가정 (필드명은 실제 엔티티에 맞게 조정 필요)
- String contentImage = content.getFirstImage();
- if (contentImage != null && !contentImage.isEmpty()) {
- return contentImage;
- }
- }
-
- // 2. ContentImageRepository에서 이미지 검색
- List<ContentImage> images = contentImageRepository.findByContent_ContentId(id);
- if (images != null && !images.isEmpty()) {
- // 첫 번째 이미지의 URL 반환 (필드명은 실제 엔티티에 맞게 조정 필요)
- return images.get(0).getOriginImgUrl();
- }
-
- // 3. 이미지가 없는 경우 기본 이미지 반환
- return DEFAULT_IMAGE_URL;
-
- } catch (NumberFormatException e) {
- log.error("Invalid contentId format: {}", contentId, e);
- return DEFAULT_IMAGE_URL;
- }
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pet != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("반려 동물 정보: "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pet.getAcmpyTypeCd() != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("동반 유형은 ").append(pet.getAcmpyTypeCd()).append(", "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pet.getEtcAcmpyInfo() != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("가능 동물: ").append(pet.getEtcAcmpyInfo()).append(", "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pet.getAcmpyPsblCpam() != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("추가 정보: ").append(pet.getAcmpyPsblCpam()).append(", "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (pet.getAcmpyNeedMtr() != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("준비물: ").append(pet.getAcmpyNeedMtr()).append(". "); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sb.append("\n"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Optional<DetailPetDto> getPetInfo(String contentId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Long id = Long.parseLong(contentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Optional<Content> contentOpt = contentRepository.findById(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (contentOpt.isPresent()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Content content = contentOpt.get(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (content.getPetTourInfo() != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DetailPetDto dto = new DetailPetDto(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dto.setContentId(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dto.setAcmpyTypeCd(content.getPetTourInfo().getAcmpyTypeCd()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dto.setAcmpyPsblCpam(content.getPetTourInfo().getAcmpyPsblCpam()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dto.setAcmpyNeedMtr(content.getPetTourInfo().getAcmpyNeedMtr()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Optional.of(dto); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Optional.empty(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (NumberFormatException e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.error("반려동물 정보 관련 오류: {}", contentId, e); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Optional.empty(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+87
to
+108
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 코드 중복 제거 필요 getPetInfo 메소드도 contentId 파싱 로직이 중복됩니다. 앞서 제안한 parseContentId 메소드를 활용하여 중복을 제거하는 것이 좋습니다. 또한 로그 메시지를 더 일관성 있게 작성하면 좋겠습니다. public Optional<DetailPetDto> getPetInfo(String contentId) {
- try {
- Long id = Long.parseLong(contentId);
- Optional<Content> contentOpt = contentRepository.findById(id);
-
- if (contentOpt.isPresent()) {
- Content content = contentOpt.get();
- if (content.getPetTourInfo() != null) {
- DetailPetDto dto = new DetailPetDto();
- dto.setContentId(id);
- dto.setAcmpyTypeCd(content.getPetTourInfo().getAcmpyTypeCd());
- dto.setAcmpyPsblCpam(content.getPetTourInfo().getAcmpyPsblCpam());
- dto.setAcmpyNeedMtr(content.getPetTourInfo().getAcmpyNeedMtr());
- return Optional.of(dto);
- }
- }
- return Optional.empty();
- } catch (NumberFormatException e) {
- log.error("반려동물 정보 관련 오류: {}", contentId, e);
- return Optional.empty();
- }
+ return parseContentId(contentId)
+ .flatMap(id -> contentRepository.findById(id)
+ .filter(content -> content.getPetTourInfo() != null)
+ .map(content -> {
+ DetailPetDto dto = new DetailPetDto();
+ dto.setContentId(id);
+ dto.setAcmpyTypeCd(content.getPetTourInfo().getAcmpyTypeCd());
+ dto.setAcmpyPsblCpam(content.getPetTourInfo().getAcmpyPsblCpam());
+ dto.setAcmpyNeedMtr(content.getPetTourInfo().getAcmpyNeedMtr());
+ return dto;
+ })
+ );
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,83 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package io.github.petty.llm.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.entity.Content; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.github.petty.tour.repository.ContentRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.NoArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.extern.slf4j.Slf4j; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Slf4j | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class EmbeddingBatchService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final ContentRepository contentRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final VectorStoreService vectorStoreService; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Content 50개 저장 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public void saveAllContentsInBatch() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 1. 상위 50개 Content 조회 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<Content> top50Contents = contentRepository.findTop20ByOrderByContentIdAsc(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("Content 20개 가져오기 완료. 저장 시작!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 2. 바로 저장 (중복 검사 없이) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vectorStoreService.saveContents(top50Contents); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("Content 20개 저장 완료!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 배치 서비스 구현에 몇 가지 개선점이 있습니다. 현재 구현된 배치 서비스는 Qdrant 연결 문제 해결에 도움이 될 것으로 보입니다. 그러나 몇 가지 개선이 필요합니다:
- // Content 50개 저장
+ // Content 20개 저장
- public void saveAllContentsInBatch() {
+ public void saveTop20ContentsInBatch() {
- // 1. 상위 50개 Content 조회
+ // 1. 상위 20개 Content 조회
List<Content> top50Contents = contentRepository.findTop20ByOrderByContentIdAsc();
log.info("Content 20개 가져오기 완료. 저장 시작!");
// 2. 바로 저장 (중복 검사 없이)
- vectorStoreService.saveContents(top50Contents);
+ try {
+ vectorStoreService.saveContents(top50Contents);
+ log.info("Content 20개 저장 완료!");
+ } catch (Exception e) {
+ log.error("Content 저장 중 오류 발생: {}", e.getMessage(), e);
+ throw new RuntimeException("벡터 DB 저장 실패", e);
+ }
-
- log.info("Content 20개 저장 완료!");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 기본 리스트 저장 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // public void saveAllContentsInBatch() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // List<Content> allContents = contentRepository.findAll(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // int batchSize = 50; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // int totalSize = allContents.size(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // // 중간에 끊긴 번호부터 시작 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// int startIndex = 450; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// // 중복 검사 = 현재 VectorStore에 저장된 contentId 리스트 가져오기 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// List<String> existingContentIds = vectorStoreService.findAllContentIds(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("총 {}개 데이터, {}번부터 배치 크기 {}로 저장 시작", totalSize, startIndex, batchSize); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// for (int i = startIndex; i < totalSize; i += batchSize) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// int end = Math.min(i + batchSize, totalSize); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// List<Content> batchList = allContents.subList(i, end); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("{}번째 batch 시작 ({} ~ {})", (i / batchSize) + 1, i, end); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// // 중복이면 제거하기 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// List<Content> filteredBatch = batchList.stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// .filter(content -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// String contentId = content.getContentId().toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// return !existingContentIds.contains(contentId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// .toList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// if (filteredBatch.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("{}번째 batch: 저장할 새 데이터 없음 (모두 중복)", (i / batchSize) + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// // 3. 저장 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// vectorStoreService.saveContents(filteredBatch); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("{}번째 batch 저장 완료 ({}개 저장)", (i / batchSize) + 1, filteredBatch.size()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // // 실패한 리스트 저장 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// public void retryFailedContents(List<Long> failedContentIds) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// List<Content> failedContents = contentRepository.findAllById(failedContentIds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("재시도할 Content 수: {}", failedContents.size()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// vectorStoreService.saveContents(failedContents); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// log.info("재시도 저장 완료"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //// } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
재시도 기능 구현을 고려해보세요.
주석 처리된 재시도 기능은 실패한 임베딩을 복구하는 데 유용할 수 있습니다. Qdrant 연결 오류가 발생했을 때 견고성을 높이기 위해 이 기능을 활성화하는 것을 고려해보세요. 주석을 제거하고 실제 구현을 완료하면 시스템의 안정성이 향상될 것입니다.
🤖 Prompt for AI Agents