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

Gen AI를 활용한 On-Call 엔지니어의 생산성 향상

Uber의 Gen AI on-call 코파일럿 구축기

2024.11.19 | 조회 932 |
0
|
from.
SaaS노동자

주간 SaaS

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

주간SaaS 오늘의 소개 글

안녕하세요. 오늘은 소개하는 글에서는, Uber가 생성형 AI 기술을 활용하여 온콜 코파일럿을 구축한 경험을 공유합니다. 실제 운영을 통해 괄목할 만한 생산성 향상을 달성 했다고 하는데요, 이 글은 RAG 아키텍처, 데이터 모델, 성능 평가 등 생성형 AI 기반 서비스 설계 시 고려해야 할 주요 사항들을 아키텍처 다이어그램과 함께 자세히 소개 합니다. 특히 생성형 AI와 RAG를 활용한 SaaS 서비스 개선을 고민하는 분들께 실질적인 도움을 드릴 수 있는 내용입니다.


소개

숨가쁘게 돌아가는 IT 업계, 끊김 없는 서비스 운영을 위해서는 탄탄한 온콜 시스템이 필수적입니다. 최근 플랫폼 엔지니어링 팀은 온콜 일정 관리, 사고 대응, 긴급 상황 시 커뮤니케이션, 그리고 Slack® 채널 고객 지원 등 쉴 틈 없는 과제에 시달리고 있습니다.

이번 뉴스레터에서는 우버가 자체 개발한 온콜 코파일럿 "지니(Genie)"를 소개합니다. 생성형 AI를 기반으로 온콜 엔지니어와의 소통 및 질의응답을 획기적으로 개선한 든든한 지원군입니다.

문제점과 개발 동기

우버에는 Michelangelo 팀을 비롯한 여러 팀들이 내부 사용자를 위한 Slack 지원 채널을 운영하고 있습니다. (그림 1)처럼 매달 약 4만 5천 건에 달하는 질문이 쏟아지는데, 이로 인해 응답 대기 시간이 길어지고, 사용자와 온콜 엔지니어 모두의 생산성이 저하되는 심각한 문제가 발생했습니다.

(그림 1: 5개월간 우버 Slack 채널 질문량 추이 - 폭발적인 질문량 증가를 시각적으로 보여주는 그래프)
(그림 1: 5개월간 우버 Slack 채널 질문량 추이 - 폭발적인 질문량 증가를 시각적으로 보여주는 그래프)

기존 방식의 한계

(그림 2: 온콜 엔지니어 응답 지연으로 인한 느린 프로세스 - 답답한 상황을 간략한 만화 형식으로 표현)
(그림 2: 온콜 엔지니어 응답 지연으로 인한 느린 프로세스 - 답답한 상황을 간략한 만화 형식으로 표현)

사용자가 Slack 채널에 질문을 올리면 온콜 엔지니어의 답변을 기다려야 합니다. 엔지니어는 질문에 답하거나 추가 정보를 요청하고, 사용자는 다시 질문을 하거나, 설명을 요구하거나, 추가 정보를 제공하는 과정이 반복됩니다. 이러한 비효율적인 핑퐁 게임은 결국 시간 낭비로 이어집니다.

정보 찾기의 어려움

사실 많은 질문은 기존 문서에 답이 있습니다. 하지만 우버 내부 위키(Engwiki), 내부 Stack Overflow 등 여러 곳에 정보가 흩어져 있어 원하는 답을 찾기가 쉽지 않았습니다. 결국 같은 질문이 반복해서 올라오고, 수백 개의 Slack 채널에서 온콜 지원 요청이 폭주하는 상황이 벌어졌습니다.

아키텍처 설계의 난관

온콜 코파일럿 구축을 위해 LLM 모델 파인튜닝과 RAG (Retrieval-Augmented Generation) 방식 중 하나를 선택해야 했습니다. 파인튜닝은 LLM 학습을 위한 고품질의 다양한 예시 데이터가 필요하며, 모델 업데이트를 위한 컴퓨팅 자원 또한 요구합니다.

반면 RAG는 초기 단계에 다양한 예시 데이터가 필수적이지 않습니다. 덕분에 코파일럿 출시 기간을 단축할 수 있었고, 저희는 이 방식을 채택했습니다.

온콜 코파일럿 개발 과정에서는 환각 현상(hallucination) 해결, 데이터 소스 보호, 사용자 경험 개선 등 몇 가지 과제에 직면했습니다. 각 과제의 해결 방안을 간략히 소개합니다.

