mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-05 07:37:50 +00:00
Merge c0753dcdb4 into 0f49db5c3b
This commit is contained in:
commit
b68f6199e4
3 changed files with 81 additions and 3 deletions
|
|
@ -15,6 +15,7 @@ from packaging.version import Version
|
|||
import litellm
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.constants import MAX_LANGFUSE_INITIALIZED_CLIENTS
|
||||
from litellm.cost_calculator import get_usage_object
|
||||
from litellm.integrations.langfuse.langfuse_mock_client import (
|
||||
create_mock_langfuse_client,
|
||||
should_use_langfuse_mock,
|
||||
|
|
@ -32,6 +33,7 @@ from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info
|
|||
from litellm.llms.custom_httpx.http_handler import get_httpx_client
|
||||
from litellm.responses.utils import ResponseAPILoggingUtils
|
||||
from litellm.secret_managers.main import str_to_bool
|
||||
from litellm.types.decisions import DecisionsResponse, OpenAIDecisionResponse
|
||||
from litellm.types.integrations.langfuse import *
|
||||
from litellm.types.llms.openai import HttpxBinaryResponseContent, ResponseAPIUsage, ResponsesAPIResponse
|
||||
from litellm.types.utils import (
|
||||
|
|
@ -584,7 +586,9 @@ class LangFuseLogger:
|
|||
| TranscriptionResponse
|
||||
| RerankResponse
|
||||
| HttpxBinaryResponseContent
|
||||
| ResponsesAPIResponse,
|
||||
| ResponsesAPIResponse
|
||||
| DecisionsResponse
|
||||
| OpenAIDecisionResponse,
|
||||
prompt: dict,
|
||||
level: str,
|
||||
status_message: str | None,
|
||||
|
|
@ -634,6 +638,11 @@ class LangFuseLogger:
|
|||
elif response_obj is not None and isinstance(response_obj, litellm.ResponsesAPIResponse):
|
||||
input = prompt
|
||||
output = self._get_responses_api_content_for_langfuse(response_obj)
|
||||
elif isinstance(response_obj, (DecisionsResponse, OpenAIDecisionResponse)):
|
||||
return ( # pyright: ignore[reportUnknownVariableType] # prompt is the caller's untyped dict, as in every branch
|
||||
prompt,
|
||||
response_obj.model_dump(mode="json", include={"answers"}),
|
||||
)
|
||||
elif (
|
||||
kwargs.get("call_type") is not None
|
||||
and kwargs.get("call_type") == "_arealtime"
|
||||
|
|
@ -859,10 +868,14 @@ class LangFuseLogger:
|
|||
usage = None
|
||||
usage_details = None
|
||||
if response_obj is not None:
|
||||
if hasattr(response_obj, "id") and response_obj.get("id", None) is not None:
|
||||
if isinstance(response_obj, _ResponseWithId) and getattr(response_obj, "id", None) is not None:
|
||||
generation_id = _logging_id(start_time, response_obj)
|
||||
_raw_usage_obj: Final[_UsageObject | None] = getattr(response_obj, "usage", None)
|
||||
_usage_obj: Final = _chat_usage(_raw_usage_obj)
|
||||
_usage_obj: Final = (
|
||||
get_usage_object(response_obj)
|
||||
if isinstance(response_obj, (DecisionsResponse, OpenAIDecisionResponse))
|
||||
else _chat_usage(_raw_usage_obj)
|
||||
)
|
||||
|
||||
if _usage_obj:
|
||||
# Safely get usage values, defaulting None to 0 for Langfuse compatibility.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "litellm-asystemone",
|
||||
"parent_span_id": null,
|
||||
"attributes": {
|
||||
"langfuse.observation.cost_details": {
|
||||
"total": 1.1886e-05
|
||||
},
|
||||
"langfuse.observation.input": {
|
||||
"messages": [
|
||||
{
|
||||
"content": "{\"state\": \"Customer writes: my payout has failed three days in a row.\", \"questions\": {\"urgent\": {\"type\": \"noul\", \"instructions\": \"Is this urgent?\"}}}",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
},
|
||||
"langfuse.observation.level": "DEFAULT",
|
||||
"langfuse.observation.metadata.api_base": "https://openrouter.ai/api/alpha/decisions",
|
||||
"langfuse.observation.model.name": "typesafe/jev-1.13",
|
||||
"langfuse.observation.model.parameters": {},
|
||||
"langfuse.observation.output": {
|
||||
"answers": {
|
||||
"urgent": {
|
||||
"noul": 0.87,
|
||||
"type": "noul"
|
||||
}
|
||||
}
|
||||
},
|
||||
"langfuse.observation.type": "generation",
|
||||
"langfuse.observation.usage_details": {
|
||||
"cache_creation_input_tokens": 0,
|
||||
"cache_read_input_tokens": 0,
|
||||
"input": 283,
|
||||
"output": 20,
|
||||
"total": 303
|
||||
},
|
||||
"langfuse.trace.name": "litellm-asystemone"
|
||||
}
|
||||
}
|
||||
|
|
@ -433,6 +433,33 @@ async def test_langfuse_logging_vllm_embedding(
|
|||
assert route.call_count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("response_id", [None, "decision-1"])
|
||||
async def test_langfuse_logging_systemone(
|
||||
langfuse_export: tuple[respx.Route, str], respx_mock: respx.MockRouter, response_id: str | None
|
||||
) -> None:
|
||||
route, trace_id = langfuse_export
|
||||
answers: Final = {"urgent": {"type": "noul", "noul": 0.87}}
|
||||
upstream: Final = respx_mock.post("https://openrouter.ai/api/alpha/decisions").respond(
|
||||
json={
|
||||
**({"id": response_id} if response_id is not None else {}),
|
||||
"model": "typesafe/jev-1.13",
|
||||
"answers": answers,
|
||||
"usage": {"input_tokens": 283, "output_tokens": 20, "cost": 1.1886e-05},
|
||||
}
|
||||
)
|
||||
await litellm.asystemone(
|
||||
model="openrouter/typesafe/jev-1.13",
|
||||
state="Customer writes: my payout has failed three days in a row.",
|
||||
questions={"urgent": {"type": "noul", "instructions": "Is this urgent?"}},
|
||||
api_key="caller-key",
|
||||
metadata={"trace_id": trace_id},
|
||||
)
|
||||
await _flush_langfuse()
|
||||
assert upstream.call_count == 1
|
||||
_expected_generation(route, "systemone.json", trace_id)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_langfuse_logging_with_router(langfuse_export: tuple[respx.Route, str]) -> None:
|
||||
route, trace_id = langfuse_export
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue