7장. 자체 임베딩과 벡터DB, 검색 품질
FAISS 와 Chroma
반찬을 담을 때 밀폐 용기만 쓸 수도 있고, 이름표와 날짜를 붙여 냉장고 칸에 정리할 수도 있습니다. FAISS 는 벡터만 담는 튼튼한 용기이고, Chroma 는 원문과 이름표(메타데이터)까지 함께 정리하는 냉장고입니다.
왼쪽 FAISS 는 벡터와 번호만 다루므로, 번호에 맞는 원문은 우리가 따로 들고 있어야 합니다. 오른쪽 Chroma 는 조각의 원문, 임베딩, 메타데이터를 한 컬렉션에 넣고, 찾을 때 원문과 메타데이터를 함께 돌려줍니다. 여기서 밀폐 용기가 FAISS, 이름표 붙인 냉장고 칸이 Chroma 입니다.
두 도구 견주기
| 견줄 것 | FAISS | Chroma |
|---|---|---|
| 담는 것 | 벡터(번호로 구분) | 원문, 벡터, 메타데이터 |
| 저장 | faiss.write_index 로 파일 하나 | 폴더 하나(PersistentClient) |
| 메타데이터로 거르기 | 없다(직접 짠다) | where={"제목": ...} |
| 인덱스 | Flat, IVF, HNSW 등 여럿을 고른다 | HNSW 를 알아서 쓴다 |
| 알맞은 곳 | 빠른 검색만 필요할 때, 큰 규모 | 작은 앱을 빨리 만들 때 |
11장에서는 폐쇄망에서 쓸 벡터DB 를 더 견줍니다.
Chroma 에 넣는 꼴
Chroma 에는 조각마다 id, 원문, 임베딩, 메타데이터를 같은 순서의 목록으로 넣습니다.
chunks = ["## 계정 잠김\n비밀번호를 5번 틀리면 계정이 30분 동안 잠깁니다.",
"## 보안 인쇄\n인사·급여 문서는 보안 인쇄로 출력합니다."]
ids = [f"s{i}" for i in range(len(chunks))] # 조각마다 겹치지 않는 이름
metas = [{"제목": c.split("\n")[0].removeprefix("## ")} for c in chunks] # 제목을 메타데이터로
print(ids)
print(metas)
# col.add(ids=ids, documents=chunks, embeddings=임베딩목록, metadatas=metas) ← 실습 3['s0', 's1'] 과 [{'제목': '계정 잠김'}, {'제목': '보안 인쇄'}] 가 나옵니다. 실습 3에서 진짜 임베딩과 함께 넣습니다.
코드에 나오는 함수
| 코드 | 쉬운 뜻 |
|---|---|
f"s{i}" | 조각 번호 앞에 s 를 붙여 s0, s1 같은 이름을 만든다. Chroma 의 id 는 글자여야 한다 |
c.split("\n")[0] | 조각을 줄 단위로 나눠 첫 줄(제목 줄)만 꺼낸다 |
.removeprefix("## ") | 글 앞에 ## 가 있으면 떼어 낸다. prefix 는 "앞에 붙은 것"이라는 뜻이다 |
{"제목": ...} | 조각 하나의 메타데이터다. 이름(제목)과 값을 짝지은 사전이다 |
col.add(ids=..., documents=..., embeddings=..., metadatas=...) | Chroma 컬렉션에 조각을 넣는 꼴이다. 네 목록의 같은 자리가 같은 조각이다. 여기서는 주석으로만 보였다 |
이 코드가 뜻하는 것
냉장고에 반찬을 넣기 전에 통마다 번호표와 이름표를 붙이는 일입니다. 여기서 번호표가 ids, 반찬이 원문 chunks, 이름표가 메타데이터 metas 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
chunks = [...] | 조각 두 개의 원문 | 반찬 두 통 |
ids = [...] | 조각마다 겹치지 않는 이름을 만든다 | 통마다 번호표 |
metas = [...] | 조각의 제목 줄에서 제목을 떼어 메타데이터로 만든다 | 통에 "계정 잠김" 같은 이름표 |
print(ids), print(metas) | 만든 목록을 확인한다 | 붙이기 전에 표를 한 번 본다 |
목록 셋의 0번째가 모두 "계정 잠김" 조각, 1번째가 모두 "보안 인쇄" 조각을 가리킵니다. 순서가 하나라도 어긋나면 엉뚱한 원문에 엉뚱한 이름표가 붙으므로, 같은 chunks 에서 한꺼번에 만들어 순서를 맞춥니다.
주의할 점
- Chroma 에 임베딩을 주지 않으면 Chroma 의 기본 임베딩 모델(영어 위주)로 알아서 만듭니다. 한국어 문서는 이 장처럼 우리가 고른 모델로 만든 임베딩을 직접 넣습니다.
- 같은 id 로 다시
add하면 겹칩니다. 문서를 고칠 때는upsert나delete뒤add를 씁니다.