본문 바로가기

프로그래밍 기록/OSS | 컨트리뷰션

[Spring AI] Spring AI 컨트리뷰트

최근에 RAG 관련해서 Spring AI 를 사용할 일이 있었는데,

PDF / HTML 같은걸 Vector DB 에 담아야한다.

Vector DB 에 담기전에, 보통 청크 -> 청크한걸 임베딩 모델을 통해서 벡터화 -> 벡터DB 에 삽입하는데 (ETL 파이프라인)

Spring AI 를 쓰게 되면 위 전 과정을 설정코드만 가지고 쓸수 있다.

그러니까 "청크" 하는 라이브러리도 Spring AI 에 포함인셈

 

PDF 의 경우 `PagePdfDocumentReader` 를 사용하는데

예시 코드는 다음과 같다.

@Component
public class MyPagePdfDocumentReader {

	List<Document> getDocsFromPdf() {

		PagePdfDocumentReader pdfReader = new PagePdfDocumentReader("classpath:/sample1.pdf",
				PdfDocumentReaderConfig.builder()
					.withPageTopMargin(0)
					.withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
						.withNumberOfTopTextLinesToDelete(0)
						.build())
					.withPagesPerDocument(1)
					.build());

		return pdfReader.read();
    }

}

ETL Pipeline :: Spring AI Reference

 

보면, 추가적인 Text Formatter 로 `ExtractedTextFormatter` 을 사용한다.

 

이 친구를 사용하면, 대충 PDF 를 도큐먼트화 할때, 위에서 몇줄 생략하기, 아래 몇줄 생략하기 같은걸 지원해주는데. (머리글 처럼 모든 PDF 페이지에 있는 쓸모없는것들 삭제하기 위해서)

 

테스트 해본다고 돌려봤는데 무슨 값을 집어넣어도 개뿔 동작을 안한다...

 

저기 관련 독스가 크게 상세한것도 아니여서 내가 이름만 보고 동작을 잘못 이해 한것인가...? 고민좀 했는데.

 

윈도우 또 너야?!

 

나는 주로 윈도우 환경 + 필요시 WSL 로 우분투를 사용하는데.

혹시나 싶어서 우분투에서 Spring 띄워서 사용해보니.. 잘만 동작한다...

윈도우 에서는 아무리 잘라도 PDF 내용이 다 나온다

 

우분투에서 돌리니까 잘만 잘린다

 

그래서 바로 코드까서 확인해보니, 

nextTruncateIndex = pageText.lastIndexOf(System.lineSeparator(), truncateIndex - 1);

이렇게 System.lineSeparator() 을 사용하는것을 확인..

 

뉴라인은 시스템 의존적인 부분이기 떄문에 System 을 사용하는게 얼핏 생각하면 맞지만,

 

사용하는 용도를 생각해보면, 저건 PDF 의 newline 을 Check 해서 자르는것이기 때문에  서버의 환경이 아니라, PDF 의 환경 (PDF official New Line Spec) 을 따라 가야한다.

 

그래서 관련 이슈랑 PR 을 날렸다.

ExtractedTextFormatter Should Not Rely on System.lineSeparator() · Issue #1913 · spring-projects/spring-ai

Added Line Separator Override Feature to ExtractedTextFormatter by Lee-WonJun · Pull Request #1914 · spring-projects/spring-ai 

 

GPT 왈 PDF 는 \n 이 기본 스펙이라고 하긴 하는데, 그것과 별개로

ExtractedTextFormatter 라는 친구가 이름을 보아하니, PDF 전용도 아닌것 같고 기존에 Case 는 동일하게 동작해야 하는 "하위 호환성" 관련 측면에서 그냥 박아버리면 안될것 같다고 생각했다.

private String lineSeparator = System.lineSeparator();

//

public Builder overrideLineSeparator(String lineSeparator) {
    this.lineSeparator = lineSeparator;
    return this;
}

그래서 요런식으로 기존 동작은 동일하게 System.lineSeparator 을 두고, 사용자가 원하면 오버라이딩 할수 있게 수정했다.

 

요렇게 PR 날리고 잊고있었는데, 어제 노티가 와서 확인해보니까

머지안해줘따..

머지 안되고 Close 됫길래 엥.. 리젝당했남.. 하고 이유를 확인하려고 봣더니

 

 

메인테이너중 한분이 커밋 메시지랑, Deprecated 관련 처리를 추가하시고 바로 메인에 커밋하셧다.

 

이래도 컨트리뷰터로 찍히더라 굳굳

728x90