|
1 | 1 | import sys |
2 | 2 | from functools import wraps |
3 | 3 |
|
4 | | -from sentry_sdk.ai.monitoring import record_token_usage |
5 | | -from sentry_sdk.ai.span_config import set_input_span_data |
6 | | -from sentry_sdk.ai.utils import set_data_normalized, transform_message_content |
| 4 | +from sentry_sdk.ai.span_config import set_request_span_data, set_response_span_data |
| 5 | +from sentry_sdk.ai.utils import ( |
| 6 | + get_first_from_sources, |
| 7 | + transform_message_content, |
| 8 | +) |
7 | 9 | from sentry_sdk.consts import OP, SPANDATA |
8 | 10 |
|
9 | 11 | from typing import TYPE_CHECKING |
|
17 | 19 | CohereIntegration, |
18 | 20 | _capture_exception, |
19 | 21 | ) |
20 | | -from sentry_sdk.integrations.cohere.utils import ( |
21 | | - get_first_from_sources, |
22 | | - set_span_data_from_sources, |
23 | | -) |
24 | 22 | from sentry_sdk.scope import should_send_default_pii |
25 | 23 | from sentry_sdk.utils import capture_internal_exceptions, reraise |
26 | 24 |
|
|
38 | 36 | except ImportError: |
39 | 37 | _has_chat_types = False |
40 | 38 |
|
| 39 | +def _extract_response_text(response): |
| 40 | + # type: (Any) -> list[str] | None |
| 41 | + text = getattr(response, "text", None) |
| 42 | + return [text] if text is not None else None |
| 43 | + |
| 44 | + |
41 | 45 | COHERE_V1_CHAT_CONFIG = { |
42 | 46 | "static": { |
43 | 47 | SPANDATA.GEN_AI_SYSTEM: "cohere", |
44 | 48 | SPANDATA.GEN_AI_OPERATION_NAME: "chat", |
45 | 49 | }, |
46 | 50 | "extract_messages": lambda kw: _extract_messages(kw), |
| 51 | + "response": { |
| 52 | + "sources": { |
| 53 | + SPANDATA.GEN_AI_RESPONSE_ID: [("generation_id",)], |
| 54 | + SPANDATA.GEN_AI_RESPONSE_FINISH_REASONS: [("finish_reason",)], |
| 55 | + }, |
| 56 | + "pii_sources": { |
| 57 | + SPANDATA.GEN_AI_RESPONSE_TOOL_CALLS: [("tool_calls",)], |
| 58 | + }, |
| 59 | + "extract_text": _extract_response_text, |
| 60 | + "usage": { |
| 61 | + "input_tokens": [ |
| 62 | + ("meta", "billed_units", "input_tokens"), |
| 63 | + ("meta", "tokens", "input_tokens"), |
| 64 | + ], |
| 65 | + "output_tokens": [ |
| 66 | + ("meta", "billed_units", "output_tokens"), |
| 67 | + ("meta", "tokens", "output_tokens"), |
| 68 | + ], |
| 69 | + }, |
| 70 | + }, |
| 71 | + "stream_response_object": [("response",)], |
47 | 72 | } |
48 | 73 |
|
49 | | -CHAT_RESPONSE_SOURCES = { |
50 | | - SPANDATA.GEN_AI_RESPONSE_ID: [("generation_id",)], |
51 | | - SPANDATA.GEN_AI_RESPONSE_FINISH_REASONS: [("finish_reason",)], |
52 | | -} |
53 | | -PII_CHAT_RESPONSE_SOURCES = { |
54 | | - SPANDATA.GEN_AI_RESPONSE_TOOL_CALLS: [("tool_calls",)], |
55 | | -} |
56 | | -CHAT_RESPONSE_TEXT_SOURCES = [("text",)] |
57 | | -CHAT_USAGE_TOKEN_SOURCES = { |
58 | | - SPANDATA.GEN_AI_USAGE_INPUT_TOKENS: [ |
59 | | - ("meta", "billed_units", "input_tokens"), |
60 | | - ("meta", "tokens", "input_tokens"), |
61 | | - ], |
62 | | - SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS: [ |
63 | | - ("meta", "billed_units", "output_tokens"), |
64 | | - ("meta", "tokens", "output_tokens"), |
65 | | - ], |
66 | | -} |
67 | | -STREAM_RESPONSE_SOURCES = [("response",)] |
68 | | - |
69 | 74 |
|
70 | 75 | def setup_v1(wrap_embed_fn): |
71 | 76 | # type: (Callable[..., Any]) -> None |
@@ -113,19 +118,20 @@ def new_chat(*args, **kwargs): |
113 | 118 | reraise(*exc_info) |
114 | 119 |
|
115 | 120 | with capture_internal_exceptions(): |
116 | | - span_data = {SPANDATA.GEN_AI_RESPONSE_STREAMING: streaming} |
117 | | - if model: |
118 | | - span_data[SPANDATA.GEN_AI_REQUEST_MODEL] = model |
119 | | - set_input_span_data( |
| 121 | + span_data = { |
| 122 | + SPANDATA.GEN_AI_RESPONSE_STREAMING: streaming, |
| 123 | + SPANDATA.GEN_AI_REQUEST_MODEL: model if model else None, |
| 124 | + } |
| 125 | + set_request_span_data( |
120 | 126 | span, kwargs, integration, COHERE_V1_CHAT_CONFIG, span_data |
121 | 127 | ) |
122 | 128 |
|
123 | 129 | if streaming: |
124 | 130 | return _iter_stream_events(res, span, include_pii) |
125 | | - if isinstance(res, NonStreamedChatResponse): |
126 | | - _collect_response_fields(span, res, include_pii=include_pii) |
127 | 131 | else: |
128 | | - set_data_normalized(span, "unknown_response", True) |
| 132 | + set_response_span_data( |
| 133 | + span, res, include_pii, COHERE_V1_CHAT_CONFIG["response"] |
| 134 | + ) |
129 | 135 | return res |
130 | 136 |
|
131 | 137 | return new_chat |
@@ -154,36 +160,11 @@ def _iter_stream_events(old_iterator, span, include_pii): |
154 | 160 | if isinstance(x, ChatStreamEndEvent) or isinstance( |
155 | 161 | x, StreamEndStreamedChatResponse |
156 | 162 | ): |
157 | | - _collect_v1_stream_end_fields(span, x, include_pii) |
| 163 | + response = get_first_from_sources( |
| 164 | + x, COHERE_V1_CHAT_CONFIG["stream_response_object"] |
| 165 | + ) |
| 166 | + if response is not None: |
| 167 | + set_response_span_data( |
| 168 | + span, response, include_pii, COHERE_V1_CHAT_CONFIG["response"] |
| 169 | + ) |
158 | 170 | yield x |
159 | | - |
160 | | - |
161 | | -def _collect_v1_stream_end_fields(span, event, include_pii): |
162 | | - # type: (Any, Any, bool) -> None |
163 | | - response = get_first_from_sources(event, STREAM_RESPONSE_SOURCES) |
164 | | - if response is not None: |
165 | | - _collect_response_fields(span, response, include_pii) |
166 | | - |
167 | | - |
168 | | -def _collect_response_fields(span, response, include_pii): |
169 | | - # type: (Any, Any, bool) -> None |
170 | | - if include_pii: |
171 | | - text = get_first_from_sources(response, CHAT_RESPONSE_TEXT_SOURCES) |
172 | | - if text is not None: |
173 | | - set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, [text]) |
174 | | - set_span_data_from_sources( |
175 | | - span, response, PII_CHAT_RESPONSE_SOURCES, require_truthy=False |
176 | | - ) |
177 | | - |
178 | | - set_span_data_from_sources( |
179 | | - span, response, CHAT_RESPONSE_SOURCES, require_truthy=False |
180 | | - ) |
181 | | - record_token_usage( |
182 | | - span, |
183 | | - input_tokens=get_first_from_sources( |
184 | | - response, CHAT_USAGE_TOKEN_SOURCES[SPANDATA.GEN_AI_USAGE_INPUT_TOKENS] |
185 | | - ), |
186 | | - output_tokens=get_first_from_sources( |
187 | | - response, CHAT_USAGE_TOKEN_SOURCES[SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS] |
188 | | - ), |
189 | | - ) |
0 commit comments