Post

문서 파이프라인 최적화

파이프라인 개선

서버에서 주기적으로 도는 텍스트 추출 관련 스케줄러가 있다.

유저가 문서를 업로드하면 텍스트를 쫙 뽑아와서 임베딩하고, 파일 기반 채팅을 하기 위해 구축된 스케줄러인데 얘가 좀 느리다. 사실 관리자가 문서를 업로드 하기 때문에 아마 초반 세팅에 문서가 많이 담길거고, 그 이후로는 소소하게 작동할 것 같긴 해서 크게 문제는 되지 않을 것 같다.

그런데 이건 내 생각이고, 실제로 어떻게 활용될 지 감도 안오거니와 다른 개발자분이랑 데이터 팀이 이 스케줄러에 의존해서 뭔가 작업을 처리하는 모습이 자주 보이는데 뭔 놈의 추출이 10시간씩 걸린댄다. 얘 잘못 돌리면 모든 작업이 다 블로킹된다. 그래서 보통 퇴근전에 돌려놓고 다음날에 출근해서 추출이 완료되면 뭔가 작업을 하시던데 이게 이렇게나 오래 걸릴 작업인가 해서 코드를 살펴봤다.

줄일 수 있는 부분도 명확했지만, 한계도 명확했다.

플로우 분석

먼저 대충 작동 플로우를 적어보자면

  1. PDF 텍스트 추출
  2. OpenAI api 요청 가능한 최대 토큰 단위로 청크
  3. 청킹된 텍스트 순회하며 임베딩 요청
  4. 저장한 임베딩 값 순회하며 추가 검색 힌트 자료 생성 및 임베딩

대충 이런 흐름인데, 3번 과정에서 api 호출 1회, db 접근 1회가 발생한다. 4번 과정에서는 api 호출 3회, db 접근 3회가 발생한다.

우리 리소스가 그리 넉넉하지는 않다 보니 큐에 태워서 별도의 워커들로 작업을 빼거나 하지는 않고, 세마포어를 이용해서 동시 작업을 제어하고 있었다. 그런데 이 세마포어가 3, 4번에 통짜로 걸려있다 보니 작업 딜레이가 꽤나 심하게 되고 있었다.

OpenAI api쪽만 호출 제한을 빡시게 걸면 될 것 같고, 나머지는 비교적 빠르게 진행해도 되지 않을까? 라는 생각에 코드를 이리저리 분리했다.

성능 개선

일단 DB 호출과 뒤섞여 있는 외부 api 호출 코드를 분리했다.

DB 호출도 쿼리에 걸리는 시간보다 반복적인 조회 작업으로 인한 네트워크 딜레이가 훨씬 길었기 때문에 적절히 코드를 분리했다. 몽고DB를 사용중인데, 관련된 컬럼들을 최대한 한번에 불러오게 변경했고 저장 방식도 bulk write로 변경해줬다.

세마포어는 OpenAI API쪽에만 걸어줬다. 이게 생각보다 호출 가능한 양이 너무 적더라. 로그 보니까 초당 4~5개씩만 보내도 조금 있으면 블락이 걸렸다.

pdf에서 텍스트 추출하는 과정도 혹시나 대용량 파일에 대비, 메모리 임시 저장 기반에서 변경할까 싶다가 냅뒀다. 작업이 커지기도 하고 1,000 페이지 정도는 크게 부담이 안 되는 것 같아서 일단 보류했다.

성능 비교

이제 얼마나 개선되었는지 퍼포먼스를 비교해봤다.

텍스트 추출에 이용한 자료는 Data Structures and Algorithms in Java Fourth Edition 라는 도서인데 내가 직접 올리기는 좀 그렇고 검색하다 보면 나온다. 대략 1,000 페이지 가까이 된다.

기존 코드

  • 8시 2분 ~ 8시 12분 5초 (10분 가량)

개선 코드

  • 8시 24분 ~ 8시 27분 14초 (3분 가량)

성능은 꽤나 개선되었다. 70% 정도 개선했다.

추가 개선점

사실 많이 아쉬운 점은 훨씬 더 빨리 끝낼 수 있는데 api 레이트 리밋이 생각보다 너무 빡빡했다. 초당 10회 정도로만 허용되었어도 훨씬 더 빠르게 처리되었을 거라 생각한다.

데이터 검증은 기존 코드가 이미 어느정도 실 검증이 되었기 때문에, 이 코드를 통해 적재된 DB 데이터와 개선한 코드로 생성한 데이터를 비교해보았다. 다행히 일치했다. 메모리 사용량도 모니터링 해봤는데 뭐 거의 안튀는 것 같다. 호수마냥 잠잠하다.

This post is licensed under CC BY 4.0 by the author.

© . Some rights reserved.

Using the Jekyll theme Chirpy