@@ -524,12 +524,21 @@ def __init__(
524524 self ._finish_reasons_set = set ()
525525 self ._error_type = None
526526 self ._input_tokens = 0
527+ self ._cached_tokens = 0
527528 self ._output_tokens = 0
528- self . sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
529+ sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
529530 _OpenTelemetryStabilitySignalType .GEN_AI
530531 )
532+ if sem_conv_opt_in_mode not in {
533+ _StabilityMode .DEFAULT ,
534+ _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL ,
535+ }:
536+ raise RuntimeError (f"{ sem_conv_opt_in_mode } mode not supported" )
537+ self .experimental_sem_convs_enabled = (
538+ sem_conv_opt_in_mode == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
539+ )
531540 self ._content_recording_enabled = is_content_recording_enabled (
532- self .sem_conv_opt_in_mode
541+ self .experimental_sem_convs_enabled
533542 )
534543 self ._response_index = 0
535544 self ._candidate_index = 0
@@ -621,6 +630,11 @@ def _maybe_update_token_counts(self, response: GenerateContentResponse):
621630 output_tokens = _get_response_property (
622631 response , "usage_metadata.candidates_token_count"
623632 )
633+ cached_tokens = _get_response_property (
634+ response , "usage_metadata.cached_content_token_count"
635+ )
636+ if cached_tokens and isinstance (cached_tokens , int ):
637+ self ._cached_tokens = cached_tokens
624638 if input_tokens and isinstance (input_tokens , int ):
625639 self ._input_tokens = input_tokens
626640 if output_tokens and isinstance (output_tokens , int ):
@@ -654,10 +668,7 @@ def _maybe_update_error_type(self, response: GenerateContentResponse):
654668 self ._error_type = f"BLOCKED_{ block_reason } "
655669
656670 def _maybe_get_tool_definitions (self , config ) -> list [ToolDefinition ]:
657- if (
658- self .sem_conv_opt_in_mode
659- != _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
660- ):
671+ if not self .experimental_sem_convs_enabled :
661672 return []
662673
663674 if tools := _config_to_tools (config ):
@@ -669,10 +680,7 @@ def _maybe_get_tool_definitions(self, config) -> list[ToolDefinition]:
669680 async def _maybe_get_tool_definitions_async (
670681 self , config
671682 ) -> list [ToolDefinition ]:
672- if (
673- self .sem_conv_opt_in_mode
674- != _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
675- ):
683+ if not self .experimental_sem_convs_enabled :
676684 return []
677685
678686 tool_definitions = []
@@ -744,10 +752,7 @@ def _maybe_log_completion_details(
744752 config : Optional [GenerateContentConfigOrDict ] = None ,
745753 tool_definitions : Optional [list [ToolDefinition ]] = None ,
746754 ):
747- if (
748- self .sem_conv_opt_in_mode
749- != _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
750- ):
755+ if not self .experimental_sem_convs_enabled :
751756 return
752757 system_instructions = []
753758 if system_content := _config_to_system_instruction (config ):
@@ -758,14 +763,21 @@ def _maybe_log_completion_details(
758763 contents = transformers .t_contents (request )
759764 )
760765 output_messages = to_output_messages (candidates = candidates )
761-
762766 span = trace .get_current_span ()
763767 event = LogRecord (
764768 event_name = "gen_ai.client.inference.operation.details" ,
765769 attributes = extra_attributes
766770 | request_attributes
767771 | final_attributes ,
768772 )
773+ # New sem conv only gets added here when we've verified that experimental mode is set.
774+ span .set_attribute (
775+ gen_ai_attributes .GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS ,
776+ self ._cached_tokens ,
777+ )
778+ event .attributes [
779+ gen_ai_attributes .GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS
780+ ] = self ._cached_tokens
769781 tool_definitions = tool_definitions or []
770782 self .completion_hook .on_completion (
771783 inputs = input_messages ,
@@ -1014,7 +1026,7 @@ def instrumented_generate_content(
10141026 ) as span :
10151027 extra_attributes = _get_extra_generate_content_attributes ()
10161028 span .set_attributes (extra_attributes | request_attributes )
1017- if helper .sem_conv_opt_in_mode == _StabilityMode . DEFAULT :
1029+ if not helper .experimental_sem_convs_enabled :
10181030 helper .process_request (contents , config , span )
10191031 try :
10201032 response = wrapped_func (
@@ -1024,10 +1036,7 @@ def instrumented_generate_content(
10241036 config = helper .wrapped_config (config ),
10251037 ** kwargs ,
10261038 )
1027- if (
1028- helper .sem_conv_opt_in_mode
1029- == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
1030- ):
1039+ if helper .experimental_sem_convs_enabled :
10311040 helper ._update_response (response )
10321041 if response .candidates :
10331042 candidates += response .candidates
@@ -1094,7 +1103,7 @@ def instrumented_generate_content_stream(
10941103 ) as span :
10951104 extra_attributes = _get_extra_generate_content_attributes ()
10961105 span .set_attributes (extra_attributes | request_attributes )
1097- if helper .sem_conv_opt_in_mode == _StabilityMode . DEFAULT :
1106+ if not helper .experimental_sem_convs_enabled :
10981107 helper .process_request (contents , config , span )
10991108 try :
11001109 for response in wrapped_func (
@@ -1104,10 +1113,7 @@ def instrumented_generate_content_stream(
11041113 config = helper .wrapped_config (config ),
11051114 ** kwargs ,
11061115 ):
1107- if (
1108- helper .sem_conv_opt_in_mode
1109- == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
1110- ):
1116+ if helper .experimental_sem_convs_enabled :
11111117 helper ._update_response (response )
11121118 if response .candidates :
11131119 candidates += response .candidates
@@ -1174,7 +1180,7 @@ async def instrumented_generate_content(
11741180 ) as span :
11751181 extra_attributes = _get_extra_generate_content_attributes ()
11761182 span .set_attributes (extra_attributes | request_attributes )
1177- if helper .sem_conv_opt_in_mode == _StabilityMode . DEFAULT :
1183+ if not helper .experimental_sem_convs_enabled :
11781184 helper .process_request (contents , config , span )
11791185 try :
11801186 response = await wrapped_func (
@@ -1184,10 +1190,7 @@ async def instrumented_generate_content(
11841190 config = helper .wrapped_config (config ),
11851191 ** kwargs ,
11861192 )
1187- if (
1188- helper .sem_conv_opt_in_mode
1189- == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
1190- ):
1193+ if helper .experimental_sem_convs_enabled :
11911194 helper ._update_response (response )
11921195 if response .candidates :
11931196 candidates += response .candidates
@@ -1255,10 +1258,7 @@ async def instrumented_generate_content_stream(
12551258 ) as span :
12561259 extra_attributes = _get_extra_generate_content_attributes ()
12571260 span .set_attributes (extra_attributes | request_attributes )
1258- if (
1259- not helper .sem_conv_opt_in_mode
1260- == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
1261- ):
1261+ if not helper .experimental_sem_convs_enabled :
12621262 helper .process_request (contents , config , span )
12631263 try :
12641264 response_async_generator = await wrapped_func (
@@ -1294,10 +1294,7 @@ async def _response_async_generator_wrapper():
12941294 with trace .use_span (span , end_on_exit = True ):
12951295 try :
12961296 async for response in response_async_generator :
1297- if (
1298- helper .sem_conv_opt_in_mode
1299- == _StabilityMode .GEN_AI_LATEST_EXPERIMENTAL
1300- ):
1297+ if helper .experimental_sem_convs_enabled :
13011298 helper ._update_response (response )
13021299 if response .candidates :
13031300 candidates += response .candidates
0 commit comments