langtrace-python-sdk 3.8.3__py3-none-any.whl → 3.8.5__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.
- langtrace_python_sdk/instrumentation/__init__.py +2 -0
- langtrace_python_sdk/instrumentation/agno/instrumentation.py +6 -3
- langtrace_python_sdk/instrumentation/agno/patch.py +277 -229
- langtrace_python_sdk/instrumentation/openai_agents/__init__.py +5 -0
- langtrace_python_sdk/instrumentation/openai_agents/instrumentation.py +52 -0
- langtrace_python_sdk/instrumentation/openai_agents/patch.py +533 -0
- langtrace_python_sdk/instrumentation/phidata/instrumentation.py +6 -3
- langtrace_python_sdk/langtrace.py +4 -3
- langtrace_python_sdk/utils/llm.py +151 -1
- langtrace_python_sdk/version.py +1 -1
- {langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/METADATA +3 -2
- {langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/RECORD +15 -12
- {langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/WHEEL +0 -0
- {langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/entry_points.txt +0 -0
- {langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/licenses/LICENSE +0 -0
@@ -94,6 +94,139 @@ def calculate_price_from_usage(model, usage):
|
|
94
94
|
return 0
|
95
95
|
|
96
96
|
|
97
|
+
def convert_mistral_messages_to_serializable(mistral_messages):
|
98
|
+
serializable_messages = []
|
99
|
+
|
100
|
+
try:
|
101
|
+
for message in mistral_messages:
|
102
|
+
serializable_message = {"role": message.role}
|
103
|
+
|
104
|
+
# Handle content
|
105
|
+
if hasattr(message, "content"):
|
106
|
+
serializable_message["content"] = message.content
|
107
|
+
|
108
|
+
# Handle tool_calls
|
109
|
+
if hasattr(message, "tool_calls") and message.tool_calls is not None:
|
110
|
+
serializable_tool_calls = []
|
111
|
+
|
112
|
+
for tool_call in message.tool_calls:
|
113
|
+
serializable_tool_call = {}
|
114
|
+
|
115
|
+
# Handle id, type, and index
|
116
|
+
if hasattr(tool_call, "id"):
|
117
|
+
serializable_tool_call["id"] = tool_call.id
|
118
|
+
if hasattr(tool_call, "type"):
|
119
|
+
serializable_tool_call["type"] = tool_call.type
|
120
|
+
if hasattr(tool_call, "index"):
|
121
|
+
serializable_tool_call["index"] = tool_call.index
|
122
|
+
|
123
|
+
# Handle function
|
124
|
+
if hasattr(tool_call, "function"):
|
125
|
+
function_call = tool_call.function
|
126
|
+
serializable_function = {}
|
127
|
+
|
128
|
+
if hasattr(function_call, "name"):
|
129
|
+
serializable_function["name"] = function_call.name
|
130
|
+
if hasattr(function_call, "arguments"):
|
131
|
+
serializable_function["arguments"] = function_call.arguments
|
132
|
+
|
133
|
+
serializable_tool_call["function"] = serializable_function
|
134
|
+
|
135
|
+
serializable_tool_calls.append(serializable_tool_call)
|
136
|
+
|
137
|
+
serializable_message["tool_calls"] = serializable_tool_calls
|
138
|
+
|
139
|
+
# Handle tool_call_id for tool messages
|
140
|
+
if hasattr(message, "tool_call_id"):
|
141
|
+
serializable_message["tool_call_id"] = message.tool_call_id
|
142
|
+
|
143
|
+
serializable_messages.append(serializable_message)
|
144
|
+
except Exception as e:
|
145
|
+
pass
|
146
|
+
|
147
|
+
return serializable_messages
|
148
|
+
|
149
|
+
|
150
|
+
def convert_gemini_messages_to_serializable(formatted_messages, system_message=None):
|
151
|
+
"""
|
152
|
+
Converts Gemini-formatted messages back to a JSON serializable format.
|
153
|
+
|
154
|
+
Args:
|
155
|
+
formatted_messages: The formatted messages from Gemini.
|
156
|
+
system_message (str, optional): System message content.
|
157
|
+
|
158
|
+
Returns:
|
159
|
+
List[dict]: JSON serializable list of message dictionaries.
|
160
|
+
"""
|
161
|
+
serializable_messages = []
|
162
|
+
|
163
|
+
try:
|
164
|
+
# Add system message if present
|
165
|
+
if system_message:
|
166
|
+
serializable_messages.append({
|
167
|
+
"role": "system",
|
168
|
+
"content": system_message
|
169
|
+
})
|
170
|
+
|
171
|
+
for message_item in formatted_messages:
|
172
|
+
# Handle the case where the item is a dict with 'role' and 'content' keys
|
173
|
+
if isinstance(message_item, dict) and 'role' in message_item and 'content' in message_item:
|
174
|
+
role = message_item['role']
|
175
|
+
content_value = message_item['content']
|
176
|
+
|
177
|
+
# Initialize our serializable message
|
178
|
+
serializable_message = {"role": role}
|
179
|
+
|
180
|
+
# If content is a list of Content objects
|
181
|
+
if isinstance(content_value, list) and len(content_value) > 0:
|
182
|
+
for content_obj in content_value:
|
183
|
+
# Process each Content object
|
184
|
+
if hasattr(content_obj, 'parts') and hasattr(content_obj, 'role'):
|
185
|
+
parts = content_obj.parts
|
186
|
+
|
187
|
+
# Extract text from parts
|
188
|
+
text_parts = []
|
189
|
+
for part in parts:
|
190
|
+
if hasattr(part, 'text') and part.text:
|
191
|
+
text_parts.append(part.text)
|
192
|
+
|
193
|
+
if text_parts:
|
194
|
+
serializable_message["content"] = " ".join(text_parts)
|
195
|
+
|
196
|
+
# Here you can add additional processing for other part types
|
197
|
+
# like function_call, function_response, inline_data, etc.
|
198
|
+
# Similar to the previous implementation
|
199
|
+
|
200
|
+
# If content is a string or already a primitive type
|
201
|
+
elif isinstance(content_value, (str, int, float, bool)) or content_value is None:
|
202
|
+
serializable_message["content"] = content_value
|
203
|
+
|
204
|
+
# Add the processed message to our list
|
205
|
+
serializable_messages.append(serializable_message)
|
206
|
+
|
207
|
+
# Handle the case where the item is a Content object directly
|
208
|
+
elif hasattr(message_item, 'role') and hasattr(message_item, 'parts'):
|
209
|
+
# This is the case from the previous implementation
|
210
|
+
# Process a Content object directly
|
211
|
+
serializable_message = {"role": message_item.role}
|
212
|
+
|
213
|
+
parts = message_item.parts
|
214
|
+
text_parts = []
|
215
|
+
|
216
|
+
for part in parts:
|
217
|
+
if hasattr(part, 'text') and part.text:
|
218
|
+
text_parts.append(part.text)
|
219
|
+
|
220
|
+
if text_parts:
|
221
|
+
serializable_message["content"] = " ".join(text_parts)
|
222
|
+
|
223
|
+
serializable_messages.append(serializable_message)
|
224
|
+
except Exception as e:
|
225
|
+
pass
|
226
|
+
|
227
|
+
return serializable_messages
|
228
|
+
|
229
|
+
|
97
230
|
def get_langtrace_attributes(version, service_provider, vendor_type="llm"):
|
98
231
|
return {
|
99
232
|
SpanAttributes.LANGTRACE_SDK_NAME: LANGTRACE_SDK_NAME,
|
@@ -120,6 +253,23 @@ def get_llm_request_attributes(kwargs, prompts=None, model=None, operation_name=
|
|
120
253
|
or kwargs.get("top_k", None)
|
121
254
|
or kwargs.get("top_n", None)
|
122
255
|
)
|
256
|
+
|
257
|
+
try:
|
258
|
+
prompts = json.dumps(prompts) if prompts else None
|
259
|
+
except Exception as e:
|
260
|
+
if "is not JSON serializable" in str(e):
|
261
|
+
# check model
|
262
|
+
if kwargs.get("model") is not None:
|
263
|
+
if kwargs.get("model").startswith("gemini"):
|
264
|
+
prompts = json.dumps(convert_gemini_messages_to_serializable(prompts))
|
265
|
+
elif kwargs.get("model").startswith("mistral"):
|
266
|
+
prompts = json.dumps(convert_mistral_messages_to_serializable(prompts))
|
267
|
+
else:
|
268
|
+
prompts = "[]"
|
269
|
+
else:
|
270
|
+
prompts = "[]"
|
271
|
+
else:
|
272
|
+
prompts = "[]"
|
123
273
|
|
124
274
|
top_p = kwargs.get("p", None) or kwargs.get("top_p", None)
|
125
275
|
tools = kwargs.get("tools", None)
|
@@ -132,7 +282,7 @@ def get_llm_request_attributes(kwargs, prompts=None, model=None, operation_name=
|
|
132
282
|
SpanAttributes.LLM_IS_STREAMING: kwargs.get("stream"),
|
133
283
|
SpanAttributes.LLM_REQUEST_TEMPERATURE: kwargs.get("temperature"),
|
134
284
|
SpanAttributes.LLM_TOP_K: top_k,
|
135
|
-
SpanAttributes.LLM_PROMPTS:
|
285
|
+
SpanAttributes.LLM_PROMPTS: prompts if prompts else None,
|
136
286
|
SpanAttributes.LLM_USER: user,
|
137
287
|
SpanAttributes.LLM_REQUEST_TOP_P: top_p,
|
138
288
|
SpanAttributes.LLM_REQUEST_MAX_TOKENS: kwargs.get("max_tokens"),
|
langtrace_python_sdk/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "3.8.
|
1
|
+
__version__ = "3.8.5"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: langtrace-python-sdk
|
3
|
-
Version: 3.8.
|
3
|
+
Version: 3.8.5
|
4
4
|
Summary: Python SDK for LangTrace
|
5
5
|
Project-URL: Homepage, https://github.com/Scale3-Labs/langtrace-python-sdk
|
6
6
|
Author-email: Scale3 Labs <engineering@scale3labs.com>
|
@@ -41,7 +41,8 @@ Requires-Dist: langchain-openai; extra == 'dev'
|
|
41
41
|
Requires-Dist: litellm==1.48.7; extra == 'dev'
|
42
42
|
Requires-Dist: mistralai; extra == 'dev'
|
43
43
|
Requires-Dist: ollama; extra == 'dev'
|
44
|
-
Requires-Dist: openai
|
44
|
+
Requires-Dist: openai-agents>=0.0.3; extra == 'dev'
|
45
|
+
Requires-Dist: openai>=1.60.0; extra == 'dev'
|
45
46
|
Requires-Dist: phidata; extra == 'dev'
|
46
47
|
Requires-Dist: pinecone; extra == 'dev'
|
47
48
|
Requires-Dist: python-dotenv; extra == 'dev'
|
@@ -115,8 +115,8 @@ examples/vertexai_example/main.py,sha256=gndId5X5ksD-ycxnAWMdEqIDbLc3kz5Vt8vm4YP
|
|
115
115
|
examples/weaviate_example/__init__.py,sha256=8JMDBsRSEV10HfTd-YC7xb4txBjD3la56snk-Bbg2Kw,618
|
116
116
|
examples/weaviate_example/query_text.py,sha256=wPHQTc_58kPoKTZMygVjTj-2ZcdrIuaausJfMxNQnQc,127162
|
117
117
|
langtrace_python_sdk/__init__.py,sha256=VZM6i71NR7pBQK6XvJWRelknuTYUhqwqE7PlicKa5Wg,1166
|
118
|
-
langtrace_python_sdk/langtrace.py,sha256=
|
119
|
-
langtrace_python_sdk/version.py,sha256=
|
118
|
+
langtrace_python_sdk/langtrace.py,sha256=T-DsDrwWaL4gAUK1lkTRRpmvoO7F2WtO5hQZdyrVAxE,13791
|
119
|
+
langtrace_python_sdk/version.py,sha256=mb3dZLLIE3dKNa7hv1kuERgx4o1UEUlj7DsxZRc2A38,22
|
120
120
|
langtrace_python_sdk/constants/__init__.py,sha256=3CNYkWMdd1DrkGqzLUgNZXjdAlM6UFMlf_F-odAToyc,146
|
121
121
|
langtrace_python_sdk/constants/exporter/langtrace_exporter.py,sha256=EVCrouYCpY98f0KSaKr4PzNxPULTZZO6dSA_crEOyJU,106
|
122
122
|
langtrace_python_sdk/constants/instrumentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -141,10 +141,10 @@ langtrace_python_sdk/constants/instrumentation/weaviate.py,sha256=gtv-JBxvNGClEM
|
|
141
141
|
langtrace_python_sdk/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
142
|
langtrace_python_sdk/extensions/langtrace_exporter.py,sha256=ckd8dMmY6h2oxE04p1JFLwUB5PSJX_Cy4eDFEM6aj4Y,6605
|
143
143
|
langtrace_python_sdk/extensions/langtrace_filesystem.py,sha256=34fZutG28EJ66l67OvTGsydAH3ZpXgikdE7hVLqBpG4,7863
|
144
|
-
langtrace_python_sdk/instrumentation/__init__.py,sha256=
|
144
|
+
langtrace_python_sdk/instrumentation/__init__.py,sha256=DC96oELorZedDf5zooQ6HGi-dmieXwUephgeB_LzfaU,2559
|
145
145
|
langtrace_python_sdk/instrumentation/agno/__init__.py,sha256=95fn4oA-CHB0mxc6KnVB20KSbXGl_ZZr9n99EEaXzrY,91
|
146
|
-
langtrace_python_sdk/instrumentation/agno/instrumentation.py,sha256=
|
147
|
-
langtrace_python_sdk/instrumentation/agno/patch.py,sha256=
|
146
|
+
langtrace_python_sdk/instrumentation/agno/instrumentation.py,sha256=XUnfvqpp13IgdF03xGKasq7kGjeaN1sXLIwCf-Nt_Nc,2667
|
147
|
+
langtrace_python_sdk/instrumentation/agno/patch.py,sha256=qCUxCkzU9cYu_d8BzLgj_Ss97qib07tRVYpYDiNnNMs,16876
|
148
148
|
langtrace_python_sdk/instrumentation/anthropic/__init__.py,sha256=donrurJAGYlxrSRA3BIf76jGeUcAx9Tq8CVpah68S0Y,101
|
149
149
|
langtrace_python_sdk/instrumentation/anthropic/instrumentation.py,sha256=ndXdruI0BG7n75rsuEpKjfzePxrZxg40gZ39ONmD_v4,1845
|
150
150
|
langtrace_python_sdk/instrumentation/anthropic/patch.py,sha256=ztPN4VZujoxYOKhTbFnup7Ibms9NAzYCPAJY43NUgKw,4935
|
@@ -225,8 +225,11 @@ langtrace_python_sdk/instrumentation/openai/__init__.py,sha256=VPHRNCQEdkizIVP2d
|
|
225
225
|
langtrace_python_sdk/instrumentation/openai/instrumentation.py,sha256=PZxI0qfoud1VsKGmJu49YDp0Z9z9TzCR8qxR3uznOMA,2810
|
226
226
|
langtrace_python_sdk/instrumentation/openai/patch.py,sha256=mRE150sHGL2dq4oOKTYWek1vup7HuRW_sqP6nNOd3N8,27862
|
227
227
|
langtrace_python_sdk/instrumentation/openai/types.py,sha256=aVkoa7tmAbYfyOhnyMrDaVjQuwhmRNLMthlNtKMtWX8,4311
|
228
|
+
langtrace_python_sdk/instrumentation/openai_agents/__init__.py,sha256=ElRfFIQYXD2-eRyL3fZnjIsDJLTrDolh5cZHPnZv0q8,107
|
229
|
+
langtrace_python_sdk/instrumentation/openai_agents/instrumentation.py,sha256=6M4FHXfem7pazrNgsimebrEfMb2FxI8lHrdEMbVf75Y,1860
|
230
|
+
langtrace_python_sdk/instrumentation/openai_agents/patch.py,sha256=zXuIjqnPvWNEu8nCDTRxxvTAi8PwAOsBJEtsFn3PXaI,24012
|
228
231
|
langtrace_python_sdk/instrumentation/phidata/__init__.py,sha256=q2v6luvqp9gFf1AJX6YrBvuyMC_q6cEnB5syl2HNPlU,97
|
229
|
-
langtrace_python_sdk/instrumentation/phidata/instrumentation.py,sha256=
|
232
|
+
langtrace_python_sdk/instrumentation/phidata/instrumentation.py,sha256=S639XMVOGmpIK9jug9NWrUBLqs1G5ywBZiIhVuCkwGk,2697
|
230
233
|
langtrace_python_sdk/instrumentation/phidata/patch.py,sha256=-Jf_20wLLRGRM6sY3RreS-ocXjdq5m33-gxNtl_eUdQ,12133
|
231
234
|
langtrace_python_sdk/instrumentation/pinecone/__init__.py,sha256=DzXyGh9_MGWveJvXULkFwdkf7PbG2s3bAWtT1Dmz7Ok,99
|
232
235
|
langtrace_python_sdk/instrumentation/pinecone/instrumentation.py,sha256=2jhxGmXPrdSsrETRR_e58Rdc_uoKfRunvsCc660v6QA,1831
|
@@ -246,7 +249,7 @@ langtrace_python_sdk/instrumentation/weaviate/patch.py,sha256=Lqixz32uAvDA2VLU3z
|
|
246
249
|
langtrace_python_sdk/types/__init__.py,sha256=SJSJzkgPjGGTVJXUZ_FyR3p9DJ5kWGx7iAnJfY4ZYHU,4669
|
247
250
|
langtrace_python_sdk/utils/__init__.py,sha256=VVDOG-QLd59ZvSHp0avjof0sbxlZ1QQOf0KoOF7ofhQ,3310
|
248
251
|
langtrace_python_sdk/utils/langtrace_sampler.py,sha256=BupNndHbU9IL_wGleKetz8FdcveqHMBVz1bfKTTW80w,1753
|
249
|
-
langtrace_python_sdk/utils/llm.py,sha256=
|
252
|
+
langtrace_python_sdk/utils/llm.py,sha256=giJU33LvMPaRjPAjUwBCehgHj_ei1HwM7gLJSVWYLnI,23238
|
250
253
|
langtrace_python_sdk/utils/misc.py,sha256=LaQr5LOmZMiuwVdjYh7aIu6o2C_Xb1wgpQGNOVmRzfE,1918
|
251
254
|
langtrace_python_sdk/utils/prompt_registry.py,sha256=n5dQMVLBw8aJZY8Utvf67bncc25ELf6AH9BYw8_hSzo,2619
|
252
255
|
langtrace_python_sdk/utils/sdk_version_checker.py,sha256=F-VVVH7Fmhr5LcY0IIe-34zIi5RQcx26uuxFpPzZesM,1782
|
@@ -297,8 +300,8 @@ tests/pinecone/cassettes/test_query.yaml,sha256=b5v9G3ssUy00oG63PlFUR3JErF2Js-5A
|
|
297
300
|
tests/pinecone/cassettes/test_upsert.yaml,sha256=neWmQ1v3d03V8WoLl8FoFeeCYImb8pxlJBWnFd_lITU,38607
|
298
301
|
tests/qdrant/conftest.py,sha256=9n0uHxxIjWk9fbYc4bx-uP8lSAgLBVx-cV9UjnsyCHM,381
|
299
302
|
tests/qdrant/test_qdrant.py,sha256=pzjAjVY2kmsmGfrI2Gs2xrolfuaNHz7l1fqGQCjp5_o,3353
|
300
|
-
langtrace_python_sdk-3.8.
|
301
|
-
langtrace_python_sdk-3.8.
|
302
|
-
langtrace_python_sdk-3.8.
|
303
|
-
langtrace_python_sdk-3.8.
|
304
|
-
langtrace_python_sdk-3.8.
|
303
|
+
langtrace_python_sdk-3.8.5.dist-info/METADATA,sha256=oM9Ya7m7DDYBDT1VtPe3uguAKkvdJImtz2WGgSxmLbo,15844
|
304
|
+
langtrace_python_sdk-3.8.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
305
|
+
langtrace_python_sdk-3.8.5.dist-info/entry_points.txt,sha256=1_b9-qvf2fE7uQNZcbUei9vLpFZBbbh9LrtGw95ssAo,70
|
306
|
+
langtrace_python_sdk-3.8.5.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
307
|
+
langtrace_python_sdk-3.8.5.dist-info/RECORD,,
|
File without changes
|
{langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/entry_points.txt
RENAMED
File without changes
|
{langtrace_python_sdk-3.8.3.dist-info → langtrace_python_sdk-3.8.5.dist-info}/licenses/LICENSE
RENAMED
File without changes
|