혼란스러운 확률적 시스템과 AI 에이전트를 제어하는 구조화된 결정론적 그래프의 대비를 보여주는 시각적 은유로, 여행 예약 상황에 특화되어 있다.
Artificial IntelligenceSoftware EngineeringMachine Learning

GPT-4는 99.4% 실패했다 — 그래서 우리는 AI에게 결정을 맡기지 않기로 했다

Ashutosh SinghalAshutosh Singhal2026년 2월 16일13 min

거의 자정 무렵이었고, 나는 우리 에이전트가 세 번 연속으로 엉뚱한 도시행 항공편을 예약하는 것을 지켜보고 있었다.

매번 다른 엉뚱한 도시가 아니라 — 같은 엉뚱한 도시였다. 데라둔이 아니라 델리. 사용자는 "데라둔"이라고 분명하게 입력했다. LLM은 사고 연쇄(chain-of-thought) 추론에서 그것을 정확히 파싱했다. 그런데 API 호출을 생성할 때, 델리의 공항 코드로 바꿔치기했다. 자신 있게. 조용히. 세 번이나.

공동 창업자가 통화에 함께 있었다. 그가 말했다. "이건 정답을 알고 있어. 추론 흔적을 봐. 말 그대로 데라둔이라고 적혀 있잖아. 그런데 다른 짓을 하고 있어."

그날 밤 나는 더 나은 프롬프트가 우리를 구해줄 것이라는 믿음을 버렸다.

우리는 여행 예약을 위한 AI 에이전트를 만들고 있었다 — 아마데우스(Amadeus)와 세이버(Sabre) 같은 글로벌 유통 시스템(GDS), 즉 지구상의 모든 항공사 예약을 구동하는 그 오래된 메인프레임 시대의 백엔드와 대화하는 종류의 에이전트였다. 그리고 우리는 2023년에 다른 모든 사람들이 하던 일을 하고 있었다. GPT-4를 얇은 오케스트레이션 레이어로 감싸고, 도구를 쥐여주고, 기도하는 것.

그 기도는 통하지 않았다.

모든 것을 바꾼 숫자

그 데라둔 사건이 있고 몇 주 뒤, 나는 TravelPlanner 벤치마크를 접하게 되었다 — 예산, 교통, 식사, 숙박 등 실제 제약 조건을 두고 여러 날에 걸친 여행 일정 계획에 대해 LLM을 시험하는 엄격한 학술 평가다. 유능한 여행사 직원이라면 20분이면 하는 종류의 일이다.

GPT-4의 전체 성공률: 0.6%.

60%가 아니다. 6%도 아니다. 0.6퍼센트다.

나는 그것을 세 번 읽었다. 그런 다음 그들이 실수한 게 아닌지 확인하려고 방법론을 열어봤다. 실수는 없었다. 세계에서 가장 발전한 언어 모델에게 예산을 지키고, 항공편을 호텔과 식당으로 연결하며, 기본적인 시간 논리를 위반하지 않는 여행을 계획하라고 시키면 — 99.4%의 확률로 실패한다.

GPT-4에게 실제 제약 조건을 두고 여행을 계획하라고 시켰을 때, 성공률은 0.6%였다. 같은 문제를 푸는 뉴로-심볼릭 에이전트는 97%를 기록했다.

97%를 기록한 시스템은 더 똑똑한 모델을 쓰지 않았다. 근본적으로 다른 아키텍처를 사용했다 — LLM이 사용자의 요청을 구조화된 데이터로 번역하고, 그런 다음 결정론적 솔버가 실제 계획을 수행하는 아키텍처였다. LLM은 번역가였다. 코드가 두뇌였다.

그 벤치마크는 단지 우리의 좌절감을 확인해준 것에 그치지 않았다. 우리에게 청사진을 주었다.

당신의 AI 에이전트는 왜 계속 실패하는가?

