feat: 임베딩 기반 맞춤 추천 추가#84
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
choihooo
left a comment
There was a problem hiding this comment.
리뷰했습니다. 전체적으로 타입체크/빌드는 통과했고, 임베딩 기반 추천 흐름에서 운영 중 빈 결과나 누락이 생길 수 있는 지점 위주로 봤습니다.
Findings
P1: 큐레이션 임베딩 갱신이 rate limit에 걸려 대량 누락될 수 있습니다
packages/web/src/lib/embedding-refresh.ts에서 큐레이션 크롤 후 최대 100개 item을 bot API로 개별 POST하는데, bot 쪽 packages/bot/src/api-server.ts의 triggerLimiter가 10 req/min으로 걸려 있습니다. 한 번에 10개 넘게 수집되면 11번째부터 429로 실패해서 대부분 임베딩이 생성되지 않습니다.
bulk endpoint를 만들거나 내부 임베딩 endpoint는 별도 rate limit/배치 처리로 분리하는 게 좋겠습니다.
P1: 추천 탭이 백필/장애 상황에서 빈 화면이 될 수 있습니다
packages/web/src/app/api/curation/route.ts와 packages/web/src/app/api/posts/route.ts 모두 사용자의 preference embedding만 있으면 바로 vector 추천 path로 들어가고, 이후 content embedding이 없는 row를 IS NOT NULL로 제외합니다.
임베딩은 best-effort/비동기라 초기 배포, 백필 전, provider 장애, 위 rate-limit 상황에서 추천 탭이 비어 보일 수 있습니다. vector 결과가 부족하면 overlap/latest로 채우는 fallback이 필요해 보여요.
P2: 큐레이션 vector 추천 cursor가 시간에 따라 불안정합니다
packages/web/src/app/api/curation/route.ts의 vector 추천 커서가 now() 기반 freshness를 포함한 finalScore를 그대로 저장/비교합니다. 다음 페이지 요청 때 점수가 재계산되면 같은 item도 이전 cursor score보다 작아져 다시 나올 수 있습니다.
keyset pagination에서는 점수가 안정적이어야 해서, cursor에 asOf를 포함해 같은 기준 시각으로 재계산하거나 freshness를 커서 정렬키에서 빼는 쪽이 안전합니다.
Verification
pnpm --filter @blog-study/shared typecheck통과pnpm --filter @blog-study/web typecheck통과pnpm --filter @blog-study/bot typecheck통과pnpm --filter @blog-study/shared test통과: 93 testspnpm --filter @blog-study/bot test통과: 150 testspnpm --filter @blog-study/web test실패: 테스트 파일 없음으로 Vitest가 code 1 종료pnpm --filter @blog-study/shared build,bot build,web build통과


🎯 Summary
/curation과/posts추천을 임베딩 기반 맞춤 추천으로 전환하고 추천 이유 UI를 추가합니다.🔴 AS-IS
/curation추천 정렬이 사용자 관심사와 아이템 태그의 단순 겹침 기준이라 추천 품질이 제한적이었습니다./posts에는 최신순/인기순만 있어 사용자 취향 기반으로 글을 발견하기 어려웠습니다.🟢 TO-BE
/api/curation?sort=recommended를 벡터 유사도 + 최신성 + 기존 관련도 보정 기반으로 정렬하도록 변경했습니다./posts에맞춤탭을 추가하고, 관심도순 정렬과 추천 이유/관심도 UI를 맞춤 탭 전용으로 표시합니다.💬 참고사항
EMBEDDING_PROVIDER=ollama,nomic-embed-text, 768차원 기준입니다.pnpm --filter @blog-study/web typecheckpnpm --filter @blog-study/shared typecheckpnpm --filter @blog-study/bot typecheckpnpm --filter @blog-study/shared test embedding-text.property.test.ts recommendation-reason.property.test.ts