langtrace-python-sdk 1.2.11__tar.gz → 1.2.14__tar.gz

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 (78) hide show
  1. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/PKG-INFO +2 -2
  2. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/README.md +1 -1
  3. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/openai/instrumentation.py +3 -3
  4. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/openai/patch.py +3 -3
  5. langtrace_python_sdk-1.2.14/src/langtrace_python_sdk/version.py +1 -0
  6. langtrace_python_sdk-1.2.14/src/tests/anthropic/test_anthropic.py +72 -0
  7. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/tests/chroma/test_chroma.py +5 -0
  8. langtrace_python_sdk-1.2.14/src/tests/langchain/test_langchain.py +68 -0
  9. langtrace_python_sdk-1.2.14/src/tests/langchain/test_langchain_community.py +68 -0
  10. langtrace_python_sdk-1.2.14/src/tests/langchain/test_langchain_core.py +113 -0
  11. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/tests/openai/test_chat_completion.py +25 -30
  12. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/tests/openai/test_image_generation.py +7 -4
  13. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/tests/pinecone/test_pinecone.py +6 -0
  14. langtrace_python_sdk-1.2.14/src/tests/utils.py +21 -0
  15. langtrace_python_sdk-1.2.11/src/langtrace_python_sdk/version.py +0 -1
  16. langtrace_python_sdk-1.2.11/src/tests/utils.py +0 -17
  17. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/.gitignore +0 -0
  18. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/LICENSE +0 -0
  19. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/pyproject.toml +0 -0
  20. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/__init__.py +0 -0
  21. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/__init__.py +0 -0
  22. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/anthropic_example/__init__.py +0 -0
  23. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/anthropic_example/completion.py +0 -0
  24. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/chroma_example/__init__.py +0 -0
  25. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/chroma_example/basic.py +0 -0
  26. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/langchain_example/__init__.py +0 -0
  27. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/langchain_example/basic.py +0 -0
  28. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/langchain_example/tool.py +0 -0
  29. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/llamaindex_example/__init__.py +0 -0
  30. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/llamaindex_example/basic.py +0 -0
  31. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/llamaindex_example/data/abramov.txt +0 -0
  32. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/openai/__init__.py +0 -0
  33. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/openai/chat_completion.py +0 -0
  34. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/openai/embeddings_create.py +0 -0
  35. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/openai/function_calling.py +0 -0
  36. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/openai/images_generate.py +0 -0
  37. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/pinecone_example/__init__.py +0 -0
  38. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/examples/pinecone_example/basic.py +0 -0
  39. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/__init__.py +0 -0
  40. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/__init__.py +0 -0
  41. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/exporter/langtrace_exporter.py +0 -0
  42. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/__init__.py +0 -0
  43. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/anthropic.py +0 -0
  44. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/chroma.py +0 -0
  45. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/common.py +0 -0
  46. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/openai.py +0 -0
  47. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/constants/instrumentation/pinecone.py +0 -0
  48. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/extensions/__init__.py +0 -0
  49. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/extensions/langtrace_exporter.py +0 -0
  50. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/__init__.py +0 -0
  51. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/anthropic/__init__.py +0 -0
  52. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/anthropic/instrumentation.py +0 -0
  53. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/anthropic/patch.py +0 -0
  54. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/chroma/__init__.py +0 -0
  55. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/chroma/instrumentation.py +0 -0
  56. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/chroma/patch.py +0 -0
  57. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain/__init__.py +0 -0
  58. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain/instrumentation.py +0 -0
  59. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain/patch.py +0 -0
  60. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_community/__init__.py +0 -0
  61. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_community/instrumentation.py +0 -0
  62. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_community/patch.py +0 -0
  63. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_core/__init__.py +0 -0
  64. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_core/instrumentation.py +0 -0
  65. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/langchain_core/patch.py +0 -0
  66. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/llamaindex/__init__.py +0 -0
  67. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/llamaindex/instrumentation.py +0 -0
  68. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/llamaindex/patch.py +0 -0
  69. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/openai/__init__.py +0 -0
  70. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/pinecone/__init__.py +0 -0
  71. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/pinecone/instrumentation.py +0 -0
  72. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/instrumentation/pinecone/patch.py +0 -0
  73. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/langtrace.py +0 -0
  74. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/utils/__init__.py +0 -0
  75. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/utils/llm.py +0 -0
  76. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/langtrace_python_sdk/utils/with_root_span.py +0 -0
  77. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/run_example.py +0 -0
  78. {langtrace_python_sdk-1.2.11 → langtrace_python_sdk-1.2.14}/src/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: langtrace-python-sdk
