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,18 @@
1
1
  """
2
- This module contains the patching logic for the Anthropic 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
 
@@ -10,14 +23,11 @@ from opentelemetry.trace.status import Status, StatusCode
10
23
 
11
24
  from langtrace_python_sdk.constants.instrumentation.cohere import APIS
12
25
  from langtrace_python_sdk.constants.instrumentation.common import (
13
- LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY,
14
- SERVICE_PROVIDERS,
15
- )
16
- from langtrace_python_sdk.utils.llm import estimate_tokens
26
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
17
27
 
18
28
 
19
- def embed_create(original_method, version, tracer):
20
- """Wrap the `embed_create` method."""
29
+ def rerank(original_method, version, tracer):
30
+ """Wrap the `rerank` method."""
21
31
 
22
32
  def traced_method(wrapped, instance, args, kwargs):
23
33
  service_provider = SERVICE_PROVIDERS["COHERE"]
@@ -29,10 +39,105 @@ def embed_create(original_method, version, tracer):
29
39
  "langtrace.service.type": "llm",
30
40
  "langtrace.service.version": version,
31
41
  "langtrace.version": "1.0.0",
32
- "url.full": APIS["EMBED_CREATE"]["URL"],
33
- "llm.api": APIS["EMBED_CREATE"]["ENDPOINT"],
42
+ "url.full": APIS["RERANK"]["URL"],
43
+ "llm.api": APIS["RERANK"]["ENDPOINT"],
34
44
  "llm.model": kwargs.get("model"),
35
45
  "llm.prompts": "",
46
+ "llm.documents": json.dumps(kwargs.get("documents")),
47
+ "llm.retrieval.query": kwargs.get("query"),
48
+ **(extra_attributes if extra_attributes is not None else {}),
49
+ }
50
+
51
+ attributes = LLMSpanAttributes(**span_attributes)
52
+
53
+ if kwargs.get("top_n") is not None:
54
+ attributes.llm_top_k = kwargs.get("top_n")
55
+
56
+ if kwargs.get("user") is not None:
57
+ attributes.llm_user = kwargs.get("user")
58
+
59
+ span = tracer.start_span(APIS["RERANK"]["METHOD"], kind=SpanKind.CLIENT)
60
+ for field, value in attributes.model_dump(by_alias=True).items():
61
+ if value is not None:
62
+ span.set_attribute(field, value)
63
+ try:
64
+ # Attempt to call the original method
65
+ result = wrapped(*args, **kwargs)
66
+
67
+ if hasattr(result, "results") and result.results is not None:
68
+ results = []
69
+ for _, doc in enumerate(result.results):
70
+ results.append(doc.json())
71
+ span.set_attribute("llm.retrieval.results", json.dumps(results))
72
+
73
+ if (hasattr(result, "response_id")) and (result.response_id is not None):
74
+ span.set_attribute("llm.response_id", result.response_id)
75
+
76
+ if hasattr(result, "meta") and result.meta is not None:
77
+ if (
78
+ hasattr(result.meta, "billed_units")
79
+ and result.meta.billed_units is not None
80
+ ):
81
+ usage = result.meta.billed_units
82
+ if usage is not None:
83
+ usage_dict = {
84
+ "input_tokens": (
85
+ usage.input_tokens
86
+ if usage.input_tokens is not None
87
+ else 0
88
+ ),
89
+ "output_tokens": (
90
+ usage.output_tokens
91
+ if usage.output_tokens is not None
92
+ else 0
93
+ ),
94
+ "total_tokens": (
95
+ usage.input_tokens + usage.output_tokens
96
+ if usage.input_tokens is not None
97
+ and usage.output_tokens is not None
98
+ else 0
99
+ ),
100
+ "search_units": (
101
+ usage.search_units
102
+ if usage.search_units is not None
103
+ else 0
104
+ ),
105
+ }
106
+ span.set_attribute(
107
+ "llm.token.counts", json.dumps(usage_dict)
108
+ )
109
+
110
+ span.set_status(StatusCode.OK)
111
+ span.end()
112
+ return result
113
+
114
+ except Exception as error:
115
+ span.record_exception(error)
116
+ span.set_status(Status(StatusCode.ERROR, str(error)))
117
+ span.end()
118
+ raise
119
+
120
+ return traced_method
121
+
122
+
123
+ def embed(original_method, version, tracer):
124
+ """Wrap the `embed` method."""
125
+
126
+ def traced_method(wrapped, instance, args, kwargs):
127
+ service_provider = SERVICE_PROVIDERS["COHERE"]
128
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
129
+
130
+ span_attributes = {
131
+ "langtrace.sdk.name": "langtrace-python-sdk",
132
+ "langtrace.service.name": service_provider,
133
+ "langtrace.service.type": "llm",
134
+ "langtrace.service.version": version,
135
+ "langtrace.version": "1.0.0",
136
+ "url.full": APIS["EMBED"]["URL"],
137
+ "llm.api": APIS["EMBED"]["ENDPOINT"],
138
+ "llm.model": kwargs.get("model"),
139
+ "llm.prompts": "",
140
+ "llm.embedding_inputs": json.dumps(kwargs.get("texts")),
36
141
  "llm.embedding_dataset_id": kwargs.get("dataset_id"),
37
142
  "llm.embedding_input_type": kwargs.get("input_type"),
38
143
  "llm.embedding_job_name": kwargs.get("name"),
@@ -44,13 +149,48 @@ def embed_create(original_method, version, tracer):
44
149
  if kwargs.get("user") is not None:
45
150
  attributes.llm_user = kwargs.get("user")
46
151
 
47
- span = tracer.start_span(APIS["EMBED_CREATE"]["METHOD"], kind=SpanKind.CLIENT)
152
+ span = tracer.start_span(APIS["EMBED"]["METHOD"], kind=SpanKind.CLIENT)
48
153
  for field, value in attributes.model_dump(by_alias=True).items():
49
154
  if value is not None:
50
155
  span.set_attribute(field, value)
51
156
  try:
52
157
  # Attempt to call the original method
53
158
  result = wrapped(*args, **kwargs)
159
+
160
+ if hasattr(result, "meta") and result.meta is not None:
161
+ if (
162
+ hasattr(result.meta, "billed_units")
163
+ and result.meta.billed_units is not None
164
+ ):
165
+ usage = result.meta.billed_units
166
+ if usage is not None:
167
+ usage_dict = {
168
+ "input_tokens": (
169
+ usage.input_tokens
170
+ if usage.input_tokens is not None
171
+ else 0
172
+ ),
173
+ "output_tokens": (
174
+ usage.output_tokens
175
+ if usage.output_tokens is not None
176
+ else 0
177
+ ),
178
+ "total_tokens": (
179
+ usage.input_tokens + usage.output_tokens
180
+ if usage.input_tokens is not None
181
+ and usage.output_tokens is not None
182
+ else 0
183
+ ),
184
+ "search_units": (
185
+ usage.search_units
186
+ if usage.search_units is not None
187
+ else 0
188
+ ),
189
+ }
190
+ span.set_attribute(
191
+ "llm.token.counts", json.dumps(usage_dict)
192
+ )
193
+
54
194
  span.set_status(StatusCode.OK)
55
195
  span.end()
56
196
  return result
@@ -71,32 +211,33 @@ def chat_create(original_method, version, tracer):
71
211
  service_provider = SERVICE_PROVIDERS["COHERE"]
72
212
 
73
213
  message = kwargs.get("message", "")
74
- prompts = json.dumps([{"role": "USER", "content": message}])
214
+ prompts = [{"role": "USER", "content": message}]
215
+ system_prompts = []
216
+ history = []
75
217
  preamble = kwargs.get("preamble")
76
218
  if preamble:
77
- prompts = json.dumps(
78
- [{"role": "system", "content": preamble}]
79
- + [{"role": "USER", "content": message}]
80
- )
219
+ system_prompts = [{"role": "system", "content": preamble}]
81
220
 
82
221
  chat_history = kwargs.get("chat_history")
83
222
  if chat_history:
84
223
  history = [
85
224
  {
86
- "message": {
87
- "role": (
88
- item.get("role") if item.get("role") is not None else "USER"
89
- ),
90
- "content": (
91
- item.get("message")
92
- if item.get("message") is not None
93
- else ""
94
- ),
95
- }
225
+ "role": (
226
+ item.get("role") if item.get("role") is not None else "USER"
227
+ ),
228
+ "content": (
229
+ item.get("message")
230
+ if item.get("message") is not None
231
+ else ""
232
+ ),
96
233
  }
97
234
  for item in chat_history
98
235
  ]
99
- prompts = prompts + json.dumps(history)
236
+ if len(history) > 0:
237
+ prompts = history + prompts
238
+ if len(system_prompts) > 0:
239
+ prompts = system_prompts + prompts
240
+ prompts = json.dumps(prompts)
100
241
 
101
242
  extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
102
243
 
@@ -121,13 +262,13 @@ def chat_create(original_method, version, tracer):
121
262
  if kwargs.get("temperature") is not None:
122
263
  attributes.llm_temperature = kwargs.get("temperature")
123
264
  if kwargs.get("max_tokens") is not None:
124
- attributes.max_tokens = kwargs.get("max_tokens")
265
+ attributes.llm_max_tokens = str(kwargs.get("max_tokens"))
125
266
  if kwargs.get("max_input_tokens") is not None:
126
- attributes.max_input_tokens = kwargs.get("max_input_tokens")
267
+ attributes.llm_max_input_tokens = str(kwargs.get("max_input_tokens"))
127
268
  if kwargs.get("p") is not None:
128
269
  attributes.llm_top_p = kwargs.get("p")
129
270
  if kwargs.get("k") is not None:
130
- attributes.llm_top_p = kwargs.get("k")
271
+ attributes.llm_top_k = kwargs.get("k")
131
272
  if kwargs.get("user") is not None:
132
273
  attributes.llm_user = kwargs.get("user")
133
274
  if kwargs.get("conversation_id") is not None:
@@ -171,36 +312,40 @@ def chat_create(original_method, version, tracer):
171
312
  span.set_attribute("llm.is_search_required", result.is_search_required)
172
313
 
173
314
  if kwargs.get("stream") is False or kwargs.get("stream") is None:
174
- if hasattr(result, "text") and result.text is not None:
315
+ if hasattr(result, "text") and result.text is not None and result.text != "":
175
316
  if (
176
317
  hasattr(result, "chat_history")
177
318
  and result.chat_history is not None
178
319
  ):
179
320
  responses = [
180
321
  {
181
- "message": {
182
- "role": (
183
- item.role
184
- if hasattr(item, "role")
185
- and item.role is not None
186
- else "USER"
187
- ),
188
- "content": (
189
- item.message
190
- if hasattr(item, "message")
191
- and item.message is not None
192
- else ""
193
- ),
194
- }
322
+ "role": (
323
+ item.role
324
+ if hasattr(item, "role")
325
+ and item.role is not None
326
+ else "USER"
327
+ ),
328
+ "content": (
329
+ item.message
330
+ if hasattr(item, "message")
331
+ and item.message is not None
332
+ else ""
333
+ ),
195
334
  }
196
335
  for item in result.chat_history
197
336
  ]
198
337
  span.set_attribute("llm.responses", json.dumps(responses))
199
338
  else:
200
339
  responses = [
201
- {"message": {"role": "CHATBOT", "content": result.text}}
340
+ {"role": "CHATBOT", "content": result.text}
202
341
  ]
203
342
  span.set_attribute("llm.responses", json.dumps(responses))
343
+ elif hasattr(result, "tool_calls") and result.tool_calls is not None:
344
+ tool_calls = []
345
+ for tool_call in result.tool_calls:
346
+ tool_calls.append(tool_call.json())
347
+ span.set_attribute("llm.tool_calls", json.dumps(tool_calls))
348
+ span.set_attribute("llm.responses", json.dumps([]))
204
349
  else:
205
350
  responses = []
206
351
  span.set_attribute("llm.responses", json.dumps(responses))
@@ -230,6 +375,11 @@ def chat_create(original_method, version, tracer):
230
375
  and usage.output_tokens is not None
231
376
  else 0
232
377
  ),
378
+ "search_units": (
379
+ usage.search_units
380
+ if usage.search_units is not None
381
+ else 0
382
+ ),
233
383
  }
234
384
  span.set_attribute(
235
385
  "llm.token.counts", json.dumps(usage_dict)
@@ -257,33 +407,33 @@ def chat_stream(original_method, version, tracer):
257
407
  service_provider = SERVICE_PROVIDERS["COHERE"]
258
408
 
259
409
  message = kwargs.get("message", "")
260
- prompt_tokens = estimate_tokens(message)
261
- prompts = json.dumps([{"role": "USER", "content": message}])
410
+ prompts = [{"role": "USER", "content": message}]
411
+ system_prompts = []
412
+ history = []
262
413
  preamble = kwargs.get("preamble")
263
414
  if preamble:
264
- prompts = json.dumps(
265
- [{"role": "system", "content": preamble}]
266
- + [{"role": "USER", "content": message}]
267
- )
415
+ system_prompts = [{"role": "system", "content": preamble}]
268
416
 
269
417
  chat_history = kwargs.get("chat_history")
270
418
  if chat_history:
271
419
  history = [
272
420
  {
273
- "message": {
274
- "role": (
275
- item.get("role") if item.get("role") is not None else "USER"
276
- ),
277
- "content": (
278
- item.get("message")
279
- if item.get("message") is not None
280
- else ""
281
- ),
282
- }
421
+ "role": (
422
+ item.get("role") if item.get("role") is not None else "USER"
423
+ ),
424
+ "content": (
425
+ item.get("message")
426
+ if item.get("message") is not None
427
+ else ""
428
+ ),
283
429
  }
284
430
  for item in chat_history
285
431
  ]
286
- prompts = prompts + json.dumps(history)
432
+ if len(history) > 0:
433
+ prompts = history + prompts
434
+ if len(system_prompts) > 0:
435
+ prompts = system_prompts + prompts
436
+ prompts = json.dumps(prompts)
287
437
 
288
438
  extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
289
439
 
@@ -308,13 +458,13 @@ def chat_stream(original_method, version, tracer):
308
458
  if kwargs.get("temperature") is not None:
309
459
  attributes.llm_temperature = kwargs.get("temperature")
310
460
  if kwargs.get("max_tokens") is not None:
311
- attributes.max_tokens = kwargs.get("max_tokens")
461
+ attributes.llm_max_tokens = str(kwargs.get("max_tokens"))
312
462
  if kwargs.get("max_input_tokens") is not None:
313
- attributes.max_input_tokens = kwargs.get("max_input_tokens")
463
+ attributes.llm_max_input_tokens = str(kwargs.get("max_input_tokens"))
314
464
  if kwargs.get("p") is not None:
315
465
  attributes.llm_top_p = kwargs.get("p")
316
466
  if kwargs.get("k") is not None:
317
- attributes.llm_top_p = kwargs.get("k")
467
+ attributes.llm_top_k = kwargs.get("k")
318
468
  if kwargs.get("user") is not None:
319
469
  attributes.llm_user = kwargs.get("user")
320
470
  if kwargs.get("conversation_id") is not None:
@@ -342,49 +492,99 @@ def chat_stream(original_method, version, tracer):
342
492
  try:
343
493
  # Attempt to call the original method
344
494
  result = wrapped(*args, **kwargs)
345
-
346
- result_content = []
347
495
  span.add_event(Event.STREAM_START.value)
348
- completion_tokens = 0
349
496
  try:
350
497
  for event in result:
351
498
  if hasattr(event, "text") and event.text is not None:
352
- completion_tokens += estimate_tokens(event.text)
353
499
  content = event.text
354
500
  else:
355
501
  content = ""
356
502
  span.add_event(
357
503
  Event.STREAM_OUTPUT.value, {"response": "".join(content)}
358
504
  )
359
- result_content.append(content)
505
+
506
+ if hasattr(event, "finish_reason") and event.finish_reason == "COMPLETE":
507
+ response = event.response
508
+
509
+ if (hasattr(response, "generation_id")) and (
510
+ response.generation_id is not None
511
+ ):
512
+ span.set_attribute("llm.generation_id", response.generation_id)
513
+ if (hasattr(response, "response_id")) and (response.response_id is not None):
514
+ span.set_attribute("llm.response_id", response.response_id)
515
+ if (hasattr(response, "is_search_required")) and (
516
+ response.is_search_required is not None
517
+ ):
518
+ span.set_attribute("llm.is_search_required", response.is_search_required)
519
+
520
+ # Set the response attributes
521
+ if hasattr(response, "text") and response.text is not None:
522
+ if (
523
+ hasattr(response, "chat_history")
524
+ and response.chat_history is not None
525
+ ):
526
+ responses = [
527
+ {
528
+ "role": (
529
+ item.role
530
+ if hasattr(item, "role")
531
+ and item.role is not None
532
+ else "USER"
533
+ ),
534
+ "content": (
535
+ item.message
536
+ if hasattr(item, "message")
537
+ and item.message is not None
538
+ else ""
539
+ ),
540
+ }
541
+ for item in response.chat_history
542
+ ]
543
+ span.set_attribute("llm.responses", json.dumps(responses))
544
+ else:
545
+ responses = [
546
+ {"role": "CHATBOT", "content": response.text}
547
+ ]
548
+ span.set_attribute("llm.responses", json.dumps(responses))
549
+
550
+ # Get the usage
551
+ if hasattr(response, "meta") and response.meta is not None:
552
+ if (
553
+ hasattr(response.meta, "billed_units")
554
+ and response.meta.billed_units is not None
555
+ ):
556
+ usage = response.meta.billed_units
557
+ if usage is not None:
558
+ usage_dict = {
559
+ "input_tokens": (
560
+ usage.input_tokens
561
+ if usage.input_tokens is not None
562
+ else 0
563
+ ),
564
+ "output_tokens": (
565
+ usage.output_tokens
566
+ if usage.output_tokens is not None
567
+ else 0
568
+ ),
569
+ "total_tokens": (
570
+ usage.input_tokens + usage.output_tokens
571
+ if usage.input_tokens is not None
572
+ and usage.output_tokens is not None
573
+ else 0
574
+ ),
575
+ "search_units": (
576
+ usage.search_units
577
+ if usage.search_units is not None
578
+ else 0
579
+ ),
580
+ }
581
+ span.set_attribute(
582
+ "llm.token.counts", json.dumps(usage_dict)
583
+ )
584
+
360
585
  yield event
361
586
  finally:
362
-
363
- # Finalize span after processing all chunks
364
587
  span.add_event(Event.STREAM_END.value)
365
- span.set_attribute(
366
- "llm.token.counts",
367
- json.dumps(
368
- {
369
- "input_tokens": prompt_tokens,
370
- "output_tokens": completion_tokens,
371
- "total_tokens": prompt_tokens + completion_tokens,
372
- }
373
- ),
374
- )
375
- span.set_attribute(
376
- "llm.responses",
377
- json.dumps(
378
- [
379
- {
380
- "message": {
381
- "role": "CHATBOT",
382
- "content": "".join(result_content),
383
- }
384
- }
385
- ]
386
- ),
387
- )
388
588
  span.set_status(StatusCode.OK)
389
589
  span.end()
390
590
 
@@ -1,9 +1,22 @@
1
1
  """
