diff --git a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py index 1f2b0f06f5..8e1e4a2366 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py @@ -15,7 +15,6 @@ _get_model_name, _set_agent_data, _set_available_tools, - _set_model_data, ) from .utils import ( _serialize_binary_content_item, @@ -306,7 +305,34 @@ def ai_client_context( if model_name: context.span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - _set_model_data(context.span, agent, model_settings) + # Extract model settings + settings = model_settings + if not settings and agent and hasattr(agent, "model_settings"): + settings = agent.model_settings + + if settings: + settings_map = { + "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, + "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE, + "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P, + "frequency_penalty": SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, + "presence_penalty": SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, + } + + # ModelSettings is a TypedDict (dict at runtime), so use dict access + if isinstance(settings, dict): + for setting_name, spandata_key in settings_map.items(): + value = settings.get(setting_name) + if value is not None: + context.span.set_attribute(spandata_key, value) # type: ignore[arg-type] + else: + # Fallback for object-style settings + for setting_name, spandata_key in settings_map.items(): + if hasattr(settings, setting_name): + value = getattr(settings, setting_name) + if value is not None: + context.span.set_attribute(spandata_key, value) + _set_available_tools(context.span, agent) # Set input messages (full conversation history) diff --git a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py index e1786a7736..4fe07ac352 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py @@ -11,7 +11,6 @@ from ..consts import SPAN_ORIGIN from ..utils import ( _set_agent_data, - _set_model_data, ) from .utils import ( _serialize_binary_content_item, @@ -53,7 +52,6 @@ def invoke_agent_span( ) _set_agent_data(span, agent) - _set_model_data(span, agent, model_settings) # Add user prompt and system prompts if available and prompts are enabled if not sentry_sdk.get_client().options["data_collection"]["gen_ai"]["inputs"]: diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index fc27d72903..af3d449029 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -13,8 +13,6 @@ from pydantic_ai import Agent from pydantic_ai.models import AbstractModel, Model - from pydantic_ai.realtime.settings import RealtimeModelSettings - from pydantic_ai.settings import ModelSettings def _set_agent_data(span: "Span", agent: "Optional[Agent]") -> None: @@ -55,47 +53,6 @@ def _get_model_name( return str(model_obj) -def _set_model_data( - span: "Span", - agent: "Optional[Agent]", - model_settings: "Optional[Union[ModelSettings, RealtimeModelSettings]]", -) -> None: - """Set model-related data on a span. - - Args: - span: The span to set data on - model: Model object (can be None, will try to get from agent if not provided) - model_settings: Model settings (can be None, will try to get from agent if not provided) - """ - # Extract model settings - settings = model_settings - if not settings and agent and hasattr(agent, "model_settings"): - settings = agent.model_settings - - if settings: - settings_map = { - "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, - "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE, - "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P, - "frequency_penalty": SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, - "presence_penalty": SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, - } - - # ModelSettings is a TypedDict (dict at runtime), so use dict access - if isinstance(settings, dict): - for setting_name, spandata_key in settings_map.items(): - value = settings.get(setting_name) - if value is not None: - span.set_attribute(spandata_key, value) # type: ignore[arg-type] - else: - # Fallback for object-style settings - for setting_name, spandata_key in settings_map.items(): - if hasattr(settings, setting_name): - value = getattr(settings, setting_name) - if value is not None: - span.set_attribute(spandata_key, value) - - def _set_available_tools(span: "Span", agent: "Optional[Agent[Any, Any]]") -> None: """Set available tools data on a span from an agent's function toolset.