공지
주간 SaaS 의 발전을 위해 설문조사에 참여해 주세요!

AI 에이전트 시대를 준비하는 SaaS를 위한 사례: Uber QueryGPT

Uber의 LLM 기반의 자연어 SQL 쿼리 생성기 개발 사례

2025.01.07 | 조회 1.11K |
0
|
from.
SaaS노동자
주간 SaaS의 프로필 이미지

주간 SaaS

B2B SaaS 비즈니스 모델과 멀티 테넌트 아키텍처 설계에 관한 좋은 콘텐츠를 소개합니다.

오늘의 소개글

안녕하세요 주간SaaS 입니다.

최근 마이크로소프트 CEO가 "AI 에이전트는 SaaS를 근본적으로 변화시킬 것"이라고 언급하며 큰 화제를 불러일으켰습니다. 'SaaS is Dead'라는 극단적인 주장부터 새로운 기회의 도래라는 긍정적인 전망까지, 업계의 반응은 엇갈리고 있습니다. 하지만 AI 에이전트가 SaaS에 새로운 패러다임을 가져올 것이라는 점은 분명해 보입니다.

오늘 소개하는 Uber의 QueryGPT는 바로 이러한 변화의 흐름을 보여주는 흥미로운 사례입니다. LLM을 활용한 자연어 처리 기반의 쿼리 생성기를 통해 개발자의 생산성을 획기적으로 높이고, 누구나 쉽게 데이터에 접근하고 분석할 수 있게 하는 이 사례는 AI를 활용하여 SaaS를 고도화하는 접근 방법에 대한 인사이트를 제공합니다.


서론 (Introduction)

Uber의 엔지니어, 운영 관리자, 데이터 과학자들은 매일 수 테라바이트의 데이터에 접근하고 조작하기 위해 SQL을 필수 도구로 사용합니다. 이러한 쿼리를 작성하려면 SQL 구문에 대한 확실한 이해뿐만 아니라 Uber 내부 데이터 모델이 비즈니스 개념을 어떻게 나타내는지에 대한 깊이 있는 지식도 필요합니다. QueryGPT는 이러한 간극을 해소하여 사용자가 자연어 프롬프트를 통해 SQL 쿼리를 생성할 수 있도록 함으로써 생산성을 크게 향상시키는 것을 목표로 합니다.

QueryGPT는 대규모 언어 모델(LLM, Large Language Model), 벡터 데이터베이스 및 유사성 검색을 사용하여 사용자가 입력으로 제공하는 영어 질문으로부터 복잡한 쿼리를 생성합니다. 이 글에서는 지난 1년간의 개발 과정과 현재 QueryGPT의 현황을 자세히 설명합니다.

동기 (Motivation)

(그림 1: 쿼리 작성 프로세스)
(그림 1: 쿼리 작성 프로세스)

Uber의 데이터 플랫폼은 매달 약 120만 건의 대화형 쿼리를 처리합니다. 가장 큰 사용자 그룹 중 하나인 운영 부서는 이러한 쿼리의 약 36%를 생성합니다. 이러한 쿼리를 작성하려면 일반적으로 데이터 딕셔너리에서 관련 데이터 세트를 검색하고 쿼리 편집기에서 쿼리를 작성하는 데 상당한 시간이 소요됩니다. 각 쿼리 작성에 약 10분이 걸린다고 가정하면, 이 프로세스를 자동화하고 약 3분 만에 신뢰할 수 있는 쿼리를 생성할 수 있는 QueryGPT의 도입은 상당한 생산성 향상을 의미합니다.

(그림 2: 쿼리 빌더 사용 현황)
(그림 2: 쿼리 빌더 사용 현황)
(그림 3: QueryGPT의 영향)
(그림 3: QueryGPT의 영향)

아키텍처 (Architecture)

QueryGPT는 2023년 5월 Uber의 Generative AI Hackdays에서 제안된 프로젝트로 시작되었습니다. 그 이후로 우리는 QueryGPT의 핵심 알고리즘을 반복적으로 개선하여 개념에서 프로덕션 준비 서비스로 전환했습니다. 아래에서는 QueryGPT의 발전 과정과 현재 아키텍처를 자세히 설명하고 주요 개선 사항을 강조합니다.

