[Langchain] Vectorstore (2) FAISS

Hunie_07·2025년 3월 30일
0

Langchain

목록 보기
11/35

(1) Chroma 에 이어서 계속됩니다.

  • 효율적인 벡터 유사도 검색 및 클러스터링을 위한 오픈소스 벡터 저장소
  • 설치: pip install faiss-cpu / poetry add faiss-cpu

1. 벡터 저장소 초기화

# 벡터 저장소에 문서를 저장할 때 적용할 임베딩 모델
from langchain_huggingface.embeddings import HuggingFaceEmbeddings

embeddings_model = HuggingFaceEmbeddings(model_name="BAAI/bge-m3")
  • .IndexFlatL2(임베딩차원) 으로 index 를 생성한다.
# 벡터 저장소 생성
import faiss 
from langchain_community.docstore.in_memory import InMemoryDocstore
from langchain_community.vectorstores import FAISS

# FAISS 인덱스 초기화 (유클리드 거리 사용)
faiss_index = faiss.IndexFlatL2(len(embeddings_model.embed_query("hello world")))
print("FAISS 인덱스 초기화 완료")

- 출력

FAISS 인덱스 초기화 완료

차원 수 확인

# FAISS 벡터 저장소의 벡터 차원 수 (임베딩 차원 수)
faiss_index.d

- 출력

1024

벡터 저장소 생성

# FAISS 벡터 저장소 생성
faiss_db = FAISS(
    embedding_function=embeddings_model,
    index=faiss_index,           # 벡터 검색을 위한 데이터 구조를 정의
    docstore=InMemoryDocstore(), # 문서 저장소 객체를 지정 - 문서의 원본 내용과 메타데이터를 보관
    index_to_docstore_id={},     # 인덱스와 문서 간의 연결을 관리 (매핑 딕셔너리)
)
# 저장된 문서의 갯수 확인
faiss_db.index.ntotal

- 출력

0

2. 벡터 저장소 관리

  • 문서 추가: vector_store.add_documents(documents, ids)
from langchain_core.documents import Document

# 문서 데이터 - (텍스트, 소스)
documents = [
    ("인공지능은 컴퓨터 과학의 한 분야입니다.", "AI 개론"),
    ("머신러닝은 인공지능의 하위 분야입니다.", "AI 개론"),
    ("딥러닝은 머신러닝의 한 종류입니다.", "딥러닝 입문"),
    ("자연어 처리는 컴퓨터가 인간의 언어를 이해하고 생성하는 기술입니다.", "AI 개론"),
    ("컴퓨터 비전은 컴퓨터가 디지털 이미지나 비디오를 이해하는 방법을 연구합니다.", "딥러닝 입문")
]

# Document 객체 생성
doc_objects = []
for content, source in documents:
    doc = Document(
        page_content=content,
        metadata={"source": source},
    )
    doc_objects.append(doc)


# 순차적 ID 리스트 생성
doc_ids = [f"DOC_{i}" for i in range(1, len(doc_objects) + 1)]

# 문서를 벡터 저장소에 저장
added_doc_ids = faiss_db.add_documents(documents=doc_objects, ids=doc_ids)

# 벡터 저장소에 저장된 문서를 확인
print(f"{len(added_doc_ids)}개의 문서가 성공적으로 벡터 저장소에 추가되었습니다.")
print(added_doc_ids)

- 출력

5개의 문서가 성공적으로 벡터 저장소에 추가되었습니다.
['DOC_1', 'DOC_2', 'DOC_3', 'DOC_4', 'DOC_5']

저장된 문서 갯수 확인

# 저장된 문서의 갯수 확인
faiss_db.index.ntotal

- 출력

5

저장된 인덱스 확인

# 저장된 인덱스 확인
faiss_db.index_to_docstore_id

- 출력

{0: 'DOC_1', 1: 'DOC_2', 2: 'DOC_3', 3: 'DOC_4', 4: 'DOC_5'}

저장된 문서 검색

# 저장된 문서 검색
faiss_db.docstore.search('DOC_1')

- 출력

Document(id='DOC_1', metadata={'source': 'AI 개론'}, page_content='인공지능은 컴퓨터 과학의 한 분야입니다.')

  • 문서 삭제: vector_store.delete(ids)
# 문서 id를 지정하여 삭제
faiss_db.delete(ids=["DOC_5"])

- 출력

True

저장된 문서 객체 확인

