langtrace-python-sdk 1.3.6__py3-none-any.whl → 2.0.0__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.
Files changed (54) hide show
  1. examples/anthropic_example/completion.py +6 -6
  2. examples/cohere_example/chat.py +5 -4
  3. examples/cohere_example/chat_stream.py +2 -4
  4. examples/cohere_example/{embed_create.py → embed.py} +4 -3
  5. examples/cohere_example/rerank.py +31 -0
  6. examples/cohere_example/tools.py +40 -0
  7. examples/openai_example/chat_completion.py +41 -0
  8. examples/{openai → openai_example}/embeddings_create.py +3 -2
  9. examples/{openai → openai_example}/function_calling.py +3 -5
  10. examples/{openai → openai_example}/images_generate.py +1 -1
  11. examples/openai_example/tool_calling.py +67 -0
  12. examples/{openai → openai_example}/tool_calling_nonstreaming.py +2 -1
  13. langtrace_python_sdk/__init__.py +14 -1
  14. langtrace_python_sdk/constants/instrumentation/cohere.py +6 -1
  15. langtrace_python_sdk/instrumentation/anthropic/instrumentation.py +16 -4
  16. langtrace_python_sdk/instrumentation/anthropic/patch.py +26 -6
  17. langtrace_python_sdk/instrumentation/chroma/instrumentation.py +14 -2
  18. langtrace_python_sdk/instrumentation/chroma/patch.py +16 -4
  19. langtrace_python_sdk/instrumentation/cohere/instrumentation.py +24 -7
  20. langtrace_python_sdk/instrumentation/cohere/patch.py +295 -95
  21. langtrace_python_sdk/instrumentation/langchain/instrumentation.py +14 -3
  22. langtrace_python_sdk/instrumentation/langchain/patch.py +16 -4
  23. langtrace_python_sdk/instrumentation/langchain_community/instrumentation.py +15 -2
  24. langtrace_python_sdk/instrumentation/langchain_community/patch.py +20 -3
  25. langtrace_python_sdk/instrumentation/langchain_core/instrumentation.py +14 -4
  26. langtrace_python_sdk/instrumentation/langchain_core/patch.py +19 -7
  27. langtrace_python_sdk/instrumentation/llamaindex/instrumentation.py +15 -11
  28. langtrace_python_sdk/instrumentation/llamaindex/patch.py +20 -10
  29. langtrace_python_sdk/instrumentation/openai/instrumentation.py +20 -9
  30. langtrace_python_sdk/instrumentation/openai/patch.py +112 -78
  31. langtrace_python_sdk/instrumentation/pinecone/instrumentation.py +14 -3
  32. langtrace_python_sdk/instrumentation/pinecone/patch.py +17 -4
  33. langtrace_python_sdk/langtrace.py +40 -35
  34. langtrace_python_sdk/utils/llm.py +17 -4
  35. langtrace_python_sdk/utils/with_root_span.py +21 -5
  36. langtrace_python_sdk/version.py +1 -1
  37. {langtrace_python_sdk-1.3.6.dist-info → langtrace_python_sdk-2.0.0.dist-info}/METADATA +2 -2
  38. {langtrace_python_sdk-1.3.6.dist-info → langtrace_python_sdk-2.0.0.dist-info}/RECORD +53 -45
  39. tests/anthropic/cassettes/test_anthropic.yaml +85 -0
  40. tests/anthropic/cassettes/test_anthropic_streaming.yaml +456 -0
  41. tests/anthropic/cassettes/test_async_anthropic_streaming.yaml +328 -0
  42. tests/anthropic/conftest.py +38 -0
  43. tests/anthropic/test_anthropic.py +108 -72
  44. tests/conftest.py +17 -0
  45. tests/openai/conftest.py +5 -13
  46. tests/openai/test_chat_completion.py +21 -0
  47. tests/openai/test_image_generation.py +20 -8
  48. examples/openai/chat_completion.py +0 -58
  49. /examples/{openai → openai_example}/__init__.py +0 -0
  50. /examples/{openai → openai_example}/async_tool_calling_nonstreaming.py +0 -0
  51. /examples/{openai → openai_example}/async_tool_calling_streaming.py +0 -0
  52. /examples/{openai → openai_example}/tool_calling_streaming.py +0 -0
  53. {langtrace_python_sdk-1.3.6.dist-info → langtrace_python_sdk-2.0.0.dist-info}/WHEEL +0 -0
  54. {langtrace_python_sdk-1.3.6.dist-info → langtrace_python_sdk-2.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,17 @@
1
1
  """
2
- Instrumentation for langchain-core.
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
3
15
  """
4
16
 
5
17
  import importlib.metadata
@@ -11,9 +23,7 @@ from opentelemetry.trace import get_tracer
11
23
  from wrapt import wrap_function_wrapper
12
24
 
13
25
  from langtrace_python_sdk.instrumentation.langchain_core.patch import (
14
- generic_patch,
15
- runnable_patch,
16
- )
26
+ generic_patch, runnable_patch)
17
27
 