아래에서는 현재 버전의 QueryGPT를 설명합니다. 두 버전 사이에는 20회 이상의 알고리즘 반복이 있었으며, 각각을 나열하고 설명하면 이 블로그 글의 길이가 어마어마해질 것입니다.

Hackdays (버전 1)

(그림 4: QueryGPT Hackdays 버전)
(그림 4: QueryGPT Hackdays 버전)

QueryGPT의 첫 번째 버전은 관련 샘플을 가져오기 위해 상당히 단순한 RAG(Retrieval Augmented Generation) 방식에 의존하여 LLM에 대한 쿼리 생성 호출에 포함해야 하는 관련 샘플을 가져왔습니다(Few Shot Prompting). 사용자의 자연어 프롬프트를 벡터화하고 SQL 샘플과 스키마에 대한 유사성 검색(k-최근접 이웃 검색 사용)을 수행하여 관련 테이블 3개와 관련 SQL 샘플 7개를 가져왔습니다.

첫 번째 버전은 7개의 Tier 1 테이블과 20개의 SQL 쿼리를 샘플 데이터 세트로 사용했습니다. SQL 쿼리는 LLM에 제공된 테이블 스키마를 사용하는 방법에 대한 지침을 제공하고, 테이블 스키마는 LLM에 해당 테이블에 존재하는 열에 대한 정보를 제공했습니다.

예를 들어, Tier 1 테이블인 uber.trips_data(실제 테이블이 아님)의 스키마는 다음과 같습니다.

(그림 5: uber.trips_data 테이블)
(그림 5: uber.trips_data 테이블)

LLM이 Uber 내부 용어를 이해하고 Uber 데이터 세트를 사용할 수 있도록 사용자 지정 지침도 LLM 호출에 포함했습니다. 아래는 LLM이 날짜를 처리하는 방법에 대한 지침의 일부입니다.

(그림 6: Uber 데이터 세트에서 날짜 처리를 위한 사용자 지정 지침)
(그림 6: Uber 데이터 세트에서 날짜 처리를 위한 사용자 지정 지침)

관련 스키마 샘플, SQL 샘플, 사용자의 자연어 프롬프트 및 Uber 비즈니스 지침을 시스템 프롬프트로 묶어 LLM에 요청을 보냈습니다.

응답에는 "SQL 쿼리"와 LLM이 쿼리를 생성한 방법에 대한 "설명"이 포함되었습니다.

첨부 이미지

이 알고리즘은 소규모 스키마 및 SQL 샘플 세트에서는 잘 작동했지만, 더 많은 테이블과 관련 SQL 샘플을 서비스에 추가하기 시작하면서 생성된 쿼리의 정확도가 저하되기 시작했습니다.

더 나은 RAG (Better RAG)

사용자의 자연어 프롬프트("어제 시애틀에서 완료된 여행 수를 찾으세요")에 대한 스키마 샘플(CREATE TABLE…) 및 SQL 쿼리(SELECT a, b, c FROM uber.foo…)에 대한 단순한 유사성 검색은 관련 결과를 반환하지 않습니다.

사용자 의도 이해 (Understanding User’s Intent)

발견된 또 다른 문제는 사용자의 자연어 프롬프트에서 관련 스키마를 찾는 것이 매우 어렵다는 점입니다. 필요한 것은 사용자의 프롬프트를 관련 스키마 및 SQL 샘플에 매핑되는 "의도"로 분류하는 중간 단계였습니다.

대규모 스키마 처리 (Handling Large Schemas)

Uber에는 일부가 200개가 넘는 열을 포함하는 일부 Tier 1 테이블에 매우 큰 스키마가 있습니다. 이러한 대규모 테이블은 요청 객체에서 최대 40-60K 토큰을 사용할 수 있습니다. (당시) 사용 가능한 가장 큰 모델(32K 토큰 지원)에서 이러한 테이블이 3개 이상 있으면 LLM 호출이 중단됩니다.

 

