1. Load - 데이터(문서) 불러오기
2. Split - 문서 분할
3. Embed - 임베딩해서 특징 벡터 생성
4. Store - 임베딩 벡터를 Vector DB에 저장
결론부터 말하자면, LLM은 '일치'하는 게 아니라, '유사성'을 가지고 찾아야 하기 때문이다. 일치하는 항목을 찾는 건 관계형 DB, 유사성을 검색하는 건 벡터 DB로 한다.
벡터 데이터베이스는 임베딩 모델 알고리즘의 아웃풋인 벡터 임베딩을 저장한다. 또한 제목, 설명 및 데이터 유형을 포함한 각 벡터의 메타데이터를 저장하며, 메타데이터 필터를 사용하여 쿼리할 수 있다.
벡터 데이터베이스는 이러한 임베딩을 수집하고 저장함으로써 유사성 검색을 빠르게 조회하여 사용자의 프롬프트와 유사한 벡터 임베딩을 일치시킬 수 있다.

예를 들어, "삼국 통일은 어느 나라가 했어?"라는 질문 Input이 들어온다면? 참고 문헌은 고조선/삼국시대/고려시대로 나뉘어져 있다.
벡터DB를 사용한다면 참고 문서 중 유사도가 높은 삼국시대 문서 안에서 답을 찾을 것이다. 반면 관계형 DB는 '일치하는' 항목을 찾기 위해 아래와 같은 코드를 칠 것이다.
select * from table
where 문서내용 like "삼국 통일"
(치고 나서 보니 꽤 잘 친 것 같기도) 하지만 우리가 하려는 건 질문과 유사한 문서를 참고해 답을 찾으려는 거지, 참고 자료 안에서 질문과 일치하는 걸 찾으려는 게 아니다.
따라서 유사도 계산을 위해 정보를 임베딩해 벡터 DB에 저장한다.


✅ Langchain을 이용해 RAG를 구현할 때 꼭 Langchain의 Document Loader를 사용해야 하는 건 아니다.
Load한 문서를 지정한 기준의 덩어리(chunk)로 나누는 작업을 진행한다. 이때 LLM을 이용하는 것이 아니라 "알고리즘 적으로" 자른다.
주요 Spliter로는 CharacterTextSpliter와 ReculsiveCharacterTextSpliter가 있다.
긴 텍스트를 지정된 최대 길이(chunk_size) 이하로 나누는 데 효과적인 텍스트 분할기(splitter)이다.
여러 구분자(separators)를 순차적으로 적용한다.
작동 방식
주요 파라미터
chunk_size: 각 조각의 최대 길이를 지정.
chunk_overlap: 연속된 청크들 간의 겹치는 문자 수를 설정. 새로운 청크 생성 시 이전 청크의 마지막 부분에서 지정된 수만큼의 문자를 가져와서 새 청크의 앞부분에 포함시켜, 청크 경계에서 문맥의 연속성을 유지한다. 예) 분할을 시/도한다. 이렇게 나뉘어질 수도 있음
separators(list): 구분자를 지정한다. 지정하면 기본 구분자가 지정한 것으로 변경된다.
embed_documents: 여러 문서embed_query: 하나의 문서