환각 현상 방지를 위해 다음과 같은 노력을 기울였습니다.

  • 응답 정확도: 코파일럿이 질문과 관련된 정확한 지식을 검색하도록 보장하여, LLM 엔진이 잘못되거나 오해의 소지가 있는 정보를 생성하는 것을 방지합니다.
  • 검증 메커니즘: 코파일럿의 응답을 권위 있는 출처와 비교 검증하는 메커니즘을 구현하여 환각 현상 발생 가능성을 줄입니다.
  • 지속적 학습: 코파일럿이 항상 최신 데이터에 접근할 수 있도록 하여 응답 정확도를 높입니다.

데이터 보안을 위해서는 Slack 채널에 노출될 수 없는 데이터 소스를 제외하고, 신중하게 데이터 소스를 선별했습니다.

사용자 경험 개선을 위해 다음과 같은 설계를 적용했습니다.

  • 직관적인 인터페이스: 코파일럿과 효율적으로 상호 작용할 수 있는 사용자 친화적인 인터페이스를 설계했습니다.
  • 피드백 루프: 사용자가 응답에 대한 피드백을 제공할 수 있는 시스템을 구축하여 코파일럿의 성능을 지속적으로 개선합니다.

저희는 안정적이고 사용자 친화적이며 안전한 온콜 코파일럿을 개발하기 위해 이러한 과제들을 해결하는 데 집중했습니다.

아키텍처

이제 '지니'라고 부르는 저희 온콜 코파일럿의 아키텍처를 자세히 살펴보겠습니다.

(그림 3: 온콜 코파일럿 아키텍처)
(그림 3: 온콜 코파일럿 아키텍처)

간략하게 설명하자면, 우버 내부 위키, 내부 Stack Overflow, 엔지니어링 요구사항 문서 등의 내부 데이터 소스를 스크래핑하고, OpenAI 임베딩 모델을 사용하여 이러한 데이터 소스에서 벡터를 생성합니다. 생성된 벡터는 벡터 데이터베이스에 저장됩니다. 사용자가 Slack 채널에 질문을 게시하면 해당 질문은 임베딩으로 변환됩니다. 서비스는 벡터 데이터베이스에서 질문과 관련된 임베딩을 검색합니다. 임베딩으로 색인된 검색 결과는 LLM에 프롬프트로 사용되어 응답을 얻습니다.

데이터 준비, 임베딩 생성, 서비스 제공을 위한 아티팩트 배포 등의 다음 단계는 Apache Spark™를 사용하는 RAG 애플리케이션으로 일반화할 수 있습니다. 이러한 일반적인 단계들이 RAG 애플리케이션의 기반을 형성합니다.

ETL

(그림 4: 데이터 수집용 Spark 애플리케이션)
(그림 4: 데이터 수집용 Spark 애플리케이션)

그림 4는 벡터 데이터베이스에 데이터를 수집하는 단계를 포함하는 맞춤형 Spark 애플리케이션을 보여줍니다. Spark 애플리케이션은 Spark executors를 사용하여 이러한 단계를 실행합니다.

데이터 준비

Spark 앱은 Uber의 내부 위키인 Engwiki 또는 Uber Stack Overflow API를 사용하여 각 데이터 소스에서 콘텐츠를 가져옵니다. 이 데이터 준비 단계에서는 Spark 데이터프레임이 출력됩니다. 스키마는 Engwiki 링크를 한 열에, Engwiki의 콘텐츠를 다른 열에 문자열 형식으로 저장합니다.

(그림 5: Engwiki 데이터 소스의 Spark 데이터프레임 열)
(그림 5: Engwiki 데이터 소스의 Spark 데이터프레임 열)

그림 5는 Uber 내부 위키를 원본 데이터 소스로 사용하는 Spark 데이터프레임의 열을 보여줍니다. 소스 URL, 콘텐츠 및 메타데이터를 저장하는 다른 열이 포함되어 있습니다.

임베딩 생성

데이터 스크래핑이 완료되면 OpenAI 임베딩 모델을 사용하여 임베딩을 생성하고 Uber의 Blob 스토리지인 Terrablob에 저장합니다. 생성된 임베딩은 Engwiki 공간과 관련된 특정 Slack 채널을 통해서만 접근할 수 있습니다. 출력 형식은 청크 콘텐츠와 해당 청크의 벡터가 매핑된 스키마를 가진 데이터프레임입니다. Uber 내부 위키 콘텐츠는 langchain을 사용하여 청크 단위로 분할되고, PySpark UDF를 통해 OpenAI에서 임베딩이 생성됩니다.

(그림 6: 벡터 임베딩이 포함된 Spark 데이터프레임 열)
(그림 6: 벡터 임베딩이 포함된 Spark 데이터프레임 열)