현재 디자인(Current Design)

아래 다이어그램은 프로덕션 환경에서 실행 중인 QueryGPT의 현재 설계를 보여줍니다. 현재 버전에는 첫 번째 버전부터 많은 반복적인 변경 사항이 포함되어 있습니다.

첨부 이미지

워크스페이스 (Workspaces)

현재 설계에서는 광고, 모빌리티 및 코어 서비스와 같은 특정 비즈니스 도메인에 맞게 조정된 SQL 샘플 및 테이블의 큐레이션된 컬렉션인 "워크스페이스"를 도입했습니다. 이러한 워크스페이스는 LLM의 초점을 좁혀 생성된 쿼리의 관련성과 정확성을 향상시킵니다.

Uber 내부의 일반적인 비즈니스 도메인을 식별하고 백엔드에서 "시스템 워크스페이스"로 생성했습니다. 모빌리티는 쿼리 생성에 사용될 수 있는 기본 도메인으로 식별된 시스템 워크스페이스 중 하나입니다.

  • 모빌리티: 여행, 운전자, 문서 세부 정보 등을 포함하는 쿼리

예: 테슬라가 어제 시애틀에서 완료한 여행 수를 찾는 쿼리를 작성하세요.

이와 함께 "코어 서비스", "플랫폼 엔지니어링", "IT", "광고" 등 11개의 다른 시스템 워크스페이스도 제공했습니다.

기존 시스템 워크스페이스가 요구 사항에 맞지 않는 경우 사용자가 "사용자 지정 워크스페이스"를 생성하고 쿼리 생성에 사용할 수 있는 기능도 포함했습니다.

의도 에이전트 (Intent Agent)

사용자로부터 들어오는 모든 프롬프트는 먼저 "의도" 에이전트를 통과합니다. 이 의도 에이전트의 목적은 사용자의 질문을 하나 이상의 비즈니스 도메인/워크스페이스(그리고 도메인에 매핑된 SQL 샘플 및 테이블 세트)에 매핑하는 것입니다. LLM 호출을 사용하여 사용자 질문에서 의도를 추론하고 이를 "시스템" 워크스페이스 또는 "사용자 지정" 워크스페이스에 매핑합니다.

비즈니스 도메인을 선택하면 RAG에 대한 검색 범위를 크게 좁힐 수 있었습니다.

테이블 에이전트 (Table Agent)

QueryGPT가 최종적으로 선택한 테이블이 정확하지 않다고 생각하는 일부 사용자의 피드백을 바탕으로 쿼리 생성에 사용되는 테이블을 사용자가 선택할 수 있도록 했습니다.

이 피드백을 해결하기 위해 올바른 테이블을 선택하고 사용자에게 "승인"하거나 제공된 목록을 편집하여 올바른 테이블을 설정하도록 하는 또 다른 LLM 에이전트(테이블 에이전트)를 추가했습니다. 사용자가 보게 될 화면의 스크린샷은 다음과 같습니다.

(그림 9: 테이블 에이전트)
(그림 9: 테이블 에이전트)

사용자는 "좋습니다" 버튼을 선택하거나 기존 목록을 편집하여 LLM이 쿼리 생성에 사용할 테이블 목록을 수정합니다.

열 제거 에이전트 (Column Prune Agent)

QueryGPT를 더 많은 사용자에게 배포한 후 발생한 또 다른 흥미로운 문제는 일부 요청에 대한 쿼리 생성 중 "간헐적" 토큰 크기 문제였습니다. 128K 토큰 제한(1106)이 있는 OpenAI GPT-4 Turbo 모델을 사용했지만, 일부 요청에는 각각 많은 토큰을 소비하는 하나 이상의 테이블이 포함되어 있어 여전히 토큰 제한 문제가 발생했습니다.

이 문제를 해결하기 위해 LLM에 제공하는 스키마에서 관련 없는 열을 제거하는 "열 제거" 에이전트를 구현했습니다.

에이전트의 출력은 다음과 같습니다.

