FAISSDocumentStore
FAISSDocumentStore
FAISSDocumentStore는 FAISS를 벡터 유사도 검색에 사용하는 로컬 Document Store예요. 벡터는 FAISS 인덱스에 저장하고, 문서 데이터는 메모리에 저장하며, 선택적으로 디스크에 영속화할 수 있어요.
출처: 문서
본문
FAISSDocumentStore는 별도의 외부 데이터베이스 서비스를 실행하지 않고 가벼운 설정을 원하는 로컬 개발 및 소규모·중간 규모 데이터셋에 잘 맞아요.
설치 (Installation)
FAISS 통합을 설치하세요.
pip install faiss-haystack
초기화 (Initialization)
FAISSDocumentStore 인스턴스를 만들고 임베딩된 문서를 작성해요.
from haystack import Document
from haystack.document_stores.types import DuplicatePolicy
from haystack_integrations.document_stores.faiss import FAISSDocumentStore
document_store = FAISSDocumentStore(
index_path="my_faiss_index", # Optional: enables persistence on disk
index_string="Flat",
embedding_dim=768,
)
document_store.write_documents(
[
Document(content="This is first", embedding=[0.1] * 768),
Document(content="This is second", embedding=[0.2] * 768),
],
policy=DuplicatePolicy.OVERWRITE,
)
print(document_store.count_documents())
# Persist index and metadata files (`.faiss` and `.json`)
document_store.save("my_faiss_index")
영속화 (Persistence)
FAISSDocumentStore를 초기화할 때 index_path를 제공하면 해당 경로에서 기존 영속 파일(.faiss와 .json)을 로드하려고 시도해요. 명시적으로 호출할 수도 있어요.
save(index_path): 인덱스와 메타데이터를 디스크에 써요.load(index_path): 나중에 다시 로드해요.
이전에 저장한 폴더/경로에서 로드하는 예시예요.
from haystack_integrations.document_stores.faiss import FAISSDocumentStore
# This loads `my_faiss_index.faiss` and `my_faiss_index.json` if they exist
document_store = FAISSDocumentStore(index_path="my_faiss_index")
# Alternatively, initialize first and then load explicitly
another_store = FAISSDocumentStore(embedding_dim=768)
another_store.load("my_faiss_index")
지원되는 리트리버 (Supported Retrievers)
FAISSEmbeddingRetriever: 쿼리 임베딩을 기반으로 FAISSDocumentStore에서 문서를 검색해요.
macOS에서 OpenMP 런타임 충돌 해결 (Fixing OpenMP Runtime Conflicts on macOS)
증상 (Symptoms)
런타임에 다음 오류 중 하나 또는 둘 다 발생할 수 있어요.
OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already initialized.
OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program.
resource_tracker: There appear to be 1 leaked semaphore objects to clean up at shutdown
OMP_NUM_THREADS=1로 설정하면 크래시가 사라진다면, 근본 원인은 여러 OpenMP 런타임이 동시에 로드된 것이에요. 각 런타임은 자체 스레드 풀과 스레드 로컬 저장소(TLS)를 유지해요. 두 런타임이 동시에 워커 스레드를 띄우면 서로의 메모리를 손상시켜 N > 1 스레드에서 세그폴트가 발생해요.
진단 (Diagnosis)
먼저 가상 환경에 libomp.dylib 복사본이 몇 개 있는지 찾아보세요.
find /path/to/your/.venv -name "libomp.dylib" 2>/dev/null
두 개 이상 보인다면, 예:
.venv/lib/pythonX.Y/site-packages/torch/lib/libomp.dylib
.venv/lib/pythonX.Y/site-packages/sklearn/.dylibs/libomp.dylib
.venv/lib/pythonX.Y/site-packages/faiss/.dylibs/libomp.dylib
이들을 단일 런타임으로 통합해야 해요.
해결 (Fix)
해결책은 하나의 표준 libomp.dylib(torch의 것을 추천)을 선택하고, 나머지 복사본을 모두 그곳을 가리키는 심볼릭 링크로 바꾸는 거예요.
각 중복에 대해 복사본을 삭제하고 심볼릭 링크로 교체하세요.
# Delete the duplicate
rm /path/to/.venv/lib/pythonX.Y/site-packages/<package>/.dylibs/libomp.dylib
# Replace with a symlink to the canonical copy
ln -s /path/to/.venv/lib/pythonX.Y/site-packages/torch/lib/libomp.dylib \
/path/to/.venv/lib/pythonX.Y/site-packages/<package>/.dylibs/libomp.dylib
발견된 모든 중복에 대해 반복하세요. 이 패키지들은 @loader_path 기준 참조로 libomp.dylib를 로드하기 때문에, 심볼릭 링크는 로드 시점에 단일 표준 런타임으로 투명하게 해석돼요.
검증 (Verify)
수정을 적용한 뒤, 단 하나의 고유한 libomp.dylib만 참조되는지 확인하세요.
find /path/to/your/.venv -name "*.so" | xargs otool -L 2>/dev/null | grep libomp | sort -u
모든 항목이 같은 표준 경로로 해석되어야 해요. 이제 OMP_NUM_THREADS=1 없이도 실행할 수 있을 거예요.