무료 모델 티어에 의존하기 전에 작은 토큰 미터를 구축하는 방법
요약
무료 모델 티어의 무분별한 토큰 소진 문제를 해결하기 위해, 개발자가 간단한 '토큰 미터(token meter)' 메커니즘을 구축하는 방법을 제시합니다. 이 미터는 HTTP 프록시 역할을 하며, 요청 시마다 사용된 토큰 수를 계산하고 원장(ledger)에 기록하며, 일일 할당량 초과 시 호출을 거부하여 비용 통제 기능을 제공합니다.
핵심 포인트
- 무료 티어의 무분별한 소진 문제를 방지하는 것이 목표입니다.
- 토큰 미터는 HTTP 프록시 역할을 하며 파이썬 표준 라이브러리만 사용합니다.
- 요청 토큰 계산, 원장 기록, 할당량 초과 시 호출 거부 세 가지 기능에 집중했습니다.
밤 11시 40분, 재시도 루프가 누군가의 무료 티어를 조용히 소진시키고 있습니다.
충돌로 인한 것이 아닙니다. 단순히 반환된 값을 확인하지 않는 for 루프, 어떤 비(非)200 응답에도 재시도하는 클라이언트, 그리고 화요일 이후 아무도 열어보지 않은 사용량 대시보드 때문입니다. 아침이 되자 할당량은 사라지고, 데모는 내일이며, 에러 메시지는 쓸모 있는 내용을 전혀 담고 있지 않습니다.
이것이 바로 무료 티어가 가진 소진(churn) 문제입니다. 지난주 DEV 게시물들이 계속해서 돌고 돌아가던 주제입니다. 우리는 AI에 지쳤고, 오픈소스 AI 레포지토리에 빠져 허우적거리고 있으며, 우리 장난감 아래의 바닥은 계속 움직이고 있습니다. 그래서 저는 스터디 그룹에서 끊임없이 이 질문을 던집니다. 요청이 몇 개의 토큰을 소모했는지 알 수 없다면, 어떻게 무료 티어가 여전히 무료인지 알 수 있을까요?
이번 사례 연구를 위해 저는 하나의 메커니즘, 즉 토큰 미터(token meter)를 구축하여 무료 모델 엔드포인트 앞에 배치했습니다. 의존성 개수: 파이썬 표준 라이브러리를 제외하고는 제로입니다.
목표, 실패할 수 있도록 명시하기
미터는 세 가지 일만 해야 하며 그 외에는 아무것도 하지 않아야 합니다. 업스트림(upstream)의 usage 블록에서 요청별 토큰을 계산하고, 호출마다 하나의 JSON 라인을 원장(ledger)에 추가하며, 오늘 총량이 하드 캡(hard cap)을 초과하면 새로운 호출을 거부해야 합니다.
세 가지 일, 세 가지 실수할 여지. 동시성(Concurrency), 사용량 데이터 누락, 그리고 엔드포인트가 반환하는 내용에 대한 저 자신의 낙관론입니다.
메커니즘
meter.py라는 하나의 파일입니다. 이것은 HTTP 프록시 역할을 합니다. 클라이언트가 여기에 연결하고, 이 프록시는 업스트림으로 포워딩하며, 무엇이 돌아왔는지 기록합니다.
# meter.py — one free model endpoint를 위한 작은 토큰 미터.
import json, os, time, threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
...
업스트림 호출에는 스텁(stub) 브랜치가 있으며, 이 브랜치 덕분에 저는 돈을 쓰지 않고도 밤 11시 40분에 이 글을 테스트할 수 있습니다.
def _call_upstream(payload):
if STUB:
text = payload[
METER_STUB=1 LEDGER_PATH=/tmp/ledger.jsonl PORT=8080 python3 meter.py &
curl -s localhost:8080/v1/chat \
...
The 출력은 구성에 의해 결정론적입니다 — 실행할 때마다 같은 바이트가 나오며, 네트워크 연결이 필요 없습니다. 스텁 콘텐츠, `usage` 블록, 그리고 `total_tokens: 20`을 보고하는 `meter` 블록을 볼 수 있을 것입니다. 이제 `cat /tmp/ledger.jsonl`를 실행하면 한 줄이 있습니다. 두 번 호출했으니, 두 줄입니다. 이것이 전체 계약 내용입니다.
그런 다음 의도적으로 제한(cap)을 초과해 보세요. `DAY_TOKEN_CAP=10`으로 재시작하고, 한 번 호출한 후 다시 호출합니다. 두 번째 호출은 `spent: 20, cap: 10`과 함께 429를 반환합니다. 본 적 없는 가드(guard)가 작동하는 것을 보면, 그 가드는 당신이 가지고 있지 않은 것입니다.
## 현실처럼 깨뜨려 보기
스텁을 수정하여 `usage`를 완전히 생략하게 만듭니다: 사용량 키(usage key) 없이 `return {
제가 MonkeyCode에서 사용하는 설정은 이렇습니다: 상위(upstream) 모델 접근은 무료로 이용하고, 호스트는 무료 서버 옵션을 사용하며, 그 사이에 프록시를 두어 모든 호출에 기록을 남기게 합니다. 이 프로젝트는 오픈 소스이며, 운영자로부터 받은 무료 티어는 1,000만 토큰입니다. 현재 수치를 직접 페이지에서 확인해 보세요. 왜냐하면 그 숫자는 변동성이 매우 큰 종류의 숫자이기 때문입니다.
공개 고지: 본 기사는 MonkeyCode의 제품 홍보 목적으로 작성되었습니다.
훔쳐 가치 할 배포 세부 사항이 있습니다: `log_message`를 서브클래스(subclass)하고 오버라이드(override)하여 단일 JSON 라인을 방출하도록 하세요. 그렇지 않으면 기본 접근 로그가 서버의 로그 뷰어를 오류처럼 보이게 채울 것입니다. 무료 박스에서는 무서운 로그 하나가 아무것도 아닌 디버깅 시간 한 시간을 비용으로 청구합니다.
## 결과, 제한 사항 및 포기해야 할 경우
스터브(stub)를 사용하면 미터는 결정론적(deterministic)이며 상한선은 산술 계산이 요구하는 정확한 시점에 작동합니다. 실제 엔드포인트에 대해서는 수치가 `usage` 블록만큼만 좋으며, 일일 한도는 호출 전에 확인되고 후에 기록됩니다. 따라서 5토큰이 남은 상태로 동시에 도착하는 두 요청 모두 통과할 것입니다. 이것은 이론적인 것이 아니라 실제 경쟁(race)이며, 신경을 쓰고 있다면 체크-앤-레코드(check-and-record) 주위에 단일 잠금장치(lock)가 정직한 해결책입니다.
이 디자인이 하지 않는 다른 것들. 인증(auth) 기능이 없으므로 공유 비밀 헤더 없이 공개적으로 노출하지 마세요. 전체 응답을 버퍼링하므로 스트리밍 클라이언트는 멈출 것입니다. 스트리밍 변형은 사용량을 위해 최종 청크를 구문 분석해야 합니다. 레저는 JSONL 파일이며, 이는 학생 한 명에게는 괜찮지만 팀에게는 적합하지 않습니다. 그리고 사용자별 할당량(quota)을 통제할 수 없고, 전역적인 일일 상한선만 통제할 수 있습니다.
누가 건너뛰어야 하는지: 대시보드에서 이미 키별로 지출 내역이 분해되는 유료 플랜의 사용자, 스프레드시트 하나가 데몬(daemon) 하나보다 나은 오프라인 배치 작업을 실행하는 사람, 그리고 엔드포인트가 비표준 클라이언트 동작을 거부하는 사람—프록시는 클라이언트이며 일부 게이트웨이는 그것을 싫어합니다.
제가 이 빌드를 통해 실제로 얻은 것은 코드보다 더 작은 깨달음입니다. 프레임워크를 찾기 전에, 단일 요청이 얼마의 비용을 발생시키는지 기록하는 15줄의 코드를 작성해보고, 그리고 그 15줄의 코드가 당신에게 거짓말을 하도록 만들어보세요. 누락된 `usage` 케이스에서 그렇게 될 것이고, 일주일간의 기능 개발보다 이 하나의 잘못된 테스트(bad fixture)로부터 더 많은 것을 배우게 될 것입니다.
그래서 여러분을 위한 예측 테스트가 있습니다. 요청이 두 건이고, 최대 토큰 수는 25개이며, 원장(ledger)은 20개를 기록합니다. 두 요청 모두 같은 밀리초에 도착했습니다. 어느 쪽이 429 에러를 받을까요? 그리고 그 후 원장은 뭐라고 말할까요? 만약 여러분의 답이 '둘 다 아니며, 40'이라면, 이미 잠금(lock)이 왜 필요한지 이해하고 있는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기