시리즈: AI와 함께 코딩 배우기

오늘 모든 LLM 호출자가 프롬프트 길이 가드를 갖게 됐다

비용 급증, 감사, 그리고 모든 LLM 호출자에 대한 프롬프트 길이 가드.

모든 LLM 호출자, 가드 하나 호출자별 토큰 예산, 절단 계층, 텔레메트리, CI 강제 무제한 호출자 5개, 길이 상한 없음 상한 적용됨 예산 편성, 로깅, 상한 적용 LLMCallGuard 절단 & 로깅 거친 폴백 시끄럽게 실패 CI 회귀 게이트
하나의 공유 가드가 조용한 비용 증폭을 시끄럽고 상한이 있는 실패로 바꾼다.

무제한 프롬프트는 언제든 터질 수 있는 비용 증폭 공격이다. RakuAI는 프롬프트 길이 규율을 보안 인프라로 취급한다 — 기억에 맡기지 않고 빌드에서 강제한다.

이 런타임은 내가 추적하고 있던 것보다 더 많은 곳에서 LLM을 호출한다. 명백한 곳이 있다(음성 기반 AR 경험을 구동하는 XRAssistantService). 덜 명백한 곳이 있다(NPC 행동 계층, 여기서는 세계 속 에이전트의 두뇌가 부분적으로 LLM 호출이다). 가장 명백하지 않은 곳이 있다(런타임 빌드에 슬금슬금 들어오기 시작한 개발 시점 도구들: 스키마 검증기, 디버그 분석기, 자동 플레이테스트 요약기).

이 각각의 지점은 지난 여섯 달 동안 독립적으로 작성되었다. 각각은 PR 시점에 리뷰되었다. 이번 주말이 되기 전까지는 그 어느 것도 프롬프트 길이에 대한 통일된 규율을 갖고 있지 않았다.

이 글은 그것이 왜 문제가 되었는지, 감사가 무엇을 발견했는지, 그리고 새로운 가드레일이 어떤 모습인지에 대한 글이다.

문제는 어떻게 드러났는가

계기는 통상적인 비용 모니터링 점검이었다. 일일 LLM API 지출을 보다가, 특정 개발 환경 하나가 다른 것들보다 열다섯 배를 쓰고 있는 것을 발견했다. 같은 에이전트 수, 같은 테스트 워크로드, 같은 모델. 열다섯 배의 비용.

그 급증을 추적하니 플레이테스트 요약기 코드 경로로 이어졌다. 이 요약기는 끝난 플레이테스트 세션을 받아서, 관련된 씬 상태를 프롬프트에 담아, 클라우드 LLM에 보내고, 그 세션에 대한 구조화된 분석을 돌려받는다. 이 함수는 씬이 작았을 때 작성되었다. “관련된 씬 상태”는 일어난 일에 대한 구조화된 요약이었다. 시간이 지나면서 그 요약은 커졌다. 특정 개발 환경이 거대한 요약을 만들어내는 긴 플레이테스트를 돌리고 있었다. 요약기는 그 요약들을 검사 없이 모델에 보내고 있었다. 모델은 토큰당 요금을 부과하고 있었다.

이 단일 호출자에 대한 수정은 명백했다. 요약 길이를 제한하라. 필요하면 절단하라. 절단이 일어날 때 로그를 남겨라.

내가 다음으로 던진 더 깊은 질문은 이것이었다. 런타임의 다른 얼마나 많은 호출자가 같은 취약점을 가지고 있는가? 나는 찾아 나섰다. 감사가 진짜 작업이었다.

감사가 발견한 것

런타임에서 LLM을 호출하는 열한 개의 지점. 그 열한 개 중.

  • 두 개는 명시적인 길이 확인과 오버플로우 시 합리적인 동작(절단, 로깅, 더 작은 컨텍스트로 재시도)을 갖고 있었다. 이들은 괜찮았다.
  • 다섯 개는 아무런 길이 확인이 없었다. 그것들은 호출자가 건넨 것을 그대로 보냈다.
  • 세 개는 길이 확인이 있었지만 쓸모가 있기에는 지나치게 관대했다(어떤 정상적인 사용보다도 훨씬 위지만 파국보다는 훨씬 아래인 십만 토큰).
  • 하나는 애초에 프로덕션 바이너리에 있어서는 안 될 디버그 경로였다. 길이 확인이 있었지만 디버그 플래그를 통해 쉽게 우회되었다.

길이 확인이 없는 다섯 개가 시급한 것들이었다. 그것들은 다음을 아울렀다. 플레이테스트 요약기(이미 파악됨), NPC 행동 두뇌(NPC가 복잡한 씬을 관찰할 수 있다면 잠재적으로 거대해질 수 있다), 스키마 검증기(임의의 파일이 건네질 수 있다), 월드 상태 서술기(임의로 큰 월드 청크를 서술할 수 있다), 그리고 개발자 대상 진단 도구 중 하나.

이들 각각은 별도의 PR로 들어왔다. 각 PR은 개별적으로는 합리적이었다. “모든 LLM 호출자가 길이 상한을 갖는다”는 집계된 규율은 누구의 일도 아니었다. 그래서 아무도 그것을 하지 않았다.

가드는 어떤 모습인가

토요일 아침 작은 인프라 조각이 들어왔고 하루 동안 모든 호출자에 적용되었다.

공유 LLMCallGuard 유틸리티. LLM과 대화하는 모든 지점은 이제 요청을 직접 구성하는 대신 이 유틸리티를 거친다. 이 유틸리티는 프롬프트 템플릿, 컨텍스트 페이로드, 타깃 모델을 받는다. 길이 상한을 강제한다(모델별로 설정 가능하며, 그 모델의 문서화된 컨텍스트 윈도우를 기반으로 한 합리적인 기본값을 갖는다). 예산 안에서 사용된 경우에는 실제 프롬프트 길이를 INFO 레벨로, 절단이 필요했을 때는 WARNING 레벨로, 절단해도 상한에 맞지 않을 때는 ERROR 레벨로 로깅한다.

