Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 660
feat(openai-agents): Support span streaming#6404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6f67df00f53ac05a5f81dc4a5366b2b0c34bf37fa253a84aedcdeb8d2c1bd19e9413c5e243b86931aa303a95520ab65aa4e1d6ebe0b4ed5ff941351515f38ad3f3d5bFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -2,15 +2,28 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import sentry_sdk | ||||||||||||||||||||||||||||||||||||||||||
| from sentry_sdk.ai.utils import get_start_span_function | ||||||||||||||||||||||||||||||||||||||||||
| from sentry_sdk.tracing_utils import has_span_streaming_enabled | ||||||||||||||||||||||||||||||||||||||||||
| from ..consts import SPAN_ORIGIN | ||||||||||||||||||||||||||||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||||||||||||||||||||||||||||
| from typing import Union | ||||||||||||||||||||||||||||||||||||||||||
| import agents | ||||||||||||||||||||||||||||||||||||||||||
| def agent_workflow_span(agent: "agents.Agent") -> "sentry_sdk.tracing.Span": | ||||||||||||||||||||||||||||||||||||||||||
| def agent_workflow_span( | ||||||||||||||||||||||||||||||||||||||||||
| agent: "agents.Agent", | ||||||||||||||||||||||||||||||||||||||||||
| ) -> "Union[sentry_sdk.tracing.Span, sentry_sdk.traces.StreamedSpan]": | ||||||||||||||||||||||||||||||||||||||||||
| # Create a transaction or a span if an transaction is already active | ||||||||||||||||||||||||||||||||||||||||||
| span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) | ||||||||||||||||||||||||||||||||||||||||||
| if span_streaming: | ||||||||||||||||||||||||||||||||||||||||||
| span = sentry_sdk.traces.start_span( | ||||||||||||||||||||||||||||||||||||||||||
| name=f"{agent.name} workflow", attributes={"sentry.origin": SPAN_ORIGIN} | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
| return span | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+26
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Taking a look at
depending on if span streaming is enabled or not or if there's a transaction that's currently active. What we can do here in order to leverage the existing streamed span awareness within that function is to, instead of invoking So the function body would look something like the following:
Suggested change
| ||||||||||||||||||||||||||||||||||||||||||
| span = get_start_span_function()( | ||||||||||||||||||||||||||||||||||||||||||
| name=f"{agent.name} workflow", | ||||||||||||||||||||||||||||||||||||||||||
| origin=SPAN_ORIGIN, | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,6 +2,8 @@ | ||
| import sentry_sdk | ||
| from sentry_sdk.consts import OP, SPANDATA | ||
| from sentry_sdk.traces import StreamedSpan | ||
| from sentry_sdk.tracing_utils import has_span_streaming_enabled | ||
| from ..consts import SPAN_ORIGIN | ||
| from ..utils import ( | ||
| @@ -12,14 +14,14 @@ | ||
| ) | ||
| if TYPE_CHECKING: | ||
| from typing import Any, Optional | ||
| from typing import Any, Optional, Union | ||
| from agents import Agent | ||
| def ai_client_span( | ||
| agent: "Agent", get_response_kwargs: "dict[str, Any]" | ||
| ) -> "sentry_sdk.tracing.Span": | ||
| ) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": | ||
| # TODO-anton: implement other types of operations. Now "chat" is hardcoded. | ||
| # Get model name from agent.model or fall back to request model (for when agent.model is None/default) | ||
| model_name = None | ||
| @@ -28,13 +30,24 @@ def ai_client_span( | ||
| elif hasattr(agent, "_sentry_request_model"): | ||
| model_name = agent._sentry_request_model | ||
| span = sentry_sdk.start_span( | ||
| op=OP.GEN_AI_CHAT, | ||
| name=f"chat {model_name}", | ||
| origin=SPAN_ORIGIN, | ||
| ) | ||
| # TODO-anton: remove hardcoded stuff and replace something that also works for embedding and so on | ||
| span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") | ||
| span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) | ||
| if span_streaming: | ||
| span = sentry_sdk.traces.start_span( | ||
| name=f"chat {model_name}", | ||
alexander-alderman-webb marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| attributes={ | ||
| "sentry.op": OP.GEN_AI_CHAT, | ||
| "sentry.origin": SPAN_ORIGIN, | ||
| SPANDATA.GEN_AI_OPERATION_NAME: "chat", | ||
| }, | ||
| ) | ||
| else: | ||
| span = sentry_sdk.start_span( | ||
| op=OP.GEN_AI_CHAT, | ||
| name=f"chat {model_name}", | ||
| origin=SPAN_ORIGIN, | ||
| ) | ||
| # TODO-anton: remove hardcoded stuff and replace something that also works for embedding and so on | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how useful this comment is anymore - any chance we can remove it? ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is still a bug 😬. | ||
| span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") | ||
| _set_agent_data(span, agent) | ||
| _set_input_data(span, get_response_kwargs) | ||
| @@ -43,7 +56,7 @@ def ai_client_span( | ||
| def update_ai_client_span( | ||
| span: "sentry_sdk.tracing.Span", | ||
| span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", | ||
| response: "Any", | ||
| response_model: "Optional[str]" = None, | ||
| agent: "Optional[Agent]" = None, | ||
| @@ -55,13 +68,17 @@ def update_ai_client_span( | ||
| if hasattr(response, "output") and response.output: | ||
| _set_output_data(span, response) | ||
| set_on_span = ( | ||
| span.set_attribute if isinstance(span, StreamedSpan) else span.set_data | ||
| ) | ||
| if response_model is not None: | ||
| span.set_data(SPANDATA.GEN_AI_RESPONSE_MODEL, response_model) | ||
| set_on_span(SPANDATA.GEN_AI_RESPONSE_MODEL, response_model) | ||
| elif hasattr(response, "model") and response.model: | ||
| span.set_data(SPANDATA.GEN_AI_RESPONSE_MODEL, str(response.model)) | ||
| set_on_span(SPANDATA.GEN_AI_RESPONSE_MODEL, str(response.model)) | ||
| # Set conversation ID from agent if available | ||
| if agent: | ||
| conv_id = getattr(agent, "_sentry_conversation_id", None) | ||
| if conv_id: | ||
| span.set_data(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) | ||
| set_on_span(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.