Skip to content

[Core] TokenBudget.check()와 reserved output token 지원 #33

Description

@HuitaePark

목적

provider 호출 전에 입력 token의 admission 값과 예약 출력량이 모델 context window 안에 드는지 overflow 없이 판정한다. 결과는 단순 boolean이 아니라 FITS / EXCEEDS / INDETERMINATE를 구분해, 불완전한 TEXT_ONLY 계산이 전체 요청 허용으로 오용되지 않게 한다.

목표 API

BudgetResult check(
    String modelId,
    TokenCountResult input,
    long reservedOutputTokens
);

권장 상태:

enum AdmissionStatus {
    FITS,
    EXCEEDS,
    INDETERMINATE
}

BudgetResult에는 최소한 다음 정보를 포함한다.

  • status
  • fits: 호환성을 위한 파생 projection. status == FITS일 때만 true
  • 판정에 사용한 input estimate/safe upper bound
  • reservedOutputTokens
  • maxContextTokens
  • remainingTokens: FITS에서만 의미가 있는 OptionalLong 또는 동등한 명시적 부재
  • bounded reason
  • canonical model id, estimator id/version, tokenizer compatibility basis

상태 판정 규칙

FITS

다음 조건을 모두 만족할 때만 FITS다.

  1. 모델이 registry에 등록되어 있다.
  2. 결과가 정상 계산 상태다.
  3. estimator/tokenizer compatibility가 모델 정의와 일치한다.
  4. scope가 REQUEST다.
  5. safe admission input과 reserved output이 context window 이내다.

따라서 fits=true는 오직 REQUEST scope의 FITS에서만 가능하다. REQUEST가 exact일 필요는 없지만, heuristic이면 요청 전체를 포함하는 보수적 상한이어야 한다.

EXCEEDS

호환 가능한 계산 결과의 보수적 admission 값이 context window를 넘는 경우다.

  • REQUEST: safe input bound와 reserved output이 window를 넘음
  • TEXT_ONLY: 문자열 자체의 safe input bound와 reserved output만으로 이미 window를 넘음

여기서 EXCEEDS는 provider의 실제 exact token 수를 단정하는 말이 아니라, 선언된 보수적 admission 값으로는 허용할 수 없다는 의미다.

INDETERMINATE

안전하게 FITS 또는 EXCEEDS로 확정할 정보가 부족한 경우다.

  • TEXT_ONLY 값이 window 이내지만 request framing/tool/media/schema가 빠져 있음
  • estimator compatibility와 모델 encoding이 불일치하거나 unknown
  • 미등록 모델
  • unavailable count
  • REQUEST라고 주장하지만 필요한 compatibility/framing 근거가 없음

control/budget 경계의 기본 정책은 fail-closed다. requireFits() 또는 adapter는 FITS만 provider 호출을 허용하고 EXCEEDS와 INDETERMINATE를 모두 호출 전에 차단하되, 두 상태의 이유는 구분한다.

Overflow-safe 계산

합계를 먼저 더하지 않는다.

if (input > max || reserved > max - input) {
    // conservative EXCEEDS
}
  • 모든 token/window 값은 0 이상이다.
  • 허용 시 remaining은 max - input - reserved다.
  • 정확히 한도와 같으면 FITS, remaining=0이다.
  • EXCEEDS/INDETERMINATE의 remainingTokens는 empty로 표현한다. 0 sentinel을 사용하면 “정확히 경계에 맞는 FITS”와 구분되지 않는다.
  • wire/API 호환성 때문에 primitive projection이 필요하면 status/reason 없이 그 값을 의사결정에 사용할 수 없도록 명시한다.

구현 범위

  • Core TokenBudget, immutable BudgetResult, AdmissionStatus
  • bounded reason: CONTEXT_EXCEEDED, INCOMPLETE_SCOPE, INCOMPATIBLE_TOKENIZER, UNKNOWN_MODEL, COUNT_UNAVAILABLE
  • [Core] versioned ModelRegistry와 최소 모델 정책 등록 #32 ModelRegistry의 canonical model/context/compatibility 조회
  • scope와 compatibility 기반 상태 전이
  • adapter가 사용할 requireFits() 또는 typed exception
  • 실제 provider 차단 연결은 #39에서 수행

테스트 시나리오

  • REQUEST exact/heuristic의 한도 미만, 정확한 경계, 1 token 초과
  • fits == (status == FITS) 불변식
  • TEXT_ONLY가 window 이내면 INDETERMINATE/fits=false
  • TEXT_ONLY의 보수적 admission 값이 window를 넘으면 EXCEEDS/fits=false
  • incompatible/unknown tokenizer basis는 INDETERMINATE
  • 미등록 모델과 unavailable count는 INDETERMINATE
  • EXCEEDS/INDETERMINATE remainingTokens는 부재다.
  • reserved output 0과 음수 거부
  • Long.MAX_VALUE 인접 값에서도 overflow가 없다.
  • fail-closed helper가 FITS 외 상태를 허용하지 않는다.

Acceptance criteria

  • FITS/EXCEEDS/INDETERMINATE가 명시적으로 구분된다.
  • fits=true는 REQUEST scope의 FITS에서만 가능하다.
  • TEXT_ONLY의 within-window 결과를 전체 요청 허용으로 표시하지 않는다.
  • estimator와 model tokenizer compatibility를 검사한다.
  • unknown/unavailable/mismatch가 INDETERMINATE로 fail-closed 된다.
  • remainingTokens가 비-FITS 상태에서 가짜 여유량으로 노출되지 않는다.
  • reserved output과 overflow-safe 비교가 테스트된다.
  • 금액 budget API와 이름·타입이 구분된다.

제외 범위

금액 예산, atomic reservation, Spring AI Advisor 연결, prompt trimming.

의존관계와 순서

#30과 #32가 선행한다. #31 완료 후 TEXT_ONLY 통합 테스트를 추가한다. 이 이슈는 보수적 비용 상한과 #39 adapter의 선행 조건이다.

Source

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmvpTokenPilot 0.1.0 MVP scope

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions