mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-06 08:16:43 +00:00
Merge pull request #18046 from BerriAI/litellm_fix_managed_files_endpoint
Fix managed files endpoint
This commit is contained in:
commit
20bdada900
4 changed files with 92 additions and 2 deletions
|
|
@ -750,9 +750,27 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
|
|||
model_id=model_id,
|
||||
model_name=model_name,
|
||||
)
|
||||
await self.store_unified_file_id( # need to store otherwise any retrieve call will fail
|
||||
|
||||
# Fetch the actual file object for the output file
|
||||
file_object = None
|
||||
try:
|
||||
# Use litellm to retrieve the file object from the provider
|
||||
from litellm import afile_retrieve
|
||||
file_object = await afile_retrieve(
|
||||
custom_llm_provider=model_name.split("/")[0] if model_name and "/" in model_name else "openai",
|
||||
file_id=original_output_file_id
|
||||
)
|
||||
verbose_logger.debug(
|
||||
f"Successfully retrieved file object for output_file_id={original_output_file_id}"
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.warning(
|
||||
f"Failed to retrieve file object for output_file_id={original_output_file_id}: {str(e)}. Storing with None and will fetch on-demand."
|
||||
)
|
||||
|
||||
await self.store_unified_file_id(
|
||||
file_id=response.output_file_id,
|
||||
file_object=None,
|
||||
file_object=file_object,
|
||||
litellm_parent_otel_span=user_api_key_dict.parent_otel_span,
|
||||
model_mappings={model_id: original_output_file_id},
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ class AmazonAnthropicClaudeMessagesConfig(
|
|||
|
||||
if beta_set:
|
||||
anthropic_messages_request["anthropic_beta"] = list(beta_set)
|
||||
|
||||
|
||||
return anthropic_messages_request
|
||||
|
||||
|
|
|
|||
|
|
@ -573,6 +573,7 @@ async def list_batches(
|
|||
if target_model_names is None:
|
||||
raise ValueError("target_model_names is required for this routing scenario")
|
||||
model = target_model_names.split(",")[0]
|
||||
data.pop("model", None)
|
||||
response = await llm_router.alist_batches(
|
||||
model=model,
|
||||
after=after,
|
||||
|
|
|
|||
|
|
@ -577,3 +577,73 @@ async def test_vertex_list_batches(monkeypatch):
|
|||
assert len(list_response["data"]) == 2
|
||||
assert list_response["data"][0].id == "test-batch-id-456"
|
||||
assert list_response["data"][1].id == "test-batch-id-789"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_batch_output_file():
|
||||
"""
|
||||
Test that deleting a batch output file works correctly.
|
||||
|
||||
This test verifies the fix for:
|
||||
- When a batch is retrieved and has an output_file_id, the file object is properly stored
|
||||
- The output file can be deleted without validation errors
|
||||
- The file_object is fetched and stored with proper metadata instead of None
|
||||
"""
|
||||
litellm._turn_on_debug()
|
||||
print("Testing delete batch output file")
|
||||
|
||||
file_name = "openai_batch_completions.jsonl"
|
||||
_current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(_current_dir, file_name)
|
||||
|
||||
# Create file for batch
|
||||
file_obj = await litellm.acreate_file(
|
||||
file=open(file_path, "rb"),
|
||||
purpose="batch",
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
print("Response from creating file=", file_obj)
|
||||
batch_input_file_id = file_obj.id
|
||||
|
||||
# Create batch
|
||||
create_batch_response = await litellm.acreate_batch(
|
||||
completion_window="24h",
|
||||
endpoint="/v1/chat/completions",
|
||||
input_file_id=batch_input_file_id,
|
||||
custom_llm_provider="openai",
|
||||
)
|
||||
print("Batch created with ID=", create_batch_response.id)
|
||||
|
||||
# Retrieve batch to get output_file_id
|
||||
retrieved_batch = await litellm.aretrieve_batch(
|
||||
batch_id=create_batch_response.id,
|
||||
custom_llm_provider="openai"
|
||||
)
|
||||
print("Retrieved batch=", retrieved_batch)
|
||||
|
||||
# If batch has completed and has output file, test deleting it
|
||||
if retrieved_batch.output_file_id:
|
||||
print(f"Testing deletion of output file: {retrieved_batch.output_file_id}")
|
||||
|
||||
# This is the key test - deleting the output file should work
|
||||
# without validation errors (file_object should not be None)
|
||||
delete_output_file_response = await litellm.afile_delete(
|
||||
file_id=retrieved_batch.output_file_id,
|
||||
custom_llm_provider="openai"
|
||||
)
|
||||
|
||||
print("Delete output file response=", delete_output_file_response)
|
||||
assert delete_output_file_response.id == retrieved_batch.output_file_id
|
||||
assert delete_output_file_response.deleted is True or hasattr(delete_output_file_response, 'id')
|
||||
print("✓ Successfully deleted batch output file")
|
||||
else:
|
||||
print("⚠ Batch has not completed yet or no output file available, skipping output file deletion test")
|
||||
|
||||
# Clean up - delete the input file
|
||||
delete_input_file_response = await litellm.afile_delete(
|
||||
file_id=batch_input_file_id,
|
||||
custom_llm_provider="openai"
|
||||
)
|
||||
print("Delete input file response=", delete_input_file_response)
|
||||
assert delete_input_file_response.id == batch_input_file_id
|
||||
print("✓ Successfully deleted batch input file")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue