키워드 기반 검색 및 hybrid 검색 성능 개선 #93
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
🔖 연관된 이슈
📂 작업 내용
mecab 설치
postgres에서 검색 기본 설정은 영어입니다.
형태소 분석기도 영어를 기준으로 동작하기 때문에 한국어 형태소를 잘 분석하지 못 하는 현상이 발생했습니다.
다음은 기본 영어 형태소 분석기를 사용했을 때 tsvector입니다.
조사를 잘 걸러내지 못 하고 있습니다.
그래서 postgres 16버전을 base 이미지로 사용하여 그 안에 mecab 형태소 분석기를 설치하는 Dockerfile을 작성했습니다.
물론 저희 프로젝트는 벡터 기반 유사도 검색과 키워드 기반 검색을 합쳐서 hybrid search를 사용하기 때문에 pgvector extension을 설치하는 코드도 함께 있습니다.
위 dockerfile로 이미지 생성 후 mecab 한국어 형태소 분석기를 적용했을 때 tsvector입니다.
조사를 잘 걸러내는 모습을 확인할 수 있습니다.
키워드 기반 검색에 제목 추가
기존에는 키워드 검색할 때 제목 정보를 사용하지 않아서 키워드 기반 검색 성능이 좋지 않았습니다.
제목 정보도 함께 사용하기 위해 title에 대한 tsvector 컬럼을 생성했습니다.
page.entity.ts
그리고 검색을 할 때 title tsvector와 document tsvector를 바탕으로 결과를 가져올 수 있도록 OR 조건으로 묶었습니다.
키워드 기반 검색을 해서 결과를 가져온 뒤 순위를 재정렬 해야 하는데 문서 내용보다는 제목에 더욱 중요한 키워드가 담길 것을 고려하여 제목에 높은 가중치를 주었습니다.
tsvector에 A, B, C, D로 가중치를 부여할 수 있습니다. (A가 가장 높음)
title tsvector에는 가장 높은 A를 주었고 docment tsvector에는 가장 낮은 D를 주었습니다.
websearch_to_tsquery 수정
기존에는 websearch_to_tsquery로 사용자의 요청을 tsquery로 변환하였습니다.
websearch_to_tsquery를 형태소를 추출한 뒤 모두 &로 묶는 함수입니다.
"모든 회의록을 날짜 별로 요약해줘"와 같은 요청을 tsquery로 변환한 결과는 아래와 같습니다.
키워드 검색에는 유용하지만 저희 서비스와 같은 자연어 요청이 들어오게 되면 변환한 tsquery를 만족하는 문서는 거의 존재하지 않습니다.
그래서 websearch_to_tsquery의 결과에서 '&' 연산자를 '|'로 바꾸어서 단 하나의 키워드를 가지고 있어도 문서를 검색할 수 있도록 구현했습니다.
상당히 많은 결과를 가져오지만 재정렬을 수행하고 순위가 높은 것들을 잘라서 가져오기 때문에 사용자의 요청과 유사한 문서를 가져올 수 있습니다.
LLM 프롬프트 수정
기존에는 검색한 문서들을 단순하게 new line으로 연결해주었습니다.
이렇게 LLM에게 문서들을 전달했더니 각 문서들을 구별하지 못 했습니다.
아래는 2월 10일 회의록을 요약해달라고 요구한 결과입니다.

실제 2월 10일에 AI 기능 구체화에 대한 회의는 이루어지지 않았습니다.
AI가 이렇게 인식한 이유는 문서들을 구별하지 못 했기 때문입니다.
"2월", "10일" "회의록"과 유사한 문서에는 다른 날짜 회의록도 함께 가져오고 단순하게 new line으로 연결했더니 모든 회의록을 하나의 문서로 인식한 것이었습니다.
문서의 구분을 위해 각 문서마다 제목, 내용이 무엇인지 알려주는 프롬프트와 각 문서들을 '====='으로 구분하였습니다.
이제 문서들을 잘 구분하고 조회한 여러 개의 문서들 중 2월 10일 회의록 문서만 요약을 해주게 되었습니다.
📑 참고 자료 & 스크린샷 (선택)
https://www.solanara.net/solanara/postgresql
https://www.postgresql.org/docs/current/textsearch-controls.html