18
28
 
19
29
  # pylint: disable=dangerous-default-value
@@ -1,5 +1,17 @@
1
1
  """
2
- This module contains the patching functions for the langchain_core package.
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
3
15
  """
4
16
 
5
17
  import json
@@ -68,12 +80,12 @@ def generic_patch(
68
80
 
69
81
  span.set_status(StatusCode.OK)
70
82
  return result
71
- except Exception as e:
83
+ except Exception as err:
72
84
  # Record the exception in the span
73
- span.record_exception(e)
85
+ span.record_exception(err)
74
86
 
75
87
  # Set the span status to indicate an error
76
- span.set_status(Status(StatusCode.ERROR, str(e)))
88
+ span.set_status(Status(StatusCode.ERROR, str(err)))
77
89
 
78
90
  # Reraise the exception to ensure it's not swallowed
79
91
  raise
@@ -157,12 +169,12 @@ def runnable_patch(
157
169
 
158
170
  span.set_status(StatusCode.OK)
159
171
  return result
160
- except Exception as e:
172
+ except Exception as err:
161
173
  # Record the exception in the span
162
- span.record_exception(e)
174
+ span.record_exception(err)
163
175
 
164
176
  # Set the span status to indicate an error
165
- span.set_status(Status(StatusCode.ERROR, str(e)))
177
+ span.set_status(Status(StatusCode.ERROR, str(err)))
166
178
 
167
179
  # Reraise the exception to ensure it's not swallowed
168
180
  raise
@@ -1,25 +1,29 @@
1
1
  """
2
- The LlamaindexInstrumentation class represents the LlamaIndex instrumentation
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
3
15
  """
4
16
 
5
17
  import importlib.metadata
6
18
  import inspect
19
+ import logging
7
20
  from typing import Collection
8
21
 
9
22
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
10
23
  from opentelemetry.trace import get_tracer
11
24
  from wrapt import wrap_function_wrapper
12
25
 
13
- from langtrace_python_sdk.instrumentation.llamaindex.patch import (
14
- generic_patch,
15
- async_generic_patch,
16
- )
17
-
18
- import logging
19
-
20
- logging.basicConfig(level=logging.FATAL)
21
-
22
- import logging
26
+ from langtrace_python_sdk.instrumentation.llamaindex.patch import generic_patch
23
27
 
24
28
  logging.basicConfig(level=logging.FATAL)
25
29
 
@@ -1,5 +1,17 @@
1
1
  """
2
- This module contains a generic patch method that wraps a function with a span.
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
3
15
  """
4
16
 
5
17
  from langtrace.trace_attributes import FrameworkSpanAttributes
@@ -8,9 +20,7 @@ from opentelemetry.trace import SpanKind
8
20
  from opentelemetry.trace.status import Status, StatusCode
9
21
 
10
22
  from langtrace_python_sdk.constants.instrumentation.common import (
11
- LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
12
- SERVICE_PROVIDERS,
13
- )
23
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
14
24
 
15
25
 
16
26
  def generic_patch(method, task, tracer, version):
@@ -42,12 +52,12 @@ def generic_patch(method, task, tracer, version):
42
52
  result = wrapped(*args, **kwargs)
43
53
  span.set_status(StatusCode.OK)
44
54
  return result
45
- except Exception as e:
55
+ except Exception as err:
46
56
  # Record the exception in the span
47
- span.record_exception(e)
57
+ span.record_exception(err)
48
58
 
49
59
  # Set the span status to indicate an error
50
- span.set_status(Status(StatusCode.ERROR, str(e)))
60
+ span.set_status(Status(StatusCode.ERROR, str(err)))
51
61
 
52
62
  # Reraise the exception to ensure it's not swallowed
53
63
  raise
@@ -84,12 +94,12 @@ def async_generic_patch(method, task, tracer, version):
84
94
  result = await wrapped(*args, **kwargs)
85
95
  span.set_status(StatusCode.OK)
86
96
  return result
87
- except Exception as e:
97
+ except Exception as err:
88
98
  # Record the exception in the span
89
- span.record_exception(e)
99
+ span.record_exception(err)
90
100
 
91
101
  # Set the span status to indicate an error
92
- span.set_status(Status(StatusCode.ERROR, str(e)))
102
+ span.set_status(Status(StatusCode.ERROR, str(err)))
93
103
 
94
104
  # Reraise the exception to ensure it's not swallowed
95
105
  raise
@@ -1,4 +1,21 @@
1
+ """
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
16
+
1
17
  import importlib.metadata
18
+ import logging
2
19
  from typing import Collection
3
20
 
4
21
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
@@ -6,15 +23,9 @@ from opentelemetry.trace import get_tracer
6
23
  from wrapt import wrap_function_wrapper
7
24
 
8
25
  from langtrace_python_sdk.instrumentation.openai.patch import (
9
- async_embeddings_create,
10
- async_images_generate,
11
- chat_completions_create,
12
- embeddings_create,
13
- images_generate,
14
- async_chat_completions_create,
15
- )
16
-
17
- import logging
26
+ async_chat_completions_create, async_embeddings_create,
27
+ async_images_generate, chat_completions_create, embeddings_create,
28
+ images_generate)
18
29
 
19
30
  logging.basicConfig(level=logging.FATAL)
20
31
 
@@ -1,19 +1,31 @@
1
1
  """
2
- This module contains the patching logic for the OpenAI library."""
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
3
16
 
4
17
  import json
5
18
 
6
19
  from langtrace.trace_attributes import Event, LLMSpanAttributes
7
- from opentelemetry import baggage, trace
20
+ from opentelemetry import baggage
8
21
  from opentelemetry.trace import SpanKind
9
22
  from opentelemetry.trace.status import Status, StatusCode
10
23
 
11
24
  from langtrace_python_sdk.constants.instrumentation.common import (
12
- LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
13
- SERVICE_PROVIDERS,
14
- )
25
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
15
26
  from langtrace_python_sdk.constants.instrumentation.openai import APIS
16
- from langtrace_python_sdk.utils.llm import calculate_prompt_tokens, estimate_tokens
27
+ from langtrace_python_sdk.utils.llm import (calculate_prompt_tokens,
28
+ estimate_tokens)
17
29
 
18
30
 
19
31
  def images_generate(original_method, version, tracer):
@@ -40,7 +52,7 @@ def images_generate(original_method, version, tracer):
40
52
  "llm.api": APIS["IMAGES_GENERATION"]["ENDPOINT"],
41
53
  "llm.model": kwargs.get("model"),
42
54
  "llm.stream": kwargs.get("stream"),
43
- "llm.prompts": json.dumps([kwargs.get("prompt", [])]),
55
+ "llm.prompts": json.dumps([{"role": "user", "content": kwargs.get("prompt", [])}]),
44
56
  **(extra_attributes if extra_attributes is not None else {}),
45
57
  }
46
58
 
@@ -63,12 +75,15 @@ def images_generate(original_method, version, tracer):
63
75
  )
64
76
  response = [
65
77
  {
66
- "url": data.url if hasattr(data, "url") else "",
67
- "revised_prompt": (
68
- data.revised_prompt
69
- if hasattr(data, "revised_prompt")
70
- else ""
71
- ),
78
+ "role": "assistant",
79
+ "content": {
80
+ "url": data.url if hasattr(data, "url") else "",
81
+ "revised_prompt": (
82
+ data.revised_prompt
83
+ if hasattr(data, "revised_prompt")
84
+ else ""
85
+ ),
86
+ }
72
87
  }
73
88
  ]
74
89
  span.set_attribute("llm.responses", json.dumps(response))
@@ -112,7 +127,7 @@ def async_images_generate(original_method, version, tracer):
112
127
  "llm.api": APIS["IMAGES_GENERATION"]["ENDPOINT"],
113
128
  "llm.model": kwargs.get("model"),
114
129
  "llm.stream": kwargs.get("stream"),
115
- "llm.prompts": json.dumps([kwargs.get("prompt", [])]),
130
+ "llm.prompts": json.dumps([{"role": "user", "content": kwargs.get("prompt", [])}]),
116
131
  **(extra_attributes if extra_attributes is not None else {}),
117
132
  }
118
133
 
@@ -136,12 +151,15 @@ def async_images_generate(original_method, version, tracer):
136
151
  )
137
152
  response = [
138
153
  {
139
- "url": data.url if hasattr(data, "url") else "",
140
- "revised_prompt": (
141
- data.revised_prompt
142
- if hasattr(data, "revised_prompt")
143
- else ""
144
- ),
154
+ "role": "assistant",
155
+ "content": {
156
+ "url": data.url if hasattr(data, "url") else "",
157
+ "revised_prompt": (
158
+ data.revised_prompt
159
+ if hasattr(data, "revised_prompt")
160
+ else ""
161
+ ),
162
+ }
145
163
  }
146
164
  ]
147
165
  span.set_attribute("llm.responses", json.dumps(response))
@@ -230,7 +248,8 @@ def chat_completions_create(original_method, version, tracer):
230
248
  if kwargs.get("user") is not None:
231
249
  attributes.llm_user = kwargs.get("user")
232
250
  if kwargs.get("functions") is not None:
233
- tools.append(json.dumps(kwargs.get("functions")))
251
+ for function in kwargs.get("functions"):
252
+ tools.append(json.dumps({"type": "function", "function": function}))
234
253
  if kwargs.get("tools") is not None:
235
254
  tools.append(json.dumps(kwargs.get("tools")))
236
255
  if len(tools) > 0:
@@ -253,25 +272,22 @@ def chat_completions_create(original_method, version, tracer):
253
272
  if hasattr(result, "choices") and result.choices is not None:
254
273
  responses = [
255
274
  {
256
- "message": {
257
- "role": (
258
- choice.message.role
259
- if choice.message and choice.message.role
260
- else "assistant"
261
- ),
262
- "content": extract_content(choice),
263
- **(
264
- {
265
- "content_filter_results": choice[
266
- "content_filter_results"
267
- ]
268
- }
269
- if "content_filter_results" in choice
270
- else {}
271
- ),
272
- }
273
- }
274
- for choice in result.choices
275
+ "role": (
276
+ choice.message.role
277
+ if choice.message and choice.message.role
278
+ else "assistant"
279
+ ),
280
+ "content": extract_content(choice),
281
+ **(
282
+ {
283
+ "content_filter_results": choice[
284
+ "content_filter_results"
285
+ ]
286
+ }
287
+ if "content_filter_results" in choice
288
+ else {}
289
+ ),
290
+ } for choice in result.choices
275
291
  ]
276
292
  span.set_attribute("llm.responses", json.dumps(responses))
277
293
  else:
@@ -348,7 +364,7 @@ def chat_completions_create(original_method, version, tracer):
348
364
  for choice in chunk.choices:
349
365
  if (
350
366
  choice.delta
351
- and choice.delta.function_call
367
+ and choice.delta.function_call is not None
352
368
  and choice.delta.function_call.arguments is not None
353
369
  ):
354
370
  token_counts = estimate_tokens(
@@ -357,10 +373,20 @@ def chat_completions_create(original_method, version, tracer):
357
373
  completion_tokens += token_counts
358
374
  content = [choice.delta.function_call.arguments]
359
375
  elif tool_calls:
360
- # TODO(Karthik): Tool calls streaming is tricky. The chunks after the
361
- # first one are missing the function name and id though the arguments
362
- # are spread across the chunks.
363
- content = []
376
+ for choice in chunk.choices:
377
+ tool_call = ""
378
+ if (choice.delta and choice.delta.tool_calls is not None):
379
+ toolcalls = choice.delta.tool_calls
380
+ content = []
381
+ for tool_call in toolcalls:
382
+ if tool_call and tool_call.function is not None and tool_call.function.arguments is not None:
383
+ token_counts = estimate_tokens(
384
+ tool_call.function.arguments
385
+ )
386
+ completion_tokens += token_counts
387
+ content = content + [tool_call.function.arguments]
388
+ else:
389
+ content = content + []
364
390
  else:
365
391
  content = []
366
392
  span.add_event(
@@ -393,10 +419,8 @@ def chat_completions_create(original_method, version, tracer):
393
419
  json.dumps(
394
420
  [
395
421
  {
396
- "message": {
397
- "role": "assistant",
398
- "content": "".join(result_content),
399
- }
422
+ "role": "assistant",
423
+ "content": "".join(result_content),
400
424
  }
401
425
  ]
402
426
  ),
@@ -477,7 +501,8 @@ def async_chat_completions_create(original_method, version, tracer):
477
501
  if kwargs.get("user") is not None:
478
502
  attributes.llm_user = kwargs.get("user")
479
503
  if kwargs.get("functions") is not None:
480
- tools.append(json.dumps(kwargs.get("functions")))
504
+ for function in kwargs.get("functions"):
505
+ tools.append(json.dumps({"type": "function", "function": function}))
481
506
  if kwargs.get("tools") is not None:
482
507
  tools.append(json.dumps(kwargs.get("tools")))
483
508
  if len(tools) > 0:
@@ -500,25 +525,22 @@ def async_chat_completions_create(original_method, version, tracer):
500
525
  if hasattr(result, "choices") and result.choices is not None:
501
526
  responses = [
502
527
  {
503
- "message": {
504
- "role": (
505
- choice.message.role
506
- if choice.message and choice.message.role
507
- else "assistant"
508
- ),
509
- "content": extract_content(choice),
510
- **(
511
- {
512
- "content_filter_results": choice[
513
- "content_filter_results"
514
- ]
515
- }
516
- if "content_filter_results" in choice
517
- else {}
518
- ),
519
- }
520
- }
521
- for choice in result.choices
528
+ "role": (
529
+ choice.message.role
530
+ if choice.message and choice.message.role
531
+ else "assistant"
532
+ ),
533
+ "content": extract_content(choice),
534
+ **(
535
+ {
536
+ "content_filter_results": choice[
537
+ "content_filter_results"
538
+ ]
539
+ }
540
+ if "content_filter_results" in choice
541
+ else {}
542
+ ),
543
+ } for choice in result.choices
522
544
  ]
523
545
  span.set_attribute("llm.responses", json.dumps(responses))
524
546
  else:
@@ -604,10 +626,20 @@ def async_chat_completions_create(original_method, version, tracer):
604
626
  completion_tokens += token_counts
605
627
  content = [choice.delta.function_call.arguments]
606
628
  elif tool_calls:
607
- # TODO(Karthik): Tool calls streaming is tricky. The chunks after the
608
- # first one are missing the function name and id though the arguments
609
- # are spread across the chunks.
610
- content = []
629
+ for choice in chunk.choices:
630
+ tool_call = ""
631
+ if (choice.delta and choice.delta.tool_calls is not None):
632
+ toolcalls = choice.delta.tool_calls
633
+ content = []
634
+ for tool_call in toolcalls:
635
+ if tool_call and tool_call.function is not None and tool_call.function.arguments is not None:
636
+ token_counts = estimate_tokens(
637
+ tool_call.function.arguments
638
+ )
639
+ completion_tokens += token_counts
640
+ content = content + [tool_call.function.arguments]
641
+ else:
642
+ content = content + []
611
643
  else:
612
644
  content = []
613
645
  span.add_event(
@@ -640,10 +672,8 @@ def async_chat_completions_create(original_method, version, tracer):
640
672
  json.dumps(
641
673
  [
642
674
  {
643
- "message": {
644
- "role": "assistant",
645
- "content": "".join(result_content),
646
- }
675
+ "role": "assistant",
676
+ "content": "".join(result_content),
647
677
  }
648
678
  ]
649
679
  ),
@@ -680,9 +710,13 @@ def embeddings_create(original_method, version, tracer):
680
710
  "llm.api": APIS["EMBEDDINGS_CREATE"]["ENDPOINT"],
681
711
  "llm.model": kwargs.get("model"),
682
712
  "llm.prompts": "",
713
+ "llm.embedding_inputs": json.dumps([kwargs.get("input", "")]),
683
714
  **(extra_attributes if extra_attributes is not None else {}),
684
715
  }
685
716
 
717
+ if kwargs.get("encoding_format") is not None:
718
+ span_attributes["llm.encoding_format"] = json.dumps([kwargs.get("encoding_format")])
719
+
686
720
  attributes = LLMSpanAttributes(**span_attributes)
687
721
  kwargs.get("encoding_format")
688
722
 
@@ -742,7 +776,7 @@ def async_embeddings_create(original_method, version, tracer):
742
776
  "url.full": base_url,
743
777
  "llm.api": APIS["EMBEDDINGS_CREATE"]["ENDPOINT"],
744
778
  "llm.model": kwargs.get("model"),
745
- "llm.prompts": "",
779
+ "llm.prompts": json.dumps([{"role": "user", "content": kwargs.get("input", "")}]),
746
780
  **(extra_attributes if extra_attributes is not None else {}),
747
781
  }
748
782
 
@@ -1,8 +1,21 @@
1
1
  """
2
- Pinecone instrumentation
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
3
15
  """
4
16
 
5
17
  import importlib.metadata
18
+ import logging
6
19
  from typing import Collection
7
20
 
8
21
  import pinecone
@@ -14,8 +27,6 @@ from wrapt import wrap_function_wrapper
14
27
  from langtrace_python_sdk.constants.instrumentation.pinecone import APIS
15
28
  from langtrace_python_sdk.instrumentation.pinecone.patch import generic_patch
16
29
 
17
- import logging
18
-
19
30
  logging.basicConfig(level=logging.FATAL)
20
31
 
21
32
 
@@ -1,5 +1,18 @@
1
1
  """
2
- This module contains the patching logic for the Pinecone client."""
2
+ Copyright (c) 2024 Scale3 Labs
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ """
3
16
 
4
17
  from langtrace.trace_attributes import DatabaseSpanAttributes
5
18
  from opentelemetry import baggage
@@ -42,12 +55,12 @@ def generic_patch(original_method, method, version, tracer):
42
55
  result = original_method(instance, *args, **kwargs)
43
56
  span.set_status(StatusCode.OK)
44
57
  return result
45
- except Exception as e:
58
+ except Exception as err:
46
59
  # Record the exception in the span
47
- span.record_exception(e)
60
+ span.record_exception(err)
48
61
 
49
62
  # Set the span status to indicate an error
50
- span.set_status(Status(StatusCode.ERROR, str(e)))
63
+ span.set_status(Status(StatusCode.ERROR, str(err)))
51
64
 
52
65
  # Reraise the exception to ensure it's not swallowed
53
66
  raise