(그림 10: 열 제거 에이전트)
(그림 10: 열 제거 에이전트)

출력에는 쿼리 생성에 필요한 각 스키마의 축소된 버전이 포함됩니다. 이 변경 사항은 토큰 크기와 각 LLM 호출의 비용을 크게 개선했을 뿐만 아니라 입력 크기가 훨씬 작아져 지연 시간도 단축했습니다.

출력 (Output)

현재 설계에서는 출력 구조를 변경하지 않았습니다. 응답에는 그림 7과 유사하게 LLM이 쿼리를 생성한 방법에 대한 설명과 함께 SQL 쿼리가 포함됩니다.

 

평가 (Evaluation)

QueryGPT 성능의 점진적인 개선을 추적하기 위해 표준화된 평가 절차가 필요했습니다. 이를 통해 서비스의 반복적인 단점과 이상적인 단점을 구분하고 알고리즘 변경이 집계 성능을 점진적으로 개선하고 있는지 확인할 수 있었습니다.

평가 세트 (Evaluation Set)

평가를 위한 질문-SQL 답변 매핑 세트를 큐레이션하려면 사전에 수동 작업에 대한 투자가 필요했습니다. QueryGPT 로그에서 일련의 실제 질문을 식별하고 질문에 답하는 데 필요한 올바른 의도, 스키마 및 골든 SQL을 수동으로 확인했습니다. 질문 세트는 다양한 데이터 세트와 비즈니스 도메인을 다룹니다.

평가 절차 (Evaluation Procedure)

다양한 제품 흐름을 사용하여 프로덕션 및 스테이징 환경에서 쿼리 생성 프로세스 전반의 신호를 포착할 수 있는 유연한 절차를 개발했습니다.

제품 흐름목적절차
VanillaQueryGPT의 기준 성능 측정질문 입력 → QueryGPT가 질문에 답하는 데 필요한 의도 및 데이터 세트 추론 → 추론된 데이터 세트 및 의도를 사용하여 SQL 생성 → 의도, 데이터 세트 및 SQL 평가
Decoupled사람이 개입하는 경험을 통한 QueryGPT 성능 측정. 이전 결과의 성능에 대한 종속성을 제거하여 구성 요소 수준 평가 가능질문, 의도 및 질문에 답하는 데 필요한 데이터 세트 입력 → QueryGPT가 의도 및 데이터 세트 추론 → 실제(추론되지 않은) 의도 및 데이터 세트를 사용하여 SQL 생성 → 의도, 데이터 세트 및 SQL 평가

각 평가 질문을 통해 다음 신호를 포착합니다.

  • 의도: 질문에 할당된 의도가 정확합니까?
  • 테이블 중복: 검색 + 테이블 에이전트를 통해 식별된 테이블이 정확합니까? 0과 1 사이의 점수로 표시됩니다. 예를 들어, "지난주 로스앤젤레스에서 운전자가 취소한 여행 수는 얼마입니까?"라는 질문에 답하는 데 필요한 쿼리가 [fact_trip_state, dim_city]를 사용해야 하고 QueryGPT가 [dim_city, fact_eats_trip]를 식별한 경우 이 출력에 대한 검색 중복 점수는 0.5가 됩니다(질문에 답하는 데 필요한 두 테이블 중 하나가 선택되었기 때문).
  • 성공적인 실행: 생성된 쿼리가 성공적으로 실행됩니까?
  • 출력이 있는 실행: 쿼리 실행이 0개보다 많은 레코드를 반환합니까? (때때로 QueryGPT는 WHERE status = "Finished"와 같은 필터를 환각하여 필터가 WHERE status = "Completed"여야 하는 경우 성공적인 실행이지만 출력이 없는 결과를 초래합니다).
  • 정성적 쿼리 유사성: 생성된 쿼리가 골든 SQL과 얼마나 유사합니까? LLM을 사용하여 0과 1 사이의 유사성 점수를 할당합니다. 이를 통해 구문상의 이유로 실패하는 생성된 쿼리가 사용된 열, 조인, 적용된 함수 등의 측면에서 올바른 방향인지 빠르게 확인할 수 있습니다.

