Metadata-Version: 2.4
Name: vecdb-demo
Version: 0.1.1
Summary: Chroma / FAISS / LanceDB 를 같은 인터페이스로 비교하는 수업용 벡터 DB 데모
License-Expression: MIT
License-File: LICENSE
Keywords: chroma,embeddings,faiss,lancedb,tutorial,vector-database
Classifier: Intended Audience :: Education
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Requires-Dist: chromadb>=1.5.9
Requires-Dist: faiss-cpu>=1.14.2
Requires-Dist: lancedb>=0.30.2
Requires-Dist: sentence-transformers>=5.5.1
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Description-Content-Type: text/markdown

# vecdb-demo: Chroma / FAISS / LanceDB

세 가지 벡터 데이터베이스에서 **insert / update / delete / search** (CRUD + 검색)를
같은 인터페이스로 구현하고 테스트해보는 수업용 패키지.

[PyPI: vecdb-demo](https://pypi.org/project/vecdb-demo/)

## 설치

```bash
pip install vecdb-demo          # PyPI 에서 설치
# 또는 소스에서 개발 설치:
uv pip install -e ".[dev]"
```

> Python 3.12 이상 필요 (`chromadb` 의존성인 `onnxruntime` 이 3.11+ wheel만 제공).

## 패키지 구조

```
src/vecdb_demo/
  sample_data.py     공통 샘플 문서 + 카테고리
  embedding.py       공통 임베딩 함수 (다국어 모델)
  chroma_store.py    Chroma  — 텍스트만 넣으면 자동 임베딩
  faiss_store.py     FAISS   — 벡터를 직접 만들어 인덱스에 추가
  lancedb_store.py   LanceDB — 벡터+원문을 한 테이블에 저장
  compare.py         세 DB를 같은 시나리오로 돌려 비교
tests/
  test_stores.py            공통 CRUD+검색 (27 케이스)
  test_chroma_features.py   Chroma 특징: 자동 임베딩, 메타데이터/본문 필터
  test_faiss_features.py    FAISS 특징: L2/IP 척도, 인덱스 저장·로드, 배치 검색
  test_lancedb_features.py  LanceDB 특징: 필터+벡터검색 결합, 디스크 영속성
  test_compare.py           세 DB 결과 일치 교차 검증
```

## 콘솔 스크립트 (설치 후 바로 실행)

```bash
vecdb-compare    # 세 DB 특징 비교표 + A/B 시나리오 결과
vecdb-chroma     # Chroma  CRUD 흐름 시연
vecdb-faiss      # FAISS   CRUD 흐름 시연
vecdb-lancedb    # LanceDB CRUD 흐름 시연
```

## 라이브러리로 사용

```python
from vecdb_demo import ChromaStore, FaissStore, LanceStore

store = ChromaStore()
store.insert(ids=[0, 1], texts=["사과는 과일이다", "강아지는 동물이다"])
print(store.search("반려동물", k=1))
# [(1, '강아지는 동물이다', 0.36...)]   # (id, 문서, 점수)
```

`FaissStore`, `LanceStore` 도 같은 메서드를 제공하므로 클래스만 바꿔 쓰면 된다.

### 비교 예제 (한 시나리오, 세 구현)

| 파일 | 내용 |
|------|------|
| `compare.py` | 세 DB를 같은 데이터·같은 시나리오로 돌려 특징을 나란히 비교 |
| `test_compare.py` | 구현은 달라도 결과가 동일한지 교차 검증 |

`compare.py` 는 세 DB를 **동일한 인터페이스**(`insert`/`search`/`search_in_category`)로
감싼 어댑터로 묶어, "카테고리 필터 + 검색"이라는 같은 시나리오를 처리한다.
같은 결과가 나오지만 필터 구현 방식이 다른 것이 핵심:

- **Chroma**: `where` 메타데이터 필터 (네이티브)
- **LanceDB**: SQL `where` prefilter (네이티브)
- **FAISS**: 메타데이터가 없어 파이썬에서 직접 후필터링

```bash
vecdb-compare                # 특징 비교표 + A/B 시나리오 결과 출력
pytest tests/test_compare.py -v
```

세 store 는 모두 동일한 메서드를 제공한다:

| 메서드 | 설명 |
|--------|------|
| `insert(ids, texts)` | 문서 여러 개 추가 |
| `update(id, text)` | 문서 내용 교체 (임베딩도 재계산) |
| `delete(id)` | 문서 삭제 |
| `get(id)` | ID로 원문 조회 |
| `count()` | 저장된 문서 수 |
| `search(query, k)` | 유사 상위 k개를 `(id, 문서, 점수)`로 반환 |

> 점수의 의미는 백엔드마다 다르다: **Chroma·LanceDB는 거리**(작을수록 가까움),
> **FAISS는 내적 유사도**(클수록 가까움). 1순위 문서 자체는 세 DB가 동일하다.

## 테스트

```bash
pytest -q                    # 전체 49 케이스
pytest tests/test_stores.py -v
```

같은 CRUD 테스트(9개)를 세 백엔드에 모두 돌려 **27개 케이스**를 검증한다.
검색은 `"유사도 검색을 해주는 저장소는?"` 질의에
"벡터 데이터베이스는 임베딩을 저장하고 유사도로 검색한다." 문서를
1순위로 찾으면 정상이다.

## 핵심 차이 (수업 포인트)

| | 임베딩 | 원문 저장 | update/delete | 저장 위치 |
|---|---|---|---|---|
| **Chroma** | 텍스트 넣으면 자동 | O (자체 보관) | id 지정 | 메모리/디스크 |
| **FAISS** | 직접 생성해 주입 | X (dict로 직접 관리) | `IndexIDMap`로 id 삭제, update는 삭제+재삽입 | 메모리 |
| **LanceDB** | 직접 생성해 주입 | O (테이블 컬럼) | SQL 같은 `where` 조건 | 디스크 |

- **Chroma**: 가장 간단. 기본 임베딩은 영어용이라 여기선 다국어 모델을 지정했다.
- **FAISS**: 순수 벡터 인덱스라 원문/ID 매핑을 직접 관리. 대규모·고속 검색에 강함.
- **LanceDB**: 벡터와 메타데이터를 한 테이블에 저장, `where` 필터링 가능.
