Microsoft AI-103

Microsoft AI-103 시험 노트개념 정리16 MIN

할당량·스케일링·비용과 성능 모니터링

TPM과 RPM이 어떻게 얽히는지, 429를 만났을 때 무엇을 늘려야 하는지, 토큰 비용을 어디서 줄이는지, 그리고 드리프트·안전 이벤트·인덱스 상태를 무엇으로 재는지 정리합니다.

앞 노트가 「어떻게 올리는가」였다면 이 노트는 「올린 뒤에 무엇을 보는가」입니다. 이 절의 문항은 다른 절과 성격이 조금 다릅니다 — 증상을 주고 원인을 찾게 합니다. 「응답이 느려졌다」·「429가 늘었다」·「답이 예전만 못하다」 셋이 단골이고, 셋의 원인이 모두 다른 자리에 있습니다.

할당량과 레이트 리밋

할당량(quota)은 구독이 특정 리전의 특정 모델에 대해 배포할 수 있는 용량의 상한이고, 배포에 그 용량을 나눠 줍니다. 실제로 요청을 막는 것은 그 용량에서 나오는 두 가지 레이트 리밋입니다.

리밋 세는 것 걸리는 상황
TPM(tokens per minute) 분당 처리 토큰(입력 + 출력 추정치) 요청 하나하나가 길 때
RPM(requests per minute) 분당 요청 수 요청이 짧고 잦을 때

둘은 따로 노는 값이 아닙니다. Azure OpenAI 배포에서 RPM은 할당한 TPM에서 함께 따라옵니다 — 1,000 TPM마다 6 RPM이 붙는 비율입니다. 그래서 배포에 60,000 TPM을 주면 RPM은 360이 되고, 두 리밋 중 먼저 닿는 쪽이 병목이 됩니다.

계산해 보면 어느 쪽이 먼저 닿는지가 곧바로 보입니다. 요청마다 토큰이 2,000이고 분당 40건이 들어오면 필요한 것은 80,000 TPM과 40 RPM입니다. 60,000 TPM 배포로는 RPM(360)은 아홉 배나 남는데 TPM이 모자라 429가 납니다. 반대로 요청이 100 토큰씩 분당 500건이면 필요한 것은 50,000 TPM과 500 RPM이라, 60,000 TPM 배포에서 토큰은 남지만 RPM 360에 걸립니다. 「429가 난다」만으로는 무엇을 늘려야 할지 알 수 없고, 요청 하나의 크기를 먼저 봐야 한다는 뜻입니다.

리밋에 닿으면 서비스는 429와 함께 Retry-After 헤더를 돌려줍니다. 그 값을 무시하고 곧바로 다시 던지면 상황이 더 나빠지므로, 헤더를 읽어 기다리고 지수 백오프를 붙이는 것이 기본형입니다.

import time
from openai import RateLimitError

def ask(client, deployment, messages, attempts=5):
    delay = 1.0
    for attempt in range(attempts):
        try:
            return client.chat.completions.create(model=deployment, messages=messages)
        except RateLimitError as error:
            wait = getattr(error.response, "headers", {}).get("retry-after")
            time.sleep(float(wait) if wait else delay)   # 서버가 말한 시간을 먼저 따른다
            delay *= 2                                    # 없으면 지수 백오프
    raise RuntimeError("레이트 리밋이 계속됩니다")

처리량을 늘리는 네 가지 길

  1. 할당량 증설을 신청한다. 리전·모델 단위라 승인이 필요하고 즉시 되지 않습니다.
  2. 배포를 여럿 두고 나눠 보낸다. 같은 리전 안에서, 또는 리전을 걸쳐 앞단에서 분산합니다.
  3. 프로비저닝드로 바꾼다. 처리량을 미리 떼어 두므로 이웃 부하에 흔들리지 않습니다.
  4. 급하지 않은 일은 배치로 내린다. 야간 요약·분류처럼 실시간이 아닌 작업을 온라인 배포에서 빼면 낮 시간대 여유가 생깁니다. 사용자를 기다리게 하지 않는 작업이 사용자 요청과 같은 배포를 쓰고 있었다는 사실 자체가 자주 원인입니다.

②를 고를 때는 나눠 보내는 방식까지 정해야 합니다. 단순히 번갈아 보내면 배포마다 남은 용량이 달라도 똑같이 나눠 주므로, 429를 받은 배포를 잠시 빼 두고 나머지로 흘리는 방식이 실제로는 더 잘 듭니다.

