목표: v1의 고정형 RAG(임베딩 기반 문맥 검색 + 단순 프롬프트) 방식의 한계를 극복
→ 사용자 질문으로부터 **검색 계획(JSON)**을 생성하고, 서버에서 안전하게 정규화/검증 → 시맨틱 검색 또는 하이브리드(벡터+텍스트) 검색 수행 → 응답을 SSE 스트리밍 방식으로 제공
현재 상태: POST /ai/v2/ask (SSE) 엔드포인트 정상 운영 중. 기존 v1 방식은 유지됨.
| 구분 | v1 현황 | v2 개선 방향 / 효과 |
|---|---|---|
| 고정 파라미터 | 임계치(threshold), LIMIT, 가중치(weights) 등이 고정되어 있어 다양한 사용자 요구 반영 불가 | top_k, threshold, weights, sort, limit 등을 질문의 맥락에 맞게 유연 조정. 다만 범위는 서버에서 강제하여 안정성 확보 |
| 시간/정렬 의도 반영 | “최근/이번 달/지난주/9월/작년” 등의 자연어 표현을 반영 못함 | filters.time 항목을 받아 KST 기준의 절대 기간(from/to)으로 변환하여 검색 쿼리에 적용. 정렬 순서(최신순/오래된순)도 반영 |
| 키워드 민감 질의 대응 | 단순 임베딩 유사도 기반 탐색만 가능 → 키워드 중심 질의에서 정확도 부족 | 하이브리드 검색 도입. 벡터 경로와 텍스트(키워드/질의) 경로 병합. 민감한 키워드 반영 가능. 리콜성과 정밀도 균형 개선 가능 |
| 관측성(어떤 검색 전략이 쓰였는지 등) 부족 | 내부 동작이 불투명, 사용자가 왜 이런 응답이 나왔는지 알기 어려움 | SSE에 중간 메타 이벤트(search_plan, rewrite, keywords, hybrid_result 등)를 포함하여 어떤 전략으로 검색했는지 사용자에게 투명하게 제공 |
| 보안 / 실행 정합성 | 사용자의 입력에 의한 시멘틱 서치만 수행하므로 실행 정합성 보장 | JSON 스키마(strict) + 서버 측 Zod 검증 + 범위 강제. SQL은 파라미터 바인딩 + 템플릿 방식 사용하여 SQL 인젝션 위험 줄임. 부적절한 계획 시 v1 경로로 폴백 가능 |
| 토큰 / 비용 관리 | 고정 상수 기준 접근 → 일부 상황(긴 질의, 많은 결과 필요 등)에서 비효율적 | top_k, (추후 적용할 limit / dedupe), 하이브리드 조합 등으로 문맥 길이 및 결과 수를 상황별로 조절 가능 → 토큰 사용 최적화 |
{
"user_id": string,
"category_ids?": [number],
"post_id?": string,
"time?": string
}
{
"enabled": boolean,
"retrieval_bias": "lexical" | "balanced" | "semantic",
"alpha?": number,
"max_rewrites?": number,
"max_keywords?": number
}
질문 → 임베딩 생성
postRepository.findSimilarChunksV2(...) 호출 — 파라미터 바인딩 기반 안전 쿼리
유사도 점수 계산:
\[
score = w_{\rm chunk} \times (1 - \text{chunk\distance}) + w{\rm title} \times (1 - \text{title\_distance})
\]
top_k 수만큼 후보 선택, threshold 아래 후보는 필터링