Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3339469
feat(decisions): serve System One format at /v1/systemone and OpenAI …
mateo-berri Oct 7, 2026
29e7154
fix(decisions): import assert_never from typing_extensions for Python…
mateo-berri Oct 7, 2026
7ef1329
fix(decisions): cap OpenAI-format questions at the System One limit
mateo-berri Oct 7, 2026
b6bb885
fix(decisions): return 400 for bodies that are not JSON
mateo-berri Oct 7, 2026
77872f6
test(decisions): send System One bodies to /v1/systemone in integrati…
mateo-berri Oct 7, 2026
b94bbbc
feat(decisions): add OpenAI as a Decisions provider
mateo-berri Oct 8, 2026
d209a85
refactor(decisions): move the OpenAI wire translation into llms/openai
mateo-berri Oct 8, 2026
0dd207f
feat(decisions): route both request formats through a shared decision…
mateo-berri Oct 8, 2026
1348de8
fix(decisions): keep provider fields inside System One answers
mateo-berri Oct 8, 2026
81d8bac
Merge remote-tracking branch 'origin/main' into litellm_systemone_end…
mateo-berri Oct 8, 2026
85f9121
Merge branch 'litellm_systemone_endpoint' into litellm_openai_decisio…
mateo-berri Oct 8, 2026
39012f1
fix(decisions): load on Python 3.10 and 3.11 and bill cached tokens o…
mateo-berri Oct 8, 2026
e465919
fix(decisions): honor litellm OpenAI key and base settings for the op…
mateo-berri Oct 8, 2026
a2951b3
test(decisions): clear every OpenAI base setting in the proxy OpenAI …
mateo-berri Oct 8, 2026
e4081f7
fix(decisions): send OpenAI instructions for System One questions wit…
mateo-berri Oct 8, 2026
2be582a
Merge remote-tracking branch 'origin/main' into litellm_systemone_end…
mateo-berri Oct 8, 2026
48f1a9c
Merge branch 'litellm_systemone_endpoint' into litellm_openai_decisio…
mateo-berri Oct 8, 2026
855f0bb
fix(decisions): return guardrail_information on OpenAI-format decisio…
mateo-berri Oct 8, 2026
f360214
refactor(decisions): validate proxy request data before reading guard…
mateo-berri Oct 8, 2026
c19ada6
Merge remote-tracking branch 'origin/litellm_systemone_endpoint' into…
mateo-berri Oct 8, 2026
7ac5bde
Merge remote-tracking branch 'origin/main' into litellm_openai_decisi…
mateo-berri Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gateway/routes/allowlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
"/rerank",
"/v1/decisions",
"/decisions",
"/v1/systemone",
"/systemone",
"/v1/ocr",
"/ocr",
"/v1/rag/",
Expand Down
3 changes: 3 additions & 0 deletions litellm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,9 @@ def set_global_gitlab_config(config: Mapping[str, object]) -> None:
from .llms.strands_decider.decisions.transformation import (
StrandsDeciderDecisionsConfig as StrandsDeciderDecisionsConfig,
)
from .llms.openai.decisions.transformation import (
OpenAIDecisionsConfig as OpenAIDecisionsConfig,
)
from .llms.nvidia_nim.rerank.transformation import (
NvidiaNimRerankConfig as NvidiaNimRerankConfig,
)
Expand Down
2 changes: 2 additions & 0 deletions litellm/_lazy_imports_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"OpenRouterDecisionsConfig",
"CloudflareDecisionsConfig",
"StrandsDeciderDecisionsConfig",
"OpenAIDecisionsConfig",
"NvidiaNimRerankConfig",
"NvidiaNimRankingConfig",
"VertexAIRerankConfig",
Expand Down Expand Up @@ -720,6 +721,7 @@
".llms.strands_decider.decisions.transformation",
"StrandsDeciderDecisionsConfig",
),
"OpenAIDecisionsConfig": (".llms.openai.decisions.transformation", "OpenAIDecisionsConfig"),
"NvidiaNimRerankConfig": (
".llms.nvidia_nim.rerank.transformation",
"NvidiaNimRerankConfig",
Expand Down
41 changes: 33 additions & 8 deletions litellm/cost_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from httpx import Response
from pydantic import BaseModel
from typing_extensions import ReadOnly, TypedDict
from typing_extensions import ReadOnly, TypedDict, assert_never

import litellm
import litellm._logging
Expand Down Expand Up @@ -100,7 +100,7 @@
from litellm.llms.xai.cost_calculator import cost_per_token as xai_cost_per_token
from litellm.responses.utils import ResponseAPILoggingUtils
from litellm.types.agents import LiteLLMSendMessageResponse
from litellm.types.decisions import DecisionsResponse, DecisionsUsage
from litellm.types.decisions import DecisionsResponse, DecisionsUsage, OpenAIDecisionResponse, OpenAIDecisionUsage
from litellm.types.llms.base import CachedTokensDetails, LiteLLMBaseModel
from litellm.types.llms.openai import (
HttpxBinaryResponseContent,
Expand Down Expand Up @@ -1034,6 +1034,8 @@
),
)

