langtrace-python-sdk 3.8.7__py3-none-any.whl → 3.8.8__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.
@@ -22,6 +22,7 @@ from .litellm import LiteLLMInstrumentation
22
22
  from .llamaindex import LlamaindexInstrumentation
23
23
  from .milvus import MilvusInstrumentation
24
24
  from .mistral import MistralInstrumentation
25
+ from .neo4j_graphrag import Neo4jGraphRAGInstrumentation
25
26
  from .ollama import OllamaInstrumentor
26
27
  from .openai import OpenAIInstrumentation
27
28
  from .openai_agents import OpenAIAgentsInstrumentation
@@ -59,6 +60,7 @@ __all__ = [
59
60
  "AWSBedrockInstrumentation",
60
61
  "CerebrasInstrumentation",
61
62
  "MilvusInstrumentation",
63
+ "Neo4jGraphRAGInstrumentation",
62
64
  "GoogleGenaiInstrumentation",
63
65
  "CrewaiToolsInstrumentation",
64
66
  "GraphlitInstrumentation",
@@ -0,0 +1,3 @@
1
+ from .instrumentation import Neo4jGraphRAGInstrumentation
2
+
3
+ __all__ = ["Neo4jGraphRAGInstrumentation"]
@@ -0,0 +1,62 @@
1
+ """
2
+ Copyright (c) 2025 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
+ from typing import Collection
18
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
19
+ from opentelemetry import trace
20
+ from wrapt import wrap_function_wrapper as _W
21
+ from importlib.metadata import version as v
22
+ from .patch import patch_graphrag_search, patch_kg_pipeline_run, \
23
+ patch_kg_pipeline_run, patch_retriever_search
24
+
25
+
26
+ class Neo4jGraphRAGInstrumentation(BaseInstrumentor):
27
+
28
+ def instrumentation_dependencies(self) -> Collection[str]:
29
+ return ["neo4j-graphrag>=1.6.0"]
30
+
31
+ def _instrument(self, **kwargs):
32
+ tracer_provider = kwargs.get("tracer_provider")
33
+ tracer = trace.get_tracer(__name__, "", tracer_provider)
34
+ graphrag_version = v("neo4j-graphrag")
35
+
36
+ try:
37
+ # instrument kg builder
38
+ _W(
39
+ "neo4j_graphrag.experimental.pipeline.kg_builder",
40
+ "SimpleKGPipeline.run_async",
41
+ patch_kg_pipeline_run("run_async", graphrag_version, tracer),
42
+ )
43
+
44
+ # Instrument GraphRAG
45
+ _W(
46
+ "neo4j_graphrag.generation.graphrag",
47
+ "GraphRAG.search",
48
+ patch_graphrag_search("search", graphrag_version, tracer),
49
+ )
50
+
51
+ # Instrument retrievers
52
+ _W(
53
+ "neo4j_graphrag.retrievers.vector",
54
+ "VectorRetriever.get_search_results",
55
+ patch_retriever_search("vector_search", graphrag_version, tracer),
56
+ )
57
+
58
+ except Exception as e:
59
+ print(f"Failed to instrument Neo4j GraphRAG: {e}")
60
+
61
+ def _uninstrument(self, **kwargs):
62
+ pass
@@ -0,0 +1,229 @@
1
+ """
2
+ Copyright (c) 2025 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
+ import json
18
+
19
+ from importlib_metadata import version as v
20
+ from langtrace.trace_attributes import FrameworkSpanAttributes
21
+ from opentelemetry import baggage
22
+ from opentelemetry.trace import Span, SpanKind, Tracer
23
+ from opentelemetry.trace.status import Status, StatusCode
24
+
25
+ from langtrace_python_sdk.constants import LANGTRACE_SDK_NAME
26
+ from langtrace_python_sdk.constants.instrumentation.common import (
27
+ LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY, SERVICE_PROVIDERS)
28
+ from langtrace_python_sdk.utils.llm import set_span_attributes
29
+ from langtrace_python_sdk.utils.misc import serialize_args, serialize_kwargs
30
+
31
+
32
+ def patch_kg_pipeline_run(operation_name: str, version: str, tracer: Tracer):
33
+
34
+ async def async_traced_method(wrapped, instance, args, kwargs):
35
+ service_provider = SERVICE_PROVIDERS.get("NEO4J_GRAPHRAG", "neo4j_graphrag")
36
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
37
+
38
+ span_attributes = {
39
+ "langtrace.sdk.name": "langtrace-python-sdk",
40
+ "langtrace.service.name": service_provider,
41
+ "langtrace.service.type": "framework",
42
+ "langtrace.service.version": version,
43
+ "langtrace.version": v(LANGTRACE_SDK_NAME),
44
+ "neo4j.pipeline.type": "SimpleKGPipeline",
45
+ **(extra_attributes if extra_attributes is not None else {}),
46
+ }
47
+
48
+ if len(args) > 0:
49
+ span_attributes["neo4j.pipeline.inputs"] = serialize_args(*args)
50
+ if kwargs:
51
+ span_attributes["neo4j.pipeline.kwargs"] = serialize_kwargs(**kwargs)
52
+
53
+ file_path = kwargs.get("file_path", args[0] if len(args) > 0 else None)
54
+ text = kwargs.get("text", args[1] if len(args) > 1 else None)
55
+ if file_path:
56
+ span_attributes["neo4j.pipeline.file_path"] = file_path
57
+ if text:
58
+ span_attributes["neo4j.pipeline.text_length"] = len(text)
59
+
60
+ if hasattr(instance, "runner") and hasattr(instance.runner, "config"):
61
+ config = instance.runner.config
62
+ if config:
63
+ span_attributes["neo4j.pipeline.from_pdf"] = getattr(config, "from_pdf", None)
64
+ span_attributes["neo4j.pipeline.perform_entity_resolution"] = getattr(config, "perform_entity_resolution", None)
65
+
66
+ attributes = FrameworkSpanAttributes(**span_attributes)
67
+
68
+ with tracer.start_as_current_span(
69
+ name=f"neo4j.pipeline.{operation_name}",
70
+ kind=SpanKind.CLIENT,
71
+ ) as span:
72
+ try:
73
+ set_span_attributes(span, attributes)
74
+
75
+ result = await wrapped(*args, **kwargs)
76
+
77
+ if result:
78
+ try:
79
+ if hasattr(result, "to_dict"):
80
+ result_dict = result.to_dict()
81
+ span.set_attribute("neo4j.pipeline.result", json.dumps(result_dict))
82
+ elif hasattr(result, "model_dump"):
83
+ result_dict = result.model_dump()
84
+ span.set_attribute("neo4j.pipeline.result", json.dumps(result_dict))
85
+ except Exception as e:
86
+ span.set_attribute("neo4j.pipeline.result_error", str(e))
87
+
88
+ span.set_status(Status(StatusCode.OK))
89
+ return result
90
+
91
+ except Exception as err:
92
+ span.record_exception(err)
93
+ span.set_status(Status(StatusCode.ERROR, str(err)))
94
+ raise
95
+
96
+ return async_traced_method
97
+
98
+
99
+ def patch_graphrag_search(operation_name: str, version: str, tracer: Tracer):
100
+
101
+ def traced_method(wrapped, instance, args, kwargs):
102
+ service_provider = SERVICE_PROVIDERS.get("NEO4J_GRAPHRAG", "neo4j_graphrag")
103
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
104
+
105
+ # Basic attributes
106
+ span_attributes = {
107
+ "langtrace.sdk.name": "langtrace-python-sdk",
108
+ "langtrace.service.name": service_provider,
109
+ "langtrace.service.type": "framework",
110
+ "langtrace.service.version": version,
111
+ "langtrace.version": v(LANGTRACE_SDK_NAME),
112
+ "neo4j_graphrag.operation": operation_name,
113
+ **(extra_attributes if extra_attributes is not None else {}),
114
+ }
115
+
116
+ query_text = kwargs.get("query_text", args[0] if len(args) > 0 else None)
117
+ if query_text:
118
+ span_attributes["neo4j_graphrag.query_text"] = query_text
119
+
120
+ retriever_config = kwargs.get("retriever_config", None)
121
+ if retriever_config:
122
+ span_attributes["neo4j_graphrag.retriever_config"] = json.dumps(retriever_config)
123
+
124
+ if hasattr(instance, "retriever"):
125
+ span_attributes["neo4j_graphrag.retriever_type"] = instance.retriever.__class__.__name__
126
+
127
+ if hasattr(instance, "llm"):
128
+ span_attributes["neo4j_graphrag.llm_type"] = instance.llm.__class__.__name__
129
+
130
+ attributes = FrameworkSpanAttributes(**span_attributes)
131
+
132
+ with tracer.start_as_current_span(
133
+ name=f"neo4j_graphrag.{operation_name}",
134
+ kind=SpanKind.CLIENT,
135
+ ) as span:
136
+ try:
137
+ set_span_attributes(span, attributes)
138
+
139
+ result = wrapped(*args, **kwargs)
140
+
141
+ if result and hasattr(result, "answer"):
142
+ span.set_attribute("neo4j_graphrag.answer", result.answer)
143
+
144
+ if hasattr(result, "retriever_result") and result.retriever_result:
145
+ try:
146
+ retriever_items = len(result.retriever_result.items)
147
+ span.set_attribute("neo4j_graphrag.context_items", retriever_items)
148
+ except Exception:
149
+ pass
150
+
151
+ span.set_status(Status(StatusCode.OK))
152
+ return result
153
+
154
+ except Exception as err:
155
+ span.record_exception(err)
156
+ span.set_status(Status(StatusCode.ERROR, str(err)))
157
+ raise
158
+
159
+ return traced_method
160
+
161
+
162
+ def patch_retriever_search(operation_name: str, version: str, tracer: Tracer):
163
+
164
+ def traced_method(wrapped, instance, args, kwargs):
165
+ service_provider = SERVICE_PROVIDERS.get("NEO4J_GRAPHRAG", "neo4j_graphrag")
166
+ extra_attributes = baggage.get_baggage(LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY)
167
+
168
+ # Basic attributes
169
+ span_attributes = {
170
+ "langtrace.sdk.name": "langtrace-python-sdk",
171
+ "langtrace.service.name": service_provider,
172
+ "langtrace.service.type": "framework",
173
+ "langtrace.service.version": version,
174
+ "langtrace.version": v(LANGTRACE_SDK_NAME),
175
+ "neo4j.retriever.operation": operation_name,
176
+ "neo4j.retriever.type": instance.__class__.__name__,
177
+ **(extra_attributes if extra_attributes is not None else {}),
178
+ }
179
+
180
+ query_text = kwargs.get("query_text", args[0] if len(args) > 0 else None)
181
+ if query_text:
182
+ span_attributes["neo4j.retriever.query_text"] = query_text
183
+
184
+ if hasattr(instance, "__class__") and hasattr(instance.__class__, "__name__"):
185
+ retriever_type = instance.__class__.__name__
186
+
187
+ if retriever_type == "VectorRetriever" and hasattr(instance, "index_name"):
188
+ span_attributes["neo4j.vector_retriever.index_name"] = instance.index_name
189
+
190
+ if retriever_type == "KnowledgeGraphRetriever" and hasattr(instance, "cypher_query"):
191
+ span_attributes["neo4j.kg_retriever.cypher_query"] = instance.cypher_query
192
+
193
+ for param in ["top_k", "similarity_threshold"]:
194
+ if param in kwargs:
195
+ span_attributes[f"neo4j.retriever.{param}"] = kwargs[param]
196
+ elif hasattr(instance, param):
197
+ span_attributes[f"neo4j.retriever.{param}"] = getattr(instance, param)
198
+
199
+ attributes = FrameworkSpanAttributes(**span_attributes)
200
+
201
+ with tracer.start_as_current_span(
202
+ name=f"neo4j.retriever.{operation_name}",
203
+ kind=SpanKind.CLIENT,
204
+ ) as span:
205
+ try:
206
+ set_span_attributes(span, attributes)
207
+
208
+ result = wrapped(*args, **kwargs)
209
+
210
+ if result:
211
+ if hasattr(result, "items") and isinstance(result.items, list):
212
+ span.set_attribute("neo4j.retriever.items_count", len(result.items))
213
+
214
+ try:
215
+ item_ids = [item.id for item in result.items[:5] if hasattr(item, "id")]
216
+ if item_ids:
217
+ span.set_attribute("neo4j.retriever.item_ids", json.dumps(item_ids))
218
+ except Exception:
219
+ pass
220
+
221
+ span.set_status(Status(StatusCode.OK))
222
+ return result
223
+
224
+ except Exception as err:
225
+ span.record_exception(err)
226
+ span.set_status(Status(StatusCode.ERROR, str(err)))
227
+ raise
228
+
229
+ return traced_method
@@ -48,8 +48,8 @@ from langtrace_python_sdk.instrumentation import (
48
48
  GeminiInstrumentation, GoogleGenaiInstrumentation, GraphlitInstrumentation,
49
49
  GroqInstrumentation, LangchainCommunityInstrumentation,
50
50
  LangchainCoreInstrumentation, LangchainInstrumentation,
51
- LanggraphInstrumentation, LiteLLMInstrumentation,
52
- LlamaindexInstrumentation, MilvusInstrumentation, MistralInstrumentation,
51
+ LanggraphInstrumentation, LiteLLMInstrumentation, LlamaindexInstrumentation,
52
+ MilvusInstrumentation, MistralInstrumentation, Neo4jGraphRAGInstrumentation,
53
53
  OllamaInstrumentor, OpenAIAgentsInstrumentation, OpenAIInstrumentation,
54
54
  PhiDataInstrumentation, PineconeInstrumentation, PyMongoInstrumentation,
55
55
  QdrantInstrumentation, VertexAIInstrumentation, WeaviateInstrumentation)
@@ -284,6 +284,7 @@ def init(
284
284
  "phidata": PhiDataInstrumentation(),
285
285
  "agno": AgnoInstrumentation(),
286
286
  "mistralai": MistralInstrumentation(),
287
+ "neo4j-graphrag": Neo4jGraphRAGInstrumentation(),
287
288
  "boto3": AWSBedrockInstrumentation(),
288
289
  "autogen": AutogenInstrumentation(),
289
290
  "pymongo": PyMongoInstrumentation(),
@@ -1 +1 @@
1
- __version__ = "3.8.7"
1
+ __version__ = "3.8.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langtrace-python-sdk
3
- Version: 3.8.7
3
+ Version: 3.8.8
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>
@@ -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=T-DsDrwWaL4gAUK1lkTRRpmvoO7F2WtO5hQZdyrVAxE,13791
119
- langtrace_python_sdk/version.py,sha256=zMoy0NhWOOCYaBDKkUvjVGd7u0NZBhM_7SModsbbTxQ,22
118
+ langtrace_python_sdk/langtrace.py,sha256=4nhcy9_T3h4m5T5Blyrvs0BJcKzPWMtkIyEDSbba8P8,13879
119
+ langtrace_python_sdk/version.py,sha256=3SjfTmtUQqjDdaQC3uiCoISksstrQ1Sqj4ASUtoUrzs,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,7 +141,7 @@ 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=DC96oELorZedDf5zooQ6HGi-dmieXwUephgeB_LzfaU,2559
144
+ langtrace_python_sdk/instrumentation/__init__.py,sha256=lw53EsTTtOK-dMhImudipmbVhZqORylt4hO5A7Mv8Uo,2652
145
145
  langtrace_python_sdk/instrumentation/agno/__init__.py,sha256=95fn4oA-CHB0mxc6KnVB20KSbXGl_ZZr9n99EEaXzrY,91
146
146
  langtrace_python_sdk/instrumentation/agno/instrumentation.py,sha256=XUnfvqpp13IgdF03xGKasq7kGjeaN1sXLIwCf-Nt_Nc,2667
147
147
  langtrace_python_sdk/instrumentation/agno/patch.py,sha256=qCUxCkzU9cYu_d8BzLgj_Ss97qib07tRVYpYDiNnNMs,16876
@@ -218,6 +218,9 @@ langtrace_python_sdk/instrumentation/milvus/patch.py,sha256=0yY5aQz0x7hpQZ8U-0qf
218
218
  langtrace_python_sdk/instrumentation/mistral/__init__.py,sha256=mkGALBQvq0jSfwDl6TU09SFwnVs6O4zkUi-yVmd3SNg,90
219
219
  langtrace_python_sdk/instrumentation/mistral/instrumentation.py,sha256=qtCkHCSOaiicUChbmTID4lcK1rbeW8oRSbpda2ogbgM,2328
220
220
  langtrace_python_sdk/instrumentation/mistral/patch.py,sha256=5EzqMeIEcMUH8P-l9-ijpRNWSc6mYwe9Gz0VY4PLrS0,6559
221
+ langtrace_python_sdk/instrumentation/neo4j_graphrag/__init__.py,sha256=K-Qpfh-kn2EPxnYZ_oubLZNqAUO9Cx7mnMrJu_ms3UU,102
222
+ langtrace_python_sdk/instrumentation/neo4j_graphrag/instrumentation.py,sha256=FLnddPSozuu5puqYD_FnXLMFet8YToVdWP-cY5QZrvM,2216
223
+ langtrace_python_sdk/instrumentation/neo4j_graphrag/patch.py,sha256=4c7NKcTJeYsbi5V4aSsuPzTiFoBqtlcXmYx2bMlE7qg,9713
221
224
  langtrace_python_sdk/instrumentation/ollama/__init__.py,sha256=g2zJsXnDHinXPzTc-WxDeTtHmr9gmAj3K6l_00kP8c8,82
222
225
  langtrace_python_sdk/instrumentation/ollama/instrumentation.py,sha256=jdsvkqUJAAUNLVPtAkn_rG26HXetVQXWtjn4a6eWZro,2029
223
226
  langtrace_python_sdk/instrumentation/ollama/patch.py,sha256=w99r9wCCVDdJnZQEezYE2lW_iNFEtrldt9vq3ISAsag,5375
@@ -300,8 +303,8 @@ tests/pinecone/cassettes/test_query.yaml,sha256=b5v9G3ssUy00oG63PlFUR3JErF2Js-5A
300
303
  tests/pinecone/cassettes/test_upsert.yaml,sha256=neWmQ1v3d03V8WoLl8FoFeeCYImb8pxlJBWnFd_lITU,38607
301
304
  tests/qdrant/conftest.py,sha256=9n0uHxxIjWk9fbYc4bx-uP8lSAgLBVx-cV9UjnsyCHM,381
302
305
  tests/qdrant/test_qdrant.py,sha256=pzjAjVY2kmsmGfrI2Gs2xrolfuaNHz7l1fqGQCjp5_o,3353
303
- langtrace_python_sdk-3.8.7.dist-info/METADATA,sha256=au8c2l_qdpKK8lgICNgotmeqr6K6mD4r_nhOS5X9pJo,15844
304
- langtrace_python_sdk-3.8.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
305
- langtrace_python_sdk-3.8.7.dist-info/entry_points.txt,sha256=1_b9-qvf2fE7uQNZcbUei9vLpFZBbbh9LrtGw95ssAo,70
306
- langtrace_python_sdk-3.8.7.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
307
- langtrace_python_sdk-3.8.7.dist-info/RECORD,,
306
+ langtrace_python_sdk-3.8.8.dist-info/METADATA,sha256=deElB8UvrgQqY6ZaOFhY7bKQnvXEinTTrnNkgz4b04o,15844
307
+ langtrace_python_sdk-3.8.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
308
+ langtrace_python_sdk-3.8.8.dist-info/entry_points.txt,sha256=1_b9-qvf2fE7uQNZcbUei9vLpFZBbbh9LrtGw95ssAo,70
309
+ langtrace_python_sdk-3.8.8.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
310
+ langtrace_python_sdk-3.8.8.dist-info/RECORD,,