연쇄된 LLM 단계의 지수적 신뢰성 감소 — "확률의 사슬" 문제 — 를 1단계, 5단계, 10단계에서의 구체적인 성공 비율과 함께 보여주는 인포그래픽.

"AI 에이전트" 골드러시에 뛰어든 누구도 이야기하고 싶어 하지 않는 사실이 있다: LLM은 추론하지 않는다. 예측한다.

GPT-4가 검색 API를 호출하기로 "결정"할 때, 그것은 논리를 실행하는 것이 아니다. 학습 데이터의 패턴을 바탕으로 통계적으로 가장 그럴듯한 다음 토큰을 예측하는 것이다. 대화에서는 그 예측이 대개 충분히 괜찮다. 각 단계가 이전 단계의 정확한 출력에 의존하는 10단계 API 워크플로에서는? 그것은 재앙이다.

나는 이것을 확률의 사슬 문제라고 부르기 시작했다. 당신의 LLM이 각 단계를 90%의 확률로 맞힌다고 가정하자 — 복잡한 도구 사용에 대해서는 후한 추정치다. 계산은 이렇다:

  • 1단계: 90% 성공
  • 5단계: 약 59% 성공
  • 10단계: 약 34% 성공

항공편 예약 워크플로 — 검색, 필터링, 선택, 가격 산정, 탑승객 정보 수집, PNR 생성, 검증, 결제, 발권 — 는 일상적으로 10단계를 넘는다. 이론상 34% 성공률이라면, 당신은 소프트웨어를 만드는 것이 아니다. 슬롯머신을 만드는 것이다.

그리고 34%는 천장이다. 실제 성능은 더 나쁘다. 우리가 프로덕션에서 계속 부딪혔던 두 가지 현상 때문이다.

환각 연쇄(Hallucination Cascade)

첫 번째는 내가 환각 연쇄(Hallucination Cascade)라고 부르는 것이다. 연쇄된 아키텍처에서는 2단계의 출력이 3단계의 입력이 된다. LLM이 초반에 미묘한 오류를 범하면 — 항공편 도착 시각을 오전 2시가 아니라 오후 2시로 잘못 읽으면 — 그 오류는 걸러지지 않는다. 전파된다. 에이전트는 환각으로 만들어낸 시각을 바탕으로 엉뚱한 날에 호텔 체크인을 예약한다. GDS API는 에이전트의 의도는 모르고, 오직 그 입력만 알기 때문에, 요청을 성공적으로 처리한다. 에이전트는 200 OK 응답을 보고 자신의 실수를 더욱 굳힌다.

결국 당신에게 남는 것은 재앙적인 실제 결과를 낳는 "성공적인" 실행 흔적이다. 에이전트는 완벽하게 해냈다고 생각한다. 고객은 공항에 나타나서야 그렇지 않다는 것을 알게 된다.

두 번째 현상은 컨텍스트 드리프트(Context Drift)이다. 에이전트가 여러 단계의 계획을 수행해 나가는 동안, 컨텍스트 윈도우는 중간 데이터 — 검색 결과, API 응답, 사용자 메시지 — 로 채워진다. 모델의 어텐션 메커니즘은 그 모든 토큰에 걸쳐 점점 더 얇게 퍼진다. 10단계에 이르면, 2단계에서 정확히 파악했던 예산 제약을 사실상 "잊어버린" 상태가 된다. 소프트맥스 함수에 지배되는 어텐션 점수가 너무 많은 무관한 토큰에 걸쳐 희석된다.

나는 잠재적 파트너를 위한 데모 도중에 이것이 실시간으로 벌어지는 것을 지켜봤다. 에이전트는 3단계에서 예산 내의 호텔을 찾았다. 8단계에서 식당을 고를 무렵에는, 남은 예산을 완전히 놓쳐버렸다. 사용자의 지출 한도를 40% 초과하게 만들 곳을 추천한 것이다. 그 파트너는 나를 돌아보며 말했다. "그러니까 이게 그냥... 잊어버린다는 거죠?"

