Skip to content

Commit

Permalink
fix(utils.py): prevent double logging when passing 'fallbacks=' to .c…
Browse files Browse the repository at this point in the history
…ompletion()

Fixes #7477
  • Loading branch information
krrishdholakia committed Jan 2, 2025
1 parent 38bfefa commit 94fa390
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 10 deletions.
41 changes: 31 additions & 10 deletions litellm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,29 @@ def function_setup( # noqa: PLR0915
raise e


async def _client_async_logging_helper(
logging_obj: LiteLLMLoggingObject,
result,
start_time,
end_time,
is_completion_with_fallbacks: bool,
):
if (
is_completion_with_fallbacks is False
): # don't log the parent event litellm.completion_with_fallbacks as a 'log_success_event', this will lead to double logging the same call - https://github.com/BerriAI/litellm/issues/7477
print_verbose(
f"Async Wrapper: Completed Call, calling async_success_handler: {logging_obj.async_success_handler}"
)
# check if user does not want this to be logged
asyncio.create_task(
logging_obj.async_success_handler(result, start_time, end_time)
)
threading.Thread(
target=logging_obj.success_handler,
args=(result, start_time, end_time),
).start()


def client(original_function): # noqa: PLR0915
rules_obj = Rules()

Expand Down Expand Up @@ -1013,6 +1036,7 @@ async def wrapper_async(*args, **kwargs): # noqa: PLR0915
kwargs["litellm_call_id"] = str(uuid.uuid4())

model: Optional[str] = args[0] if len(args) > 0 else kwargs.get("model", None)
is_completion_with_fallbacks = kwargs.get("fallbacks") is not None

try:
if logging_obj is None:
Expand Down Expand Up @@ -1115,18 +1139,15 @@ async def wrapper_async(*args, **kwargs): # noqa: PLR0915
)

# LOG SUCCESS - handle streaming success logging in the _next_ object
print_verbose(
f"Async Wrapper: Completed Call, calling async_success_handler: {logging_obj.async_success_handler}"
)
# check if user does not want this to be logged
asyncio.create_task(
logging_obj.async_success_handler(result, start_time, end_time)
_client_async_logging_helper(
logging_obj=logging_obj,
result=result,
start_time=start_time,
end_time=end_time,
is_completion_with_fallbacks=is_completion_with_fallbacks,
)
)
threading.Thread(
target=logging_obj.success_handler,
args=(result, start_time, end_time),
).start()

# REBUILD EMBEDDING CACHING
if (
isinstance(result, EmbeddingResponse)
Expand Down
24 changes: 24 additions & 0 deletions tests/local_testing/test_acompletion.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,27 @@ def test_acompletion_params():


# test_acompletion_params()


@pytest.mark.asyncio
async def test_langfuse_double_logging():
import litellm

litellm.set_verbose = True
litellm.success_callback = ["langfuse"]
litellm.failure_callback = ["langfuse"] # logs errors to langfuse

models = ["gpt-4o-mini", "claude-3-5-haiku-20241022"]

messages = [
{"role": "user", "content": "Hello, how are you?"},
]

resp = await litellm.acompletion(
model=models[0],
messages=messages,
temperature=0.0,
fallbacks=models[1:],
# metadata={"generation_name": "test-gen", "project": "litellm-test"},
)
return resp

0 comments on commit 94fa390

Please sign in to comment.