사후 필터링을 사용한 하이브리드 검색

Cloud_ Ghost·2025년 8월 11일

opensearch

목록 보기
5/23

사후 필터링을 사용한 하이브리드 검색

https://docs.opensearch.org/latest/vector-search/ai-search/hybrid-search/inner-hits/

2.13 버전에서 도입됨

쿼리에 post_filter 매개변수를 제공하여 하이브리드 검색 결과에 사후 필터링을 수행할 수 있습니다.

post_filter 절은 검색 결과가 검색된 후에 적용됩니다. 사후 필터링은 점수 매기기나 결과 순서에 영향을 주지 않고 검색 결과에 추가 필터를 적용하는 데 유용합니다.

사후 필터링은 문서 관련성 점수나 집계 결과에 영향을 주지 않습니다.

예제

다음 예제 요청은 두 개의 쿼리 절(term 쿼리와 match 쿼리)을 결합하고 post_filter를 포함합니다:

GET /my-nlp-index/_search?search_pipeline=nlp-search-pipeline
{
  "query": {
    "hybrid":{
      "queries":[
        {
          "match":{
            "passage_text": "hello"
          }
        },
        {
          "term":{
            "passage_text":{
              "value":"planet"
            }
          }
        }
      ]
    }
  },
  "post_filter":{
    "match": { "passage_text": "world" }
  }
}

사후 필터링이 없는 예제의 결과와 비교해보세요. 사후 필터링이 없는 예제에서는 응답이 두 개의 문서를 포함합니다. 이 예제에서는 두 번째 문서가 필터링되어 응답이 하나의 문서를 포함합니다:

{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.3,
    "hits": [
      {
        "_index": "my-nlp-index",
        "_id": "1",
        "_score": 0.3,
        "_source": {
          "id": "s1",
          "passage_text": "Hello world"
        }
      }
    ]
  }
}

사후 필터링이 검색 결과와 점수 매기기에 미치는 영향

사후 필터링은 최종 검색 결과와 문서 점수를 크게 변경할 수 있습니다. 다음 시나리오를 고려해보세요.

단일 쿼리 시나리오

다음 결과를 반환하는 쿼리를 고려해보세요:

  • 정규화 이전 쿼리 결과: [d2: 5.0, d4: 3.0, d1: 2.0]
  • 정규화된 점수: [d2: 1.0, d4: 0.33, d1: 0.0]

초기 쿼리 결과에 사후 필터를 적용한 후 결과는 다음과 같습니다:

  • 사후 필터 일치 항목: [d2, d4]
  • 결과 점수: [d2: 1.0, d4: 0.0]

사후 필터를 적용한 후 문서 d4의 점수가 0.33에서 0.0으로 변경된 것을 주목하세요.

다중 쿼리 시나리오

두 개의 하위 쿼리가 있는 쿼리를 고려해보세요:

  • 쿼리 1 결과: [d2: 5.0, d4: 3.0, d1: 2.0]
  • 쿼리 2 결과: [d1: 1.0, d5: 0.5, d4: 0.25]
  • 정규화된 점수:
    • 쿼리 1: [d2: 1.0, d4: 0.33, d1: 0.0]
    • 쿼리 2: [d1: 1.0, d5: 0.33, d4: 0.0]
  • 결합된 초기 점수: [d2: 1.0, d1: 0.5, d5: 0.33, d4: 0.165]

초기 쿼리 결과에 사후 필터를 적용한 후 결과는 다음과 같습니다:

  • 사후 필터 일치 항목: [d2, d4]
  • 결과 점수:
    • 쿼리 1: [d2: 5.0, d4: 3.0]
    • 쿼리 2: [d4: 0.25]
  • 정규화된 점수:
    • 쿼리 1: [d2: 1.0, d4: 0.0]
    • 쿼리 2: [d4: 1.0]
  • 결합된 최종 점수: [d2: 1.0, d4: 0.5]

다음을 관찰할 수 있습니다:

  • 문서 d2의 점수는 변경되지 않았습니다.
  • 문서 d4의 점수가 변경되었습니다.

1. 점수 보존 효과

  • 기존 검색 점수 유지: 사후 필터링은 원본 검색 결과의 관련성 점수를 변경하지 않고 단순히 결과를 필터링만 합니다
  • 순위 알고리즘 보호: 복잡한 검색 알고리즘의 점수 계산 로직이 필터링으로 인해 왜곡되지 않습니다

2. 성능 최적화

  • 집계 성능 향상: 집계는 필터링 전 전체 데이터셋에서 수행되므로 더 정확하고 빠른 집계 결과를 얻을 수 있습니다
  • 캐싱 효율성: 메인 쿼리 결과는 캐시될 수 있고, 다른 필터 조건으로 재사용 가능합니다

3. 유연한 사용자 경험

// 예시: 전자상거래 검색
{
  "query": {
    "hybrid": {
      "queries": [
        {"match": {"product_name": "노트북"}},
        {"neural": {"description_vector": {...}}}
      ]
    }
  },
  "post_filter": {
    "range": {"price": {"gte": 500000, "lte": 1500000}}
  }
}
  • 동적 필터링: 사용자가 검색 후 가격 범위, 브랜드 등을 조정할 때 메인 검색을 다시 실행하지 않고 필터만 적용
  • 패싯 네비게이션: 검색 결과에서 카테고리별 필터를 단계적으로 적용 가능

4. 비즈니스 로직 분리

  • 검색 vs 필터링 분리: 핵심 검색 로직과 비즈니스 필터링 로직을 명확히 구분
  • A/B 테스트 용이성: 메인 검색은 고정하고 다양한 필터 전략을 테스트 가능

5. 실제 활용 시나리오

전자상거래

// 상품 검색 + 재고/배송 필터링
"post_filter": {
  "bool": {
    "must": [
      {"term": {"in_stock": true}},
      {"term": {"fast_shipping": true}}
    ]
  }
}

콘텐츠 검색

// 문서 검색 + 권한/지역 필터링
"post_filter": {
  "bool": {
    "must": [
      {"term": {"access_level": "public"}},
      {"term": {"region": "KR"}}
    ]
  }
}

개인화 검색

// 개인 취향 반영하면서 기본 검색 품질 유지
"post_filter": {
  "bool": {
    "should": [
      {"term": {"user_preference": "electronics"}},
      {"range": {"user_rating": {"gte": 4.0}}}
    ]
  }
}

6. 개발 및 운영상 이점

  • 디버깅 용이성: 메인 쿼리와 필터를 분리하여 각각의 영향을 독립적으로 분석 가능
  • 점진적 개선: 기존 검색 품질을 유지하면서 추가 비즈니스 로직을 안전하게 적용
  • 모니터링: 필터링 전후 결과 수를 비교하여 필터의 효과를 정량적으로 측정 가능

사후 필터링은 특히 검색 품질을 해치지 않으면서 비즈니스 요구사항을 반영해야 하는 상황에서 매우 유용한 도구입니다.

profile
행복합시다~

0개의 댓글