-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Scrubbing sensitive content #2014
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
Changes from all commits
81cce2f
5989ad2
c7cd7b8
810b1db
8ebee59
16a9920
1d2ba54
15384f3
94e08dd
08189b1
3aa29dc
77e58d6
58297f5
1031dab
c9a83e5
ac4c40a
fb5361a
c330c86
1c75cfc
4f3ecd1
7e81361
f592149
70a4161
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 |
---|---|---|
|
@@ -76,8 +76,11 @@ class SystemPromptPart: | |
part_kind: Literal['system-prompt'] = 'system-prompt' | ||
"""Part type identifier, this is available on all parts as a discriminator.""" | ||
|
||
def otel_event(self, _settings: InstrumentationSettings) -> Event: | ||
return Event('gen_ai.system.message', body={'content': self.content, 'role': 'system'}) | ||
def otel_event(self, settings: InstrumentationSettings) -> Event: | ||
return Event( | ||
'gen_ai.system.message', | ||
body={'role': 'system', **({'content': self.content} if settings.include_content else {})}, | ||
) | ||
|
||
__repr__ = _utils.dataclasses_no_defaults_repr | ||
|
||
|
@@ -362,12 +365,12 @@ def otel_event(self, settings: InstrumentationSettings) -> Event: | |
content = [] | ||
for part in self.content: | ||
if isinstance(part, str): | ||
content.append(part) | ||
content.append(part if settings.include_content else {'kind': 'text'}) | ||
elif isinstance(part, (ImageUrl, AudioUrl, DocumentUrl, VideoUrl)): | ||
content.append({'kind': part.kind, 'url': part.url}) | ||
content.append({'kind': part.kind, **({'url': part.url} if settings.include_content else {})}) | ||
elif isinstance(part, BinaryContent): | ||
converted_part = {'kind': part.kind, 'media_type': part.media_type} | ||
if settings.include_binary_content: | ||
if settings.include_content and settings.include_binary_content: | ||
adtyavrdhn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
converted_part['binary_content'] = base64.b64encode(part.data).decode() | ||
content.append(converted_part) | ||
else: | ||
|
@@ -414,10 +417,15 @@ def model_response_object(self) -> dict[str, Any]: | |
else: | ||
return {'return_value': tool_return_ta.dump_python(self.content, mode='json')} | ||
|
||
def otel_event(self, _settings: InstrumentationSettings) -> Event: | ||
def otel_event(self, settings: InstrumentationSettings) -> Event: | ||
return Event( | ||
'gen_ai.tool.message', | ||
body={'content': self.content, 'role': 'tool', 'id': self.tool_call_id, 'name': self.tool_name}, | ||
body={ | ||
**({'content': self.content} if settings.include_content else {}), | ||
'role': 'tool', | ||
'id': self.tool_call_id, | ||
'name': self.tool_name, | ||
}, | ||
) | ||
|
||
__repr__ = _utils.dataclasses_no_defaults_repr | ||
|
@@ -473,14 +481,14 @@ def model_response(self) -> str: | |
description = f'{len(self.content)} validation errors: {json_errors.decode()}' | ||
return f'{description}\n\nFix the errors and try again.' | ||
|
||
def otel_event(self, _settings: InstrumentationSettings) -> Event: | ||
def otel_event(self, settings: InstrumentationSettings) -> Event: | ||
if self.tool_name is None: | ||
return Event('gen_ai.user.message', body={'content': self.model_response(), 'role': 'user'}) | ||
else: | ||
return Event( | ||
'gen_ai.tool.message', | ||
body={ | ||
'content': self.model_response(), | ||
**({'content': self.model_response()} if settings.include_content else {}), | ||
'role': 'tool', | ||
'id': self.tool_call_id, | ||
'name': self.tool_name, | ||
|
@@ -657,7 +665,7 @@ class ModelResponse: | |
vendor_id: str | None = None | ||
"""Vendor ID as specified by the model provider. This can be used to track the specific request to the model.""" | ||
|
||
def otel_events(self) -> list[Event]: | ||
def otel_events(self, settings: InstrumentationSettings) -> list[Event]: | ||
"""Return OpenTelemetry events for the response.""" | ||
result: list[Event] = [] | ||
|
||
|
@@ -683,7 +691,8 @@ def new_event_body(): | |
elif isinstance(part, TextPart): | ||
if body.get('content'): | ||
body = new_event_body() | ||
body['content'] = part.content | ||
if settings.include_content: | ||
body['content'] = part.content | ||
Comment on lines
692
to
+695
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. This implies that the number of events produced will depend on whether content is included if multiple tool calls are made in a single message. 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. Trying to understand what you mean exactly Would you say the below test captures what you are trying to imply:
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. sorry, i didn't think this through properly. the difference would be if a message had multiple text parts. but i don't think this happens in practice, so it isn't worth worrying about. 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 caught up on this whole conversation, but I do think a message with multiple text parts could be realistic. For example, multiple text parts could be used to separate different inputs:
Of course this could be done by concatenating all text into a single part. 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. Yep, I get it. Something like this would cause this issue.
|
||
|
||
return result | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.