호출자별 예산. 런타임의 각 LLM 호출자는 이제 명시적인 호출당 토큰 예산을 갖는다. 이 예산은 모델의 컨텍스트 윈도우보다 낮은데, 응답을 위한 여유를 남겨두고 싶고 모델이 조용히 실패하기 전에 시끄럽게 실패하고 싶기 때문이다. 예산은 수천 토큰(스키마 검증기)부터 이만 토큰(플레이테스트 요약기, 원래 사건을 막는 실제 상한과 함께)까지 다양하다.

텔레메트리. 이제 모든 LLM 호출은 프롬프트 크기, 응답 크기, 모델, 소비된 예산, 지연 시간을 기록한다. 이 텔레메트리가 바로 청구서가 오기 전에 다음 사건을 눈치챌 수 있게 해주는 것이다.

실패 양상 계층. 호출자의 페이로드가 예산을 초과하면, 유틸리티는 순서대로 일련의 수정을 시도한다. 첫째, 지능적인 절단을 시도한다(가장 최근 컨텍스트를 보존하고, 가장 오래된 것을 버리고, 시스템 프롬프트는 그대로 유지한다). 둘째, 지능적인 절단으로도 맞지 않으면 더 거친 절단을 시도한다(섹션 전체를 버린다). 셋째, 어떤 절단으로도 맞지 않으면, 모델이 거부할 크기가 지나친 요청을 보내는 대신 명확한 에러와 함께 시끄럽게 실패한다. 이 계층 덕분에 대부분의 경우는 우아하게 복구되고, 엣지 케이스는 관찰 가능한 방식으로 실패하며, 어떤 호출자도 무제한 페이로드를 보내는 일은 절대 없다.

회귀를 막는 CI 체크. LLM과 대화하는 새로운 코드는 LLMCallGuard를 거쳐야 한다. CI 스캔은 이 유틸리티를 우회하는 새로운 직접 LLM 호출을 찾아 PR에 표시한다. 이 패턴은 몇 주 전 주말 보안 감사가 관리자 엔드포인트에 썼던 것과 같다. 규율을 리뷰가 아니라 빌드에서 강제하라.

배운 것

세 가지다.

누구의 일도 아닌 규율은 일어나지 않는 규율이다. 열한 개의 LLM 호출자 각각은 PR 시점에서는 합리적이었다. 그 집합적인 행동은 아무도 그 크로스커팅 관심사를 소유하지 않았기 때문에 리뷰되지 않았다. 해결책은 그 크로스커팅 관심사를 모든 호출자가 거쳐야 하는 하나의 인프라 조각으로 만드는 것이었고, 이는 그 규율을 잊는 것을 불가능하게 만든다.

비용은 보안 관심사다. 나는 “무제한 프롬프트”를 정확성이나 견고성에 대한 관심사로 생각하고 있었다. 개발 환경의 비용 급증은 그것을 보안 관심사로 생각하도록 가르쳐줬다. 런타임의 LLM 호출 내용에 영향을 미칠 수 있는 공격자는 운영자에게 임의의 비용을 부과할 수 있다. 같은 방어책(길이 상한, 예산 강제, 텔레메트리)이 견고성 실패와 비용 증폭 공격 둘 다로부터 보호한다.

정기적으로 감사하라. 오늘의 감사는 PR 리뷰가 놓친 다섯 개의 취약점을 발견했다. 다음 감사는 다른 것들을 발견할 것이다. 특정 크로스커팅 관심사에 대해 예정된 감사 패스를 실행하는 규율은 리뷰가 놓치는 것들을 드러내는 유일하고 신뢰할 만한 방법이라는 것을 나는 발견했다.

파트너와 빌더가 여기서 가져가야 할 것

프로덕션 코드에서 LLM을 호출하는 무언가를 운영하고 있고 모든 호출자에 대해 프롬프트 길이 규율을 감사한 적이 없다면, 지금 해보라. 감사는 작다. 발견 사항은 나올 가능성이 높다. 오늘 그것을 하는 비용은 사건이 터진 이후에 하는 비용보다 훨씬 작다.

다른 LLM을 호출하는 에이전트를 만드는 AI 랩이라면, 최적화해야 할 지표는 “그 에이전트가 무제한 프롬프트를 구성하고 있을 때 그것을 표시하는가”이다. 대부분의 에이전트는 그렇게 하지 않는다. 그렇게 하는 에이전트가 내가 진지한 작업에서 신뢰하는 에이전트다.

파트너십을 위해 엔진을 평가하고 있고 그 엔진이 클라우드 LLM과 통합된다면, 프롬프트 길이 규율에 대해 물어보라. 옳은 답은 “모든 호출자가 호출자별 예산, 텔레메트리, CI 가드를 갖춘 공유 유틸리티를 거친다”이다. 틀린 답은 “아직 그런 문제를 본 적이 없다”이다.

토요일 오후. 런타임의 모든 LLM 호출자가 이제 같은 가드를 거친다. 다음 감사 주기는 달력에 올라 있다.

다시 빌드하러 간다.

모든 LLM 호출을 지키는 런타임 위에서 빌드하라

RakuAI는 당신의 모델이 프로덕션에서 구동하는 AI 네이티브 공간 런타임이다 — 프롬프트 길이 예산, 텔레메트리, CI 강제가 그 경계에 내장되어 있다. 규율 있는 인프라가 당신의 스택을 위해 무엇을 열어주는지 확인하라.

← 전체 글