mseep-agentops 0.4.18__py3-none-any.whl → 0.4.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentops/__init__.py +0 -0
- agentops/client/api/base.py +28 -30
- agentops/client/api/versions/v3.py +29 -25
- agentops/client/api/versions/v4.py +87 -46
- agentops/client/client.py +98 -29
- agentops/client/http/README.md +87 -0
- agentops/client/http/http_client.py +126 -172
- agentops/config.py +8 -2
- agentops/instrumentation/OpenTelemetry.md +133 -0
- agentops/instrumentation/README.md +167 -0
- agentops/instrumentation/__init__.py +13 -1
- agentops/instrumentation/agentic/ag2/__init__.py +18 -0
- agentops/instrumentation/agentic/ag2/instrumentor.py +922 -0
- agentops/instrumentation/agentic/agno/__init__.py +19 -0
- agentops/instrumentation/agentic/agno/attributes/__init__.py +20 -0
- agentops/instrumentation/agentic/agno/attributes/agent.py +250 -0
- agentops/instrumentation/agentic/agno/attributes/metrics.py +214 -0
- agentops/instrumentation/agentic/agno/attributes/storage.py +158 -0
- agentops/instrumentation/agentic/agno/attributes/team.py +195 -0
- agentops/instrumentation/agentic/agno/attributes/tool.py +210 -0
- agentops/instrumentation/agentic/agno/attributes/workflow.py +254 -0
- agentops/instrumentation/agentic/agno/instrumentor.py +1313 -0
- agentops/instrumentation/agentic/crewai/LICENSE +201 -0
- agentops/instrumentation/agentic/crewai/NOTICE.md +10 -0
- agentops/instrumentation/agentic/crewai/__init__.py +6 -0
- agentops/instrumentation/agentic/crewai/crewai_span_attributes.py +335 -0
- agentops/instrumentation/agentic/crewai/instrumentation.py +535 -0
- agentops/instrumentation/agentic/crewai/version.py +1 -0
- agentops/instrumentation/agentic/google_adk/__init__.py +19 -0
- agentops/instrumentation/agentic/google_adk/instrumentor.py +68 -0
- agentops/instrumentation/agentic/google_adk/patch.py +767 -0
- agentops/instrumentation/agentic/haystack/__init__.py +1 -0
- agentops/instrumentation/agentic/haystack/instrumentor.py +186 -0
- agentops/instrumentation/agentic/langgraph/__init__.py +3 -0
- agentops/instrumentation/agentic/langgraph/attributes.py +54 -0
- agentops/instrumentation/agentic/langgraph/instrumentation.py +598 -0
- agentops/instrumentation/agentic/langgraph/version.py +1 -0
- agentops/instrumentation/agentic/openai_agents/README.md +156 -0
- agentops/instrumentation/agentic/openai_agents/SPANS.md +145 -0
- agentops/instrumentation/agentic/openai_agents/TRACING_API.md +144 -0
- agentops/instrumentation/agentic/openai_agents/__init__.py +30 -0
- agentops/instrumentation/agentic/openai_agents/attributes/common.py +549 -0
- agentops/instrumentation/agentic/openai_agents/attributes/completion.py +172 -0
- agentops/instrumentation/agentic/openai_agents/attributes/model.py +58 -0
- agentops/instrumentation/agentic/openai_agents/attributes/tokens.py +275 -0
- agentops/instrumentation/agentic/openai_agents/exporter.py +469 -0
- agentops/instrumentation/agentic/openai_agents/instrumentor.py +107 -0
- agentops/instrumentation/agentic/openai_agents/processor.py +58 -0
- agentops/instrumentation/agentic/smolagents/README.md +88 -0
- agentops/instrumentation/agentic/smolagents/__init__.py +12 -0
- agentops/instrumentation/agentic/smolagents/attributes/agent.py +354 -0
- agentops/instrumentation/agentic/smolagents/attributes/model.py +205 -0
- agentops/instrumentation/agentic/smolagents/instrumentor.py +286 -0
- agentops/instrumentation/agentic/smolagents/stream_wrapper.py +258 -0
- agentops/instrumentation/agentic/xpander/__init__.py +15 -0
- agentops/instrumentation/agentic/xpander/context.py +112 -0
- agentops/instrumentation/agentic/xpander/instrumentor.py +877 -0
- agentops/instrumentation/agentic/xpander/trace_probe.py +86 -0
- agentops/instrumentation/agentic/xpander/version.py +3 -0
- agentops/instrumentation/common/README.md +65 -0
- agentops/instrumentation/common/attributes.py +1 -2
- agentops/instrumentation/providers/anthropic/__init__.py +24 -0
- agentops/instrumentation/providers/anthropic/attributes/__init__.py +23 -0
- agentops/instrumentation/providers/anthropic/attributes/common.py +64 -0
- agentops/instrumentation/providers/anthropic/attributes/message.py +541 -0
- agentops/instrumentation/providers/anthropic/attributes/tools.py +231 -0
- agentops/instrumentation/providers/anthropic/event_handler_wrapper.py +90 -0
- agentops/instrumentation/providers/anthropic/instrumentor.py +146 -0
- agentops/instrumentation/providers/anthropic/stream_wrapper.py +436 -0
- agentops/instrumentation/providers/google_genai/README.md +33 -0
- agentops/instrumentation/providers/google_genai/__init__.py +24 -0
- agentops/instrumentation/providers/google_genai/attributes/__init__.py +25 -0
- agentops/instrumentation/providers/google_genai/attributes/chat.py +125 -0
- agentops/instrumentation/providers/google_genai/attributes/common.py +88 -0
- agentops/instrumentation/providers/google_genai/attributes/model.py +284 -0
- agentops/instrumentation/providers/google_genai/instrumentor.py +170 -0
- agentops/instrumentation/providers/google_genai/stream_wrapper.py +238 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/__init__.py +28 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/attributes/__init__.py +27 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/attributes/attributes.py +277 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/attributes/common.py +104 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/instrumentor.py +162 -0
- agentops/instrumentation/providers/ibm_watsonx_ai/stream_wrapper.py +302 -0
- agentops/instrumentation/providers/mem0/__init__.py +45 -0
- agentops/instrumentation/providers/mem0/common.py +377 -0
- agentops/instrumentation/providers/mem0/instrumentor.py +270 -0
- agentops/instrumentation/providers/mem0/memory.py +430 -0
- agentops/instrumentation/providers/openai/__init__.py +21 -0
- agentops/instrumentation/providers/openai/attributes/__init__.py +7 -0
- agentops/instrumentation/providers/openai/attributes/common.py +55 -0
- agentops/instrumentation/providers/openai/attributes/response.py +607 -0
- agentops/instrumentation/providers/openai/config.py +36 -0
- agentops/instrumentation/providers/openai/instrumentor.py +312 -0
- agentops/instrumentation/providers/openai/stream_wrapper.py +941 -0
- agentops/instrumentation/providers/openai/utils.py +44 -0
- agentops/instrumentation/providers/openai/v0.py +176 -0
- agentops/instrumentation/providers/openai/v0_wrappers.py +483 -0
- agentops/instrumentation/providers/openai/wrappers/__init__.py +30 -0
- agentops/instrumentation/providers/openai/wrappers/assistant.py +277 -0
- agentops/instrumentation/providers/openai/wrappers/chat.py +259 -0
- agentops/instrumentation/providers/openai/wrappers/completion.py +109 -0
- agentops/instrumentation/providers/openai/wrappers/embeddings.py +94 -0
- agentops/instrumentation/providers/openai/wrappers/image_gen.py +75 -0
- agentops/instrumentation/providers/openai/wrappers/responses.py +191 -0
- agentops/instrumentation/providers/openai/wrappers/shared.py +81 -0
- agentops/instrumentation/utilities/concurrent_futures/__init__.py +10 -0
- agentops/instrumentation/utilities/concurrent_futures/instrumentation.py +206 -0
- agentops/integration/callbacks/dspy/__init__.py +11 -0
- agentops/integration/callbacks/dspy/callback.py +471 -0
- agentops/integration/callbacks/langchain/README.md +59 -0
- agentops/integration/callbacks/langchain/__init__.py +15 -0
- agentops/integration/callbacks/langchain/callback.py +791 -0
- agentops/integration/callbacks/langchain/utils.py +54 -0
- agentops/legacy/crewai.md +121 -0
- agentops/logging/instrument_logging.py +4 -0
- agentops/sdk/README.md +220 -0
- agentops/sdk/core.py +75 -32
- agentops/sdk/descriptors/classproperty.py +28 -0
- agentops/sdk/exporters.py +152 -33
- agentops/semconv/README.md +125 -0
- agentops/semconv/span_kinds.py +0 -2
- agentops/validation.py +102 -63
- {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.22.dist-info}/METADATA +30 -40
- mseep_agentops-0.4.22.dist-info/RECORD +178 -0
- {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.22.dist-info}/WHEEL +1 -2
- mseep_agentops-0.4.18.dist-info/RECORD +0 -94
- mseep_agentops-0.4.18.dist-info/top_level.txt +0 -2
- tests/conftest.py +0 -10
- tests/unit/client/__init__.py +0 -1
- tests/unit/client/test_http_adapter.py +0 -221
- tests/unit/client/test_http_client.py +0 -206
- tests/unit/conftest.py +0 -54
- tests/unit/sdk/__init__.py +0 -1
- tests/unit/sdk/instrumentation_tester.py +0 -207
- tests/unit/sdk/test_attributes.py +0 -392
- tests/unit/sdk/test_concurrent_instrumentation.py +0 -468
- tests/unit/sdk/test_decorators.py +0 -763
- tests/unit/sdk/test_exporters.py +0 -241
- tests/unit/sdk/test_factory.py +0 -1188
- tests/unit/sdk/test_internal_span_processor.py +0 -397
- tests/unit/sdk/test_resource_attributes.py +0 -35
- tests/unit/test_config.py +0 -82
- tests/unit/test_context_manager.py +0 -777
- tests/unit/test_events.py +0 -27
- tests/unit/test_host_env.py +0 -54
- tests/unit/test_init_py.py +0 -501
- tests/unit/test_serialization.py +0 -433
- tests/unit/test_session.py +0 -676
- tests/unit/test_user_agent.py +0 -34
- tests/unit/test_validation.py +0 -405
- {tests → agentops/instrumentation/agentic/openai_agents/attributes}/__init__.py +0 -0
- /tests/unit/__init__.py → /agentops/instrumentation/providers/openai/attributes/tools.py +0 -0
- {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.22.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,430 @@
|
|
1
|
+
"""Memory operation attribute extractors and wrappers for Mem0 instrumentation."""
|
2
|
+
|
3
|
+
from typing import Optional, Tuple, Dict, Any
|
4
|
+
|
5
|
+
from agentops.instrumentation.common.attributes import AttributeMap
|
6
|
+
from agentops.semconv import SpanAttributes, LLMRequestTypeValues, MessageAttributes
|
7
|
+
from .common import (
|
8
|
+
get_common_attributes,
|
9
|
+
_extract_common_kwargs_attributes,
|
10
|
+
_extract_memory_response_attributes,
|
11
|
+
create_universal_mem0_wrapper,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
def get_add_attributes(
|
16
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
17
|
+
) -> AttributeMap:
|
18
|
+
"""Extract attributes for Mem0's add method.
|
19
|
+
|
20
|
+
Args:
|
21
|
+
args: Positional arguments to the method
|
22
|
+
kwargs: Keyword arguments to the method
|
23
|
+
return_value: Return value from the method
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
Dictionary of extracted attributes
|
27
|
+
"""
|
28
|
+
print(f"args: {args}")
|
29
|
+
print(f"kwargs: {kwargs}")
|
30
|
+
print(f"return_value: {return_value}")
|
31
|
+
attributes = get_common_attributes()
|
32
|
+
attributes[SpanAttributes.OPERATION_NAME] = "add"
|
33
|
+
attributes[SpanAttributes.LLM_REQUEST_TYPE] = LLMRequestTypeValues.CHAT.value
|
34
|
+
|
35
|
+
# Extract message content from args
|
36
|
+
if args and len(args) > 0:
|
37
|
+
messages = args[0]
|
38
|
+
# Get user_id from kwargs for speaker, default to "user" if not found
|
39
|
+
speaker = kwargs.get("user_id", "user") if kwargs else "user"
|
40
|
+
|
41
|
+
if isinstance(messages, str):
|
42
|
+
attributes["mem0.message"] = messages
|
43
|
+
# Set as prompt for consistency with LLM patterns
|
44
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = messages
|
45
|
+
attributes[MessageAttributes.PROMPT_SPEAKER.format(i=0)] = speaker
|
46
|
+
elif isinstance(messages, list):
|
47
|
+
attributes["mem0.message_count"] = len(messages)
|
48
|
+
# Extract message types if available
|
49
|
+
message_types = set()
|
50
|
+
for i, msg in enumerate(messages):
|
51
|
+
if isinstance(msg, dict):
|
52
|
+
if "role" in msg:
|
53
|
+
message_types.add(msg["role"])
|
54
|
+
attributes[MessageAttributes.PROMPT_ROLE.format(i=i)] = msg["role"]
|
55
|
+
if "content" in msg:
|
56
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=i)] = msg["content"]
|
57
|
+
# Set speaker for each message
|
58
|
+
attributes[MessageAttributes.PROMPT_SPEAKER.format(i=i)] = speaker
|
59
|
+
else:
|
60
|
+
# String message
|
61
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=i)] = str(msg)
|
62
|
+
|
63
|
+
attributes[MessageAttributes.PROMPT_SPEAKER.format(i=i)] = speaker
|
64
|
+
if message_types:
|
65
|
+
attributes["mem0.message_types"] = ",".join(message_types)
|
66
|
+
|
67
|
+
# Extract kwargs attributes
|
68
|
+
if kwargs:
|
69
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
70
|
+
|
71
|
+
# Extract memory type
|
72
|
+
if "memory_type" in kwargs:
|
73
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
74
|
+
|
75
|
+
# Extract inference flag
|
76
|
+
if "infer" in kwargs:
|
77
|
+
attributes[SpanAttributes.MEM0_INFER] = str(kwargs["infer"])
|
78
|
+
|
79
|
+
# Extract response attributes
|
80
|
+
if return_value:
|
81
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
82
|
+
|
83
|
+
return attributes
|
84
|
+
|
85
|
+
|
86
|
+
def get_search_attributes(
|
87
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
88
|
+
) -> AttributeMap:
|
89
|
+
"""Extract attributes for Mem0's search method.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
args: Positional arguments to the method
|
93
|
+
kwargs: Keyword arguments to the method
|
94
|
+
return_value: Return value from the method
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
Dictionary of extracted attributes
|
98
|
+
"""
|
99
|
+
print(f"get_search_attributes args: {args}")
|
100
|
+
print(f"get_search_attributes kwargs: {kwargs}")
|
101
|
+
print(f"get_search_attributes return_value: {return_value}")
|
102
|
+
attributes = get_common_attributes()
|
103
|
+
attributes[SpanAttributes.OPERATION_NAME] = "search"
|
104
|
+
attributes[SpanAttributes.LLM_REQUEST_TYPE] = LLMRequestTypeValues.CHAT.value
|
105
|
+
|
106
|
+
# Extract search query from args
|
107
|
+
if args and len(args) > 0:
|
108
|
+
query = args[0]
|
109
|
+
# Get user_id from kwargs for speaker, default to "user" if not found
|
110
|
+
speaker = kwargs.get("user_id", "user") if kwargs else "user"
|
111
|
+
|
112
|
+
if isinstance(query, str):
|
113
|
+
attributes["mem0.message"] = query
|
114
|
+
# Set as prompt for consistency
|
115
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = query
|
116
|
+
attributes[MessageAttributes.PROMPT_SPEAKER.format(i=0)] = speaker
|
117
|
+
|
118
|
+
# Extract kwargs attributes
|
119
|
+
if kwargs:
|
120
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
121
|
+
|
122
|
+
# Extract memory type
|
123
|
+
if "memory_type" in kwargs:
|
124
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
125
|
+
|
126
|
+
# Extract limit parameter
|
127
|
+
if "limit" in kwargs:
|
128
|
+
attributes["mem0.search.limit"] = str(kwargs["limit"])
|
129
|
+
|
130
|
+
# Extract response attributes
|
131
|
+
if return_value:
|
132
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
133
|
+
|
134
|
+
return attributes
|
135
|
+
|
136
|
+
|
137
|
+
def get_get_all_attributes(
|
138
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
139
|
+
) -> AttributeMap:
|
140
|
+
"""Extract attributes for Mem0's get_all method.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
args: Positional arguments to the method
|
144
|
+
kwargs: Keyword arguments to the method
|
145
|
+
return_value: Return value from the method
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
Dictionary of extracted attributes
|
149
|
+
"""
|
150
|
+
attributes = get_common_attributes()
|
151
|
+
attributes[SpanAttributes.OPERATION_NAME] = "get_all"
|
152
|
+
|
153
|
+
# Extract kwargs attributes
|
154
|
+
if kwargs:
|
155
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
156
|
+
|
157
|
+
# Extract memory type
|
158
|
+
if "memory_type" in kwargs:
|
159
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
160
|
+
|
161
|
+
# Extract response attributes
|
162
|
+
if return_value:
|
163
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
164
|
+
|
165
|
+
return attributes
|
166
|
+
|
167
|
+
|
168
|
+
def get_get_attributes(
|
169
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
170
|
+
) -> AttributeMap:
|
171
|
+
"""Extract attributes for Mem0's get method.
|
172
|
+
|
173
|
+
Args:
|
174
|
+
args: Positional arguments to the method
|
175
|
+
kwargs: Keyword arguments to the method
|
176
|
+
return_value: Return value from the method
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
Dictionary of extracted attributes
|
180
|
+
"""
|
181
|
+
attributes = get_common_attributes()
|
182
|
+
attributes[SpanAttributes.OPERATION_NAME] = "get"
|
183
|
+
|
184
|
+
# Extract memory ID from args
|
185
|
+
if args and len(args) > 0:
|
186
|
+
memory_id = args[0]
|
187
|
+
if memory_id:
|
188
|
+
attributes["mem0.memory_id"] = str(memory_id)
|
189
|
+
|
190
|
+
# Extract response attributes
|
191
|
+
if return_value:
|
192
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
193
|
+
|
194
|
+
return attributes
|
195
|
+
|
196
|
+
|
197
|
+
def get_delete_attributes(
|
198
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
199
|
+
) -> AttributeMap:
|
200
|
+
"""Extract attributes for Mem0's delete method.
|
201
|
+
|
202
|
+
Args:
|
203
|
+
args: Positional arguments to the method
|
204
|
+
kwargs: Keyword arguments to the method
|
205
|
+
return_value: Return value from the method
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
Dictionary of extracted attributes
|
209
|
+
"""
|
210
|
+
attributes = get_common_attributes()
|
211
|
+
attributes[SpanAttributes.OPERATION_NAME] = "delete"
|
212
|
+
|
213
|
+
# Extract memory ID from args if available
|
214
|
+
if args and len(args) > 0:
|
215
|
+
memory_id = args[0]
|
216
|
+
if memory_id:
|
217
|
+
attributes["mem0.memory_id"] = str(memory_id)
|
218
|
+
|
219
|
+
# Extract kwargs attributes if available
|
220
|
+
if kwargs:
|
221
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
222
|
+
|
223
|
+
# Extract memory type
|
224
|
+
if "memory_type" in kwargs:
|
225
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
226
|
+
|
227
|
+
# Extract response attributes
|
228
|
+
if return_value:
|
229
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
230
|
+
|
231
|
+
return attributes
|
232
|
+
|
233
|
+
|
234
|
+
def get_update_attributes(
|
235
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
236
|
+
) -> AttributeMap:
|
237
|
+
"""Extract attributes for Mem0's update method.
|
238
|
+
|
239
|
+
Args:
|
240
|
+
args: Positional arguments to the method
|
241
|
+
kwargs: Keyword arguments to the method
|
242
|
+
return_value: Return value from the method
|
243
|
+
|
244
|
+
Returns:
|
245
|
+
Dictionary of extracted attributes
|
246
|
+
"""
|
247
|
+
attributes = get_common_attributes()
|
248
|
+
attributes[SpanAttributes.OPERATION_NAME] = "update"
|
249
|
+
|
250
|
+
# Extract memory ID from args (if available)
|
251
|
+
if args and len(args) > 0:
|
252
|
+
memory_id = args[0]
|
253
|
+
if memory_id:
|
254
|
+
attributes["mem0.memory_id"] = str(memory_id)
|
255
|
+
|
256
|
+
# Extract data from args (if available)
|
257
|
+
if args and len(args) > 1:
|
258
|
+
data = args[1]
|
259
|
+
if isinstance(data, str):
|
260
|
+
attributes["mem0.message"] = data
|
261
|
+
# Set as prompt for consistency
|
262
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = data
|
263
|
+
elif isinstance(data, dict):
|
264
|
+
# Handle case where data is a dictionary with "memory" key
|
265
|
+
if "memory" in data:
|
266
|
+
memory_text = data["memory"]
|
267
|
+
attributes["mem0.message"] = memory_text
|
268
|
+
# Set as prompt for consistency
|
269
|
+
attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = memory_text
|
270
|
+
|
271
|
+
# Extract metadata from data dict if present
|
272
|
+
if "metadata" in data and isinstance(data["metadata"], dict):
|
273
|
+
for key, value in data["metadata"].items():
|
274
|
+
attributes[f"mem0.metadata.{key}"] = str(value)
|
275
|
+
|
276
|
+
# Extract kwargs attributes (if available)
|
277
|
+
if kwargs:
|
278
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
279
|
+
|
280
|
+
# Extract memory type
|
281
|
+
if "memory_type" in kwargs:
|
282
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
283
|
+
|
284
|
+
# Extract response attributes
|
285
|
+
if return_value:
|
286
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
287
|
+
|
288
|
+
return attributes
|
289
|
+
|
290
|
+
|
291
|
+
def get_delete_all_attributes(
|
292
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
293
|
+
) -> AttributeMap:
|
294
|
+
"""Extract attributes for Mem0's delete_all method.
|
295
|
+
|
296
|
+
Args:
|
297
|
+
args: Positional arguments to the method
|
298
|
+
kwargs: Keyword arguments to the method
|
299
|
+
return_value: Return value from the method
|
300
|
+
|
301
|
+
Returns:
|
302
|
+
Dictionary of extracted attributes
|
303
|
+
"""
|
304
|
+
attributes = get_common_attributes()
|
305
|
+
attributes[SpanAttributes.OPERATION_NAME] = "delete_all"
|
306
|
+
|
307
|
+
# Extract kwargs attributes if available
|
308
|
+
if kwargs:
|
309
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
310
|
+
|
311
|
+
# Extract memory type
|
312
|
+
if "memory_type" in kwargs:
|
313
|
+
attributes["mem0.memory_type"] = str(kwargs["memory_type"])
|
314
|
+
|
315
|
+
# Extract user_id for tracking which user's memories are being deleted
|
316
|
+
if "user_id" in kwargs:
|
317
|
+
attributes["mem0.delete_all.user_id"] = str(kwargs["user_id"])
|
318
|
+
|
319
|
+
# Extract agent_id for tracking which agent's memories are being deleted
|
320
|
+
if "agent_id" in kwargs:
|
321
|
+
attributes["mem0.delete_all.agent_id"] = str(kwargs["agent_id"])
|
322
|
+
|
323
|
+
# Extract run_id for tracking which run's memories are being deleted
|
324
|
+
if "run_id" in kwargs:
|
325
|
+
attributes["mem0.delete_all.run_id"] = str(kwargs["run_id"])
|
326
|
+
|
327
|
+
# Extract response attributes
|
328
|
+
if return_value:
|
329
|
+
attributes.update(_extract_memory_response_attributes(return_value))
|
330
|
+
|
331
|
+
return attributes
|
332
|
+
|
333
|
+
|
334
|
+
def get_history_attributes(
|
335
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
|
336
|
+
) -> AttributeMap:
|
337
|
+
"""Extract attributes for Mem0's history method.
|
338
|
+
|
339
|
+
Args:
|
340
|
+
args: Positional arguments to the method
|
341
|
+
kwargs: Keyword arguments to the method
|
342
|
+
return_value: Return value from the method
|
343
|
+
|
344
|
+
Returns:
|
345
|
+
Dictionary of extracted attributes
|
346
|
+
"""
|
347
|
+
attributes = get_common_attributes()
|
348
|
+
attributes[SpanAttributes.OPERATION_NAME] = "history"
|
349
|
+
|
350
|
+
# Extract memory ID from args
|
351
|
+
if args and len(args) > 0:
|
352
|
+
memory_id = args[0]
|
353
|
+
if memory_id:
|
354
|
+
attributes["mem0.memory_id"] = str(memory_id)
|
355
|
+
|
356
|
+
# Extract kwargs attributes if available
|
357
|
+
if kwargs:
|
358
|
+
attributes.update(_extract_common_kwargs_attributes(kwargs))
|
359
|
+
|
360
|
+
# Extract history data from return value
|
361
|
+
if return_value and isinstance(return_value, list):
|
362
|
+
attributes["mem0.history.count"] = len(return_value)
|
363
|
+
|
364
|
+
# Extract event types and other details from history entries
|
365
|
+
event_types = set()
|
366
|
+
actor_ids = set()
|
367
|
+
roles = set()
|
368
|
+
|
369
|
+
for i, entry in enumerate(return_value):
|
370
|
+
if isinstance(entry, dict):
|
371
|
+
# Extract event type
|
372
|
+
if "event" in entry:
|
373
|
+
event_types.add(entry["event"])
|
374
|
+
attributes[f"mem0.history.{i}.event"] = entry["event"]
|
375
|
+
|
376
|
+
# Extract memory content changes
|
377
|
+
if "old_memory" in entry:
|
378
|
+
if entry["old_memory"]:
|
379
|
+
attributes[f"mem0.history.{i}.old_memory"] = entry["old_memory"]
|
380
|
+
|
381
|
+
if "new_memory" in entry:
|
382
|
+
if entry["new_memory"]:
|
383
|
+
attributes[f"mem0.history.{i}.new_memory"] = entry["new_memory"]
|
384
|
+
|
385
|
+
# Extract timestamps
|
386
|
+
if "created_at" in entry:
|
387
|
+
attributes[f"mem0.history.{i}.created_at"] = entry["created_at"]
|
388
|
+
|
389
|
+
if "updated_at" in entry and entry["updated_at"]:
|
390
|
+
attributes[f"mem0.history.{i}.updated_at"] = entry["updated_at"]
|
391
|
+
|
392
|
+
# Extract actor information
|
393
|
+
if "actor_id" in entry and entry["actor_id"]:
|
394
|
+
actor_ids.add(entry["actor_id"])
|
395
|
+
attributes[f"mem0.history.{i}.actor_id"] = entry["actor_id"]
|
396
|
+
|
397
|
+
if "role" in entry and entry["role"]:
|
398
|
+
roles.add(entry["role"])
|
399
|
+
attributes[f"mem0.history.{i}.role"] = entry["role"]
|
400
|
+
|
401
|
+
# Extract deletion status
|
402
|
+
if "is_deleted" in entry:
|
403
|
+
attributes[f"mem0.history.{i}.is_deleted"] = str(entry["is_deleted"])
|
404
|
+
|
405
|
+
# Extract history entry ID
|
406
|
+
if "id" in entry:
|
407
|
+
attributes[f"mem0.history.{i}.id"] = entry["id"]
|
408
|
+
|
409
|
+
# Set aggregated attributes
|
410
|
+
if event_types:
|
411
|
+
attributes["mem0.history.event_types"] = ",".join(event_types)
|
412
|
+
|
413
|
+
if actor_ids:
|
414
|
+
attributes["mem0.history.actor_ids"] = ",".join(actor_ids)
|
415
|
+
|
416
|
+
if roles:
|
417
|
+
attributes["mem0.history.roles"] = ",".join(roles)
|
418
|
+
|
419
|
+
return attributes
|
420
|
+
|
421
|
+
|
422
|
+
# Create universal Mem0 wrappers that work for both sync and async operations
|
423
|
+
mem0_add_wrapper = create_universal_mem0_wrapper("add", get_add_attributes)
|
424
|
+
mem0_search_wrapper = create_universal_mem0_wrapper("search", get_search_attributes)
|
425
|
+
mem0_get_all_wrapper = create_universal_mem0_wrapper("get_all", get_get_all_attributes)
|
426
|
+
mem0_get_wrapper = create_universal_mem0_wrapper("get", get_get_attributes)
|
427
|
+
mem0_delete_wrapper = create_universal_mem0_wrapper("delete", get_delete_attributes)
|
428
|
+
mem0_update_wrapper = create_universal_mem0_wrapper("update", get_update_attributes)
|
429
|
+
mem0_delete_all_wrapper = create_universal_mem0_wrapper("delete_all", get_delete_all_attributes)
|
430
|
+
mem0_history_wrapper = create_universal_mem0_wrapper("history", get_history_attributes)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"""OpenAI API instrumentation for AgentOps.
|
2
|
+
|
3
|
+
This package provides OpenTelemetry-based instrumentation for OpenAI API calls,
|
4
|
+
extending the third-party instrumentation to add support for OpenAI responses.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from agentops.instrumentation.common import LibraryInfo
|
8
|
+
|
9
|
+
# Library information
|
10
|
+
_library_info = LibraryInfo(name="openai")
|
11
|
+
LIBRARY_NAME = _library_info.name
|
12
|
+
LIBRARY_VERSION = _library_info.version
|
13
|
+
|
14
|
+
# Import after defining constants to avoid circular imports
|
15
|
+
from agentops.instrumentation.providers.openai.instrumentor import OpenaiInstrumentor # noqa: E402
|
16
|
+
|
17
|
+
__all__ = [
|
18
|
+
"LIBRARY_NAME",
|
19
|
+
"LIBRARY_VERSION",
|
20
|
+
"OpenaiInstrumentor",
|
21
|
+
]
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from typing import Optional, Tuple, Dict
|
2
|
+
from agentops.logging import logger
|
3
|
+
from agentops.semconv import InstrumentationAttributes
|
4
|
+
from agentops.instrumentation.providers.openai import LIBRARY_NAME, LIBRARY_VERSION
|
5
|
+
from agentops.instrumentation.common.attributes import AttributeMap, get_common_attributes
|
6
|
+
from agentops.instrumentation.providers.openai.attributes.response import (
|
7
|
+
get_response_kwarg_attributes,
|
8
|
+
get_response_response_attributes,
|
9
|
+
)
|
10
|
+
|
11
|
+
try:
|
12
|
+
from openai.types.responses import Response
|
13
|
+
except ImportError as e:
|
14
|
+
logger.debug(f"[agentops.instrumentation.openai] Could not import OpenAI types: {e}")
|
15
|
+
|
16
|
+
|
17
|
+
def get_common_instrumentation_attributes() -> AttributeMap:
|
18
|
+
"""Get common instrumentation attributes for the OpenAI Agents instrumentation.
|
19
|
+
|
20
|
+
This combines the generic AgentOps attributes with OpenAI Agents specific library attributes.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Dictionary of common instrumentation attributes
|
24
|
+
"""
|
25
|
+
attributes = get_common_attributes()
|
26
|
+
attributes.update(
|
27
|
+
{
|
28
|
+
InstrumentationAttributes.LIBRARY_NAME: LIBRARY_NAME,
|
29
|
+
InstrumentationAttributes.LIBRARY_VERSION: LIBRARY_VERSION,
|
30
|
+
}
|
31
|
+
)
|
32
|
+
return attributes
|
33
|
+
|
34
|
+
|
35
|
+
def get_response_attributes(
|
36
|
+
args: Optional[Tuple] = None, kwargs: Optional[Dict] = None, return_value: Optional["Response"] = None
|
37
|
+
) -> AttributeMap:
|
38
|
+
""" """
|
39
|
+
# We can get an context object before, and after the request is made, so
|
40
|
+
# conditionally handle the data we have available.
|
41
|
+
attributes = get_common_instrumentation_attributes()
|
42
|
+
|
43
|
+
# Parse the keyword arguments to extract relevant attributes
|
44
|
+
# We do not ever get `args` from this method call since it is a keyword-only method
|
45
|
+
if kwargs:
|
46
|
+
attributes.update(get_response_kwarg_attributes(kwargs))
|
47
|
+
|
48
|
+
# Parse the return value to extract relevant attributes
|
49
|
+
if return_value:
|
50
|
+
if isinstance(return_value, Response):
|
51
|
+
attributes.update(get_response_response_attributes(return_value))
|
52
|
+
else:
|
53
|
+
logger.debug(f"[agentops.instrumentation.openai] Got an unexpected return type: {type(return_value)}")
|
54
|
+
|
55
|
+
return attributes
|