updated_at: 2025-07-22 22:59

distance_function

distance_function은 벡터 간 유사도를 어떻게 계산할지를 결정하는 핵심 설정입니다. 특히 ChromaDB, FAISS, Pinecone, Weaviate 등 모든 벡터 DB에서 반드시 지정하는 요소이며, 챗봇의 "답변 정확도"에 직접적인 영향을 미칩니다.

distance_function 종류 및 차이

종류 의미 특징 유사도 판단 방식
'cosine' 코사인 거리 벡터 간 방향(각도) 비교 0에 가까울수록 유사
'l2' 또는 'euclidean' 유클리드 거리 벡터 간 직선 거리 비교 0에 가까울수록 유사
'ip' 또는 'dot' inner product (내적) 벡터 간 길이 포함 곱 값이 클수록 유사

예시 비교

  • cosine: A와 B의 방향이 같은지 비교 (문장이 길든 짧든 무관)
  • l2: A와 B가 얼마나 가까운 위치에 있는지 (길이도 중요)
  • ip: A와 B를 dot product 하여 문장이 길수록 유리 (크기가 커질수록 값도 커짐)

실제 사용 사례

분야 distance_function 추천
검색엔진(텍스트 유사도) cosine 👍
이미지 검색 l2 또는 ip
고객 FAQ 챗봇 cosine 👍👍
추천 시스템 (행동 기반 벡터) ip (dot product)

요약 정리

항목 선택
고객지원 챗봇에서 추천 cosine
내적 기반 빠른 추천이 필요할 때 ip 가능 (but 정밀도 낮음)
검색 정확도와 정밀도 우선 cosine 필수

추가팁

  • ip를 쓰면 normalize 하지 말고 쓰는 게 좋습니다.
  • cosine을 쓰면 normalize 벡터 필수입니다.
  • l2는 일반 텍스트에는 잘 안 씁니다. (단어 순서 중요할 때도 적합하지 않음)

예제

cosine

import { ChromaClient } from 'chromadb';
..........
client = new ChromaClient();
..........
normalize(vec) {
  const norm = Math.sqrt(vec.reduce((sum, v) => sum + v * v, 0));
  return vec.map(v => v / norm);
}

// 데이타 저장
async function getOrCreateCollection() {
  this.collection = await client.getOrCreateCollection({
    name: this.collectionName,
    metadata: { distance_function: 'cosine' }
  });

  console.log('📝 FAQ 데이터 저장 중...');
  const embeddings = await Promise.all(
    this.faqData.map(item =>
      this.getEmbedding(item.question).then(this.normalize)
    )
  );

  await this.collection.add({
    ids: this.faqData.map((_, i) => 'faq_' + i),
    documents: this.faqData.map(item => item.question),
    metadatas: this.faqData.map(item => ({ answer: item.answer })),
    embeddings
  });
}

// 답변 가져오기
async findAnswer(userQuestion) {
  if (!this.collection) {
    this.collection = await this.client.getCollection({ name: this.collectionName });
  }

  const queryEmbedding = this.normalize(await this.getEmbedding(userQuestion));
  const results = await this.collection.query({
    queryEmbeddings: [queryEmbedding],
    nResults: 1
  });

  const best = results?.metadatas?.[0]?.[0];
  const bestScore = results?.distances?.[0]?.[0]; // cosine: 낮을수록 유사함

  console.log('🔍 유사도 검색 결과(best):', best, '코사인 거리(bestScore):', bestScore);

  // ✅ cosine 거리 기준: 0.3 이하이면 매우 유사
  const COSINE_THRESHOLD = 0.35;

  if (!best || bestScore > COSINE_THRESHOLD) {
    return await this.generateGeneralResponse(userQuestion);
  }

  const final = await this.paraphraseAnswer(best.answer, userQuestion);
  return final;
}

평점을 남겨주세요
평점 : 2.5
총 투표수 : 1

질문 및 답글