안녕하세요! 저희는 'AI Chatbot for Data Analytics Text2SQL' 주제를 연구 중인 skql팀 입니다.
이번 포스트에서는 8월 22일 진행되었던 중간발표에서 발표한 저희 주제 및 진행 상황에 대해 설명드리고, 중간발표에서 얻은 피드백 기반으로 설립한 향후 계획을 공유드리겠습니다!
저희는 현재 크게 두 개의 태스크, Text2SQL과 이벤트 분석을 진행하고 있습니다.
저희가 개발 중인 Text2SQL 챗봇은 자연어를 입력하면 SQL문을 반환해 주는 챗봇입니다. 이는 SQL에 익숙지 않은 데이터 분석가 및 기타 유저들을 위해 만들어졌고, 그들의 업무 편리성 및 효율성을 제공하는 것을 목표로합니다.
기존에 SQL문을 작성하기 위해 유저가 원하는 정보(자연어)에 1:1 대응되는 컬럼을 찾아서 SQL문을 구성하고, 구성한 SQL문을 AWS Athena로 실행하여 결과를 받게 됩니다. 하지만 컬럼명이 직관적이지 않을 경우 (docs에서 description을 통해) 필요한 컬럼을 찾아야 해서 시간이 많이 소요됩니다. 또한 SQL문 작성이 능숙하지 않은 분석가는 쿼리문 구성에 있어 어려움을 느낍니다. 데이터 보안 문제로 인해 컬럼 정보를 chatGPT, claude 와 같은 웹 서비스에 직접 전달하는 것 또한 불가능하므로 어려움을 해결하기가 쉽지 않습니다.
저희가 개발한 Text2SQL 챗봇은 유저가 입력한 자연어를 SQL로 자동 생성해 주고, 사내 claude 기반으로 만들어졌기 때문에 데이터 보안 문제도 해결할 수 있습니다.
Text2SQL은 크게 ‘자연어처리’,’SQL생성’,’DB실행’ 로 구성되었습니다.
'자연어 처리'에서는 사용자의 입력 질의 분석, 핵심 요소와 의도 추출, 구조화된 형식으로 변환 단계를 포함하고 있고, 'SQL 생성'은 추출한 정보를 SQL문에 매핑, SQL 쿼리 문법 검사를 포함하고 있고, 'DB실행'에서는 DB에서 SQL 쿼리 실행, 결과 검색 및 반환 단계를 포함하고 있습니다.
다음으로 저희 두 번째 태스크인 이벤트 분석에 대해 설명드리겠습니다. 이벤트 분석은 이벤트가 발생했을 때, 이벤트 기간과 평시 기간을 비교하여 이벤트가 발생한 장소의 기지국/셀의 품질변화를 레포트 형식으로 리턴해주는 시나리오입니다.
이벤트 분석 데이터의 저장 방식은 '웹크롤링'과 '사용자 직업등록' 방식이 있습니다. '웹크롤링'은 네이버에 축제하고 검색하면 나오는 이벤트 정보를 크롤링 하는 것이고, '사용자 직접등록'은 사용자가 idcube 이벤트분석앱을 통해 이벤트를 등록하는 방식입니다.
우선 Text2SQL 태스크의 연구 진행 현황부터 설명드리겠습니다.
아래 그림은 Text2SQL의 전체적인 flow를 보여주고 있습니다.
다음으로 각 단계를 구체적으로 설명드리겠습니다.
Intent Recognition 단계에서 LLM이 입력문이 ‘Text2SQL’, ‘이벤트 분석’, ‘평시’ 중 어느 카테고리 인지를 판단합니다. 예를 들어 '충북 쪽에 있는 002 코드가 포함된 시설을 알려줘'라는 입력문이 들어왔을 때, 그림에 있는 프롬프트에 의해 예시 형식으로 output이 출력됩니다. 해당 경우 Analysis로 출력되어, 모델이 입력문을 Text2SQL문으로 파악하고 있다는 것을 알 수 있습니다.
Similar Query단계는 입력 쿼리와 유사한 질문을 반환해 주는 단계입니다. 여기서 저희가 rag를 통해 DB에서 유사한 질문을 가져왔고, 검색 기법으로는 Lexical Search와 Semantic Search를 활용하였습니다. Lexical Search는 문자 그대로 단어나 구문을 검색하는 방법이고, Semantic Search는 단어의 의미와 문맥을 고려하여 텍스트를 검색하는 방법입니다. 앞에 ‘충북 쪽에 있는 002 코드가 포함된 시설을 알려줘’라는 질문에 대해 검색된 관련 질문은 Lexical Search top3과 Semantic Search top3가 같습니다. 저희가 테스트한 결과 Lexical Search top3과 Semantic Search top3가 같거나 한 가지만 다르게 나옵니다.
Query Check 단계에서 SQL문으로 변환하는 근거를 제공해 줍니다. 프롬프트에 요청 내용 및 앞에 검색한 top-k 내용을 예시로 넣어주었습니다. 챗봇이 변환의 단계별 근거를 설명해 주고 SQL도 같이 작성해 줍니다.
이벤트 분석 질문으로 '다음주 예정 이벤트 뭐 있어'와 같은 질문이 들어올 경우 질의를 Question, Time, Place로 구조화한 다음, DB 검색 후 이벤트 리스트를 반환하면 챗봇이 질문에 대한 답변을 해줍니다.
'설봉산 별빛축제 장비 리스트 알려'와 같은 질문이 들어왔을 경우, 위치 조회 후 근처 장비 조회 완료 후 장비 리스트를 반환하게 됩니다.
이벤트 분석 태스크에서도 LLM이 ‘Text2SQL’, ‘이벤트 분석’, ‘평시’ 중 입력문이 어느 카테고리 인지를 판단합니다. 여기서 '다음주 부산에서 열리는 이벤트 알려줘' 와 같은 질문은 LLM이 EVENT로 판단한 것을 볼 수 있습니다.
부산에서 열리는 이벤트의 장소를 검색하는 과정입니다. 현재 저희가 네이버에서 크롤링 한 데이터의 위치 정보 결측치가 75%이므로 해당 문제를 추후에 해결해야 합니다. 장소가 너무 넓은 경우, 너무 자세한 경우, 여러 곳인 경우 등 상황으로 위치를 특정할 수 없으므로 적절한 장소 데이터가 필요합니다.
챗봇UI는 아래와 같습니다.
저희가 pipline을 개발 시 LangGraph라는 개념을 활용했습니다. 기존의 RAG는 이전 단계로 돌아가기 어려운 단방향 파이프라인이기 때문에 모든 단계가 한 번에 잘 수행되어야 했습니다. 하지만LangGraph에서는 RAG pipeline의 각 단계를 노드로 취급하여 워크플로우에 순환(cycle) 연산 기능을 추가하여 세부 단계 별 흐름을 제어할 수가 있습니다.
입력이 들어오면 LLM_Router에서 사용자가 입력한 질의의 의도, 즉 analysis, common, event 중 어느 카테고리에 속하는지를 파악합니다. Analysis 엣지는 Text2SQL 전환 요청을 하고, Common 엣지는 LLM이 갖고 있는 지식으로 답할 수 있는 수준의 평시 질문에 대한 답을 요청하며, Event 엣지는 특정 시간이나 장소의 이벤트 리스트 요청합니다.
Retrieve 노드에서 Lexical, semantic 유사도에 따라 hybrid search가 진행되고, 각각 top 3 유사 쿼리를 반환합니다. LLM_Final_Generate 노드에서 Retrieve된 쿼리를 바탕으로 SQL문을 작성하고, 해당 SQL문을 생성한 근거도 함께 작성해 줍니다. LLM_event_list에서 사용자가 제시한 조건에 부합하는 이벤트 리스트 를 반환합니다.
향후 아래 4가지 방향으로 과제를 개선해나갈 계획입니다.
[파이프라인]
[프롬프트]
[평가]
[기타]