33
44from sentry_sdk .ai .monitoring import record_token_usage
55from sentry_sdk .consts import OP , SPANDATA
6- from sentry_sdk .ai .utils import (
7- set_data_normalized ,
8- normalize_message_roles ,
9- truncate_and_annotate_messages ,
10- )
6+ from sentry_sdk .ai .utils import set_data_normalized
7+ from sentry_sdk .ai .span_config import set_input_span_data
118
129from typing import TYPE_CHECKING
1310
4845 "preamble" : SPANDATA .GEN_AI_SYSTEM_INSTRUCTIONS ,
4946}
5047
48+
49+ def _extract_messages_v1 (kwargs ):
50+ # type: (dict[str, Any]) -> list[dict[str, str]]
51+ """Extract role/content dicts from V1-style chat_history + message."""
52+ messages = []
53+ for x in kwargs .get ("chat_history" , []):
54+ messages .append (
55+ {
56+ "role" : getattr (x , "role" , "" ).lower (),
57+ "content" : getattr (x , "message" , "" ),
58+ }
59+ )
60+ message = kwargs .get ("message" )
61+ if message :
62+ messages .append ({"role" : "user" , "content" : message })
63+ return messages
64+
65+
66+ COHERE_V1_CHAT_CONFIG = {
67+ "system" : "cohere" ,
68+ "operation" : "chat" ,
69+ "params" : COLLECTED_CHAT_PARAMS ,
70+ "pii_params" : COLLECTED_PII_CHAT_PARAMS ,
71+ "extract_messages" : _extract_messages_v1 ,
72+ }
73+
5174COLLECTED_CHAT_RESP_ATTRS = {
5275 "generation_id" : SPANDATA .GEN_AI_RESPONSE_ID ,
5376 "finish_reason" : SPANDATA .GEN_AI_RESPONSE_FINISH_REASONS ,
@@ -77,36 +100,6 @@ def _wrap_chat(f, streaming):
77100 if not _has_chat_types :
78101 return f
79102
80- def collect_chat_response_fields (span , res , include_pii ):
81- # type: (Span, NonStreamedChatResponse, bool) -> None
82- if include_pii :
83- if hasattr (res , "text" ):
84- set_data_normalized (
85- span ,
86- SPANDATA .GEN_AI_RESPONSE_TEXT ,
87- [res .text ],
88- )
89- for attr , spandata_key in COLLECTED_PII_CHAT_RESP_ATTRS .items ():
90- if hasattr (res , attr ):
91- set_data_normalized (span , spandata_key , getattr (res , attr ))
92-
93- for attr , spandata_key in COLLECTED_CHAT_RESP_ATTRS .items ():
94- if hasattr (res , attr ):
95- set_data_normalized (span , spandata_key , getattr (res , attr ))
96-
97- if hasattr (res , "meta" ):
98- if hasattr (res .meta , "billed_units" ):
99- record_token_usage (
100- span ,
101- input_tokens = res .meta .billed_units .input_tokens ,
102- output_tokens = res .meta .billed_units .output_tokens ,
103- )
104- elif hasattr (res .meta , "tokens" ):
105- record_token_usage (
106- span ,
107- input_tokens = res .meta .tokens .input_tokens ,
108- output_tokens = res .meta .tokens .output_tokens ,
109- )
110103
111104 @wraps (f )
112105 def new_chat (* args , ** kwargs ):
@@ -120,7 +113,6 @@ def new_chat(*args, **kwargs):
120113 ):
121114 return f (* args , ** kwargs )
122115
123- message = kwargs .get ("message" )
124116 model = kwargs .get ("model" , "" )
125117
126118 with sentry_sdk .start_span (
@@ -137,41 +129,10 @@ def new_chat(*args, **kwargs):
137129 reraise (* exc_info )
138130
139131 with capture_internal_exceptions ():
140- set_data_normalized (span , SPANDATA .GEN_AI_SYSTEM , "cohere" )
141- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "chat" )
142- if model :
143- set_data_normalized (span , SPANDATA .GEN_AI_REQUEST_MODEL , model )
144-
145- if should_send_default_pii () and integration .include_prompts :
146- messages = []
147- for x in kwargs .get ("chat_history" , []):
148- messages .append (
149- {
150- "role" : getattr (x , "role" , "" ).lower (),
151- "content" : getattr (x , "message" , "" ),
152- }
153- )
154- messages .append ({"role" : "user" , "content" : message })
155- messages = normalize_message_roles (messages )
156- scope = sentry_sdk .get_current_scope ()
157- messages_data = truncate_and_annotate_messages (
158- messages , span , scope
159- )
160- if messages_data is not None :
161- set_data_normalized (
162- span ,
163- SPANDATA .GEN_AI_REQUEST_MESSAGES ,
164- messages_data ,
165- unpack = False ,
166- )
167- for k , v in COLLECTED_PII_CHAT_PARAMS .items ():
168- if k in kwargs :
169- set_data_normalized (span , v , kwargs [k ])
170-
171- for k , v in COLLECTED_CHAT_PARAMS .items ():
172- if k in kwargs :
173- set_data_normalized (span , v , kwargs [k ])
174- set_data_normalized (span , SPANDATA .GEN_AI_RESPONSE_STREAMING , streaming )
132+ set_input_span_data (span , kwargs , integration , {
133+ ** COHERE_V1_CHAT_CONFIG ,
134+ "extra_static" : {SPANDATA .GEN_AI_RESPONSE_STREAMING : streaming },
135+ })
175136
176137 if streaming :
177138 old_iterator = res
@@ -203,4 +164,34 @@ def new_iterator():
203164 set_data_normalized (span , "unknown_response" , True )
204165 return res
205166
167+ def collect_chat_response_fields (span , res , include_pii ):
168+ # type: (Span, NonStreamedChatResponse, bool) -> None
169+ if include_pii :
170+ if hasattr (res , "text" ):
171+ set_data_normalized (
172+ span ,
173+ SPANDATA .GEN_AI_RESPONSE_TEXT ,
174+ [res .text ],
175+ )
176+ for attr , spandata_key in COLLECTED_PII_CHAT_RESP_ATTRS .items ():
177+ if hasattr (res , attr ):
178+ set_data_normalized (span , spandata_key , getattr (res , attr ))
179+
180+ for attr , spandata_key in COLLECTED_CHAT_RESP_ATTRS .items ():
181+ if hasattr (res , attr ):
182+ set_data_normalized (span , spandata_key , getattr (res , attr ))
183+
184+ if hasattr (res , "meta" ):
185+ if hasattr (res .meta , "billed_units" ):
186+ record_token_usage (
187+ span ,
188+ input_tokens = res .meta .billed_units .input_tokens ,
189+ output_tokens = res .meta .billed_units .output_tokens ,
190+ )
191+ elif hasattr (res .meta , "tokens" ):
192+ record_token_usage (
193+ span ,
194+ input_tokens = res .meta .tokens .input_tokens ,
195+ output_tokens = res .meta .tokens .output_tokens ,
196+ )
206197 return new_chat
0 commit comments