그렇다. 그냥 잊어버린다.

AI가 메인프레임을 만나면 어떤 일이 벌어지는가?

왜 우리가 다른 접근이 필요했는지 제대로 이해하려면, 글로벌 유통 시스템(GDS)을 다루는 것이 어떤 일인지 알아야 한다.

아마데우스, 세이버, 트래블포트 — 이들은 글로벌 항공 여행의 근간이다. 메인프레임 시대에 설계되었고, 그 시대답게 동작한다. 항공편 예약은 단일 API 호출이 아니다. 그것은 유한 상태 기계(finite state machine)이며, 재배열하거나 건너뛰거나 근사할 수 없는 정밀한 연산 순서를 가진다.

인증을 하고 세션 토큰을 받는다. 그 토큰은 이후의 모든 헤더에 전달되어야 한다 — LLM이 그것을 "잊거나" 새로운 토큰을 환각으로 만들어내면, 전체 트랜잭션 컨텍스트가 사라진다. 그런 다음 항공편을 검색하면, GDS는 운임 기준 코드, 수하물 모델, 구간 참조 정보를 담은 거대한 중첩 JSON 페이로드 — 종종 50KB 이상 — 를 반환한다. LLM은 그 페이로드에서 특정 offerId를 추출해야 진행할 수 있다. 하지만 LLM은 손실 압축기다. 요약한다. 잘라낸다. GDS가 바이트 단위까지 정확하기를 요구하는 데이터 형식을 "친절하게" 정규화해버린다.

어느 날 밤, 우리는 예약 실패를 디버깅하는 데 네 시간을 썼다. LLM이 운임 기준 코드를 "수정"한 것이었다 — 영어 텍스트로 학습된 모델에게는 그것이 더 "올바르게" 보였기 때문에, 소문자를 대문자로 바꿔버렸다. GDS는 알쏭달쏭한 오류로 그것을 거부했다: ERR 1209 - SEQUENCE ERROR. 설명도 없다. 제안도 없다. 그저 벽뿐이다.

LLM은 손실 압축기다. API 호출 사이에서 데이터를 전달할 때, 엔터프라이즈 시스템이 요구하는 암호학적 무결성을 깨뜨리는 방식으로 "자동 수정"하고 "정규화"한다.

그리고 GDS가 UC (Unable to Confirm, 확인 불가) 같은 오류를 반환하면, LLM은 어떻게 해야 할지 전혀 모른다. 도움이 되도록 학습되었기 때문에, 오류를 일시적 결함으로 해석하고 똑같은 요청을 정확히 다시 시도한다. 또. 또다시. 우리는 에이전트가 수천 개의 토큰을 태우고 API 속도 제한에 걸리며, 우리가 "죽음의 루프"라고 부르기 시작한 상태에 갇히는 것을 지켜봤다 — 이해하지 못하는 벽에 반복해서 부딪히면서.

우리가 아키텍처를 뒤집은 밤

전환점은 한 논쟁 중에 찾아왔다.

프로젝트에 착수한 지 3개월째였다. 엔지니어링 리드는 프롬프트를 계속 개선하고 싶어 했다 — 더 긴 시스템 메시지, 더 많은 예시, 사고 연쇄 지시. "거의 다 왔어." 그는 계속 말했다. "PNR 생성 단계에 맞게 프롬프트를 더 잘 구조화하기만 하면..."

나는 우리 로그를 열어봤다. 지난 한 주 동안, 테스트 환경에서 예약 시도가 47건 실패했다. 11건은 죽음의 루프였다. 9건은 환각으로 만들어낸 공항 코드였다. 6건은 LLM이 필수 "Received From" 필드를 추가하기 전에 PNR을 커밋하려 한 것이었다 — 아무리 프롬프트를 손봐도 고쳐지지 않는 순서 오류였다. 모델에게는 학습 데이터에서 흡수한 것 이상의, 시간적 순서에 대한 본질적 개념이 없었기 때문이다.