# 저장된 문서 객체를 확인
faiss_db.docstore._dict

- 출력

{'DOC_1': Document(id='DOC_1', metadata={'source': 'AI 개론'}, page_content='인공지능은 컴퓨터 과학의 한 분야입니다.'),
 'DOC_2': Document(id='DOC_2', metadata={'source': 'AI 개론'}, page_content='머신러닝은 인공지능의 하위 분야입니다.'),
 'DOC_3': Document(id='DOC_3', metadata={'source': '딥러닝 입문'}, page_content='딥러닝은 머신러닝의 한 종류입니다.'),
 'DOC_4': Document(id='DOC_4', metadata={'source': 'AI 개론'}, page_content='자연어 처리는 컴퓨터가 인간의 언어를 이해하고 생성하는 기술입니다.')}

3. 문서 검색

  • 유사도 검색 similarity_search
    • 주어진 쿼리와 가장 유사한 문서를 반환
    • k=2는 상위 2개의 결과를 반환하도록 지정
    • filter를 사용하여 특정 출처의 문서만 검색 가능
query = "인공지능과 머신러닝의 차이점은 무엇인가요?"
results = faiss_db.similarity_search(
    query,
    k=2,
    filter={"source": "AI 개론"}
)

print("유사도 검색 결과:")
for doc in results:
    print(f"- {doc.page_content} [출처: {doc.metadata['source']}]")

- 출력

유사도 검색 결과:
- 머신러닝은 인공지능의 하위 분야입니다. [출처: AI 개론]
- 인공지능은 컴퓨터 과학의 한 분야입니다. [출처: AI 개론]

  • 유사도 점수가 포함된 검색 similarity_search_with_score
    • 유사도 점수를 함께 반환
    • 점수가 낮을수록 더 유사한 것을 의미
query = "딥러닝은 어떤 분야에서 사용되나요?"
results = faiss_db.similarity_search_with_score(
    query,
    k=2,
    filter={"source": "AI 개론"}
)

print("점수가 포함된 유사도 검색 결과:\n")
for doc, score in results:
    print(f"- 점수: {score:.4f}")
    print(f"  내용: {doc.page_content}")
    print(f"  [출처: {doc.metadata['source']}]")
    print()

- 출력

점수가 포함된 유사도 검색 결과:

- 점수: 0.8442
  내용: 머신러닝은 인공지능의 하위 분야입니다.
  [출처: AI 개론]

- 점수: 0.9845
  내용: 인공지능은 컴퓨터 과학의 한 분야입니다.
  [출처: AI 개론]

  • 관련성 점수가 포함된 검색 similarity_search_with_relevance_scores
    • 문서와 함께 0에서 1 사이의 관련성 점수를 반환
    • 0은 가장 관련성이 낮고, 1은 가장 관련성이 높음을 의미
query = "딥러닝은 어떤 분야에서 사용되나요?"
results = faiss_db.similarity_search_with_relevance_scores(
    query,
    k=2,
    filter={"source": "AI 개론"}
)

print(f"쿼리: {query}")
print("\n검색 결과 (관련성 점수 포함):")
for doc, score in results:
    print(f"- 관련성 점수: {score:.4f}")
    print(f"  내용: {doc.page_content}")
    print(f"  [출처: {doc.metadata['source']}]")
    print()

- 출력

쿼리: 딥러닝은 어떤 분야에서 사용되나요?

검색 결과 (관련성 점수 포함):
- 관련성 점수: 0.4031
  내용: 머신러닝은 인공지능의 하위 분야입니다.
  [출처: AI 개론]

- 관련성 점수: 0.3038
  내용: 인공지능은 컴퓨터 과학의 한 분야입니다.
  [출처: AI 개론]

4. 로컬에 저장 및 로드

  • Chroma 의 경우 저장소 생성시 collection_namepersist_directory 로 이름과 저장 경로를 설정했었으나 FAISS 의 경우 생성 후 별도 저장 / 로드

로컬에 저장

  • folder_pathindex_name 으로 경로와 이름 설정 가능
# 로컬에 저장
faiss_db.save_local("faiss_ai_sample_index")

▶ 위와 같은 형태로 저장된 모습


로컬에 저장된 저장소 로드

# 로컬에 저장된 FAISS 벡터 저장소 불러오기
faiss_db2 = FAISS.load_local(
    "faiss_ai_sample_index", embeddings_model, allow_dangerous_deserialization=True
)

0개의 댓글