본문으로 건너뛰기

© 2026 Molayo

LangChain헤드라인2026. 05. 21. 03:45

높은 카디널리티 (High Cardinality) 상황에서의 쿼리 분석 벤치마킹

요약

LLM을 활용한 구조화된 데이터 추출 및 쿼리 분석 시, 가능한 값의 종류가 매우 많은 '높은 카디널리티(High Cardinality)' 범주형 값을 처리하는 문제와 해결 방안을 다룹니다. 가능한 값이 많아질수록 컨텍스트 제한, 비용, 추론 성능 저하 등의 문제가 발생하므로 이를 효율적으로 처리하기 위한 실험과 벤치마크 결과를 제공합니다.

핵심 포인트

  • 높은 카디널리티 범주형 값은 LLM이 허용된 값의 범위를 알지 못해 임의의 값을 생성(Hallucination)할 위험이 있음
  • 모든 가능한 값을 프롬프트에 포함하는 방식은 컨텍스트 크기 제한, 비용 증가, 추론 능력 저하 문제를 야기함
  • 쿼리 분석 유스케이스에서 저자 이름과 별칭(Aliases)을 처리하는 시나리오를 통해 문제 해결 방안을 실험함
  • 엔터프라이즈 환경의 복잡한 데이터 구조를 처리하기 위한 효율적인 접근 방식이 필요함

LLM (Large Language Models)의 몇 가지 주요 유스케이스 (use cases)는 데이터를 구조화된 형식 (structured format)으로 반환하는 것을 포함합니다. 추출 (Extraction)은 그러한 유스케이스 중 하나이며, 우리는 최근 업데이트된 문서와 전용 리포지토리 (repo)를 통해 이를 강조한 바 있습니다. 쿼리 분석 (Query analysis) 또한 또 다른 유스케이스이며, 최근 이와 관련된 문서도 업데이트했습니다. 정보를 구조화된 형식으로 반환할 때, 필드 (fields)는 문자열 (string), 불리언 (boolean), 정수 (integers) 등 무수히 많은 유형이 될 수 있습니다. 올바르게 처리하기 가장 어려운 유형 중 하나는 높은 카디널리티 (high-cardinality) 범주형 값 (categorical values) 또는 열거형 (enums)입니다.

“높은 카디널리티 범주형 값 (high-cardinality categorical values)”이란 무엇을 의미할까요? “범주형 값 (Categorical values)”은 몇 가지 가능한 값 중 하나여야 하는 값을 의미합니다. 예를 들어, 임의의 숫자나 문자열이 될 수 없으며 반드시 허용된 집합 내에 있어야 합니다. “높은 카디널리티 (High cardinality)”는 유효한 값의 개수가 많다는 것을 의미합니다.

이것이 왜 어려울까요? 이는 LLM이 해당 필드가 가질 수 있는 실제 가능한 값들이 무엇인지 본질적으로 알지 못하기 때문입니다. 따라서 LLM에게 가능한 값의 범위에 대한 정보를 제공해야 합니다. 만약 이렇게 하지 않으면, LLM은 값을 임의로 만들어낼 것입니다. 가능한 범주형 값의 수가 적다면 이는 쉽습니다. 단순히 프롬프트 (prompt)에 해당 값들을 넣고 LLM에게 그 값들만 사용하도록 정중하게 요청하면 됩니다. 하지만 값의 양이 많아지면 상황은 더 까다로워집니다.

가능한 값의 수가 증가함에 따라, LLM이 올바른 값을 채워 넣는 것은 점점 더 어려워집니다. 첫째, 가능한 값의 수가 충분히 많아지면 컨텍스트 (context)에 다 들어가지 않을 수 있습니다. 둘째, 모든 가능한 값이 컨텍스트에 들어갈 수 있다고 하더라도, 그것들을 모두 밀어 넣는 것은 속도, 비용, 그리고 해당 컨텍스트 전체를 추론하는 LLM의 능력에 문제를 일으킬 수 있습니다.

최근 저희는 쿼리 분석 (Query Analysis)에 대해 많은 시간을 할애하여 고민해 왔으며, 이 유스케이스 (Use case)에 대한 문서를 개편할 때 높은 카디널리티 (High cardinality) 범주형 값 (Categorical values)을 처리하는 방법에 대한 페이지를 명시적으로 추가했습니다. 이 블로그에서는 저희가 실험했던 몇 가지 접근 방식에 대해 심층적으로 살펴보고, 그것들이 어떻게 작동하는지에 대한 구체적인 벤치마크 (Benchmarks)를 제공하고자 합니다.

다음은 결과의 미리보기이며, LangSmith에서도 확인하실 수 있습니다. 자세한 내용은 계속해서 읽어주세요:

데이터셋 (The Dataset)

데이터셋은 여기에서 확인하실 수 있습니다.

