본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

갱신, 삭제, 재임베딩

~20 min · chroma, lifecycle

Level 0Scout
0 XP0/41 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

ID를 기준으로 upsert해

다시 수집할 때는 collection.upsert()를 써. ID가 있으면 갱신하고 없으면 새로 넣어. 이 원칙이 여러 번 실행해도 결과가 같은 수집 파이프라인과 두 번째 실행에서 망가지는 파이프라인을 가르는 차이야.

논리 삭제는 표시로, 물리 삭제는 ID로

변경 이력을 중시하는 시스템에서는 삭제한 청크의 메타데이터에 {'deleted': True}를 표시하고 검색할 때 제외해. 실제 저장 공간에서도 지워야 한다면 collection.delete(ids=[...])로 물리적으로 제거해.

재임베딩 전략

임베딩 모델을 바꾸면 모든 벡터를 다시 만들어야 해. 방법은 두 가지야.

  • 컬렉션을 나란히 만들기. docs-bge-m3-v1 옆에 docs-bge-m3-v2를 구축하고, 준비되면 읽기 포인터를 전환해. 일주일 뒤 v1을 삭제하면 돼.
  • 기존 컬렉션에서 다시 만들기. ID를 순회하며 재임베딩하고 upsert해. 작은 컬렉션에서는 쓸 수 있지만, 큰 컬렉션은 작업 도중 벡터가 섞여 검색의 일관성을 잃으므로 위험해.

가능하면 컬렉션을 나란히 만들어. 문제가 생겼을 때 읽기 포인터를 v1으로 되돌리기만 하면 돼.

Code

upsert로 반복 가능한 수집 만들기·python
docs.upsert(
    ids       =[c['id']       for c in chunks],
    documents =[c['text']     for c in chunks],
    metadatas =[c['metadata'] for c in chunks],
    embeddings=vecs,
)
컬렉션을 나란히 만드는 재임베딩 이전·python
src = client.get_collection('docs-bge-m3-v1')
dst = client.get_or_create_collection('docs-bge-m3-v2',
                                      metadata={'hnsw:space': 'cosine'})

batch = src.get(include=['documents', 'metadatas'])
new_vecs = new_model.encode(batch['documents'], normalize_embeddings=True).tolist()

dst.upsert(
    ids       =batch['ids'],
    documents =batch['documents'],
    metadatas =batch['metadatas'],
    embeddings=new_vecs,
)
# dst.count() == src.count() 되면 앱 config 의 read pointer 전환

External links

Exercise

작은 병렬 이전을 만들어 봐. 한 모델로 만든 청크 200개를 v1 컬렉션에 넣고, 다른 모델로 임베딩해 v2에 복사해. 같은 쿼리 다섯 개를 양쪽에 실행해 상위 세 결과가 얼마나 겹치는지 확인해. 그 수치가 이전 과정에서 감수할 검색 변화의 기준이 돼.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.