mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-12 03:48:56 +00:00
* test(integration): streamed request bills the same SpendLogs row as the non-streamed request Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): write the stream parity cells as StreamParityTestCase literals Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): express stream parity cells as CostTrackingTestCase pairs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): stream parity asserts exactly one SpendLogs row per leg after a settle window Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): stream parity forces a spend-log flush with a /v1/responses row instead of a settle sleep Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): stream parity covers messages -> chat and messages -> converse bridges Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): stream parity bridges use xai/grok-4.7 and us.anthropic.claude-opus-5-5 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): use latest frontier models in stream parity cells (gpt-5.6, claude-opus-5-5) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): switch OpenAI parity cells to gpt-6.1-sol and the chat -> responses bridge to gpt-5.5-pro Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: kerry <kerry@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
70 lines
3.2 KiB
Python
70 lines
3.2 KiB
Python
from collections import Counter
|
|
from hashlib import sha256
|
|
from typing import Final
|
|
|
|
from integration._support.client import Gateway, Scenario
|
|
from integration.cost_calculation.assertions import assert_exact
|
|
from integration.cost_calculation.conftest import (
|
|
poll_rows,
|
|
poll_rows_where,
|
|
read_rows_now,
|
|
register_scenario_deployment,
|
|
)
|
|
from integration.cost_calculation.cost_tracking_case import ExactExpected
|
|
from integration.cost_calculation.stream_parity.bases import openai_responses
|
|
from integration.cost_calculation.stream_parity.case import StreamParityTestCase
|
|
|
|
FLUSH_CASE: Final = openai_responses.GPT_6_1_SOL_RESPONSES
|
|
|
|
|
|
def flush_spend_logs(scenario: Scenario, gateway: Gateway, key: str) -> str:
|
|
"""A /v1/responses row wakes the spend-log writer at once, and the queue is FIFO, so every row queued before it lands."""
|
|
flush: Final = register_scenario_deployment(scenario, FLUSH_CASE, "flush", key)
|
|
response: Final = gateway.request(
|
|
"POST", FLUSH_CASE.endpoint, {**FLUSH_CASE.request, "model": flush.model_name}, key=key
|
|
)
|
|
assert response.status_code == 200, ("flush", response.text[:400])
|
|
poll_rows_where(key, 1, lambda row: row.model_id == flush.identity)
|
|
return flush.identity
|
|
|
|
|
|
def assert_stream_parity(case: StreamParityTestCase, gateway: Gateway) -> None:
|
|
expected: Final = case.plain.expected
|
|
assert isinstance(expected, ExactExpected), case.id
|
|
with gateway.scenario() as scenario:
|
|
key: Final = scenario.key()
|
|
deployments: Final = {
|
|
leg.name: register_scenario_deployment(scenario, leg, sha256(leg.name.encode()).hexdigest()[:12], key)
|
|
for leg in (case.plain, case.streamed)
|
|
}
|
|
responses: Final = {
|
|
leg.name: gateway.request(
|
|
"POST", leg.endpoint, {**leg.request, "model": deployments[leg.name].model_name}, key=key
|
|
)
|
|
for leg in (case.plain, case.streamed)
|
|
}
|
|
for leg in (case.plain, case.streamed):
|
|
assert responses[leg.name].status_code == 200, (leg.name, responses[leg.name].text[:400])
|
|
|
|
poll_rows(key, 2)
|
|
flush_identity: Final = flush_spend_logs(scenario, gateway, key)
|
|
rows: Final = read_rows_now(key)
|
|
rows_per_deployment: Final = Counter(row.model_id for row in rows)
|
|
expected_rows: Final = {deployments[leg.name].identity: 1 for leg in (case.plain, case.streamed)}
|
|
assert rows_per_deployment == {**expected_rows, flush_identity: 1}, (
|
|
f"{case.id}: expected exactly one SpendLogs row per leg plus the flush row, got {dict(rows_per_deployment)}",
|
|
rows,
|
|
)
|
|
billed: Final = {
|
|
leg.name: next(row for row in rows if row.model_id == deployments[leg.name].identity)
|
|
for leg in (case.plain, case.streamed)
|
|
}
|
|
for leg in (case.plain, case.streamed):
|
|
assert_exact(leg.name, leg.response.content_type, expected, billed[leg.name], responses[leg.name])
|
|
plain: Final = billed[case.plain.name]
|
|
streamed: Final = billed[case.streamed.name]
|
|
assert (streamed.spend, streamed.prompt_tokens, streamed.completion_tokens) == (
|
|
plain.spend,
|
|
plain.prompt_tokens,
|
|
plain.completion_tokens,
|
|
), (plain, streamed)
|