이 문제를 시뮬레이션하기 위해, 우리는 저자별로 책을 검색하고자 하는 상황을 가정할 것입니다. 저자 필드는 높은 카디널리티를 가진 범주형 변수 (Categorical variable)입니다. 즉, 가질 수 있는 값이 매우 많지만, 구체적이고 유효한 저자 이름이어야 합니다. 이를 테스트하기 위해, 우리는 저자 이름과 흔히 쓰이는 별칭 (Aliases)으로 구성된 데이터셋을 만들었습니다. 예를 들어, 'Harry Chase'는 'Harrison Chase'의 별칭일 수 있습니다. 우리는 지능적인 시스템이 이러한 유형의 별칭을 처리할 수 있기를 기대합니다. 이름과 별칭 목록을 만든 후, 우리는 10,000개의 다른 무작위 이름을 생성했습니다. 참고로 10,000개는 사실 그리 높은 카디널리티도 아닙니다. 엔터프라이즈 시스템 (Enterprise systems)의 경우, 이는 수백만 개에 달할 수도 있습니다.

이 데이터셋이 생성되면, 우리는 “Harry Chase가 쓴 외계인에 관한 책은 무엇인가요?”와 같은 질문을 던질 것입니다. 우리의 쿼리 분석 시스템은 이 질문을 주제 (Topic)와 저자 (Author)라는 두 개의 필드를 가진 구조화된 형식 (Structured format)으로 파싱 (Parse)할 것으로 기대됩니다. 이 경우, 예상되는 결과는 {"topic": "aliens", "author": "Harrison Chase"}가 될 것입니다. 우리는 시스템이 Harry Chase라는 이름의 저자는 없지만, 사용자가 의도한 것은 아마도 Harrison Chase일 것이라는 점을 인식하기를 기대합니다.

이 설정을 통해 우리는 우리가 생성한 별칭 (aliases) 데이터셋을 대상으로 실험을 진행하여, 이들이 실제 이름으로 올바르게 매핑되는지 확인할 수 있었습니다. 또한 지연 시간 (latency)과 비용 (cost)도 추적했습니다. 이러한 유형의 쿼리 분석 시스템 (query analysis system)은 검색 (search) 분야에서 자주 사용되는데, 이는 우리가 두 요소 모두에 상당한 관심을 기울여야 함을 의미합니다. 이러한 이유로 우리는 모든 접근 방식이 오직 단 한 번의 LLM 호출 (LLM call)만 수행하도록 제한했습니다. 향후 포스트에서 여러 번의 LLM 호출을 사용하는 접근 방식들을 벤치마킹할 수도 있습니다.

아래에서는 몇 가지 서로 다른 접근 방식과 그 성능을 제시합니다.

전체 결과는 여기 LangSmith에서 확인할 수 있으며, 이를 재현하기 위한 코드는 여기에서 확인할 수 있습니다.

베이스라인 (Baseline)

먼저, 유효한 이름이 무엇인지에 대한 지식을 제공하지 않고 단순히 LLM에게 쿼리 분석을 수행하도록 요청하는 베이스라인을 벤치마킹했습니다. 예상대로, 단 하나의 응답도 맞추지 못했습니다. 이는 의도된 결과입니다. 우리는 별칭을 통해 저자를 명시적으로 묻는 데이터셋을 벤치마킹하고 있기 때문입니다.

컨텍스트 스터핑 (Context Stuffing)

이 접근 방식에서는 10,000개의 모든 정당한 저자 이름을 프롬프트 (prompt)에 밀어 넣고, LLM에게 해당 이름들이 정당한 저자 이름임을 유념하며 쿼리 분석을 수행하도록 요청했습니다. 일부 모델 (GPT-3.5와 같은)은 (컨텍스트 창 (context window) 제한으로 인해) 이를 아예 실행조차 할 수 없었습니다. 더 긴 컨텍스트 창을 가진 다른 모델들은 올바른 이름을 정확하게 선택하는 데 어려움을 겪었습니다. GPT-4는 예시의 **26%**에서만 올바른 이름을 선택했습니다. 가장 큰 실수는 이름을 수정하지 않고 그대로 추출하는 것이었습니다. 이 방법은 또한 상당히 느리고 비용이 많이 들었는데, 실행하는 데 평균 5초가 소요되었고 총 $8.44의 비용이 발생했습니다.

Pre-LLM 필터링 (Pre-LLM Filtering)

우리가 벤치마킹한 다음 접근 방식은 LLM (Large Language Model)에 전달할 가능한 값들의 목록을 필터링하는 것이었습니다. 이 방식은 가능한 이름들의 부분 집합(subset)을 LLM에 전달한다는 장점이 있으며, 이는 LLM이 고려해야 할 이름이 훨씬 적음을 의미합니다. 이를 통해 쿼리 분석을 더 빠르고, 저렴하며, 정확하게 수행할 수 있기를 기대할 수 있습니다. 다만, 이는 별도의 잠재적인 실패 모드(failure mode)를 추가합니다. 즉, 초기 필터링이 잘못된다면 어떻게 될까요?

