fix(proxy): count tool array fields that declare no items in the local estimate
Some checks failed
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
LiteLLM Rust / rust-wheel (push) Has been cancelled

This commit is contained in:
shrey kharbanda 2026-09-27 04:14:47 +00:00
parent e40a7ffb04
commit eefd997d07
No known key found for this signature in database
3 changed files with 39 additions and 2 deletions

View file

@ -1033,8 +1033,7 @@ def _format_type(props, indent):
return " | ".join([f'"{item}"' for item in props["enum"]])
return "string"
elif type == "array":
# items is required, OpenAI throws an error if it's missing
return f"{_format_type(props['items'], indent)}[]"
return f"{_format_type(props.get('items', {}), indent)}[]"
elif type == "object":
return f"{{\n{_format_object_parameters(props, indent + 2)}\n}}"
elif type in ["integer", "number"]:

View file

@ -1565,6 +1565,21 @@ def test_token_counter_uses_the_tokenizer_of_each_model_family_and_of_a_custom_t
}
def test_token_counter_counts_array_parameter_without_items():
messages = [{"role": "user", "content": "tag this"}]
tags_tool = {
"type": "function",
"function": {
"name": "set_tags",
"parameters": {"type": "object", "properties": {"tags": {"type": "array"}}, "required": ["tags"]},
},
}
assert token_counter(model="gpt-4o", messages=messages, tools=[tags_tool]) > token_counter(
model="gpt-4o", messages=messages
)
class _Unprintable:
def __str__(self) -> str:
raise AssertionError("opaque block values must be dropped before they are serialized")
@ -1608,6 +1623,7 @@ def test_uncountable_block_nesting_past_the_depth_limit_is_truncated():
assert "leaf" not in text
def test_uncountable_block_elides_inline_base64_data_but_keeps_plain_text_data():
(message,) = messages_with_uncountable_blocks_as_text(
[

View file

@ -1382,3 +1382,25 @@ async def test_gemini_non_json_success_body_surfaces_as_bad_gateway_when_fallbac
)
assert exc_info.value.code == "502"
@pytest.mark.asyncio
async def test_local_estimate_counts_a_tool_with_an_array_property_without_items(monkeypatch):
monkeypatch.setattr(litellm.proxy.proxy_server, "llm_router", None)
tags_tool = {
"type": "function",
"function": {
"name": "set_tags",
"description": "Set tags",
"parameters": {"type": "object", "properties": {"tags": {"type": "array"}}, "required": ["tags"]},
},
}
async def count(tools: list[dict[str, object]] | None) -> int:
result = await token_counter(
request=TokenCountRequest(model="gpt-4o", messages=[{"role": "user", "content": "tag this"}], tools=tools)
)
return result.total_tokens
assert await count([tags_tool]) > await count(None)