3
- Version: 1.2.11
3
+ Version: 1.2.14
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>
@@ -175,7 +175,7 @@ Langtrace automatically captures traces from the following vendors:
175
175
 
176
176
  ## Contributions
177
177
 
178
- We welcome contributions to this project. To get started, fork this repository and start developing. To get involved, join our Slack workspace.
178
+ We welcome contributions to this project. To get started, fork this repository and start developing. To get involved, join our [Discord](https://discord.langtrace.ai) workspace.
179
179
 
180
180
  ---
181
181
 
@@ -147,7 +147,7 @@ Langtrace automatically captures traces from the following vendors:
147
147
 
148
148
  ## Contributions
149
149
 
150
- We welcome contributions to this project. To get started, fork this repository and start developing. To get involved, join our Slack workspace.
150
+ We welcome contributions to this project. To get started, fork this repository and start developing. To get involved, join our [Discord](https://discord.langtrace.ai) workspace.
151
151
 
152
152
  ---
153
153
 
@@ -25,17 +25,17 @@ class OpenAIInstrumentation(BaseInstrumentor):
25
25
  wrap_function_wrapper(
26
26
  "openai.resources.chat.completions",
27
27
  "Completions.create",
28
- chat_completions_create(openai.chat.completions.create, version, tracer),
28
+ chat_completions_create("openai.chat.completions.create", version, tracer),
29
29
  )
30
30
  wrap_function_wrapper(
31
31
  "openai.resources.images",
32
32
  "Images.generate",
33
- images_generate(openai.images.generate, version, tracer),
33
+ images_generate("openai.images.generate", version, tracer),
34
34
  )
35
35
  wrap_function_wrapper(
36
36
  "openai.resources.embeddings",
37
37
  "Embeddings.create",
38
- embeddings_create(openai.embeddings.create, version, tracer),
38
+ embeddings_create("openai.embeddings.create", version, tracer),
39
39
  )
40
40
 
41
41
  def _uninstrument(self, **kwargs):
@@ -52,7 +52,7 @@ def images_generate(original_method, version, tracer):
52
52
  span.set_attribute(field, value)
53
53
  try:
54
54
  # Attempt to call the original method
55
- result = original_method(*args, **kwargs)
55
+ result = wrapped(*args, **kwargs)
56
56
  if kwargs.get("stream") is False or kwargs.get("stream") is None:
57
57
  data = (
58
58
  result.data[0]
@@ -132,7 +132,7 @@ def chat_completions_create(original_method, version, tracer):
132
132
  span.set_attribute(field, value)
133
133
  try:
134
134
  # Attempt to call the original method
135
- result = original_method(*args, **kwargs)
135
+ result = wrapped(*args, **kwargs)
136
136
  if kwargs.get("stream") is False:
137
137
  span.set_attribute("llm.model", result.model)
138
138
  if hasattr(result, "choices") and result.choices is not None:
@@ -345,7 +345,7 @@ def embeddings_create(original_method, version, tracer):
345
345
  span.set_attribute(field, value)
346
346
  try:
347
347
  # Attempt to call the original method
348
- result = original_method(*args, **kwargs)
348
+ result = wrapped(*args, **kwargs)
349
349
  span.set_status(StatusCode.OK)
350
350
  return result
351
351
  except Exception as e:
@@ -0,0 +1 @@
1
+ __version__ = "1.2.14"
@@ -0,0 +1,72 @@
1
+ import unittest
2
+ from unittest.mock import MagicMock, call
3
+ from langtrace_python_sdk.instrumentation.anthropic.patch import messages_create
4
+ from opentelemetry.trace import SpanKind
5
+ import importlib.metadata
6
+ from langtrace_python_sdk.constants.instrumentation.anthropic import APIS
7
+ from opentelemetry.trace.status import Status, StatusCode
8
+ import json
9
+ from langtrace.trace_attributes import Event, LLMSpanAttributes
10
+
11
+ from tests.utils import common_setup
12
+
13
+ class TestAnthropic(unittest.TestCase):
14
+
15
+ data = {
16
+ "content" : [MagicMock(text="Some text", type="text")],
17
+ "system_fingerprint" : "None",
18
+ "usage" : MagicMock(input_tokens=23, output_tokens=44),
19
+ "chunks" : [MagicMock(delta="Some text", message="text")]}
20
+
21
+
22
+ def setUp(self):
23
+
24
+ # Mock the original method
25
+ self.anthropic_mock, self.tracer, self.span = common_setup(self.data, None)
26
+
27
+ def tearDown(self):
28
+ pass
29
+
30
+ def test_anthropic(self):
31
+ # Arrange
32
+ version = importlib.metadata.version('anthropic')
33
+ kwargs = {
34
+ "model": "claude-3-opus-20240229",
35
+ "messages" : [{"role": "user", "content": "How are you today?"}],
36
+ "stream": False
37
+ }
38
+
39
+ # Act
40
+ wrapped_function = messages_create("anthropic.messages.create", version, self.tracer)
41
+ result = wrapped_function(self.anthropic_mock, MagicMock(), (), kwargs)
42
+
43
+
44
+ # Assert
45
+ self.assertTrue(self.tracer.start_as_current_span.called_once_with("anthropic.messages.create", kind=SpanKind.CLIENT))
46
+ self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
47
+
48
+ expected_attributes = {
49
+ "langtrace.service.name": "Anthropic",
50
+ "langtrace.service.type": "llm",
51
+ "langtrace.service.version": version,
52
+ "langtrace.version": "1.0.0",
53
+ "url.full": "/v1/messages",
54
+ "llm.api": APIS["MESSAGES_CREATE"]["ENDPOINT"],
55
+ "llm.model": kwargs.get("model"),
56
+ "llm.prompts": json.dumps(kwargs.get("messages", [])),
57
+ "llm.stream": kwargs.get("stream"),
58
+ }
59
+
60
+ self.assertTrue(
61
+ self.span.set_attribute.has_calls(
62
+ [call(key, value) for key, value in expected_attributes.items()], any_order=True
63
+ )
64
+ )
65
+
66
+ expected_result_data = {"system_fingerprint": "None" }
67
+
68
+ self.assertEqual(result.system_fingerprint, expected_result_data["system_fingerprint"])
69
+
70
+
71
+ if __name__ == '__main__':
72
+ unittest.main()
@@ -49,6 +49,11 @@ class TestChromaPatch(unittest.TestCase):
49
49
  }
50
50
  for key, value in expected_attributes.items():
51
51
  self.span.set_attribute.assert_has_calls([call(key, value)], any_order=True)
52
+
53
+ actual_calls = self.span.set_attribute.call_args_list
54
+
55
+ for key, value in expected_attributes.items():
56
+ self.assertIn(call(key, value), actual_calls)
52
57
 
53
58
  # Assert the span status is set to OK
54
59
  self.span.set_status.assert_called_with(StatusCode.OK)
@@ -0,0 +1,68 @@
1
+
2
+ import unittest
3
+ from unittest.mock import MagicMock, call
4
+ from langtrace_python_sdk.instrumentation.langchain.patch import generic_patch
5
+ from opentelemetry.trace import SpanKind
6
+ from opentelemetry.trace import get_tracer
7
+ import importlib.metadata
8
+ from langtrace_python_sdk.constants.instrumentation.openai import APIS
9
+ from opentelemetry.trace.status import Status, StatusCode
10
+ from tests.utils import common_setup
11
+ import json
12
+
13
+ class TestGenericPatch(unittest.TestCase):
14
+ data = {"key": "value"}
15
+ def setUp(self):
16
+ self.langchain_mock, self.tracer, self.span = common_setup(self.data, None)
17
+
18
+ def tearDown(self):
19
+ # Clean up after each test case
20
+ pass
21
+
22
+ def test_generic_patch(self):
23
+ # Arrange
24
+ method_name = "example_method"
25
+ trace_output = False
26
+ trace_input = False # Change as per your requirement
27
+ args = (1, 2, 3)
28
+ task = "split_text"
29
+ kwargs = {'key': 'value'}
30
+ version = importlib.metadata.version('langchain')
31
+
32
+ # Act
33
+ wrapped_function = generic_patch("langchain.text_splitter", task, self.tracer, version, trace_output, trace_input)
34
+ result = wrapped_function(self.langchain_mock, MagicMock(), args, kwargs)
35
+
36
+ # Assert
37
+ self.assertTrue(self.tracer.start_as_current_span.called_once_with(method_name, kind=SpanKind.CLIENT))
38
+
39
+ service_provider = "Langchain"
40
+ expected_attributes = {
41
+ "langtrace.service.name": service_provider,
42
+ "langtrace.service.type": "framework",
43
+ "langtrace.service.version": version,
44
+ "langtrace.version": "1.0.0",
45
+ "langchain.task.name": task,
46
+ }
47
+
48
+
49
+ self.assertTrue(
50
+ self.span.set_attribute.has_calls(
51
+ [call(key, value) for key, value in expected_attributes.items()], any_order=True
52
+ )
53
+ )
54
+
55
+ actual_calls = self.span.set_attribute.call_args_list
56
+
57
+ for key, value in expected_attributes.items():
58
+ self.assertIn(call(key, value), actual_calls)
59
+
60
+ self.assertEqual(self.span.set_status.call_count, 1)
61
+ self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
62
+
63
+ expected_result_data = {"key": "value" }
64
+
65
+ self.assertEqual(result.key, expected_result_data["key"])
66
+
67
+ if __name__ == '__main__':
68
+ unittest.main()
@@ -0,0 +1,68 @@
1
+
2
+ import unittest
3
+ from unittest.mock import MagicMock, Mock, patch, call
4
+ from langtrace_python_sdk.instrumentation.langchain_community.patch import generic_patch
5
+ from opentelemetry.trace import SpanKind
6
+ from opentelemetry.trace import get_tracer
7
+ import importlib.metadata
8
+ import openai
9
+ from langtrace_python_sdk.constants.instrumentation.openai import APIS
10
+ from opentelemetry.trace.status import Status, StatusCode
11
+ import json
12
+ from tests.utils import common_setup
13
+ class TestGenericPatch(unittest.TestCase):
14
+ data = {"key": "value"}
15
+ def setUp(self):
16
+ self.langchain_mock, self.tracer, self.span = common_setup(self.data, None)
17
+
18
+ def tearDown(self):
19
+ # Clean up after each test case
20
+ pass
21
+
22
+ def test_generic_patch(self):
23
+ # Arrange
24
+ method_name = "example_method"
25
+ trace_output = False
26
+ trace_input = False
27
+ args = (1, 2, 3)
28
+ task = "vector_store"
29
+ kwargs = {'key': 'value'}
30
+ version = importlib.metadata.version("langchain-community")
31
+
32
+ # Act
33
+ wrapped_function = generic_patch("langchain_community.vectorstores.faiss", task, self.tracer, version, trace_output, trace_input)
34
+ result = wrapped_function(self.langchain_mock, MagicMock(), args, kwargs)
35
+
36
+ # Assert
37
+ self.assertTrue(self.tracer.start_as_current_span.called_once_with(method_name, kind=SpanKind.CLIENT))
38
+
39
+ service_provider = "Langchain Community"
40
+ expected_attributes = {
41
+ "langtrace.service.name": service_provider,
42
+ "langtrace.service.type": "framework",
43
+ "langtrace.service.version": version,
44
+ "langtrace.version": "1.0.0",
45
+ "langchain.task.name": task,
46
+ }
47
+
48
+
49
+ self.assertTrue(
50
+ self.span.set_attribute.has_calls(
51
+ [call(key, value) for key, value in expected_attributes.items()], any_order=True
52
+ )
53
+ )
54
+
55
+ actual_calls = self.span.set_attribute.call_args_list
56
+
57
+ for key, value in expected_attributes.items():
58
+ self.assertIn(call(key, value), actual_calls)
59
+
60
+ self.assertEqual(self.span.set_status.call_count, 1)
61
+ self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
62
+
63
+ expected_result_data = {"key": "value" }
64
+ self.assertEqual(result.key, expected_result_data["key"])
65
+
66
+
67
+ if __name__ == '__main__':
68
+ unittest.main()
@@ -0,0 +1,113 @@
1
+
2
+ import unittest
3
+ from unittest.mock import MagicMock, Mock, patch, call
4
+ from langtrace_python_sdk.instrumentation.langchain_core.patch import generic_patch, runnable_patch
5
+ from opentelemetry.trace import SpanKind
6
+ from opentelemetry.trace import get_tracer
7
+ import importlib.metadata
8
+ import openai
9
+ from langtrace_python_sdk.constants.instrumentation.openai import APIS
10
+ from opentelemetry.trace.status import Status, StatusCode
11
+ import json
12
+ from tests.utils import common_setup
13
+ class TestGenericPatch(unittest.TestCase):
14
+ data = {"items": "value"}
15
+ def setUp(self):
16
+ self.langchain_mock, self.tracer, self.span = common_setup(self.data, None)
17
+
18
+ def tearDown(self):
19
+ # Clean up after each test case
20
+ pass
21
+
22
+ def test_generic_patch(self):
23
+ # Arrange
24
+ method_name = "example_method"
25
+ trace_output = False
26
+ trace_input = True
27
+ task = "retriever"
28
+ args = (1, 2, 3)
29
+ kwargs = {'key': 'value'}
30
+ version = importlib.metadata.version("langchain-core")
31
+
32
+ # Act
33
+ wrapped_function = generic_patch("langchain_core.retrievers", task , self.tracer, version, trace_output, trace_input)
34
+ result = wrapped_function(self.langchain_mock, MagicMock(), args, kwargs)
35
+
36
+ # Assert
37
+ self.assertTrue(self.tracer.start_as_current_span.called_once_with(method_name, kind=SpanKind.CLIENT))
38
+
39
+ service_provider = "Langchain Core"
40
+ expected_attributes = {
41
+ "langtrace.service.name": service_provider,
42
+ "langtrace.service.type": "framework",
43
+ "langtrace.service.version": version,
44
+ "langtrace.version": "1.0.0",
45
+ "langchain.task.name": task,
46
+ }
47
+
48
+ self.assertTrue(
49
+ self.span.set_attribute.has_calls(
50
+ [call(key, value) for key, value in expected_attributes.items()], any_order=True
51
+ )
52
+ )
53
+
54
+ actual_calls = self.span.set_attribute.call_args_list
55
+ for key, value in expected_attributes.items():
56
+ self.assertIn(call(key, value), actual_calls)
57
+
58
+
59
+ self.assertEqual(self.span.set_status.call_count, 1)
60
+ self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
61
+
62
+ expected_result_data = {"items": "value" }
63
+ self.assertEqual(result.items, expected_result_data["items"])
64
+
65
+ def test_runnable_patch(self):
66
+ # Arrange
67
+ method_name = "example_method"
68
+ trace_output = False
69
+ trace_input = True
70
+ args = (1, 2, 3)
71
+ kwargs = {'key': 'value'}
72
+ version = importlib.metadata.version("langchain-core")
73
+
74
+ # Act
75
+ wrapped_function = runnable_patch("langchain_core.runnables.passthrough",
76
+ "runnablepassthrough", self.tracer, version, trace_output, trace_input)
77
+
78
+ result = wrapped_function(self.langchain_mock, MagicMock(), args, kwargs)
79
+
80
+ # Assert
81
+ self.assertTrue(self.tracer.start_as_current_span.called_once_with(method_name, kind=SpanKind.CLIENT))
82
+
83
+ service_provider = "Langchain Core"
84
+ expected_attributes = {
85
+ "langtrace.service.name": service_provider,
86
+ "langtrace.service.type": "framework",
87
+ "langtrace.service.version": version,
88
+ "langtrace.version": "1.0.0",
89
+ "langchain.task.name": "runnablepassthrough",
90
+ }
91
+
92
+ self.assertTrue(
93
+ self.span.set_attribute.has_calls(
94
+ [call(key, value) for key, value in expected_attributes.items()], any_order=True
95
+ )
96
+ )
97
+
98
+ actual_calls = self.span.set_attribute.call_args_list
99
+
100
+ for key, value in expected_attributes.items():
101
+ self.assertIn(call(key, value), actual_calls)
102
+
103
+
104
+ self.assertEqual(self.span.set_status.call_count, 1)
105
+ self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
106
+
107
+ expected_result_data = {"items": "value" }
108
+
109
+ self.assertEqual(result.items, expected_result_data["items"])
110
+
111
+
112
+ if __name__ == '__main__':
113
+ unittest.main()
@@ -10,38 +10,35 @@ from opentelemetry.trace.status import Status, StatusCode
10
10
  import json
11
11
  from tests.utils import common_setup
12
12
  class TestChatCompletion(unittest.TestCase):
13
+
13
14
  data = {
14
15
  "id": "chatcmpl-93wIW4A2r0YjlDvx7PKvHV0VxbprP",
15
- "choices": [
16
- {
17
- "finish_reason": "stop",
18
- "index": 0,
19
- "logprobs": None,
20
- "message": {
21
- "content": "This is a test, this is a test, this is a test.",
22
- "role": "assistant",
23
- "function_call": None,
24
- "tool_calls": None
25
- }
26
- }
16
+ "choices":[
17
+ MagicMock(
18
+ finish_reason="stop",
19
+ index=0,
20
+ logprobs=None,
21
+ message=MagicMock(
22
+ content="This is a test, this is a test, this is a test.",
23
+ role="assistant",
24
+ function_call=None,
25
+ tool_calls=None
26
+ )
27
+ )
27
28
  ],
28
29
  "created": 1710726108,
29
30
  "model": "gpt-4-0613",
30
31
  "object": "chat.completion",
31
32
  "system_fingerprint": None,
32
- "usage": {
33
- "completion_tokens": 15,
34
- "prompt_tokens": 14,
35
- "total_tokens": 29
36
- }
33
+ "usage": MagicMock(prompt_tokens = 14, completion_tokens = 15, total_tokens = 29)
37
34
  }
38
35
 
39
36
  def setUp(self):
40
- self.openai_mock, self.tracer, self.span = common_setup(self.data, 'openai.chat.completions.create')
41
-
42
-
37
+ self.openai_mock, self.tracer, self.span = common_setup(self.data, None)
38
+
39
+
43
40
  def tearDown(self):
44
- self.openai_mock.stop()
41
+ pass
45
42
 
46
43
  def test_chat_completions_create_non_streaming(self):
47
44
  # Arrange
@@ -49,15 +46,18 @@ class TestChatCompletion(unittest.TestCase):
49
46
  llm_model_value = 'gpt-4'
50
47
  messages_value = [{'role': 'user', 'content': 'Say this is a test three times'}]
51
48
 
49
+
52
50
  kwargs = {
53
51
  'model': llm_model_value,
54
52
  'messages': messages_value,
55
53
  'stream': False,
56
54
  }
57
55
 
56
+
58
57
  # Act
59
- wrapped_function = chat_completions_create(openai.chat.completions.create, version, self.tracer)
58
+ wrapped_function = chat_completions_create(self.openai_mock, version, self.tracer)
60
59
  result = wrapped_function(MagicMock(), MagicMock(), (), kwargs)
60
+
61
61
 
62
62
  # Assert
63
63
  self.assertTrue(self.tracer.start_as_current_span.called_once_with("openai.chat.completions.create", kind=SpanKind.CLIENT))
@@ -79,17 +79,12 @@ class TestChatCompletion(unittest.TestCase):
79
79
  )
80
80
  )
81
81
 
82
- self.assertEqual(self.span.set_status.call_count, 1)
83
82
  self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
84
83
 
85
- expected_result = ['id', 'choices', 'created', 'model', 'system_fingerprint', 'object', 'usage']
86
- result_keys = json.loads(result).keys()
87
- self.assertSetEqual(set(expected_result), set(result_keys), "Keys mismatch")
84
+ expected_result_data = {"model": "gpt-4-0613"}
85
+
86
+ self.assertEqual(result.model, expected_result_data["model"])
88
87
 
89
- expected_content = "This is a test, this is a test, this is a test."
90
- self.assertEqual(
91
- json.loads(result).get('choices')[0].get('message').get('content'), expected_content, "Content mismatch"
92
- )
93
88
 
94
89
  if __name__ == '__main__':
95
90
  unittest.main()
@@ -3,6 +3,7 @@ from unittest.mock import MagicMock, Mock, patch, call
3
3
  from langtrace_python_sdk.instrumentation.openai.patch import images_generate
4
4
  from opentelemetry.trace import SpanKind
5
5
  from opentelemetry.trace import get_tracer
6
+ from opentelemetry import baggage
6
7
  import importlib.metadata
7
8
  import openai
8
9
  from langtrace_python_sdk.constants.instrumentation.openai import APIS
@@ -11,6 +12,7 @@ from opentelemetry.trace.status import Status, StatusCode
11
12
  import json
12
13
  from tests.utils import common_setup
13
14
 
15
+
14
16
  class TestImageGeneration(unittest.TestCase):
15
17
  data = {
16
18
  "created": 1710983755,
@@ -24,7 +26,7 @@ class TestImageGeneration(unittest.TestCase):
24
26
  }
25
27
 
26
28
  def setUp(self):
27
- self.openai_mock, self.tracer, self.span = common_setup(self.data, 'openai.images.generate')
29
+ self.openai_mock, self.tracer, self.span = common_setup(self.data, "openai.images.generate")
28
30
 
29
31
 
30
32
  def tearDown(self):
@@ -38,7 +40,8 @@ class TestImageGeneration(unittest.TestCase):
38
40
  kwargs = {
39
41
  'model': llm_model_value,
40
42
  'prompt': prompt_value,
41
- 'stream': False }
43
+ 'stream': False }
44
+
42
45
 