임베딩 유사도에 의한 필터링 (Filter by Embedding Similarity)

초기 필터링을 위해 우리는 임베딩 (embedding) 기반 접근 방식을 사용하였으며, 쿼리와 가장 유사한 상위 10개의 이름을 선택했습니다. 여기서 우리는 전체 쿼리를 이름과 비교하고 있다는 점에 유의하십시오. 이는 아주 훌륭한 비교 방식은 아닙!

우리는 이 접근 방식을 통해 GPT-3.5가 예시의 **57%**를 정확하게 맞추는 데 성공했다는 것을 발견했습니다. 이 방식 또한 이전 방법보다 훨씬 빠르고 저렴했으며, 평균 실행 시간은 0.76초였고 총 비용은 $0.002가 소요되었습니다.

NGram 유사도에 의한 필터링 (Filter by NGram Similarity)

우리가 사용한 두 번째 필터링 접근 방식은 모든 유효한 이름의 3-gram 문자 시퀀스 (character sequences)에 TF-IDF 벡터라이저 (vectorizer)를 적용하고, 벡터화된 유효한 이름들과 벡터화된 사용자 입력 사이의 코사인 유사도 (cosine similarity)를 사용하여 모델 프롬프트에 추가할 가장 관련성 높은 상위 10개의 유효한 이름을 선택하는 것이었습니다. 여기서 우리는 전체 쿼리를 이름과 비교하고 있다는 점에 유의하십시오. 이는 아주 훌륭한 비교 방식은 아닙!

우리는 이 접근 방식을 통해 GPT-3.5가 예시의 **65%**를 정확하게 맞추는 데 성공했다는 것을 발견했습니다. 이 방식 또한 이전 방법보다 훨씬 빠르고 저렴했으며, 평균 실행 시간은 0.57초였고 총 비용은 $0.002가 소요되었습니다.

Post-LLM 선택 (Post-LLM Selection)

우리가 벤치마킹한 마지막 방법은 먼저 LLM으로 쿼리 분석 (Query Analysis)을 수행한 다음, 사후에 오류를 수정하려고 시도하는 방식이었습니다. 우리는 먼저 사용자 입력에 대해 쿼리 분석을 실행했으며, 프롬프트에 유효한 저자 이름이 무엇인지에 대한 어떠한 정보도 넣지 않았습니다. 이는 우리가 처음에 실행했던 베이스라인 (Baseline)과 동일했습니다. 그 후, 저자 필드에 있는 이름을 가져와 가장 유사한 유효한 이름을 찾는 단계를 추가로 실행했습니다.

임베딩 유사도에 의한 선택 (Select by Embedding Similarity)

먼저 임베딩 (Embeddings)을 사용하여 이 유사도 검사를 수행했습니다.

이 접근 방식에서 GPT-3.5는 예시의 **83%**를 정확하게 맞추는 데 성공했습니다. 이는 이전 방법보다 훨씬 빠르고 저렴했으며, 평균 실행 시간은 0.66초였고 총 비용은 $0.001이 소요되었습니다.

NGram 유사도에 의한 선택 (Select by NGram Similarity)

마지막으로 우리의 3-gram 벡터라이저 (Vectorizer)를 사용하여 이 유사도 검사를 시도했습니다.

이 접근 방식에서 GPT-3.5는 예시의 **74%**를 정확하게 맞추는 데 성공했습니다. 이 역시 이전 방법보다 훨씬 빠르고 저렴했으며, 평균 실행 시간은 0.48초였고 총 비용은 $0.001이 소요되었습니다.

결론 (Conclusion)

우리는 높은 카디널리티 (High Cardinality) 범주형 변수를 사용하여 쿼리 분석을 수행하는 다양한 방법들을 벤치마킹했습니다. 우리는 단 한 번의 LLM 호출 (LLM Call)만 허용하도록 제약을 두었으며, 이로 인해 체이닝 (Chaining)이나 에이전트 (Agent) 기술을 사용할 수 없었습니다. 이는 실제 환경의 지연 시간 (Latency) 제약을 모사하기 위함이었습니다. 우리는 임베딩 유사도를 통한 사후 LLM 선택 (Post-LLM Selection) 방식이 가장 우수한 성능을 보인다는 것을 발견했습니다.

벤치마킹할 다른 방법들이 더 남아 있습니다. 특히, (LLM 호출 전후에) 가장 유사한 범주형 값을 찾기 위해 고려할 수 있는 많은 방법이 있습니다. 또한 이 데이터셋에서 사용된 카테고리는 많은 엔터프라이즈 시스템이 다루어야 하는 것만큼 카디널리티가 높지는 않습니다. 이 데이터셋은 약 1만 개의 값을 가지고 있었지만, 실제 환경의 많은 데이터는 수백만 개에 달합니다. 더 높은 카디널리티의 데이터와 더 많은 양의 데이터를 대상으로 벤치마킹을 수행할 가치가 있을 것입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 LangChain Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0