2
- Instrumentation for langchain.
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
@@ -12,8 +25,6 @@ from wrapt import wrap_function_wrapper
12
25
 
13
26
  from langtrace_python_sdk.instrumentation.langchain.patch import generic_patch
14
27
 
15
- import logging
16
-
17
28
  logging.basicConfig(level=logging.FATAL)
18
29
 
19
30
 
@@ -1,5 +1,17 @@
1
1
  """
2
- This module contains the patching logic for the langchain 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
@@ -51,12 +63,12 @@ def generic_patch(
51
63
 
52
64
  span.set_status(StatusCode.OK)
53
65
  return result
54
- except Exception as e:
66
+ except Exception as err:
55
67
  # Record the exception in the span
56
- span.record_exception(e)
68
+ span.record_exception(err)
57
69
 
58
70
  # Set the span status to indicate an error
59
- span.set_status(Status(StatusCode.ERROR, str(e)))
71
+ span.set_status(Status(StatusCode.ERROR, str(err)))
60
72
 
61
73
  # Reraise the exception to ensure it's not swallowed
62
74
  raise
@@ -1,5 +1,17 @@
1
1
  """
2
- Instrumentation for langchain-community.
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
@@ -10,7 +22,8 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
10
22
  from opentelemetry.trace import get_tracer
11
23
  from wrapt import wrap_function_wrapper
12
24
 
13
- from langtrace_python_sdk.instrumentation.langchain_community.patch import generic_patch
25
+ from langtrace_python_sdk.instrumentation.langchain_community.patch import \
26
+ generic_patch
14
27
 
15
28
 
16
29
  def patch_module_classes(
@@ -1,3 +1,20 @@
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
+
17
+
1
18
  import json
2
19
 
3
20
  from langtrace.trace_attributes import FrameworkSpanAttributes
@@ -43,12 +60,12 @@ def generic_patch(
43
60
 
44
61
  span.set_status(StatusCode.OK)
45
62
  return result
46
- except Exception as e:
63
+ except Exception as err:
47
64
  # Record the exception in the span
48
- span.record_exception(e)
65
+ span.record_exception(err)
49
66
 
50
67
  # Set the span status to indicate an error
51
- span.set_status(Status(StatusCode.ERROR, str(e)))
68
+ span.set_status(Status(StatusCode.ERROR, str(err)))
52
69
 
53
70
  # Reraise the exception to ensure it's not swallowed
54
71
  raise