완료됨 — PR #23, merge commit 09d5058
문제
기존 구조는 provider의 output total에 reasoning token이 이미 포함된 경우에도 세부량을 다시 더할 수 있어 token과 비용이 중복 집계될 위험이 있었다. cache도 하나의 독립 토큰처럼 취급하면 같은 문제가 발생한다.
적용된 도메인 계약
inputTokens = cache read/create를 포함하는 전체 입력
outputTokens = reasoning을 포함하는 전체 출력
totalTokens = inputTokens + outputTokens
cacheReadInputTokens + cacheCreationInputTokens <= inputTokens
reasoningOutputTokens <= outputTokens
TokenUsageDetails.cacheReadInputTokens: 캐시에서 읽은 입력 세부량
TokenUsageDetails.cacheCreationInputTokens: 캐시에 새로 쓴 입력 세부량
TokenUsageDetails.reasoningOutputTokens: 출력에 포함된 추론 세부량
- 세부 필드의
null: provider가 값을 보고하지 않음
- 세부 필드의
0: provider가 값을 보고했으며 사용량이 0
UsageSource: provider reported/derived, local tokenizer, heuristic, unavailable을 구분
totalTokens(): Math.addExact(inputTokens, outputTokens)로 overflow를 명시적으로 감지
metadata: null이면 빈 Map, 그 외에는 방어적 복사
완료된 구현
대표 검증 예
input = 1,000
├─ regular = 500
├─ cache read = 400
└─ cache creation = 100
output = 1,000
├─ regular = 800
└─ reasoning = 200
totalTokens = 2,000
비용은 다섯 구간에 각 단가를 적용하지만 token total은 언제나 input + output이다.
후속 작업
Source
문제
기존 구조는 provider의 output total에 reasoning token이 이미 포함된 경우에도 세부량을 다시 더할 수 있어 token과 비용이 중복 집계될 위험이 있었다. cache도 하나의 독립 토큰처럼 취급하면 같은 문제가 발생한다.
적용된 도메인 계약
TokenUsageDetails.cacheReadInputTokens: 캐시에서 읽은 입력 세부량TokenUsageDetails.cacheCreationInputTokens: 캐시에 새로 쓴 입력 세부량TokenUsageDetails.reasoningOutputTokens: 출력에 포함된 추론 세부량null: provider가 값을 보고하지 않음0: provider가 값을 보고했으며 사용량이 0UsageSource: provider reported/derived, local tokenizer, heuristic, unavailable을 구분totalTokens():Math.addExact(inputTokens, outputTokens)로 overflow를 명시적으로 감지metadata: null이면 빈 Map, 그 외에는 방어적 복사완료된 구현
DefaultCostCalculator가 총량을 배타적 과금 구간으로 나누어 중복 과금 방지대표 검증 예
비용은 다섯 구간에 각 단가를 적용하지만 token total은 언제나
input + output이다.후속 작업
Source