순서가 중요합니다. 시험은 「지금 당장」이라는 말을 넣어 ①을 오답으로 만듭니다 — 증설은 신청과 승인이 걸리므로 즉시 대응은 ②나 ④입니다.

비용은 어디서 새는가

과금 단위는 배포가 아니라 토큰입니다. 그래서 비용을 줄이는 손잡이도 토큰 위에 있습니다.

손잡이 무엇을 줄이나
max_tokens 상한 출력 토큰. 출력 단가가 입력보다 몇 배 비싸므로 효과가 크다
프롬프트 정리와 few-shot 예시 줄이기 입력 토큰
검색 결과 개수와 청크 크기 RAG에서 프롬프트에 붙는 입력 토큰
쉬운 요청을 작은 모델로 보내기 요청당 단가
같은 접두사를 재사용해 캐시가 듣게 하기 반복되는 입력의 단가

표의 마지막 줄이 RAG에서 특히 크게 듣습니다. 검색 결과를 여덟 개 붙이던 것을 넷으로 줄이면 프롬프트에 들어가는 입력 토큰이 대략 절반이 되는데, 관련성 지표를 함께 보면 답의 품질은 거의 그대로인 경우가 많습니다. 상위 넷 밖의 조각은 근거로 거의 쓰이지 않으면서 토큰만 먹고 있었던 것입니다. 줄이기 전에 관련성부터 재 두어야 품질이 같은지 판단할 수 있다는 것이 이 손잡이의 조건입니다.

비용 추적은 태그와 배포 이름으로 갈라 봅니다. 팀이나 기능마다 배포를 따로 두면 청구서에서 어느 기능이 얼마를 썼는지가 그대로 갈립니다 — 한 배포에 전부 몰아 두면 나중에 되짚을 방법이 없습니다. 요청 단위로 더 잘게 봐야 하면 응답의 usage 필드에 실린 입력·출력 토큰 수를 로그에 남겨 사용자·기능별로 집계합니다.

성능과 드리프트를 무엇으로 재는가

드리프트는 모델도 코드도 그대로인데 답의 품질이 시간이 지나며 달라지는 현상입니다. 원인이 대개 우리 쪽에 있습니다 — 사용자가 묻는 방식이 바뀌었거나, 색인의 문서가 낡았거나, 자동 승격으로 모델 버전이 올라갔거나입니다.

보는 것 무엇을 알려 주나
지연(첫 토큰까지, 응답 완료까지) 사용자가 느끼는 속도. 둘을 갈라 봐야 스트리밍 효과가 보인다
429·5xx 비율 용량이 모자라거나 서비스 쪽 문제
요청당 토큰 분포 프롬프트가 슬금슬금 길어지는 것
평가자 점수 추이 품질이 내려앉는 것
안전 필터 차단 건수 공격 시도나 필터 오작동
그라운디드니스 점수 답이 근거 문서에 실제로 붙어 있는 정도

그라운디드니스는 모델의 답이 함께 준 근거 안에 있는 내용인지를 재는 지표입니다. 이 값이 내려가는데 검색 쪽 지표는 멀쩡하다면 프롬프트나 모델 버전을 의심하고, 검색 쪽 지표가 함께 내려갔다면 색인을 의심합니다.

안전 이벤트는 따로 센다

안전 이벤트는 안전 필터나 방어 장치가 무언가를 걸러 냈다는 기록입니다. 품질 지표와 섞어 보면 안 되는 이유가 있습니다 — 차단은 시스템이 제대로 일한 결과일 수도 있고, 멀쩡한 요청을 막은 오작동일 수도 있어서 건수만으로는 좋은 신호인지 나쁜 신호인지 알 수 없기 때문입니다. 그래서 무엇이 걸렸는지를 갈라 셉니다.

세는 것 갑자기 늘었을 때 의심할 것
범주별 차단 건수(증오·성적·폭력·자해) 필터 임계값을 너무 낮게 잡았거나 사용자층이 바뀌었다
차단 목록에 걸린 건수 목록에 넣은 낱말이 정상 문맥에도 나타난다
프롬프트 실드가 잡은 건수 탈옥·간접 주입 시도가 실제로 늘었다
그라운디드니스 실패 건수 검색이 근거를 못 찾아 모델이 지어내고 있다

마지막 줄이 앞 절의 품질 지표와 이어집니다. 그라운디드니스가 낮은 응답이 늘었는데 안전 필터 쪽은 조용하다면 안전 문제가 아니라 검색 문제이므로, 볼 곳은 필터 설정이 아니라 색인입니다.

