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.
@@ -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: json.dumps(prompts) if prompts else None,
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"),
@@ -1 +1 @@
1
- __version__ = "3.8.3"
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
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==1.60.0; extra == 'dev'
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=L0ktJXsGjvKS0dc6kWGCOUoNsGTERLEmd-1QfzDppq8,13706
119
- langtrace_python_sdk/version.py,sha256=suroMOhipFiXYE6cgp5XFXSXtW2pHyZibLMFSNkHUec,22
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=UOtU6nT-ZT-ZvHzOgPNhG_IooMe5jU8lzgdoDCHpeBc,2469
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=CrwHzkzLpdo2m2nBHE69d8MIFMxZuvTsT1LTxqlTWV0,2664
147
- langtrace_python_sdk/instrumentation/agno/patch.py,sha256=tbMscAxsZuo4MAEUQ9tUPiluyj8RRcksF7sYU-v2knM,13399
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=E_u0WUtBukmWjKjkgtJgeCS6ab_2xhcamLOH9cERNCM,2694
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=693egq-ztVLmlwdZ9KkTTzMpg_k397ErA28XFL00_ws,16733
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.3.dist-info/METADATA,sha256=Etxr0XXT7aO2v4RKQduS0KHOe5qKWY9Ozid_Ciu3efs,15792
301
- langtrace_python_sdk-3.8.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
302
- langtrace_python_sdk-3.8.3.dist-info/entry_points.txt,sha256=1_b9-qvf2fE7uQNZcbUei9vLpFZBbbh9LrtGw95ssAo,70
303
- langtrace_python_sdk-3.8.3.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
304
- langtrace_python_sdk-3.8.3.dist-info/RECORD,,
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,,