43
46
  # Act
44
47
  wrapped_function = images_generate(openai.images.generate, version, self.tracer)
@@ -48,7 +51,7 @@ class TestImageGeneration(unittest.TestCase):
48
51
  self.assertTrue(self.tracer.start_as_current_span.called_once_with("openai.images.generate", kind=SpanKind.CLIENT))
49
52
 
50
53
  expected_attributes = {
51
- "langtrace.service.name": 'OpenAI',
54
+ "langtrace.service.name": "OpenAI",
52
55
  "langtrace.service.type": "llm",
53
56
  "langtrace.service.version": version,
54
57
  "langtrace.version": "1.0.0",
@@ -56,7 +59,7 @@ class TestImageGeneration(unittest.TestCase):
56
59
  "llm.api": "images_generation_endpoint",
57
60
  "llm.model": kwargs.get('model'),
58
61
  "llm.stream": kwargs.get('stream'),
59
- "llm.prompts": json.dumps([kwargs.get('prompt', [])])
62
+ "llm.prompts": json.dumps([kwargs.get('prompt', [])]),
60
63
  }
61
64
  self.assertTrue(self.span.set_attribute.has_calls([call(key, value) for key, value in expected_attributes.items()], any_order=True))
62
65
  self.assertTrue(self.span.set_status.called_once_with(Status(StatusCode.OK)))
