10차시. 벡터저장소 이해
실습 1 — 벡터저장소 이해 실습 따라 하기
관련 수업 자료: 10차시 「3. 실습 ① — 인덱스 만들고 저장하기」(7쪽), 10차시 「4. 실습 ② — 불러와서 재사용하기」(9~10쪽) · 실습 코드 10/build_index.py, 10/load_index.py, 10/indexer.py
이 실습은 교안 해설(10_벡터저장소이해.md)의 실습 순서를 옮긴 것입니다. OpenAI 임베딩이나 채팅 모델을 부르는 파일은 .env 에 API 키가 있어야 돌아갑니다. 키가 없으면 실행 결과 샘플로 출력 모양을 확인합니다.
수업 자료와 이어지는 곳
| 실습 코드 | 원본 PDF | 이어지는 내용 |
|---|---|---|
10/build_index.py | 7쪽 | 10차시 「3. 실습 ① — 인덱스 만들고 저장하기」 아래에 실었습니다 |
10/load_index.py | 9쪽 | 10차시 「4. 실습 ② — 불러와서 재사용하기」 아래에 실었습니다 |
10/indexer.py | 9~10쪽 | 10차시 「4. 실습 ② — 불러와서 재사용하기」 › 4-1) 있으면 불러오고 없으면 만들기 아래에 실었습니다 |
실행 흐름
faiss index가 있나 → load local (있다)
faiss index가 있나 → 읽기 분할 임베딩 (없다)
읽기 분할 임베딩 → save local
save local → load local
load local → 질문 검색실습 순서
키가 있으면 build_index.py로 저장하고, 같은 폴더에서 load_index.py를 다시 실행해 두 번째가 빠른지 봅니다. indexer.py는 그 분기를 함수로 감쌉니다.
스스로 확인
- 인덱스를 질문마다 만들면 안 되는 이유를 아는가?
- faiss 파일과 pkl 파일이 각각 무엇을 담는가?
- 거리 점수와 유사도 점수를 섞어 읽으면 어떤 실수가 나는가?
코드 설명
store.save_local(INDEX_PATH)는 폴더 하나에index.faiss와index.pkl을 씁니다. 벡터만으로는 원문을 복원할 수 없어서, 원문과 metadata는 .pkl에 따로 담깁니다.FAISS.load_local(INDEX_PATH, emb, allow_dangerous_deserialization=True)의 마지막 옵션을 빠뜨리면 ValueError가 납니다. pickle 파일은 열 때 코드가 실행될 수 있으므로 내가 만든 인덱스에만 씁니다.load_local에도emb를 넘기는 까닭은 질문을 임베딩해야 하기 때문입니다. 저장할 때와 다른 모델을 넘기면 오류 없이 엉뚱한 결과가 나옵니다. 여기서 많이들 헷갈리십니다.- load_index.py의
chunks = prepare_chuncks(DOC_PATH)는 PDF를 다시 읽기만 하고 검색에는 쓰이지 않습니다. 실행 결과에 "로딩 완료"가 두 번 찍히는 것도 이 줄과 import 때문입니다. - indexer.py는
from datetime import datetime으로 클래스를 가져왔으므로datetime.now()라고 써야 합니다. 지금처럼datetime.datetime.now()이면 폴더가 없어 새로 만드는 첫 실행에서 AttributeError가 납니다. store.index.ntotal은 FAISS 안에 든 벡터 개수입니다. 조각 하나에 벡터 하나이므로 조각 수와 같습니다.