시간 경과에 따른 진행 상황을 시각화하여 회귀 및 개선 영역을 보여주는 패턴을 식별합니다.

아래 그림은 질문 레벨의 실행 결과의 예로, 개별 질문 수준에서 반복되는 단점을 확인할 수 있습니다.

(그림 11A: SQL 쿼리 평가)
(그림 11A: SQL 쿼리 평가)
(그림 11B: 다양한 환경에서의 SQL 쿼리 평가)
(그림 11B: 다양한 환경에서의 SQL 쿼리 평가)

각 질문에 대해 생성된 SQL, 오류 원인 및 관련 성능 메트릭을 볼 수 있습니다. 아래는 WHERE 절에 파티션 필터를 적용하지 않아(*🐶그림의 빨간색 박스) 정기적으로 실패하는 생성된 쿼리가 있는 질문입니다. 그러나 정성적 LLM 기반 평가에 따르면 생성된 SQL은 골든 SQL과 유사합니다.

(그림 12: SQL 평가 통계)
(그림 12: SQL 평가 통계)

또한 시간 경과에 따른 성능을 추적하기 위해 각 평가 실행에 대한 정확도 및 대기 시간 메트릭을 집계합니다.

(그림 13: SQL 평가 기준)
(그림 13: SQL 평가 기준)


한계 (Limitations)

LLM의 비결정적 특성으로 인해 기본 QueryGPT 서비스를 변경하지 않고 동일한 평가를 실행하면 결과가 달라질 수 있습니다. 일반적으로 대부분의 메트릭에서 약 5%의 실행 간 변경 사항을 기반으로 결정을 과도하게 지정하지 않습니다. 대신, 특정 기능 개선을 통해 해결할 수 있는 장기간에 걸친 오류 패턴을 식별합니다.

Uber에는 다양한 수준의 문서화가 된 수십만 개의 데이터 세트가 있습니다. 따라서 평가 질문 세트가 사용자가 질문할 수 있는 모든 비즈니스 질문을 완전히 다룰 수는 없습니다. 대신 제품의 현재 사용량을 나타내는 질문 세트를 큐레이션했습니다. 정확도가 향상되고 새로운 버그가 발생함에 따라 평가 세트는 제품의 방향을 포착하도록 발전할 것입니다.

항상 하나의 정답이 있는 것은 아닙니다. 종종 동일한 질문에 대해 다른 테이블을 쿼리하거나 다른 스타일로 쿼리를 작성하여 답변할 수 있습니다. 골든 SQL과 반환된 SQL을 시각화하고 LLM 기반 평가 점수를 사용하여 생성된 쿼리가 다른 스타일로 작성되었지만 골든 SQL과 관련된 유사한 의도를 가지고 있는지 이해할 수 있습니다.

교훈 (Learnings)

지난 1년 동안 GPT 및 LLM과 같은 초기 기술을 사용하면서 에이전트와 LLM이 데이터를 사용하여 사용자 질문에 대한 응답을 생성하는 방법에 대한 다양한 뉘앙스를 실험하고 배울 수 있었습니다. 아래에서는 우리 여정에서 얻은 교훈 중 일부를 간략하게 설명합니다.

LLM은 뛰어난 분류기입니다.

QueryGPT에서 사용한 중간 에이전트는 사용자의 자연어 프롬프트를 RAG에 대한 더 나은 신호로 분해하여 첫 번째 버전부터 정확도를 크게 향상시켰으며, 이는 LLM이 수행해야 할 작은 단위의 전문 작업을 제공받았을 때 매우 잘 작동했기 때문입니다.

의도 에이전트, 테이블 에이전트 및 열 제거 에이전트는 각각 광범위한 일반화된 작업이 아닌 단일 작업 단위에서 작업하도록 요청받았기 때문에 탁월한 성능을 발휘했습니다.

환각 (Hallucinations)

이는 우리가 끊임없이 노력하고 있는 영역이지만, 요약하자면 LLM이 존재하지 않는 테이블이나 해당 테이블에 존재하지 않는 열을 사용하여 쿼리를 생성하는 경우가 있습니다.

