fix(xai): keep the batch id as the batch output filename

Managed xAI batch output files keep the filename main already returns
(the batch id) instead of renaming them to <batch id>_results.jsonl.
This commit is contained in:
Yucheng He 2026-10-12 14:40:41 -07:00
parent e698297818
commit 9c85e8d1ff
4 changed files with 27 additions and 27 deletions

View file

@ -96,7 +96,7 @@ def xai_batch_results_file_object(batch: LiteLLMBatch) -> OpenAIFileObject:
id=batch.output_file_id,
object="file",
purpose="batch_output",
filename=f"{batch.output_file_id}_results.jsonl",
filename=batch.output_file_id,
bytes=0,
created_at=int(time.time()),
status="processed",

View file

@ -186,7 +186,7 @@ def test_xai_batch_output_file_is_sized_by_the_batch_job_and_never_downloaded_or
assert (first_detail["id"], first_detail["purpose"], first_detail["filename"]) == (
output_id,
"batch_output",
f"{raw_batch_id}_results.jsonl",
raw_batch_id,
), first_detail
content: Final = gateway.request("GET", f"/v1/files/{output_id}/content", key=batch.owner_key)
@ -206,7 +206,7 @@ def test_xai_batch_output_file_is_sized_by_the_batch_job_and_never_downloaded_or
lambda detail: detail.get("bytes") == len(content.content),
seconds=60,
)
assert (sized["filename"], "litellm_details_fallback" in sized) == (f"{raw_batch_id}_results.jsonl", False)
assert (sized["filename"], "litellm_details_fallback" in sized) == (raw_batch_id, False)
settled_reads: Final = _stable_results_reads(gateway, batch, raw_batch_id)
reads: Final = (
@ -217,7 +217,7 @@ def test_xai_batch_output_file_is_sized_by_the_batch_job_and_never_downloaded_or
assert all(response.status_code == 200 for response in reads), [response.text for response in reads]
listed_output: Final = next(value for value in reads[-1].json()["data"] if value.get("id") == output_id)
assert (listed_output["filename"], listed_output["bytes"]) == (
f"{raw_batch_id}_results.jsonl",
raw_batch_id,
len(content.content),
), listed_output
assert _results_reads(gateway, batch, raw_batch_id) == settled_reads
@ -244,7 +244,7 @@ def test_xai_batch_output_file_answers_at_once_while_results_are_unavailable_and
assert unavailable.status_code == 200, unavailable.text
unavailable_detail: Final = JSON_OBJECT.validate_json(unavailable.content)
assert (unavailable_detail["filename"], unavailable_detail["bytes"]) == (
f"{raw_batch_id}_results.jsonl",
raw_batch_id,
0,
), unavailable_detail
assert elapsed < 5, elapsed
@ -259,7 +259,7 @@ def test_xai_batch_output_file_answers_at_once_while_results_are_unavailable_and
lambda detail: detail.get("bytes") == len(content.content),
seconds=60,
)
assert (recovered["purpose"], recovered["filename"]) == ("batch_output", f"{raw_batch_id}_results.jsonl")
assert (recovered["purpose"], recovered["filename"]) == ("batch_output", raw_batch_id)
file_lookups: Final = tuple(
path for path in _upstream_paths(gateway, batch.upstream.scenario_id) if "/v1/files/batch_" in path
@ -276,11 +276,11 @@ def test_xai_batch_output_file_registered_by_the_batch_job_first_carries_the_dow
lambda: gateway.request("GET", "/v1/files", key=batch.owner_key, params={"purpose": "batch_output"}).json()[
"data"
],
lambda values: any(value.get("filename") == f"{raw_batch_id}_results.jsonl" for value in values),
lambda values: any(value.get("filename") == raw_batch_id for value in values),
seconds=60,
)
listed_output: Final = next(
value for value in listed if value.get("filename") == f"{raw_batch_id}_results.jsonl"
value for value in listed if value.get("filename") == raw_batch_id
)
content: Final = gateway.request("GET", f"/v1/files/{listed_output['id']}/content", key=batch.owner_key)
assert content.status_code == 200, content.text
@ -321,7 +321,7 @@ def test_xai_batch_output_file_left_as_a_placeholder_keeps_its_registration_time
lambda detail: detail.get("created_at") == REGISTERED_AT,
seconds=30,
)
assert refreshed["filename"] == f"{raw_batch_id}_results.jsonl", refreshed
assert refreshed["filename"] == raw_batch_id, refreshed
stored: Final = object_value(
read_rows('SELECT file_object FROM "LiteLLM_ManagedFileTable" WHERE unified_file_id=%s', (output_id,))[0][
"file_object"
@ -329,6 +329,6 @@ def test_xai_batch_output_file_left_as_a_placeholder_keeps_its_registration_time
)
assert (stored["created_at"], stored["filename"], stored.get("litellm_details_fallback")) == (
REGISTERED_AT,
f"{raw_batch_id}_results.jsonl",
raw_batch_id,
None,
), stored

View file

@ -2517,7 +2517,7 @@ async def test_store_batch_output_file_fills_only_an_unknown_size_on_an_unmarked
@pytest.mark.usefixtures("_respx_sees_provider_calls")
@pytest.mark.parametrize(
("provider", "expected_filename", "expected_bytes"),
[("xai", f"{_XAI_BATCH_ID}_results.jsonl", 2565), ("openai", "output.jsonl", 836)],
[("xai", _XAI_BATCH_ID, 2565), ("openai", "output.jsonl", 836)],
)
@pytest.mark.parametrize("has_marked_row", [False, True])
@respx.mock
@ -2568,7 +2568,7 @@ async def test_store_batch_output_file_keeps_its_measured_size_when_a_read_refre
managed_file_table.rows["unified-output"] = placeholder.model_copy(
update={
"file_object": placeholder.file_object.model_copy(
update={"filename": f"{_XAI_BATCH_ID}_results.jsonl", "litellm_details_fallback": None}
update={"filename": _XAI_BATCH_ID, "litellm_details_fallback": None}
)
}
)
@ -2588,7 +2588,7 @@ async def test_store_batch_output_file_keeps_its_measured_size_when_a_read_refre
stored: Final = managed_file_table.rows["unified-output"].file_object
assert stored is not None
assert (stored.filename, stored.bytes, stored.litellm_details_fallback) == (
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
2565,
None,
)
@ -2613,7 +2613,7 @@ async def test_store_batch_output_file_from_a_batch_read_leaves_a_newer_row_alon
update={
"file_object": placeholder.file_object.model_copy(
update={
"filename": f"{_XAI_BATCH_ID}_results.jsonl",
"filename": _XAI_BATCH_ID,
"bytes": 2565,
"litellm_details_fallback": None,
}
@ -2635,7 +2635,7 @@ async def test_store_batch_output_file_from_a_batch_read_leaves_a_newer_row_alon
stored: Final = managed_file_table.rows["unified-output"].file_object
assert stored is not None
assert (stored.filename, stored.bytes) == (f"{_XAI_BATCH_ID}_results.jsonl", 2565)
assert (stored.filename, stored.bytes) == (_XAI_BATCH_ID, 2565)
assert len(managed_file_table.update_many_calls) == 1
assert len(managed_file_table.find_first_calls) - reads_before_store == 1
@ -2669,7 +2669,7 @@ async def test_store_batch_output_file_sizes_the_refreshed_details_instead_of_re
placeholder_row.model_copy(update={"file_object": recent_placeholder}),
recent_placeholder.model_copy(
update={
"filename": f"{_XAI_BATCH_ID}_results.jsonl",
"filename": _XAI_BATCH_ID,
"bytes": refreshed_bytes,
"litellm_details_fallback": None,
}
@ -2691,7 +2691,7 @@ async def test_store_batch_output_file_sizes_the_refreshed_details_instead_of_re
stored: Final = table.rows["unified-output"].file_object
assert stored is not None
assert (stored.filename, stored.bytes, stored.litellm_details_fallback) == (
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
expected_bytes,
None,
)
@ -2731,7 +2731,7 @@ async def test_store_batch_output_file_rereads_a_lost_row_from_the_writer_not_a_
placeholder_row.model_copy(
update={
"file_object": placeholder_row.file_object.model_copy(
update={"filename": f"{_XAI_BATCH_ID}_results.jsonl", "litellm_details_fallback": None}
update={"filename": _XAI_BATCH_ID, "litellm_details_fallback": None}
)
}
)
@ -2753,7 +2753,7 @@ async def test_store_batch_output_file_rereads_a_lost_row_from_the_writer_not_a_
stored: Final = writer.rows["unified-output"].file_object
assert stored is not None
assert (stored.filename, stored.bytes) == (f"{_XAI_BATCH_ID}_results.jsonl", 2565)
assert (stored.filename, stored.bytes) == (_XAI_BATCH_ID, 2565)
@pytest.mark.asyncio
@ -2777,7 +2777,7 @@ async def test_afile_retrieve_refresh_keeps_the_registration_time_of_an_xai_plac
assert (response.created_at, stored.created_at, stored.filename) == (
123,
123,
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
)
@ -2804,7 +2804,7 @@ async def test_store_batch_output_file_keeps_the_registration_time_of_an_xai_pla
stored: Final = managed_file_table.rows["unified-output"].file_object
assert stored is not None
assert (stored.created_at, stored.bytes, stored.filename) == (123, 2565, f"{_XAI_BATCH_ID}_results.jsonl")
assert (stored.created_at, stored.bytes, stored.filename) == (123, 2565, _XAI_BATCH_ID)
@pytest.mark.asyncio
@ -2826,11 +2826,11 @@ async def test_afile_retrieve_refresh_keeps_the_known_size_when_the_provider_rep
assert stored is not None
assert (response.id, response.filename, response.bytes) == (
"unified-output",
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
2565,
)
assert (stored.filename, stored.bytes, stored.litellm_details_fallback) == (
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
2565,
None,
)
@ -2860,7 +2860,7 @@ async def test_afile_retrieve_refresh_keeps_a_size_the_batch_job_writes_while_it
raced_row: Final = managed_file_table.rows["unified-output"].file_object
assert raced_row is not None
assert (raced_response.filename, raced_row.bytes, raced_row.filename) == (
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
2565,
_XAI_BATCH_ID,
)
@ -2875,7 +2875,7 @@ async def test_afile_retrieve_refresh_keeps_a_size_the_batch_job_writes_while_it
assert (next_response.bytes, stored.bytes, stored.filename, stored.litellm_details_fallback) == (
2565,
2565,
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
None,
)
assert len(managed_file_table.update_many_calls) == 2
@ -2907,7 +2907,7 @@ async def test_afile_retrieve_refresh_that_loses_its_write_still_answers_with_th
assert (response.bytes, response.created_at, response.filename) == (
2565,
123,
f"{_XAI_BATCH_ID}_results.jsonl",
_XAI_BATCH_ID,
)
assert managed_file_table.rows["unified-output"].file_object == newer_file_object

View file

@ -298,7 +298,7 @@ async def test_file_retrieve_of_a_batch_id_describes_its_results_from_one_batch_
assert (file_object.id, file_object.purpose, file_object.filename, file_object.bytes, file_object.status) == (
batch_id,
"batch_output",
f"{batch_id}_results.jsonl",
batch_id,
0,
"processed",
)