"우리는 거의 다 온 게 아니야." 내가 말했다. "우리는 천장에 도달했어. 아키텍처가 문제야."

그 주에, 우리는 모든 것을 다시 작성했다. LLM에게 오케스트레이션을 시키기를 멈췄다. LLM이 다음 단계를 결정하도록 두는 것을 멈췄다. 가공되지 않은 GDS 응답을 LLM에 먹이면서 올바른 필드를 추출해주기를 바라는 것을 멈췄다.

대신, 우리는 그래프를 만들었다.

우리가 무엇을 왜 만들었는지에 대한 완전한 기술적 분석을 원한다면, 나는 상세한 연구 논문을 썼는데, 그 아키텍처를 깊이 파고든다.

뉴로-심볼릭 AI는 실제로 어떻게 작동하는가?

2계층 뉴로-심볼릭 분할 — 번역가/인터페이스 계층으로서의 LLM 대 실행/관리자 계층으로서의 결정론적 그래프 — 을 각 계층이 처리하는 구체적인 예시와 함께 보여주는 라벨이 붙은 아키텍처 다이어그램.

핵심 아이디어는 겉보기와 달리 단순하다: 제어 흐름은 언어 과제가 아니다.

엄격한 비즈니스 프로세스에서 다음에 무엇을 할지 결정하는 것은 토큰 예측의 문제가 되어서는 안 된다. 조건부 논리의 문제여야 한다. "결제 요청" 결정은 "항공편이 선택됨" 그리고 "가격이 확정됨"일 때만 발동되어야 한다. 그것은 불리언 조건이지, 확률적 제안이 아니다.

우리는 시스템을 두 개의 계층으로 나눴다:

LLM은 인터페이스 계층 — 번역가 — 가 되었다. 사용자의 자연어("데라둔행 아침 항공편을 원하는데, 너무 비싸지 않게")를 구조화된 데이터로 파싱한다: {origin: "DEL", destination: "DED", date: "2024-03-15", time_preference: "morning", budget: "economy"}. 그것이 바로 LLM이 진정으로 뛰어난 부분이다: 지저분한 인간의 의도를 이해하는 것.

그래프는 실행 계층 — 관리자 — 가 되었다. 그 구조화된 데이터를 받아 결정론적 코드를 사용해 비즈니스 로직을 실행한다. 하드코딩된 노드. 타입이 지정된 상태 스키마. 분위기가 아니라 변수를 검사하는 조건부 에지.

우리는 이것을 만드는 데 LangGraph를 사용했다. 필요한 기본 요소를 제공하기 때문이다: 공유 상태 스키마(채팅 기록이 아니라 데이터베이스로 뒷받침되는), 그저 파이썬 함수일 뿐인 노드, 그리고 실제 변수 값에 기반해 경로를 정하는 조건부 에지.

LLM은 작업자 — 데이터 추출, 텍스트 요약, JSON 포매팅 — 여야 하고, 관리자는 하드코딩된 소프트웨어여야 한다. 이 제어의 역전이 견고한 에이전트 시스템을 규정하는 특징이다.

우리 아키텍처에서, LLM은 말 그대로 단계를 건너뛸 수 없다. 시스템이 selected_offer_id 변수가 상태에 채워지기 전에 예약을 시도하는 것은 물리적으로 불가능하다. 우리가 프롬프트에서 LLM에게 "그렇게 하지 마"라고 말했기 때문이 아니라, 그래프 에지가 발동하지 않기 때문이다. 그것은 벽을 뚫고 운전하려는 것과 같다 — 코드가 그저 허용하지 않는다.

실제 시스템은 어떤 모습인가?

