9
9
Any ,
10
10
Dict ,
11
11
Iterator ,
12
+ List ,
12
13
Literal ,
13
14
Optional ,
14
15
Tuple ,
19
20
from typing_extensions import TypeGuard
20
21
21
22
from openinference .semconv .trace import (
23
+ DocumentAttributes ,
24
+ EmbeddingAttributes ,
22
25
ImageAttributes ,
23
26
MessageAttributes ,
24
27
MessageContentAttributes ,
25
28
OpenInferenceLLMProviderValues ,
26
29
OpenInferenceLLMSystemValues ,
27
30
OpenInferenceMimeTypeValues ,
28
31
OpenInferenceSpanKindValues ,
32
+ RerankerAttributes ,
29
33
SpanAttributes ,
30
34
ToolAttributes ,
31
35
ToolCallAttributes ,
32
36
)
33
37
34
38
from ._types import (
39
+ Document ,
40
+ Embedding ,
35
41
Message ,
36
42
OpenInferenceLLMProvider ,
37
43
OpenInferenceLLMSystem ,
40
46
TokenCount ,
41
47
Tool ,
42
48
)
49
+ from .helpers import safe_json_dumps
43
50
44
51
pydantic : Optional [ModuleType ]
45
52
try :
51
58
from _typeshed import DataclassInstance
52
59
53
60
61
+ def get_reranker_attributes (
62
+ * ,
63
+ query : Optional [str ] = None ,
64
+ model_name : Optional [str ] = None ,
65
+ input_documents : Optional [List [Document ]] = None ,
66
+ output_documents : Optional [List [Document ]] = None ,
67
+ top_k : Optional [int ] = None ,
68
+ ) -> Dict [str , AttributeValue ]:
69
+ attributes : Dict [str , AttributeValue ] = {}
70
+ if query is not None :
71
+ attributes [RERANKER_QUERY ] = query
72
+ if model_name is not None :
73
+ attributes [RERANKER_MODEL_NAME ] = model_name
74
+ if top_k is not None :
75
+ attributes [RERANKER_TOP_K ] = top_k
76
+ if isinstance (input_documents , list ):
77
+ for index , document in enumerate (input_documents ):
78
+ attributes .update (
79
+ _document_attributes (
80
+ document = document ,
81
+ document_index = index ,
82
+ key_prefix = RERANKER_INPUT_DOCUMENTS ,
83
+ )
84
+ )
85
+ if isinstance (output_documents , list ):
86
+ for index , document in enumerate (output_documents ):
87
+ attributes .update (
88
+ _document_attributes (
89
+ document = document ,
90
+ document_index = index ,
91
+ key_prefix = RERANKER_OUTPUT_DOCUMENTS ,
92
+ )
93
+ )
94
+ return attributes
95
+
96
+
97
+ def get_retriever_attributes (* , documents : List [Document ]) -> Dict [str , AttributeValue ]:
98
+ attributes : Dict [str , AttributeValue ] = {}
99
+ if not isinstance (documents , list ):
100
+ return attributes
101
+ for index , document in enumerate (documents ):
102
+ attributes .update (
103
+ _document_attributes (
104
+ document = document ,
105
+ document_index = index ,
106
+ key_prefix = RETRIEVAL_DOCUMENTS ,
107
+ )
108
+ )
109
+ return attributes
110
+
111
+
112
+ def _document_attributes (
113
+ * ,
114
+ document : Document ,
115
+ document_index : str ,
116
+ key_prefix : str ,
117
+ ) -> Iterator [Tuple [str , AttributeValue ]]:
118
+ if not isinstance (document , dict ):
119
+ return
120
+ if (content := document .get ("content" )) is not None :
121
+ yield f"{ key_prefix } .{ document_index } .{ DOCUMENT_CONTENT } " , content
122
+ if (document_id := document .get ("id" )) is not None :
123
+ yield f"{ key_prefix } .{ document_index } .{ DOCUMENT_ID } " , document_id
124
+ if (metadata := document .get ("metadata" )) is not None :
125
+ key = f"{ key_prefix } .{ document_index } .{ DOCUMENT_METADATA } "
126
+ serialized_metadata : str
127
+ if isinstance (metadata , str ):
128
+ serialized_metadata = metadata
129
+ else :
130
+ serialized_metadata = safe_json_dumps (metadata )
131
+ yield key , serialized_metadata
132
+ if (score := document .get ("score" )) is not None :
133
+ return f"{ key_prefix } .{ document_index } .{ DOCUMENT_SCORE } " , score
134
+
135
+
136
+ def get_embedding_attributes (
137
+ * ,
138
+ model_name : Optional [str ] = None ,
139
+ embeddings : Optional [List [Embedding ]] = None ,
140
+ ) -> Dict [str , AttributeValue ]:
141
+ attributes : Dict [str , AttributeValue ] = {}
142
+ if model_name is not None :
143
+ attributes [EMBEDDING_MODEL_NAME ] = model_name
144
+ if isinstance (embeddings , list ):
145
+ for index , embedding in enumerate (embeddings ):
146
+ if (text := embedding .get ("text" )) is not None :
147
+ key = f"{ EMBEDDING_EMBEDDINGS } .{ index } .{ EMBEDDING_TEXT } "
148
+ attributes [key ] = text
149
+ if (vector := embedding .get ("vector" )) is not None :
150
+ key = f"{ EMBEDDING_EMBEDDINGS } .{ index } .{ EMBEDDING_VECTOR } "
151
+ attributes [key ] = vector
152
+ return attributes
153
+
154
+
155
+ def get_context_attributes (
156
+ * ,
157
+ session_id : Optional [str ] = None ,
158
+ user_id : Optional [str ] = None ,
159
+ metadata : Optional [Union [str , Dict [str , Any ]]] = None ,
160
+ tags : Optional [List [str ]] = None ,
161
+ ) -> Dict [str , AttributeValue ]:
162
+ attributes : Dict [str , AttributeValue ] = {}
163
+ if session_id is not None :
164
+ attributes .update (get_session_attributes (session_id = session_id ))
165
+ if user_id is not None :
166
+ attributes .update (get_user_id_attributes (user_id = user_id ))
167
+ if metadata is not None :
168
+ attributes .update (get_metadata_attributes (metadata = metadata ))
169
+ if tags is not None :
170
+ attributes .update (get_tag_attributes (tags = tags ))
171
+ return attributes
172
+
173
+
174
+ def get_session_attributes (* , session_id : str ) -> Dict [str , AttributeValue ]:
175
+ return {SESSION_ID : session_id }
176
+
177
+
178
+ def get_tag_attributes (* , tags : List [str ]) -> Dict [str , AttributeValue ]:
179
+ return {TAG_TAGS : tags }
180
+
181
+
182
+ def get_metadata_attributes (* , metadata : Union [str , Dict [str , Any ]]) -> Dict [str , AttributeValue ]:
183
+ serialized_metadata : str
184
+ if isinstance (metadata , str ):
185
+ serialized_metadata = metadata
186
+ else :
187
+ serialized_metadata = safe_json_dumps (metadata )
188
+ return {METADATA : serialized_metadata }
189
+
190
+
191
+ def get_user_id_attributes (* , user_id : str ) -> Dict [str , AttributeValue ]:
192
+ return {USER_ID : user_id }
193
+
194
+
54
195
def get_span_kind_attributes (kind : "OpenInferenceSpanKind" , / ) -> Dict [str , AttributeValue ]:
55
196
normalized_kind = _normalize_openinference_span_kind (kind )
56
197
return {
@@ -350,6 +491,14 @@ def get_llm_token_count_attributes(
350
491
attributes [LLM_TOKEN_COUNT_COMPLETION ] = completion
351
492
if (total := token_count .get ("total" )) is not None :
352
493
attributes [LLM_TOKEN_COUNT_TOTAL ] = total
494
+ if (prompt_details := token_count .get ("prompt_details" )) is not None :
495
+ if isinstance (prompt_details , dict ):
496
+ if (cache_write := prompt_details .get ("cache_write" )) is not None :
497
+ attributes [LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE ] = cache_write
498
+ if (cache_read := prompt_details .get ("cache_read" )) is not None :
499
+ attributes [LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ ] = cache_read
500
+ if (audio := prompt_details .get ("audio" )) is not None :
501
+ attributes [LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO ] = audio
353
502
return attributes
354
503
355
504
@@ -371,25 +520,41 @@ def get_llm_tool_attributes(
371
520
return attributes
372
521
373
522
523
+ # document attributes
524
+ DOCUMENT_CONTENT = DocumentAttributes .DOCUMENT_CONTENT
525
+ DOCUMENT_ID = DocumentAttributes .DOCUMENT_ID
526
+ DOCUMENT_METADATA = DocumentAttributes .DOCUMENT_METADATA
527
+ DOCUMENT_SCORE = DocumentAttributes .DOCUMENT_SCORE
528
+
529
+ # embedding attributes
530
+ EMBEDDING_TEXT = EmbeddingAttributes .EMBEDDING_TEXT
531
+ EMBEDDING_VECTOR = EmbeddingAttributes .EMBEDDING_VECTOR
532
+
374
533
# image attributes
375
534
IMAGE_URL = ImageAttributes .IMAGE_URL
376
535
377
-
378
536
# message attributes
379
537
MESSAGE_CONTENT = MessageAttributes .MESSAGE_CONTENT
380
538
MESSAGE_CONTENTS = MessageAttributes .MESSAGE_CONTENTS
381
539
MESSAGE_ROLE = MessageAttributes .MESSAGE_ROLE
382
540
MESSAGE_TOOL_CALL_ID = MessageAttributes .MESSAGE_TOOL_CALL_ID
383
541
MESSAGE_TOOL_CALLS = MessageAttributes .MESSAGE_TOOL_CALLS
384
542
385
-
386
543
# message content attributes
387
544
MESSAGE_CONTENT_IMAGE = MessageContentAttributes .MESSAGE_CONTENT_IMAGE
388
545
MESSAGE_CONTENT_TEXT = MessageContentAttributes .MESSAGE_CONTENT_TEXT
389
546
MESSAGE_CONTENT_TYPE = MessageContentAttributes .MESSAGE_CONTENT_TYPE
390
547
548
+ # reranker attributes
549
+ RERANKER_INPUT_DOCUMENTS = RerankerAttributes .RERANKER_INPUT_DOCUMENTS
550
+ RERANKER_MODEL_NAME = RerankerAttributes .RERANKER_MODEL_NAME
551
+ RERANKER_OUTPUT_DOCUMENTS = RerankerAttributes .RERANKER_OUTPUT_DOCUMENTS
552
+ RERANKER_QUERY = RerankerAttributes .RERANKER_QUERY
553
+ RERANKER_TOP_K = RerankerAttributes .RERANKER_TOP_K
391
554
392
555
# span attributes
556
+ EMBEDDING_EMBEDDINGS = SpanAttributes .EMBEDDING_EMBEDDINGS
557
+ EMBEDDING_MODEL_NAME = SpanAttributes .EMBEDDING_MODEL_NAME
393
558
INPUT_MIME_TYPE = SpanAttributes .INPUT_MIME_TYPE
394
559
INPUT_VALUE = SpanAttributes .INPUT_VALUE
395
560
LLM_INPUT_MESSAGES = SpanAttributes .LLM_INPUT_MESSAGES
@@ -400,20 +565,28 @@ def get_llm_tool_attributes(
400
565
LLM_SYSTEM = SpanAttributes .LLM_SYSTEM
401
566
LLM_TOKEN_COUNT_COMPLETION = SpanAttributes .LLM_TOKEN_COUNT_COMPLETION
402
567
LLM_TOKEN_COUNT_PROMPT = SpanAttributes .LLM_TOKEN_COUNT_PROMPT
568
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO = SpanAttributes .LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO
569
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ = SpanAttributes .LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ
570
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE = (
571
+ SpanAttributes .LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE
572
+ )
403
573
LLM_TOKEN_COUNT_TOTAL = SpanAttributes .LLM_TOKEN_COUNT_TOTAL
404
574
LLM_TOOLS = SpanAttributes .LLM_TOOLS
575
+ METADATA = SpanAttributes .METADATA
405
576
OPENINFERENCE_SPAN_KIND = SpanAttributes .OPENINFERENCE_SPAN_KIND
406
577
OUTPUT_MIME_TYPE = SpanAttributes .OUTPUT_MIME_TYPE
407
578
OUTPUT_VALUE = SpanAttributes .OUTPUT_VALUE
579
+ RETRIEVAL_DOCUMENTS = SpanAttributes .RETRIEVAL_DOCUMENTS
580
+ SESSION_ID = SpanAttributes .SESSION_ID
581
+ TAG_TAGS = SpanAttributes .TAG_TAGS
408
582
TOOL_DESCRIPTION = SpanAttributes .TOOL_DESCRIPTION
409
583
TOOL_NAME = SpanAttributes .TOOL_NAME
410
584
TOOL_PARAMETERS = SpanAttributes .TOOL_PARAMETERS
411
-
585
+ USER_ID = SpanAttributes . USER_ID
412
586
413
587
# tool attributes
414
588
TOOL_JSON_SCHEMA = ToolAttributes .TOOL_JSON_SCHEMA
415
589
416
-
417
590
# tool call attributes
418
591
TOOL_CALL_FUNCTION_ARGUMENTS_JSON = ToolCallAttributes .TOOL_CALL_FUNCTION_ARGUMENTS_JSON
419
592
TOOL_CALL_FUNCTION_NAME = ToolCallAttributes .TOOL_CALL_FUNCTION_NAME
0 commit comments