-
Notifications
You must be signed in to change notification settings - Fork 517
fix(ai_guard): record model output in LLMObs when blocked after model call #18585
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
base: main
Are you sure you want to change the base?
Changes from all commits
35e14dc
4753eb1
4ad25a0
1c85f5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| from typing import Union | ||
|
|
||
| from ddtrace.internal.logger import get_logger | ||
| from ddtrace.llmobs._constants import AI_GUARD_BLOCKED | ||
| from ddtrace.llmobs._constants import CACHE_READ_INPUT_TOKENS_METRIC_KEY | ||
| from ddtrace.llmobs._constants import CACHE_WRITE_1H_INPUT_TOKENS_METRIC_KEY | ||
| from ddtrace.llmobs._constants import CACHE_WRITE_5M_INPUT_TOKENS_METRIC_KEY | ||
|
|
@@ -68,7 +69,10 @@ def _llmobs_set_tags( | |
| input_messages = self._extract_input_message(list(messages) if messages else [], system_prompt) | ||
|
|
||
| output_messages: list[Message] = [Message(content="")] | ||
| if not span.error and response is not None: | ||
| # Record output when a response exists. ``span.error`` normally | ||
| # suppresses output, but an AI Guard block after the model call errors | ||
| # the span while still having a valid response (APPSEC-68147). | ||
| if response is not None and (not span.error or span._get_ctx_item(AI_GUARD_BLOCKED)): | ||
|
Contributor
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. we should just gate this on |
||
| output_messages = self._extract_output_message(response) | ||
| span_kind = "workflow" if span._get_ctx_item(PROXY_REQUEST) else "llm" | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| from ddtrace.internal import core | ||
| from ddtrace.internal.logger import get_logger | ||
| from ddtrace.internal.utils.formats import format_trace_id | ||
| from ddtrace.llmobs._constants import AI_GUARD_BLOCKED | ||
| from ddtrace.llmobs._constants import DISPATCH_ON_LLM_TOOL_CHOICE | ||
| from ddtrace.llmobs._constants import DISPATCH_ON_TOOL_CALL_OUTPUT_USED | ||
| from ddtrace.llmobs._constants import FILE_FALLBACK_MARKER | ||
|
|
@@ -395,7 +396,9 @@ def openai_set_meta_tags_from_chat( | |
| span, input_messages=input_messages, metadata=parameters, tool_definitions=tool_definitions | ||
| ) | ||
|
|
||
| if span.error or not messages: | ||
| # ``span.error`` normally suppresses output, but an AI Guard block after the | ||
| # model call errors the span while a valid response exists (APPSEC-68147). | ||
| if (span.error and not span._get_ctx_item(AI_GUARD_BLOCKED)) or not messages: | ||
|
Contributor
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. what's stopping us from just gating this as |
||
| _annotate_llmobs_span_data(span, output_messages=[Message(content="")]) | ||
| return | ||
|
|
||
|
|
@@ -1023,7 +1026,9 @@ def openai_set_meta_tags_from_response( | |
| prompt=validated_prompt, | ||
| ) | ||
|
|
||
| if span.error or not response: | ||
| # ``span.error`` normally suppresses output, but an AI Guard block after the | ||
| # model call errors the span while a valid response exists (APPSEC-68147). | ||
| if (span.error and not span._get_ctx_item(AI_GUARD_BLOCKED)) or not response: | ||
| _annotate_llmobs_span_data(span, output_messages=[Message(content="")]) | ||
| return | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| fixes: | ||
| - | | ||
| LLM Observability: This fix resolves an issue where the OpenAI and Anthropic | ||
| integrations did not record the model output on the LLM Observability span | ||
| when AI Guard blocked the request after the model call completed. The model | ||
| response is now captured even though the span is marked as errored by the | ||
| block. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just always set the
event.response = respbefore we do the AI Guard after core dispatch? This way we can decouple AI Guard errors from non-none responses.