이 글에서 설명한 실제 예약 파이프라인을 노드별로 상세히 보여주는 순서도로, 각 노드 유형(Collector, Retriever, Summarizer, Selector, Gatekeeper, Transactor), 각 노드가 LLM을 쓰는지 코드를 쓰는지, 그리고 Gatekeeper에서의 일시 중단/재개 기능을 보여준다.

누군가 "다음 주 화요일 뭄바이에서 런던으로 가는 항공편을 예약해줘"라고 말할 때 어떤 일이 벌어지는지 안내하겠다.

먼저, LLM으로 구동되는 Collector 노드가 그 문장을 구조화된 필드로 파싱한다. 특정 스키마를 출력하기 위해 유도 생성(JSON 모드)을 사용한다. 파이썬 검증기가 공항 코드가 실재하는지 확인한다. "런던"은 모호하다 — 히스로인가 개트윅인가? — 그래서 그래프는 명확화 노드로 경로를 돌린다. LLM은 추측하지 않는다. 묻는다.

검증된 검색 조건을 확보하고 나면, Retriever 노드가 아마데우스 API를 호출한다. 이것은 순수한 코드다. LLM은 관여하지 않는다. 응답이 돌아와 상태에 캐시되고, 그 다음에야 비로소 Summarizer 노드 — LLM인 — 가 상위 다섯 개 결과를 사람이 읽을 수 있는 메시지로 변환한다. 하지만 엄격하게 제약된다: 캐시된 JSON에 있는 데이터만 표시할 수 있다. 특전을 지어내거나 가격을 바꿀 수 없다.

사용자가 옵션 하나를 고른다. Selector 노드가 "두 번째 것"을 특정 offer_id 해시로 해석한다. Gatekeeper 노드가 비즈니스 규칙을 확인한다 — 이것이 회사 정책 범위 안인가? 항공사가 블랙리스트에 올라 있는가? 위반이 있으면, 그래프는 일시 중단된다. 그래프는 자신의 상태를 데이터베이스에 저장하고, 관리자에게 승인 요청을 보내고, 기다린다. 몇 시간 뒤, 관리자가 "승인"을 클릭하면, 그래프는 정확한 상태를 다시 불러와 예약 노드에서 재개한다.

마지막으로, Transactor 노드가 PNR 생성 순서 — 구간, 탑승객 정보, 가격 산정, 커밋 — 를 GDS가 요구하는 정확한 순서대로 실행한다. GDS가 가격 변동 경고(여행 업계에서 흔하다)를 반환하면, 노드는 멈추고 사용자에게 확인을 요청한다. 더 높은 요금으로 자동 예약하지 않는다.

모든 노드 전환이 로그로 남는다. 모든 결정이 추적 가능하다. 감사자는 실행 로그를 읽고 시스템이 특정 항공편을 예약한 것이 정확히 인지 이해할 수 있다 — 뒤죽박죽인 토큰을 해석해서가 아니라, 구조화된 기록을 읽어서: Node:Gatekeeper | Input: Price=1200 | Rule: Policy_Limit=1000 | Output: REJECT_NEED_APPROVAL.

나는 전체 아키텍처에 대해, 인터랙티브 다이어그램을 포함해, 백서의 인터랙티브 버전에서 다뤘다.

이건 그냥... 평범한 소프트웨어 엔지니어링 아닌가?

사람들은 나에게 이것을 끊임없이 묻는다. "그러니까 AI를 쓰는 대신 코드를 작성해야 한다는 거죠? 혁명적이네요."

아니다. 내가 말하는 것은, AI 산업이 언어 모델의 마법에 너무 취해서 지난 60년간의 컴퓨터 과학을 잊어버렸다는 것이다. 상태 기계, 타입이 지정된 스키마, 조건부 분기, 트랜잭션 무결성 — 이것들은 낡은 개념이 아니다. 당신의 은행이 실수로 엉뚱한 계좌로 돈을 송금하지 않는 이유다.