if isinstance(completion_response, (DecisionsResponse, OpenAIDecisionResponse)):
return None if completion_response.usage is None else _decisions_usage(completion_response.usage)
if usage_obj is None:
return None
if isinstance(usage_obj, Usage):
Expand Down Expand Up @@ -1064,12 +1066,37 @@
return None


def _decisions_prompt_tokens_details(usage: DecisionsUsage | OpenAIDecisionUsage) -> PromptTokensDetailsWrapper:
match usage:
case DecisionsUsage():
return PromptTokensDetailsWrapper(
cached_tokens=usage.cached_tokens, cache_write_tokens=usage.cache_write_tokens
)
case OpenAIDecisionUsage():
return PromptTokensDetailsWrapper(
cached_tokens=usage.input_tokens_details.cached_tokens,
cache_write_tokens=usage.input_tokens_details.cache_write_tokens,
)
case _:
assert_never(usage)


def _decisions_usage(usage: DecisionsUsage | OpenAIDecisionUsage) -> Usage:
return Usage(
prompt_tokens=usage.input_tokens,
completion_tokens=usage.output_tokens,
total_tokens=usage.input_tokens + usage.output_tokens,
prompt_tokens_details=_decisions_prompt_tokens_details(usage),
)


def _is_known_usage_objects(usage_obj):
"""Returns True if the usage obj is a known Usage type"""
return (
isinstance(usage_obj, litellm.Usage)
or isinstance(usage_obj, ResponseAPIUsage)
or isinstance(usage_obj, DecisionsUsage)
or isinstance(usage_obj, OpenAIDecisionUsage)
or TranscriptionUsageObjectTransformation.is_transcription_usage_object(usage_obj)
)

Expand Down Expand Up @@ -1481,11 +1508,8 @@
"usage",
litellm.Usage(**_usage_for_dump.model_dump()),
)
if isinstance(usage_obj, DecisionsUsage):
_usage = {
"prompt_tokens": usage_obj.input_tokens,
"completion_tokens": usage_obj.output_tokens,
}
if isinstance(usage_obj, (DecisionsUsage, OpenAIDecisionUsage)):
_usage = _decisions_usage(usage_obj).model_dump()
elif usage_obj is None:
_usage = {}
elif isinstance(usage_obj, BaseModel):
Expand Down Expand Up @@ -1977,7 +2001,8 @@
| OpenAIModerationResponse
| Response
| SearchResponse
| DecisionsResponse,
| DecisionsResponse
| OpenAIDecisionResponse,
model: str,
custom_llm_provider: str | None,
call_type: Literal[
Expand Down Expand Up @@ -2612,8 +2637,8 @@

verbose_logger.debug(
"Calculating batch cost per token. model=%s, custom_llm_provider=%s",
model,

Check warning

Code scanning / CodeQL

Log Injection Medium

This log entry depends on a
user-provided value
.
custom_llm_provider,

Check warning

Code scanning / CodeQL

Log Injection Medium

This log entry depends on a
user-provided value
.
)

if model_info is None:
Expand Down
Loading
Loading