환각을 줄이기 위한 프롬프트를 실험하고 있으며, 사용자가 생성된 쿼리를 반복할 수 있는 채팅 스타일 모드를 도입했으며, 환각을 재귀적으로 수정하려는 "검증" 에이전트를 포함하는 것을 고려하고 있지만, 이는 아직 완전히 해결되지 않은 영역입니다.

사용자 프롬프트가 항상 "상황"이 풍부한 것은 아닙니다.

QueryGPT에서 사용자가 입력한 질문은 검색 범위를 좁히는 데 적합한 키워드가 포함된 매우 자세한 질문부터 여러 테이블에 걸친 조인이 필요한 광범위한 질문에 답하기 위한 5단어 질문(오타 포함)까지 다양했습니다.

사용자 질문만을 LLM에 대한 "좋은" 입력으로 의존하면 정확성과 신뢰성에 문제가 발생했습니다. LLM에 보내기 전에 사용자 질문을 더욱 상황이 풍부한 질문으로 "다듬기" 위해 "프롬프트 향상기" 또는 "프롬프트 확장기"가 필요했습니다.

LLM이 만들어낸 SQL 출력에 대한 높은 기준

이 버전의 QueryGPT는 광범위한 사용자에게 유용하지만, 생성된 쿼리가 매우 정확하고 "그냥 작동"할 것이라는 기대가 많은 사용자가 있습니다. 기준이 높습니다!

우리의 경험에 따르면 이와 같은 제품을 구축할 때 적절한 사용자를 대상으로 테스트하는 것이 가장 좋습니다.

결론 (Conclusion)

Uber에서 QueryGPT를 개발하는 것은 변혁적인 여정이었으며, 자연어 프롬프트에서 SQL 쿼리를 생성하는 생산성과 효율성을 크게 향상시켰습니다. 첨단 생성 AI 모델을 활용하는 QueryGPT는 Uber의 광범위한 데이터 에코시스템과 원활하게 통합되어 쿼리 작성 시간을 단축하고 정확성을 향상시켜 데이터 요구 사항의 규모와 복잡성 모두를 해결합니다.

대규모 스키마 처리 및 환각 감소와 같은 과제가 남아 있지만, 반복적인 접근 방식과 끊임없는 학습을 통해 지속적인 개선을 이루었습니다. QueryGPT는 데이터 접근을 단순화할 뿐만 아니라 민주화하여 Uber 내 다양한 팀에서 강력한 데이터 통찰력에 더 쉽게 접근할 수 있도록 합니다.

운영 및 지원팀 일부에 제한적으로 출시한 결과, 하루 평균 약 300명의 활성 사용자가 있으며, 약 78%가 생성된 쿼리가 처음부터 작성하는 데 걸리는 시간을 단축했다고 말합니다.

앞으로 더욱 정교한 AI 기술과 사용자 피드백을 통합하여 QueryGPT가 데이터 플랫폼에서 중요한 도구로 남을 수 있도록 지속적으로 개선해 나갈 것입니다.

다가올 뉴스레터가 궁금하신가요?

지금 구독해서 새로운 레터를 받아보세요

✉️

이번 뉴스레터 어떠셨나요?

주간 SaaS 님에게 ☕️ 커피와 ✉️ 쪽지를 보내보세요!

댓글

의견을 남겨주세요

확인
의견이 있으신가요? 제일 먼저 댓글을 달아보세요 !

다른 뉴스레터

© 2025 주간 SaaS

B2B SaaS 비즈니스 모델과 멀티 테넌트 아키텍처 설계에 관한 좋은 콘텐츠를 소개합니다.

메일리 로고

자주 묻는 질문 서비스 소개서 오류 및 기능 관련 제보

서비스 이용 문의admin@team.maily.so

메일리 사업자 정보

메일리 (대표자: 이한결) | 사업자번호: 717-47-00705 | 서울 서초구 강남대로53길 8, 8층 11-7호

이용약관 | 개인정보처리방침 | 정기결제 이용약관 | 라이선스