나의 AI 기능이 하루 동안 작동하지 않았다. 하지만 지표는 정상이라고 말했다.
요약
로컬 LLM을 활용한 드론 조기 경보 시스템 운영 중, 모델의 응답 실패와 검증 게이트에 의한 거절을 동일한 지표로 처리하여 발생한 오류를 다룹니다. 모델이 메모리에서 언로드되어 발생하는 타임아웃 문제를 명명 오류(naming error)로 인해 오판한 사례를 분석합니다.
핵심 포인트
- 모델 응답 실패와 검증 게이트 거절을 동일한 카운터로 측정하는 오류 주의
- 로컬 모델 운영 시 메모리 관리로 인한 모델 언로드 및 콜드 스타트 문제 발생 가능성
- 타임아웃 설정이 모델 로딩 시간보다 짧을 경우 기능이 실행되지 않을 수 있음
- 정확한 디버깅을 위해 시스템 상태를 구분하는 명확한 명명과 감사 추적 필요
어제 나의 드론 조기 경보 시연기(demonstrator)는 네 개의 AI 생성 설명을 기록했다. 네 개 모두 그 앞에 위치한 검증 게이트(validation gate)에 의해 폐기되었다.
나는 그 숫자를 보고 기분이 좋았다. 4개 중 4개를 거절하는 게이트는 제 역할을 다하고 있는 것이다. 그것은 기술 보고서(technical brief)에 넣기에 딱 좋은 통계였다.
하지만 틀렸다. 게이트가 틀린 것이 아니라, 나의 해석이 틀렸다.
시스템이 하는 일
이 시연기는 여러 소스의 신호를 융합하고 결정론적 규칙(deterministic rules)을 사용하여 위협 수준을 결정한다. 어떤 모델도 그 결정에는 관여하지 않는다. 그 후 로컬 언어 모델(local language model)은 단 한 가지 일만 수행하도록 허용된다. 바로 기계의 추론을 운영자가 빠르게 읽을 수 있는 문장으로 다시 쓰는 것이다.
작은 로컬 모델은 항상 순종적이지 않기 때문에, 누군가 보기 전에 문장을 검사한다. 문장은 규칙이 계산한 위협 수준을 명시해야 하며, 그 외의 다른 수준을 언급해서는 안 된다. 그 외의 모든 것은 버려지며 결정론적인 문구가 유지된다. 나는 게이트를 만들 때 이를 테스트했다. 25개의 문장 중 7개가 운영자 디스플레이에 부적합했다. 게이트를 추가한 후에는 30개 중 30개가 모두 부합했다.
그래서 운영 환경의 카운터가 4개 중 0개가 생존했다고 말했을 때, 이야기는 저절로 써 내려가졌다. 산발적인 위협 상승, 작은 모델, 엄격한 게이트. 당연히 일부는 폐기될 수밖에 없다고 생각했다.
카운터가 서로 다른 두 가지를 측정하고 있었다
모델을 호출하는 함수는 게이트가 텍스트를 거절할 때 아무것도 반환하지 않는다. 또한 모델이 전혀 응답하지 않을 때도 아무것도 반환하지 않는다. 타임아웃(Timeout), 연결 거부(connection refused), 그 무엇이든 말이다. 두 경우 모두 동일한 빈 결과(empty result)로 돌아왔고, 나는 두 경우 모두를 "게이트에 의해 거절됨"으로 기록했다.
이것이 버그의 전부이며, 사실 코딩 실수는 아니다. 명명(naming) 실수다. 나는 하나의 카운터에 두 가지 서로 다른 사실을 부여했다.
그 사실 중 하나는 안전 메커니즘이 작동하고 있다는 것이다. 다른 하나는 기능이 죽었다는 것이다. 이 둘은 정반대이며, 나는 이 둘을 구별할 수 없게 만들었다.
실제로 일어나고 있었던 일
모델은 동일한 머신에서 로컬로 실행되는데, 이것이 핵심입니다. 즉, 운영 배포 환경(operational deployment)이 상용 API로 가는 경로가 없는 네트워크 상에 위치해 있다는 점입니다. 런타임(runtime)은 메모리를 확보하기 위해 유휴 상태(idle)인 모델을 메모리에서 언로드(unload)합니다. 4개의 CPU 코어에서 2GB를 다시 로드하는 작업은 제가 설정해 둔 30초의 타임아웃(timeout)보다 더 오래 걸립니다.
에스컬레이션(Escalations)은 설계상 산발적으로 발생합니다. 시스템은 대부분의 시간 동안 조용합니다. 그래서 거의 모든 에스컬레이션이 발생했을 때 모델은 콜드(cold) 상태였고, 30초를 기다린 뒤 포기하고 결정론적인 문구(deterministic wording)로 폴백(fallback)되었습니다.
웜(Warm) 상태일 때는 동일한 프롬프트(prompt)에 대해 7.8초 만에 답변하며 첫 번째 시도에서 게이트(gate)를 통과합니다. 진단 후에 정확한 운영 프롬프트를 사용하여 실행 중인 모델과 직접 비교 측정해 보았습니다.
기능이 실패한 것이 아니었습니다. 기능이 아예 실행되지 않았던 것입니다.
해결에는 10분이 걸렸지만, 원인을 찾는 데는 감사 추적(audit trail)이 필요했다
세 가지 변경 사항이 있었습니다. 첫째, 조용한 한 시간이 다음 에스컬레이션의 실패를 보장하지 않도록 런타임에 모델을 상주(resident)시키도록 요청했습니다. 둘째, 폴백(fallback)이 이미 정확한 경우에는 느린 답변이 비용을 발생시키지 않으므로, 타임아웃을 콜드 로드(cold load) 시간보다 훨씬 길게 늘렸습니다. 셋째, 카운터를 네 가지로 분리했습니다: 수락됨(accepted), 게이트에 의해 거부됨(rejected by the gate), 비어 있음(empty), 답변되지 않음(never answered).
마지막 변경 사항이 가장 중요합니다. 앞의 두 가지는 설정(configuration)입니다. 세 번째는 당신이 조치를 취할 수 있는 숫자와 당신을 안심시키기만 하는 숫자의 차이입니다.
만약 제가 같은 날 오후에 만든 것이 없었다면 이 중 그 어떤 것도 찾아내지 못했을 것입니다. 바로 내구성이 있는 히스토리(durable history)입니다. 이를 통해 모든 평가 결과가 규칙이 결정한 내용, 모델이 말한 내용, 그리고 그 문장이 통과했는지 여부와 함께 디스크에 기록됩니다. 해당 스토리지 레이어(storage layer)는 완전히 다른 이유로 존재했습니다. 호스트 사이트에 결국 측정된 허위 경보율(false alarm rate)을 전달하기 위해 구축된 것이었습니다. 그것이 도입된 지 4시간 만에, 메인 AI 기능이 하루 동안 비활성 상태였다는 사실을 저에게 알려주었습니다.
그것이 잡아낸 두 번째 사항
모델이 다시 답변하기 시작했을 때, 그 문장 중 하나는 다음과 같았습니다: "높은(HIGH) 신뢰 수준(confidence level)은 높은(HIGH) 위협 수준(threat level)을 정당화합니다."
게이트(gate)는 자신의 규칙에 따라 그것을 올바르게 수락했습니다. 왜냐하면 그 문장이 계산된 수준(level)만을 명시하고 다른 것은 명시하지 않았기 때문입니다. 하지만 그 문장이 무엇을 주장하고 있는지 보십시오. 시스템은 각 탐지기(detector)별로 신뢰도(confidence)를 계산합니다. 시스템은 그 어떤 것에 대해서도 집계된 신뢰도(aggregate confidence)를 계산하지 않습니다. 해당 문장은 시스템이 생성하지 않은 측정값을 기술하고 있습니다.
프롬프트(prompt)는 이미 그것을 금지했습니다. 지침(instruction)은 시스템 메시지(system message)에 명시되어 있었지만, 모델은 이를 무시했습니다. 이것이 바로 신뢰(trust) 대신 게이트(gate)가 존재하는 근본적인 이유입니다.
따라서 이제 게이트는 해당 문구를 허용하는 대신 거부합니다. 기존의 한 테스트는 이전의 관대한 동작을 주장했습니다. 저는 의도적으로 그것을 뒤집고 그 이유를 기록했습니다. 의미를 조용히 바꾸는 테스트는 테스트가 없는 것보다 더 나쁘기 때문입니다.
여기서 얻은 교훈
어떤 종류의 체크(check) 뒤에서 모델을 프로덕션(production) 환경에 실행한다면, 유용한 질문은 체크가 얼마나 자주 발생하는가가 아닙니다. 체크가 작동하는 것과 모델이 아예 응답하지 않는 것 사이의 차이를 구별할 수 있느냐 하는 것입니다.
외부에서 보기에는 두 상황이 동일해 보입니다. 둘 다 출력을 생성하지 않습니다. 둘 다 폴백(fallback)을 작동시킵니다. 둘 다 안전 메커니즘이 활발히 작동하는 것처럼 보이게 만드는 하나의 깔끔한 숫자로 보고될 수 있습니다.
그 차이를 계측(instrument)하십시오. 작동 중인 안전장치(safeguard)와 죽어버린 의존성(dependency)을 하나로 합쳐버리는 카운터(counter)는 카운터가 없는 것보다 더 나쁩니다. 왜냐하면 그것은 침묵하지 않기 때문입니다. 그것은 당신을 안심시킵니다.
불편한 부분은 저의 실패 모드(failure mode)가 제가 글을 쓰는 내용과 동일했다는 점입니다. 즉, 실체는 없으면서 확신에 찬 출력(confident output)을 내놓는 것이었습니다. 단지 그것이 모델이 아닌 지표(metric)에서 발생했을 뿐입니다.
이 카테고리에서 중요하기에 이 시스템이 무엇인지에 대해 언급합니다. DroneWatch AI는 작동 가능한 개념 증명(concept demonstrator)입니다. 위협 신호(threat signals)는 시뮬레이션된 것입니다. 항공 교통 피드(air traffic feed)는 실시간이며 실제입니다. 이것은 운영 시스템이 아니며, 실제 드론을 탐지하지 않고, 현장에서 검증된 성능을 주장하지 않습니다. 이것은 엄격히 방어적이며, 차단(interdiction)이나 대응(countermeasure) 기능 없이 탐지 및 조기 경보만을 목적으로 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기