feat: add anthropic cached token values for local backends that support it
This commit is contained in:
parent
1d012a92ef
commit
04bc69993d
3 changed files with 93 additions and 16 deletions
|
|
@ -257,15 +257,46 @@ def finish_reason_to_stop_reason(finish_reason, has_tool_use=False):
|
|||
return _STOP_REASON_MAP.get(finish_reason, "end_turn")
|
||||
|
||||
|
||||
def _cached_prompt_tokens(usage):
|
||||
"""Read ``prompt_tokens_details.cached_tokens`` from a chat usage (dict or SDK obj).
|
||||
|
||||
OpenAI-compatible backends with automatic prefix caching (vLLM, recent
|
||||
llama-server) report the reused-prefix token count here; backends that don't
|
||||
populate it yield 0.
|
||||
"""
|
||||
if not usage:
|
||||
return 0
|
||||
details = usage.get("prompt_tokens_details") if isinstance(usage, dict) \
|
||||
else getattr(usage, "prompt_tokens_details", None)
|
||||
if details is None:
|
||||
return 0
|
||||
if isinstance(details, dict):
|
||||
return details.get("cached_tokens") or 0
|
||||
return getattr(details, "cached_tokens", 0) or 0
|
||||
|
||||
|
||||
def usage_chat_to_anthropic(usage, cache_read_tokens=0, cache_creation_tokens=0):
|
||||
"""Map chat usage → Anthropic usage, folding in nomyo-cache attribution."""
|
||||
prompt = (usage or {}).get("prompt_tokens") or 0
|
||||
completion = (usage or {}).get("completion_tokens") or 0
|
||||
"""Map chat usage → Anthropic usage.
|
||||
|
||||
``cached_tokens`` reported by the backend (automatic prefix-cache reuse) plus any
|
||||
explicit ``cache_read_tokens`` become ``cache_read_input_tokens``; ``input_tokens``
|
||||
is the remaining uncached prompt so ``input + cache_read`` equals the prompt total.
|
||||
|
||||
``cache_creation_input_tokens`` stays at ``cache_creation_tokens`` (0 by default):
|
||||
local backends do automatic KV-prefix reuse with no explicit ``cache_control``
|
||||
write/breakpoint concept, so there is no honest "tokens written" figure to report —
|
||||
that value is only real on the native Anthropic passthrough path.
|
||||
"""
|
||||
prompt = (usage or {}).get("prompt_tokens") or 0 if isinstance(usage, dict) \
|
||||
else (getattr(usage, "prompt_tokens", 0) or 0)
|
||||
completion = (usage or {}).get("completion_tokens") or 0 if isinstance(usage, dict) \
|
||||
else (getattr(usage, "completion_tokens", 0) or 0)
|
||||
cache_read = _cached_prompt_tokens(usage) + cache_read_tokens
|
||||
return {
|
||||
"input_tokens": prompt,
|
||||
"input_tokens": max(prompt - cache_read, 0),
|
||||
"output_tokens": completion,
|
||||
"cache_creation_input_tokens": cache_creation_tokens,
|
||||
"cache_read_input_tokens": cache_read_tokens,
|
||||
"cache_read_input_tokens": cache_read,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -430,6 +461,7 @@ class ChatToMessagesStream:
|
|||
self.usage = {
|
||||
"prompt_tokens": getattr(usage, "prompt_tokens", 0) or 0,
|
||||
"completion_tokens": getattr(usage, "completion_tokens", 0) or 0,
|
||||
"prompt_tokens_details": {"cached_tokens": _cached_prompt_tokens(usage)},
|
||||
}
|
||||
choices = getattr(chunk, "choices", None)
|
||||
if not choices:
|
||||
|
|
@ -512,8 +544,15 @@ class ChatToMessagesStream:
|
|||
"type": "tool_use", "id": state["id"], "name": state["name"], "input": parsed})
|
||||
|
||||
self.stop_reason = finish_reason_to_stop_reason(finish_reason, has_tool_use=bool(tc_state))
|
||||
out_tokens = (self.usage or {}).get("completion_tokens", 0)
|
||||
final_usage = usage_chat_to_anthropic(
|
||||
self.usage, cache_read_tokens=self.cache_read_tokens,
|
||||
cache_creation_tokens=self.cache_creation_tokens)
|
||||
yield _sse("message_delta", {
|
||||
"delta": {"stop_reason": self.stop_reason, "stop_sequence": None},
|
||||
"usage": {"output_tokens": out_tokens}})
|
||||
"usage": {
|
||||
"input_tokens": final_usage["input_tokens"],
|
||||
"output_tokens": final_usage["output_tokens"],
|
||||
"cache_read_input_tokens": final_usage["cache_read_input_tokens"],
|
||||
"cache_creation_input_tokens": final_usage["cache_creation_input_tokens"],
|
||||
}})
|
||||
yield _sse("message_stop", {})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue