YogiPick
해커톤 3위요기픽
프로젝트 설명
"뭐 먹지"를 스와이프 3분으로 끝내는 AI 메뉴·매장 매칭 서비스입니다. 순위는 Oracle AI Database 26ai의 벡터 검색이 정하고 LLM은 자연어 입출력만 담당하는 구조로 설계했습니다. 요기요 X 오라클 AI 해커톤에서 예선 약 190팀 중 본선 8팀에 올라 최종 3위(장려상)를 수상했습니다.
- 요기요 X 오라클 AI 해커톤 최종 3위(장려상) — 예선 약 190팀 중 본선 8팀 진출 (Team FLOW)
- Expo(React Native) 앱 16개 화면 단독 구현 + 웹/APK 데모 배포
- Oracle AI Database 26ai VECTOR(36) + HNSW ANN 검색으로 메뉴 2,670개 실시간 추천
- 순위는 벡터 수학, LLM은 NLU·설명만 담당 — 할루시네이션이 추천 품질을 오염시키지 않는 구조
- 알레르기는 BITAND 비트마스크로 SQL 후보 단계에서 원천 차단 (점수 감점이 아닌 하드 제약)
- 그룹 동시 스와이프 Least-Misery 합의 스코어링 + Socket.IO 실시간 매장 투표
기술 스택
아키텍처
사용자 (iOS/Android/Web — Expo) ├─ REST ────────▶ NestJS (OCI 컨테이너 인스턴스) │ ├─ /recommendations → 36차원 쿼리 벡터 합성 │ │ └─ Oracle AI DB 26ai — VECTOR_DISTANCE(COSINE) + HNSW ANN │ ├─ /swipes → PICK/PASS EMA 취향 학습 │ └─ llm.service → OCI GenAI (Llama 3.3 70B) NLU·추천 이유 └─ WebSocket ───▶ Socket.IO Gateway (그룹 동시 스와이프·매장 투표)
추천 순위는 Oracle 벡터 검색 + 5-factor 앙상블 재랭킹이 결정하고, LLM은 자연어 입출력(NLU 파싱·추천 이유 생성)만 담당합니다. 배포는 main push → GitHub Actions → Docker Hub → OCI 컨테이너 인스턴스 재시작으로 자동화했습니다.
주요 기능
스와이프 취향 학습
PICK/PASS를 EMA로 36차원 취향 벡터에 반영. 반응 속도를 가중(빠른 PICK = 강한 선호)하고, 메뉴판 체류시간(dwell)은 약한 신호로 별도 학습률 적용
Oracle 26ai 벡터 검색
VECTOR(36, FLOAT32) 컬럼 + HNSW 인메모리 이웃 그래프 인덱스. FETCH APPROXIMATE FIRST ANN 검색, ANN vs 정확 검색 실행계획을 그대로 반환하는 검증 API 제공
쿼리 벡터 합성 + 재랭킹
취향 0.5 + 컨텍스트 0.3 + 실시간(시간대·날씨 API) 0.2로 쿼리 벡터를 합성한 뒤, 취향 궁합 0.5 / 리뷰 성격 0.2 / 별점 0.1 / 시간대 주문 패턴 0.1 / 인기도 0.1 앙상블로 재랭킹
NLU 2단계 처리
키워드 룰 1차로 대부분 즉답하고, 애매한 자유 문장만 OCI GenAI 2차 호출 + 캐시로 LLM 지연을 흡수
알레르기 하드 제약
BITAND(exclusion_mask, :mask) = 0 으로 SQL WHERE 절에서 후보 자체를 제거 — AI가 실수할 수 없는 구간으로 분리
그룹 합의 알고리즘
멤버 취향 벡터에 Least-Misery(평균 0.5 + 최소값 0.5) 스코어링을 적용해 "아무도 불행하지 않은" 메뉴를 상위 배치. Socket.IO 동시 스와이프 + 60초 매장 투표
시드 데이터 파이프라인
카카오/공공데이터 수집 + OCI GenAI 콘텐츠 생성으로 매장 320곳·메뉴 2,670개·리뷰 프로필 구축 (Python 수집·벡터화 스크립트)