@@ -54,6 +54,12 @@ class TestPinecone(unittest.TestCase):
54
54
  [call(key, value) for key, value in expected_attributes.items()], any_order=True
55
55
  )
56
56
  )
57
+
58
+ actual_calls = self.span.set_attribute.call_args_list
59
+
60
+ for key, value in expected_attributes.items():
61
+ self.assertIn(call(key, value), actual_calls)
62
+
57
63
  self.assertEqual(self.span.set_status.call_count, 1)
58
64
  self.assertTrue(self.span.set_status.has_calls([call(Status(StatusCode.OK))]))
59
65
 
@@ -0,0 +1,21 @@
1
+ from unittest.mock import MagicMock, patch
2
+ import json
3
+
4
+ def common_setup(data, method_to_mock=None):
5
+ if method_to_mock:
6
+ service_mock = patch(method_to_mock)
7
+ mock_method = service_mock.start()
8
+ mock_method.return_value = json.dumps(data)
9
+ else:
10
+ service_mock = MagicMock()
11
+ service_mock.return_value = MagicMock(**data)
12
+
13
+
14
+ tracer = MagicMock()
15
+ span = MagicMock()
16
+
17
+ context_manager_mock = MagicMock()
18
+ context_manager_mock.__enter__.return_value = span
19
+ tracer.start_as_current_span.return_value = context_manager_mock
20
+
21
+ return service_mock, tracer, span
@@ -1 +0,0 @@
1
- __version__ = "1.2.11"
@@ -1,17 +0,0 @@
1
- import importlib.metadata
2
- from unittest.mock import MagicMock, patch
3
- import json
4
-
5
- def common_setup(data, method_to_mock):
6
- service_mock = patch(method_to_mock)
7
- mock_image_generate = service_mock.start()
8
- mock_image_generate.return_value = json.dumps(data)
9
-
10
- tracer = MagicMock()
11
- span = MagicMock()
12
-
13
- context_manager_mock = MagicMock()
14
- context_manager_mock.__enter__.return_value = span
15
- tracer.start_as_current_span.return_value = context_manager_mock
16
-
17
- return service_mock, tracer, span