색인 쪽에서 볼 것은 셋입니다. 인덱서 실행 성공률과 실패한 문서 수, 마지막 성공 실행 시각, 그리고 검색 관련성입니다. 앞 둘이 나빠지면 색인에 최신 문서가 안 들어온 것이고, 앞 둘이 멀쩡한데 관련성만 나빠지면 문서는 들어왔지만 청킹이나 질의 쪽이 어긋난 것입니다. 이 셋을 갈라 두는 것이 「답이 예전만 못하다」는 신고를 받았을 때 어디부터 열어 볼지를 정해 줍니다.

연습 문제

  1. 배포에 30,000 TPM을 할당했습니다. 함께 붙는 RPM은 얼마입니까?
    ① 30
    ② 180
    ③ 300
    ④ 3,000
    ②. 1,000 TPM마다 6 RPM이므로 30×6=18030 \times 6 = 180 RPM입니다.
  2. 요청 하나에 입력 1,600·출력 400 토큰이 들고 분당 50건이 들어옵니다. 60,000 TPM 배포에서 벌어질 일은?
    ① RPM에 먼저 걸린다
    ② TPM에 걸린다. 필요한 것이 100,000 TPM이므로
    ③ 둘 다 여유가 있다
    ④ TPM은 남고 RPM만 모자란다
    ②. 요청당 2,000 토큰 × 50건 = 100,000 TPM이 필요한데 할당은 60,000입니다. RPM은 50만 필요하고 360이 붙어 있으므로 여유입니다.
  3. 위 파이썬 조각에서 Retry-After 헤더를 읽어 그 값을 우선 쓰는 이유는?
    ① 헤더가 없으면 예외가 나므로
    ② 서비스가 알려 준 대기 시간을 무시하고 즉시 재시도하면 리밋을 더 밀어 올리므로
    ③ 지수 백오프보다 항상 짧으므로
    ④ 할당량이 자동으로 늘어나므로
    ②. ③은 사실이 아니고 — 서버가 더 긴 시간을 요구할 수 있습니다 — ①도 아닙니다. 조각은 헤더가 없으면 백오프 값으로 떨어지게 되어 있습니다.
  4. 「내일 아침까지 429를 줄여야 한다」는 상황에서 즉시 효과를 볼 수 없는 대응은?
    ① 다른 리전에 배포를 하나 더 만들어 나눠 보낸다
    ② 할당량 증설을 신청한다
    ③ 야간 배치 작업을 온라인 배포에서 뺀다
    ④ max_tokens를 줄여 출력 토큰을 깎는다
    ②. 증설은 신청과 승인이 필요해 즉시 되지 않습니다. 나머지 셋은 우리 손으로 오늘 할 수 있습니다.
  5. 요청당 입력 1,000·출력 500 토큰이고, 가정한 단가가 입력 100만 토큰당 3달러, 출력 100만 토큰당 12달러입니다. max_tokens를 낮춰 출력을 평균 300 토큰으로 줄이면 요청 100만 건 기준으로 비용이 얼마나 줄어듭니까?
    ① 240달러
    ② 600달러
    ③ 2,400달러
    ④ 6,000달러
    ③. 출력이 건당 200 토큰 줄고 요청이 100만 건이므로 줄어든 출력은 200×106=2×108200 \times 10^6 = 2 \times 10^8 토큰, 곧 200개의 100만 토큰 단위입니다. 200×12=2,400200 \times 12 = 2{,}400 달러입니다. 입력 단가는 이 계산에 들어오지 않습니다 — 입력 토큰은 그대로이기 때문입니다.
  6. 「답이 예전만 못하다」는 신고를 받았고, 인덱서의 마지막 성공 실행이 3주 전입니다. 가장 먼저 볼 곳은?
    ① 모델 버전 업데이트 정책
    ② 인덱서 실패 로그와 색인의 문서 수
    ③ 안전 필터의 심각도 임계값
    ④ temperature 설정
    ②. 3주 동안 새 문서가 색인에 안 들어왔다는 뜻이므로 검색 단계부터 무너져 있습니다. ①은 인덱서가 멀쩡한데 품질만 내려갔을 때 볼 곳입니다.

증상에서 자리를 찾는 연습이 이 절의 전부입니다. 429는 용량, 느려짐은 지연 분해, 품질 저하는 검색부터 거슬러 프롬프트와 모델 버전 순입니다. 그리고 세 증상 모두 평소에 재 두지 않으면 사후에 알 수 없다는 공통점이 있어서, 「무엇을 계측하겠는가」를 묻는 문항이 「어떻게 고치겠는가」만큼 자주 나옵니다.

Microsoft AI-103 시험 노트 전체 보기