langtrace-python-sdk 2.3.2__py3-none-any.whl → 2.3.4__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.
- examples/anthropic_example/completion.py +1 -1
- examples/crewai_example/instagram_post/__init__.py +0 -0
- examples/crewai_example/instagram_post/agents.py +96 -0
- examples/crewai_example/instagram_post/main.py +80 -0
- examples/crewai_example/instagram_post/tasks.py +146 -0
- examples/crewai_example/instagram_post/tools/__init__.py +0 -0
- examples/crewai_example/instagram_post/tools/browser_tools.py +40 -0
- examples/openai_example/__init__.py +1 -0
- langtrace_python_sdk/instrumentation/anthropic/instrumentation.py +10 -9
- langtrace_python_sdk/instrumentation/anthropic/patch.py +33 -29
- langtrace_python_sdk/instrumentation/anthropic/types.py +105 -0
- langtrace_python_sdk/instrumentation/cohere/patch.py +1 -4
- langtrace_python_sdk/instrumentation/crewai/instrumentation.py +15 -0
- langtrace_python_sdk/instrumentation/crewai/patch.py +47 -25
- langtrace_python_sdk/instrumentation/gemini/patch.py +2 -5
- langtrace_python_sdk/instrumentation/groq/patch.py +7 -19
- langtrace_python_sdk/instrumentation/openai/instrumentation.py +14 -19
- langtrace_python_sdk/instrumentation/openai/patch.py +93 -101
- langtrace_python_sdk/instrumentation/openai/types.py +170 -0
- langtrace_python_sdk/instrumentation/vertexai/patch.py +2 -5
- langtrace_python_sdk/instrumentation/weaviate/patch.py +3 -13
- langtrace_python_sdk/langtrace.py +20 -21
- langtrace_python_sdk/utils/llm.py +12 -7
- langtrace_python_sdk/utils/silently_fail.py +19 -3
- langtrace_python_sdk/version.py +1 -1
- {langtrace_python_sdk-2.3.2.dist-info → langtrace_python_sdk-2.3.4.dist-info}/METADATA +1 -1
- {langtrace_python_sdk-2.3.2.dist-info → langtrace_python_sdk-2.3.4.dist-info}/RECORD +30 -22
- {langtrace_python_sdk-2.3.2.dist-info → langtrace_python_sdk-2.3.4.dist-info}/WHEEL +0 -0
- {langtrace_python_sdk-2.3.2.dist-info → langtrace_python_sdk-2.3.4.dist-info}/entry_points.txt +0 -0
- {langtrace_python_sdk-2.3.2.dist-info → langtrace_python_sdk-2.3.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -39,6 +39,21 @@ class CrewAIInstrumentation(BaseInstrumentor):
|
|
|
39
39
|
"Crew.kickoff",
|
|
40
40
|
patch_crew("Crew.kickoff", version, tracer),
|
|
41
41
|
)
|
|
42
|
+
_W(
|
|
43
|
+
"crewai.crew",
|
|
44
|
+
"Crew.kickoff_for_each",
|
|
45
|
+
patch_crew("Crew.kickoff_for_each", version, tracer),
|
|
46
|
+
)
|
|
47
|
+
_W(
|
|
48
|
+
"crewai.crew",
|
|
49
|
+
"Crew.kickoff_async",
|
|
50
|
+
patch_crew("Crew.kickoff_async", version, tracer),
|
|
51
|
+
)
|
|
52
|
+
_W(
|
|
53
|
+
"crewai.crew",
|
|
54
|
+
"Crew.kickoff_for_each_async",
|
|
55
|
+
patch_crew("Crew.kickoff_for_each_async", version, tracer),
|
|
56
|
+
)
|
|
42
57
|
_W(
|
|
43
58
|
"crewai.agent",
|
|
44
59
|
"Agent.execute_task",
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import json
|
|
2
|
+
|
|
2
3
|
from importlib_metadata import version as v
|
|
4
|
+
from langtrace.trace_attributes import FrameworkSpanAttributes
|
|
5
|
+
from opentelemetry import baggage
|
|
6
|
+
from opentelemetry.trace import Span, SpanKind, Tracer
|
|
7
|
+
from opentelemetry.trace.status import Status, StatusCode
|
|
8
|
+
|
|
3
9
|
from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
|
|
4
|
-
from langtrace_python_sdk.utils import set_span_attribute
|
|
5
|
-
from langtrace_python_sdk.utils.llm import get_span_name, set_span_attributes
|
|
6
10
|
from langtrace_python_sdk.constants.instrumentation.common import (
|
|
7
11
|
LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
|
|
8
12
|
SERVICE_PROVIDERS,
|
|
9
13
|
)
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from opentelemetry.trace import SpanKind, Span, Tracer
|
|
13
|
-
from opentelemetry.trace.status import Status, StatusCode
|
|
14
|
+
from langtrace_python_sdk.utils import set_span_attribute
|
|
15
|
+
from langtrace_python_sdk.utils.llm import get_span_name, set_span_attributes
|
|
14
16
|
from langtrace_python_sdk.utils.misc import serialize_args, serialize_kwargs
|
|
15
17
|
|
|
16
18
|
|
|
@@ -44,7 +46,9 @@ def patch_memory(operation_name, version, tracer: Tracer):
|
|
|
44
46
|
set_span_attributes(span, attributes)
|
|
45
47
|
result = wrapped(*args, **kwargs)
|
|
46
48
|
if result is not None and len(result) > 0:
|
|
47
|
-
set_span_attribute(
|
|
49
|
+
set_span_attribute(
|
|
50
|
+
span, "crewai.memory.storage.rag_storage.outputs", str(result)
|
|
51
|
+
)
|
|
48
52
|
if result:
|
|
49
53
|
span.set_status(Status(StatusCode.OK))
|
|
50
54
|
span.end()
|
|
@@ -87,20 +91,17 @@ def patch_crew(operation_name, version, tracer: Tracer):
|
|
|
87
91
|
CrewAISpanAttributes(span=span, instance=instance)
|
|
88
92
|
result = wrapped(*args, **kwargs)
|
|
89
93
|
if result:
|
|
94
|
+
class_name = instance.__class__.__name__
|
|
95
|
+
span.set_attribute(
|
|
96
|
+
f"crewai.{class_name.lower()}.result", str(result)
|
|
97
|
+
)
|
|
90
98
|
span.set_status(Status(StatusCode.OK))
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if hasattr(result, "usage_metrics"):
|
|
98
|
-
span.set_attribute("crewai.crew.usage_metrics", str((result.usage_metrics)))
|
|
99
|
-
elif instance.__class__.__name__ == "Agent":
|
|
100
|
-
span.set_attribute("crewai.agent.result", str(result))
|
|
101
|
-
elif instance.__class__.__name__ == "Task":
|
|
102
|
-
span.set_attribute("crewai.task.result", str(result))
|
|
103
|
-
|
|
99
|
+
if class_name == "Crew":
|
|
100
|
+
for attr in ["tasks_output", "token_usage", "usage_metrics"]:
|
|
101
|
+
if hasattr(result, attr):
|
|
102
|
+
span.set_attribute(
|
|
103
|
+
f"crewai.crew.{attr}", str(getattr(result, attr))
|
|
104
|
+
)
|
|
104
105
|
span.end()
|
|
105
106
|
return result
|
|
106
107
|
|
|
@@ -137,22 +138,27 @@ class CrewAISpanAttributes:
|
|
|
137
138
|
self.set_crew_attributes()
|
|
138
139
|
for key, value in self.crew.items():
|
|
139
140
|
key = f"crewai.crew.{key}"
|
|
140
|
-
|
|
141
|
+
if value is not None:
|
|
142
|
+
set_span_attribute(self.span, key, value)
|
|
141
143
|
|
|
142
144
|
elif instance_name == "Agent":
|
|
143
145
|
agent = self.set_agent_attributes()
|
|
144
146
|
for key, value in agent.items():
|
|
145
147
|
key = f"crewai.agent.{key}"
|
|
146
|
-
|
|
148
|
+
if value is not None:
|
|
149
|
+
set_span_attribute(self.span, key, value)
|
|
147
150
|
|
|
148
151
|
elif instance_name == "Task":
|
|
149
152
|
task = self.set_task_attributes()
|
|
150
153
|
for key, value in task.items():
|
|
151
154
|
key = f"crewai.task.{key}"
|
|
152
|
-
|
|
155
|
+
if value is not None:
|
|
156
|
+
set_span_attribute(self.span, key, value)
|
|
153
157
|
|
|
154
158
|
def set_crew_attributes(self):
|
|
155
159
|
for key, value in self.instance.__dict__.items():
|
|
160
|
+
if value is None:
|
|
161
|
+
continue
|
|
156
162
|
if key == "tasks":
|
|
157
163
|
self._parse_tasks(value)
|
|
158
164
|
elif key == "agents":
|
|
@@ -163,6 +169,8 @@ class CrewAISpanAttributes:
|
|
|
163
169
|
def set_agent_attributes(self):
|
|
164
170
|
agent = {}
|
|
165
171
|
for key, value in self.instance.__dict__.items():
|
|
172
|
+
if key == "tools":
|
|
173
|
+
value = self._parse_tools(value)
|
|
166
174
|
if value is None:
|
|
167
175
|
continue
|
|
168
176
|
agent[key] = str(value)
|
|
@@ -174,8 +182,10 @@ class CrewAISpanAttributes:
|
|
|
174
182
|
for key, value in self.instance.__dict__.items():
|
|
175
183
|
if value is None:
|
|
176
184
|
continue
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
if key == "tools":
|
|
186
|
+
value = self._parse_tools(value)
|
|
187
|
+
task[key] = value
|
|
188
|
+
elif key == "agent":
|
|
179
189
|
task[key] = value.role
|
|
180
190
|
else:
|
|
181
191
|
task[key] = str(value)
|
|
@@ -218,3 +228,15 @@ class CrewAISpanAttributes:
|
|
|
218
228
|
"output_file": task.output_file,
|
|
219
229
|
}
|
|
220
230
|
)
|
|
231
|
+
|
|
232
|
+
def _parse_tools(self, tools):
|
|
233
|
+
result = []
|
|
234
|
+
for tool in tools:
|
|
235
|
+
res = {}
|
|
236
|
+
if hasattr(tool, "name") and tool.name is not None:
|
|
237
|
+
res["name"] = tool.name
|
|
238
|
+
if hasattr(tool, "description") and tool.description is not None:
|
|
239
|
+
res["description"] = tool.description
|
|
240
|
+
if res:
|
|
241
|
+
result.append(res)
|
|
242
|
+
return json.dumps(result)
|
|
@@ -100,12 +100,9 @@ def apatch_gemini(name, version, tracer: Tracer):
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
def get_llm_model(instance):
|
|
103
|
-
llm_model = "unknown"
|
|
104
|
-
if hasattr(instance, "_model_id"):
|
|
105
|
-
llm_model = instance._model_id
|
|
106
103
|
if hasattr(instance, "_model_name"):
|
|
107
|
-
|
|
108
|
-
return
|
|
104
|
+
return instance._model_name.replace("models/", "")
|
|
105
|
+
return getattr(instance, "_model_id", "unknown")
|
|
109
106
|
|
|
110
107
|
|
|
111
108
|
def serialize_prompts(args, kwargs, instance):
|
|
@@ -158,7 +158,7 @@ def chat_completions_create(original_method, version, tracer):
|
|
|
158
158
|
usage = result.usage
|
|
159
159
|
set_usage_attributes(span, dict(usage))
|
|
160
160
|
|
|
161
|
-
span.set_status(StatusCode.OK)
|
|
161
|
+
span.set_status(Status(StatusCode.OK))
|
|
162
162
|
span.end()
|
|
163
163
|
return result
|
|
164
164
|
else:
|
|
@@ -257,7 +257,7 @@ def chat_completions_create(original_method, version, tracer):
|
|
|
257
257
|
span, [{"role": "assistant", "content": "".join(result_content)}]
|
|
258
258
|
)
|
|
259
259
|
|
|
260
|
-
span.set_status(StatusCode.OK)
|
|
260
|
+
span.set_status(Status(StatusCode.OK))
|
|
261
261
|
span.end()
|
|
262
262
|
|
|
263
263
|
# return the wrapped method
|
|
@@ -282,21 +282,13 @@ def async_chat_completions_create(original_method, version, tracer):
|
|
|
282
282
|
tool_calls = []
|
|
283
283
|
for tool_call in item.tool_calls:
|
|
284
284
|
tool_call_dict = {
|
|
285
|
-
"id":
|
|
286
|
-
"type":
|
|
285
|
+
"id": getattr(tool_call, "id", ""),
|
|
286
|
+
"type": getattr(tool_call, "type", ""),
|
|
287
287
|
}
|
|
288
288
|
if hasattr(tool_call, "function"):
|
|
289
289
|
tool_call_dict["function"] = {
|
|
290
|
-
"name": (
|
|
291
|
-
|
|
292
|
-
if hasattr(tool_call.function, "name")
|
|
293
|
-
else ""
|
|
294
|
-
),
|
|
295
|
-
"arguments": (
|
|
296
|
-
tool_call.function.arguments
|
|
297
|
-
if hasattr(tool_call.function, "arguments")
|
|
298
|
-
else ""
|
|
299
|
-
),
|
|
290
|
+
"name": getattr(tool_call.function, "name", ""),
|
|
291
|
+
"arguments": getattr(tool_call.function, "arguments", ""),
|
|
300
292
|
}
|
|
301
293
|
tool_calls.append(tool_call_dict)
|
|
302
294
|
llm_prompts.append(tool_calls)
|
|
@@ -459,11 +451,7 @@ def async_chat_completions_create(original_method, version, tracer):
|
|
|
459
451
|
tool_call.function.arguments
|
|
460
452
|
)
|
|
461
453
|
completion_tokens += token_counts
|
|
462
|
-
content
|
|
463
|
-
tool_call.function.arguments
|
|
464
|
-
]
|
|
465
|
-
else:
|
|
466
|
-
content = content + []
|
|
454
|
+
content += [tool_call.function.arguments]
|
|
467
455
|
else:
|
|
468
456
|
content = []
|
|
469
457
|
span.add_event(
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Copyright (c) 2024 Scale3 Labs
|
|
3
|
-
|
|
4
3
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
4
|
you may not use this file except in compliance with the License.
|
|
6
5
|
You may obtain a copy of the License at
|
|
7
|
-
|
|
8
6
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
|
|
10
7
|
Unless required by applicable law or agreed to in writing, software
|
|
11
8
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
9
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
@@ -14,12 +11,12 @@ See the License for the specific language governing permissions and
|
|
|
14
11
|
limitations under the License.
|
|
15
12
|
"""
|
|
16
13
|
|
|
14
|
+
from typing import Collection, Optional, Any
|
|
17
15
|
import importlib.metadata
|
|
18
16
|
import logging
|
|
19
|
-
from typing import Collection
|
|
20
17
|
|
|
21
18
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
22
|
-
from opentelemetry.trace import get_tracer
|
|
19
|
+
from opentelemetry.trace import get_tracer, TracerProvider
|
|
23
20
|
from wrapt import wrap_function_wrapper
|
|
24
21
|
|
|
25
22
|
from langtrace_python_sdk.instrumentation.openai.patch import (
|
|
@@ -35,59 +32,57 @@ from langtrace_python_sdk.instrumentation.openai.patch import (
|
|
|
35
32
|
logging.basicConfig(level=logging.FATAL)
|
|
36
33
|
|
|
37
34
|
|
|
38
|
-
class OpenAIInstrumentation(BaseInstrumentor):
|
|
35
|
+
class OpenAIInstrumentation(BaseInstrumentor): # type: ignore
|
|
39
36
|
|
|
40
37
|
def instrumentation_dependencies(self) -> Collection[str]:
|
|
41
38
|
return ["openai >= 0.27.0", "trace-attributes >= 4.0.5"]
|
|
42
39
|
|
|
43
|
-
def _instrument(self, **kwargs):
|
|
44
|
-
tracer_provider = kwargs.get("tracer_provider")
|
|
40
|
+
def _instrument(self, **kwargs: Any) -> None:
|
|
41
|
+
tracer_provider: Optional[TracerProvider] = kwargs.get("tracer_provider")
|
|
45
42
|
tracer = get_tracer(__name__, "", tracer_provider)
|
|
46
|
-
version = importlib.metadata.version("openai")
|
|
43
|
+
version: str = importlib.metadata.version("openai")
|
|
47
44
|
|
|
48
45
|
wrap_function_wrapper(
|
|
49
46
|
"openai.resources.chat.completions",
|
|
50
47
|
"Completions.create",
|
|
51
|
-
chat_completions_create(
|
|
48
|
+
chat_completions_create(version, tracer),
|
|
52
49
|
)
|
|
53
50
|
|
|
54
51
|
wrap_function_wrapper(
|
|
55
52
|
"openai.resources.chat.completions",
|
|
56
53
|
"AsyncCompletions.create",
|
|
57
|
-
async_chat_completions_create(
|
|
58
|
-
"openai.chat.completions.create_stream", version, tracer
|
|
59
|
-
),
|
|
54
|
+
async_chat_completions_create(version, tracer),
|
|
60
55
|
)
|
|
61
56
|
|
|
62
57
|
wrap_function_wrapper(
|
|
63
58
|
"openai.resources.images",
|
|
64
59
|
"Images.generate",
|
|
65
|
-
images_generate(
|
|
60
|
+
images_generate(version, tracer),
|
|
66
61
|
)
|
|
67
62
|
|
|
68
63
|
wrap_function_wrapper(
|
|
69
64
|
"openai.resources.images",
|
|
70
65
|
"AsyncImages.generate",
|
|
71
|
-
async_images_generate(
|
|
66
|
+
async_images_generate(version, tracer),
|
|
72
67
|
)
|
|
73
68
|
|
|
74
69
|
wrap_function_wrapper(
|
|
75
70
|
"openai.resources.images",
|
|
76
71
|
"Images.edit",
|
|
77
|
-
images_edit(
|
|
72
|
+
images_edit(version, tracer),
|
|
78
73
|
)
|
|
79
74
|
|
|
80
75
|
wrap_function_wrapper(
|
|
81
76
|
"openai.resources.embeddings",
|
|
82
77
|
"Embeddings.create",
|
|
83
|
-
embeddings_create(
|
|
78
|
+
embeddings_create(version, tracer),
|
|
84
79
|
)
|
|
85
80
|
|
|
86
81
|
wrap_function_wrapper(
|
|
87
82
|
"openai.resources.embeddings",
|
|
88
83
|
"AsyncEmbeddings.create",
|
|
89
|
-
async_embeddings_create(
|
|
84
|
+
async_embeddings_create(version, tracer),
|
|
90
85
|
)
|
|
91
86
|
|
|
92
|
-
def _uninstrument(self, **kwargs):
|
|
87
|
+
def _uninstrument(self, **kwargs: Any) -> None:
|
|
93
88
|
pass
|