뉴로-심볼릭 접근은 반(反)AI가 아니다. 친(親)아키텍처다. 우리는 LLM을 적극적으로 사용한다 — 의도 파싱을 위해, 명확화를 위해, 요약을 위해, 그리고 인간이 모호한 무언가를 입력할 때 그것이 무엇을 의미하는지 이해하는 진정으로 어려운 문제를 다루기 위해. 하지만 차가 고속도로 위에 있을 때 우리는 LLM이 운전대를 만지도록 두지 않는다.

일을 한다고 말하는 챗봇을 만들 수도 있고, 실제로 일을 하는 에이전트를 설계할 수도 있다. 그 차이가 바로 그래프다.

나를 놀라게 한 비용 논거도 있다. 순수 LLM 에이전트는 비싸다 — 호출당 추론 비용이 커서가 아니라, 실패 루프 때문이다. 에이전트가 새로운 매개변수를 환각으로 만들어내며 GDS 오류를 재시도하다 막히면, 타임아웃되기 전까지 수천 개의 토큰을 태운다. 막힌 세션 하나가 API 크레딧으로 $5-$10의 비용을 낼 수 있다. 우리의 하드코딩된 오류 핸들러는 그런 실패를 토큰 비용 0으로 잡아낸다. 그리고 우리는 50KB짜리 GDS 응답 전체가 아니라 관련된 5개 필드만 LLM에 보내기 때문에, 컨텍스트 윈도우 사용량을 약 90% 줄인다.

하지만 결국 모델이 충분히 좋아지지 않을까?

어쩌면. GPT-6나 GPT-7이 가드레일 없이 10단계 API 워크플로를 오케스트레이션할 만큼 충분히 신뢰할 수 있을지 나는 정말 모른다. 하지만 두 가지는 안다.

첫째, 모델이 극적으로 개선되더라도, 확률의 사슬 문제는 기술적인 것이 아니라 수학적인 것이다. 모델이 단계당 99% 신뢰할 수 있다면 — 놀라운 성취다 — 10단계 워크플로는 여전히 10%의 확률로 실패한다. 엔터프라이즈 트랜잭션에서 그것은 여전히 용납할 수 없다. 그래프는 라우팅이 확률적이지 않기 때문에 이것을 완전히 제거한다.

둘째, 모델이 좋아지기를 기다리는 것은 대부분의 기업이 누릴 수 없는 사치다. 그들에게 필요한 것은 지금 작동하고, 지금 감사 가능하며, EU AI 법의 투명성 요구 사항을 지금 준수하는 에이전트다. 뉴로-심볼릭 접근은 미래에 베팅하지 않는다. 오늘날 이용 가능한 최고의 AI 역량을 사용하면서 검증된 엔지니어링 원칙 위에 구축한다.

아키텍처가 곧 제품이다

나는 투자자와 엔터프라이즈 구매자들과 충분히 많은 방에 있어봤기에 AI 산업이 깨어나기 시작했다는 것을 안다. 질문은 "누가 가장 똑똑한 모델을 가졌는가?"에서 "누가 가장 견고한 시스템을 가졌는가?"로 옮겨가고 있다. 컨퍼런스 발표에서 눈부신 데모 — 통제된 환경에서 에이전트가 완벽하게 항공편을 예약하는 그런 데모 — 는 값싸다. 값비싸고 중요한 것은, 첫 번째 요청만큼이나 신뢰성 있게 만 번째 요청에서도 작동하는 무언가를 만드는 것이다.

우리는 차별화 요소가 모델이 아닌 시대로 들어서고 있다. 그것은 그래프일 것이다. 상태 스키마. 오류 핸들러. 조건부 에지. 확률적 마법을 감싸고 그것이 집을 태워버리지 못하게 막는, 지루하고 엄격하며 결정론적인 소프트웨어 엔지니어링.

마법은 결코 프롬프트에 있지 않았다. 그것은 언제나 아키텍처에 있었다.

Related Research

Also Published On