Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions sentry_sdk/ai/utils.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import json

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Any
from sentry_sdk.tracing import Span

from sentry_sdk.tracing import Span
from sentry_sdk.utils import logger


def _normalize_data(data, unpack=True):
# type: (Any, bool) -> Any

# convert pydantic data (e.g. OpenAI v1+) to json compatible format
if hasattr(data, "model_dump"):
try:
return data.model_dump()
return _normalize_data(data.model_dump(), unpack=unpack)
except Exception as e:
logger.warning("Could not convert pydantic data to JSON: %s", e)
return data
return data if isinstance(data, (int, float, bool, str)) else str(data)

if isinstance(data, list):
if unpack and len(data) == 1:
return _normalize_data(data[0], unpack=unpack) # remove empty dimensions
return list(_normalize_data(x, unpack=unpack) for x in data)

if isinstance(data, dict):
return {k: _normalize_data(v, unpack=unpack) for (k, v) in data.items()}

return data
return data if isinstance(data, (int, float, bool, str)) else str(data)


def set_data_normalized(span, key, value, unpack=True):
Expand All @@ -33,4 +36,4 @@ def set_data_normalized(span, key, value, unpack=True):
if isinstance(normalized, (int, float, bool, str)):
span.set_data(key, normalized)
else:
span.set_data(key, str(normalized))
span.set_data(key, json.dumps(normalized))
8 changes: 4 additions & 4 deletions tests/integrations/cohere/test_cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ def test_nonstreaming_chat(

if send_default_pii and include_prompts:
assert (
"{'role': 'system', 'content': 'some context'}"
'{"role": "system", "content": "some context"}'
in span["data"][SPANDATA.AI_INPUT_MESSAGES]
)
assert (
"{'role': 'user', 'content': 'hello'}"
'{"role": "user", "content": "hello"}'
in span["data"][SPANDATA.AI_INPUT_MESSAGES]
)
assert "the model response" in span["data"][SPANDATA.AI_RESPONSES]
Expand Down Expand Up @@ -135,11 +135,11 @@ def test_streaming_chat(sentry_init, capture_events, send_default_pii, include_p

if send_default_pii and include_prompts:
assert (
"{'role': 'system', 'content': 'some context'}"
'{"role": "system", "content": "some context"}'
in span["data"][SPANDATA.AI_INPUT_MESSAGES]
)
assert (
"{'role': 'user', 'content': 'hello'}"
'{"role": "user", "content": "hello"}'
in span["data"][SPANDATA.AI_INPUT_MESSAGES]
)
assert "the model response" in span["data"][SPANDATA.AI_RESPONSES]
Expand Down
Loading