그림 6는 Uber 내부 위키를 원본 데이터 소스로 사용하는 Spark 데이터프레임의 열을 보여줍니다. 소스 URL, 콘텐츠, 청크 콘텐츠 및 해당 청크의 임베딩이 포함되어 있습니다.

푸셔 (Pusher)

(그림 7: Terrablob로 벡터를 푸시하는 흐름)
(그림 7: Terrablob로 벡터를 푸시하는 흐름)

그림 7은 벡터가 Terrablob로 푸시되는 방식을 보여줍니다. 데이터 소스에서 Uber의 자체 벡터 데이터베이스 솔루션인 Sia로 데이터를 수집하기 위해 부트스트랩 작업이 트리거됩니다. 그런 다음 인덱스 빌드 및 병합, Terrablob에 데이터 수집을 위해 두 개의 Spark 작업이 트리거됩니다. 모든 leaf는 Terrablob에 저장된 기본 인덱스 및 스냅샷을 동기화하고 다운로드합니다. 검색 중에는 쿼리가 각 leaf로 직접 전송됩니다.

Knowledge Service

(그림 8: 백엔드 Knowledge Service 흐름)
(그림 8: 백엔드 Knowledge Service 흐름)

지니는 Knowledge Service라는 백엔드 서비스를 가지고 있습니다. 이 서비스는 들어오는 모든 쿼리에 대해 먼저 쿼리를 임베딩으로 변환한 다음 벡터 데이터베이스에서 가장 관련성이 높은 청크를 가져와서 응답합니다.

비용 추적

(그림 9: 지니 비용 추적 흐름)
(그림 9: 지니 비용 추적 흐름)

비용 추적을 위해 Slack 클라이언트 또는 다른 플랫폼에서 Knowledge Service를 호출하면 UUID가 Knowledge Service로 전달되고, Knowledge Service는 해당 UUID를 컨텍스트 헤더를 통해 Michelangelo Gateway로 전달합니다. Michelangelo Gateway는 LLM에 대한 패스스루 서비스로, UUID별 비용 추적에 사용되는 감사 로그에 추가될 수 있도록 합니다.

지니 성능 평가

메트릭 프레임워크

사용자는 지니의 답변에서 관련 버튼을 클릭하여 Slack에서 바로 피드백을 제공할 수 있습니다. 사용자는 다음 중 하나를 선택할 수 있습니다.

  • 해결됨: 답변으로 문제가 완전히 해결됨
  • 도움됨: 답변이 부분적으로 도움이 되었지만 추가 지원이 필요함
  • 도움 안 됨: 답변이 잘못되었거나 관련이 없음
  • 관련 없음: 지니가 도움을 줄 수 없는 경우 (예: 코드 검토) 온콜 담당자의 지원이 필요함
(그림 10: 지니 사용자 피드백 흐름)
(그림 10: 지니 사용자 피드백 흐름)

사용자가 피드백을 남기면 Slack 플러그인이 이를 수집하고 특정 Kafka 토픽을 사용하여 피드백 및 모든 관련 메타데이터와 함께 Hive 테이블로 메트릭을 스트리밍합니다. 나중에 이러한 메트릭을 대시보드에서 시각화합니다.

성능 평가

지니 사용자에게는 맞춤형 평가를 실행할 수 있는 옵션을 제공합니다. 사용 사례에 중요하다고 생각되는 환각 현상, 답변 관련성 또는 기타 지표를 평가할 수 있습니다. 이 평가는 모든 관련 RAG 구성 요소(검색 및 생성)를 더 잘 조정하는 데 사용할 수 있습니다.

(그림 11: 성능 평가 프로세스)
(그림 11: 성능 평가 프로세스)

그림 11은 기존에 구축된 Michelangelo 구성 요소를 사용하는 별도의 ETL 파이프라인인 평가 프로세스를 보여줍니다. 지니의 컨텍스트와 응답은 Hive에서 검색되고 Slack 메타데이터 및 사용자 피드백과 같은 기타 관련 데이터와 결합됩니다. 처리된 후 평가자(Evaluator)로 전달됩니다. 평가자는 지정된 프롬프트를 가져오고 LLM을 판단자(Judge)로 실행합니다. 지정된 메트릭이 추출되어 평가 보고서에 포함되며, 사용자는 UI에서 이 보고서를 확인할 수 있습니다.

문서 평가

정확한 정보 검색은 소스 문서의 명확성과 정확성에 달려있습니다. 문서 자체의 품질이 좋지 않으면 LLM의 성능이 아무리 뛰어나더라도 좋은 성능을 얻을 수 없습니다. 따라서 효율적이고 효과적인 RAG 시스템을 위해서는 문서를 평가하고 문서 품질을 개선하기 위한 실행 가능한 제안을 할 수 있는 기능이 필수적입니다.

