본문 바로가기

프로젝트

Qdrant 임베딩

728x90

이번 프로젝트에서는 Qdrant를 Docker로 띄워서, 매운 음식 데이터를 기반으로 질의응답 서버를 구축했다.

사용자가 좋아하는 음식을 입력하면, 의미 기반 벡터 검색과 조건 필터링으로 관련 음식을 추천해준다.

Qdrant 띄우기

docker run -p 6333:6333 qdrant/qdrant

대시보드 접속: http://localhost:6333/dashboard#/collections

Collection 생성

임베딩 벡터 차원은 사용하는 모델 all-MiniLM-L6-v2 기준 384차원으로 설정했습니다.

curl -X PUT "http://localhost:6333/collections/food_collection" \
  -H "Content-Type: application/json" \
  -d '{
    "vectors": {
      "size": 384,
      "distance": "Cosine"
    }
  }'

샘플 데이터

{
  "id": "buldak_bokkeum_myeon",
  "name": "불닭볶음면",
  "country": "Korea",
  "spice_level": 5,
  "scoville_estimate": 4400,
  "ingredients": ["라면", "닭고기 추출물", "고추", "간장", "설탕"],
  "category": "instant noodles",
  "description": "입안이 얼얼할 정도로 맵고, 기름진 닭볶음 양념이 강렬하다. 한국에서 인기 있는 매운 라면.",
  "tags": ["매운","라면","인기","한국"]
}
  • description: 체감형 매운맛 묘사 → 임베딩 품질 향상
  • spice_level, scoville_estimate: 숫자 기반 필터링
  • country, ingredients, category: 조건 검색/하이브리드 검색 활용

Vector vs Payload

Qdrant에 데이터를 넣을 때는 두 가지 역할로 분리한다.

  • Vector: 의미 기반 검색용 (name + description + ingredients)
  • Payload: 메타데이터/필터용 (id, country, spice_level 등)
{
  "id": "buldak_bokkeum_myeon",
  "vector": [0.12, 0.82, 0.48, ...],
  "payload": {
    "name": "불닭볶음면",
    "country": "Korea",
    "spice_level": 5,
    "scoville_estimate": 4400,
    "ingredients": ["라면", "닭고기 추출물", "고추", "간장", "설탕"],
    "category": "instant noodles",
    "description": "입안이 얼얼할 정도로 맵고..."
  }
}

코사인 유사도

  • 1 → 거의 같은 의미
  • 0 → 관련 없음
  • -1 → 완전히 반대 의미

예시: "매운 라면" ↔ "불닭볶음면" → 0.95, "매운 라면" ↔ "바닐라 아이스크림" → 0.1

검색 방법

  • Similarity Search: 벡터끼리 비교 → 맛/재료/설명 유사한 음식 추천
  • Hybrid Search: 벡터 검색 + Payload 필터링 → 조건 포함 검색 가능
    • 예: "불닭볶음면과 비슷한 음식 중 한국 음식만"
    • 예: "한국에서 닭고기 들어간 매운 라면"

검색 예시 (Axios)

const response = await axios.post(
  `http://localhost:6333/collections/food_collection/points/search`,
  {
    vector,
    limit: 3,
    with_payload: true,
    filter: {
      must: [
        { key: "ingredients", match: { value: "닭고기" } }
      ]
    }
  },
  { headers: { "Content-Type": "application/json" } }
);

검색 결과 예시

{
  "search_results": [
    {
      "score": "0.5414",
      "name": "불닭",
      "description": "매운 양념으로 양념된 닭고기..."
    },
    {
      "score": "0.3152",
      "name": "매운 인도 팔 커리",
      "description": "세계에서 가장 매운 커리 중 하나..."
    },
    {
      "score": "0.3043",
      "name": "매운 멕시코 팅가",
      "description": "닭고기를 매운 고추와 토마토 소스로..."
    }
  ]
}

요약

  • Qdrant: HNSW 기반 ANN 벡터 검색 + 필터링
  • Vector: 의미 검색(name/description/ingredients)
  • Payload: 조건/숫자 필터용(id, country, spice_level)
  • Similarity Search + Payload 필터 → 추천/검색 품질 최적화
728x90
반응형