(그림 12: 문서 평가 앱의 워크플로우)
(그림 12: 문서 평가 앱의 워크플로우)

그림 12는 문서 평가 앱의 워크플로우를 보여줍니다. 데이터 스크래핑 후 지식 베이스의 문서는 Spark 데이터프레임으로 변환됩니다. 데이터프레임의 각 행은 지식 베이스의 한 문서를 나타냅니다. 그런 다음 LLM을 판단자로 호출하여 평가를 처리합니다. 여기서 LLM에 맞춤형 평가 프롬프트를 제공합니다. LLM은 각 문서의 품질을 개선하는 방법에 대한 실행 가능한 제안과 함께 평가 점수 및 점수에 대한 설명을 반환합니다. 이러한 모든 메트릭은 평가 보고서로 게시되며, 사용자는 Michelangelo UI에서 액세스할 수 있습니다.

도전 과제 해결 방안

환각 현상을 줄이기 위해 벡터 데이터베이스에서 가져온 LLM에 프롬프트를 전달하는 방식을 변경했습니다. 벡터 데이터베이스에서 얻은 모든 결과에 대해 하위 컨텍스트의 소스 URL과 함께 "하위 컨텍스트"라는 섹션을 명시적으로 추가했습니다. LLM에 제공된 다양한 하위 컨텍스트에서만 답변을 제공하고 답변 출처를 인용하기 위해 소스 URL을 반환하도록 요청했습니다. 이는 모든 답변에 대해 소스 URL을 제공하기 위한 것입니다.

민감한 데이터 소스에 대한 접근 권한이 없는 사용자에게 OpenAI 또는 Slack에서 임베딩을 생성하는 데 사용하는 데이터 소스가 유출되지 않도록, 대부분의 Uber 엔지니어가 널리 이용할 수 있는 데이터 소스를 사전에 선별하여 임베딩 생성에 이러한 데이터 소스만 사용하도록 허용했습니다.

지니의 질문 답변 잠재력을 극대화하기 위해 새로운 상호 작용 모드를 개발했습니다. 이 모드를 사용하면 사용자가 더 편리하게 추가 질문을 하고 지니의 답변을 더 주의 깊게 읽도록 유도합니다. 지니가 질문에 답변할 수 없는 경우 사용자는 문제를 온콜 지원 담당자에게 쉽게 에스컬레이션할 수 있습니다.

(그림 13: 지니가 사용자 질문에 응답하는 흐름)
(그림 13: 지니가 사용자 질문에 응답하는 흐름)

새로운 상호 작용 모드에서는 사용자가 질문을 하면 지니가 다음 단계 작업 버튼을 제공하며 답변합니다. 사용자는 이러한 버튼을 사용하여 쉽게 추가 질문을 하거나, 질문을 해결됨으로 표시하거나, 사람 지원 담당자에게 연락할 수 있습니다.

결과

2023년 9월 출시 이후 지니는 154개의 Slack 채널로 확장되어 70,000개 이상의 질문에 답변했습니다. 지니는 48.9%의 도움률을 자랑하며 효과성이 점점 높아지고 있음을 보여줍니다. 출시 이후 지금까지 13,000시간의 엔지니어링 시간을 절약한 것으로 추산됩니다.

향후 계획

지니는 온콜 관리를 간소화하고, 사고 대응을 최적화하고, 팀 협업을 개선하도록 설계된 최첨단 Slack 봇입니다. 간편성과 효율성에 중점을 두고 개발된 지니는 엔지니어링 팀이 온콜 책임을 원활하게 처리할 수 있도록 지원하는 포괄적인 비서 역할을 합니다.

이 온콜 보조 코파일럿은 모든 플랫폼의 사용자와 온콜 엔지니어가 각 플랫폼의 Slack 채널 내에서 상호 작용하고 참여하는 방식을 완전히 바꿀 수 있는 잠재력을 가지고 있습니다. Michelangelo 또는 IDE와 같은 각 제품 내에서도 사용자가 온콜 지원을 기다릴 필요 없이 제품 내 또는 제품별 Slack 채널에서 제품 관련 도움말을 찾을 수 있도록 경험을 바꿀 수 있습니다.

결론

온콜 보조 코파일럿인 지니는 엔지니어링 팀의 온콜 업무 관리 방식에 혁신을 가져옵니다. 자동 해결 기능을 제공하고 통찰력 있는 분석을 제공함으로써 지니는 팀이 온콜 책임을 효율적이고 효과적으로 처리할 수 있도록 지원합니다.

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

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

✉️

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

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

댓글

의견을 남겨주세요

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

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

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

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

메일리 사업자 정보

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

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