ragaai-catalyst 2.1.7b0__py3-none-any.whl → 2.1.7.1__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.
@@ -14,7 +14,7 @@ class DynamicTraceExporter(SpanExporter):
14
14
  certain properties to be updated dynamically during execution.
15
15
  """
16
16
 
17
- def __init__(self, tracer_type, files_to_zip, project_name, project_id, dataset_name, user_details, base_url, custom_model_cost, timeout=120, post_processor = None):
17
+ def __init__(self, tracer_type, files_to_zip, project_name, project_id, dataset_name, user_details, base_url, custom_model_cost, timeout=120, post_processor = None, max_upload_workers = 30,user_context = None, external_id=None):
18
18
  """
19
19
  Initialize the DynamicTraceExporter.
20
20
 
@@ -27,6 +27,7 @@ class DynamicTraceExporter(SpanExporter):
27
27
  user_details: User details
28
28
  base_url: Base URL for API
29
29
  post_processor: Post processing function before uploading trace
30
+ max_upload_workers: Maximum number of upload workers
30
31
  """
31
32
  self._exporter = RAGATraceExporter(
32
33
  tracer_type=tracer_type,
@@ -38,7 +39,10 @@ class DynamicTraceExporter(SpanExporter):
38
39
  base_url=base_url,
39
40
  custom_model_cost=custom_model_cost,
40
41
  timeout=timeout,
41
- post_processor= post_processor
42
+ post_processor= post_processor,
43
+ max_upload_workers = max_upload_workers,
44
+ user_context = user_context,
45
+ external_id=external_id
42
46
  )
43
47
 
44
48
  # Store the initial values
@@ -50,6 +54,8 @@ class DynamicTraceExporter(SpanExporter):
50
54
  self._base_url = base_url
51
55
  self._custom_model_cost = custom_model_cost
52
56
  self._post_processor = post_processor
57
+ self._max_upload_workers = max_upload_workers
58
+ self._user_context = user_context
53
59
 
54
60
 
55
61
  def export(self, spans):
@@ -107,6 +113,8 @@ class DynamicTraceExporter(SpanExporter):
107
113
  self._exporter.base_url = self._base_url
108
114
  self._exporter.custom_model_cost = self._custom_model_cost
109
115
  self._exporter.post_processor = self._post_processor
116
+ self._exporter.max_upload_workers = self._max_upload_workers
117
+ self._exporter.user_context = self._user_context
110
118
 
111
119
  # Getter and setter methods for dynamic properties
112
120
 
@@ -165,3 +173,20 @@ class DynamicTraceExporter(SpanExporter):
165
173
  @custom_model_cost.setter
166
174
  def custom_model_cost(self, value):
167
175
  self._custom_model_cost = value
176
+
177
+ @property
178
+ def max_upload_workers(self):
179
+ return self._max_upload_workers
180
+
181
+ @max_upload_workers.setter
182
+ def max_upload_workers(self, value):
183
+ self._max_upload_workers = value
184
+
185
+ @property
186
+ def user_context(self):
187
+ return self._user_context
188
+
189
+ @user_context.setter
190
+ def user_context(self, value):
191
+ self._user_context = value
192
+
@@ -26,7 +26,7 @@ logging_level = (
26
26
 
27
27
 
28
28
  class RAGATraceExporter(SpanExporter):
29
- def __init__(self, tracer_type, files_to_zip, project_name, project_id, dataset_name, user_details, base_url, custom_model_cost, timeout=120, post_processor = None):
29
+ def __init__(self, tracer_type, files_to_zip, project_name, project_id, dataset_name, user_details, base_url, custom_model_cost, timeout=120, post_processor = None, max_upload_workers = 30,user_context = None, external_id=None):
30
30
  self.trace_spans = dict()
31
31
  self.tmp_dir = tempfile.gettempdir()
32
32
  self.tracer_type = tracer_type
@@ -40,6 +40,9 @@ class RAGATraceExporter(SpanExporter):
40
40
  self.system_monitor = SystemMonitor(dataset_name)
41
41
  self.timeout = timeout
42
42
  self.post_processor = post_processor
43
+ self.max_upload_workers = max_upload_workers
44
+ self.user_context = user_context
45
+ self.external_id = external_id
43
46
 
44
47
  def export(self, spans):
45
48
  for span in spans:
@@ -85,12 +88,33 @@ class RAGATraceExporter(SpanExporter):
85
88
  ragaai_trace_details = self.prepare_trace(spans, trace_id)
86
89
  except Exception as e:
87
90
  print(f"Error converting trace {trace_id}: {e}")
91
+ return # Exit early if conversion fails
92
+
93
+ # Check if trace details are None (conversion failed)
94
+ if ragaai_trace_details is None:
95
+ logger.error(f"Cannot upload trace {trace_id}: conversion failed and returned None")
96
+ return # Exit early if conversion failed
97
+
88
98
  # Upload the trace if upload_trace function is provided
89
99
  try:
90
100
  if self.post_processor!=None:
91
101
  ragaai_trace_details['trace_file_path'] = self.post_processor(ragaai_trace_details['trace_file_path'])
92
102
  if self.tracer_type == "langchain":
93
- asyncio.run(self.upload_rag_trace(ragaai_trace_details, additional_metadata, trace_id))
103
+ # Check if we're already in an event loop
104
+ try:
105
+ loop = asyncio.get_event_loop()
106
+ if loop.is_running():
107
+ # We're in a running event loop (like in Colab/Jupyter)
108
+ # Create a future and run the coroutine
109
+ future = asyncio.ensure_future(self.upload_rag_trace(ragaai_trace_details, additional_metadata, trace_id))
110
+ # We don't wait for it to complete as this would block the event loop
111
+ logger.info(f"Scheduled async upload for trace {trace_id} in existing event loop")
112
+ else:
113
+ # No running event loop, use asyncio.run()
114
+ asyncio.run(self.upload_rag_trace(ragaai_trace_details, additional_metadata, trace_id))
115
+ except RuntimeError:
116
+ # No event loop exists, create one
117
+ asyncio.run(self.upload_rag_trace(ragaai_trace_details, additional_metadata, trace_id))
94
118
  else:
95
119
  self.upload_trace(ragaai_trace_details, trace_id)
96
120
  except Exception as e:
@@ -184,12 +208,14 @@ class RAGATraceExporter(SpanExporter):
184
208
 
185
209
  async def upload_rag_trace(self, ragaai_trace, additional_metadata, trace_id):
186
210
  try:
211
+ ragaai_trace[0]['external_id'] = self.external_id
187
212
  trace_file_path = os.path.join(self.tmp_dir, f"{trace_id}.json")
188
213
  with open(trace_file_path, 'w') as f:
189
214
  json.dump(ragaai_trace, f, indent=2)
190
-
215
+ logger.info(f"Trace file saved at {trace_file_path}")
216
+
191
217
  # Create a ThreadPoolExecutor with max_workers=30
192
- with concurrent.futures.ThreadPoolExecutor(max_workers=30) as executor:
218
+ with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_upload_workers) as executor:
193
219
  # Create a partial function with all the necessary arguments
194
220
  upload_func = partial(
195
221
  UploadTraces(
@@ -232,7 +258,7 @@ class RAGATraceExporter(SpanExporter):
232
258
 
233
259
  def prepare_rag_trace(self, spans, trace_id):
234
260
  try:
235
- ragaai_trace, additional_metadata = rag_trace_json_converter(spans, self.custom_model_cost, trace_id, self.user_details, self.tracer_type)
261
+ ragaai_trace, additional_metadata = rag_trace_json_converter(spans, self.custom_model_cost, trace_id, self.user_details, self.tracer_type,self.user_context)
236
262
  ragaai_trace["metadata"]["recorded_on"] = datetime.datetime.now().astimezone().isoformat()
237
263
  ragaai_trace["metadata"]["log_source"] = "langchain_tracer"
238
264
 
@@ -24,6 +24,7 @@ from ragaai_catalyst.tracers.exporters.raga_exporter import RagaExporter
24
24
  from ragaai_catalyst.tracers.utils import get_unique_key
25
25
  # from ragaai_catalyst.tracers.llamaindex_callback import LlamaIndexTracer
26
26
  from ragaai_catalyst.tracers.llamaindex_instrumentation import LlamaIndexInstrumentationTracer
27
+ from openinference.instrumentation.langchain import LangChainInstrumentor
27
28
  from ragaai_catalyst import RagaAICatalyst
28
29
  from ragaai_catalyst.tracers.agentic_tracing import AgenticTracing
29
30
  from ragaai_catalyst.tracers.agentic_tracing.tracers.llm_tracer import LLMTracerMixin
@@ -59,6 +60,8 @@ class Tracer(AgenticTracing):
59
60
  },
60
61
  interval_time=2,
61
62
  # auto_instrumentation=True/False # to control automatic instrumentation of everything
63
+ max_upload_workers=30,
64
+ external_id=None
62
65
 
63
66
  ):
64
67
  """
@@ -141,6 +144,11 @@ class Tracer(AgenticTracing):
141
144
  self.user_context = "" # Initialize user_context to store context from add_context
142
145
  self.file_tracker = TrackName()
143
146
  self.post_processor = None
147
+ self.max_upload_workers = max_upload_workers
148
+ self.user_details = self._pass_user_data()
149
+ self.update_llm_cost = update_llm_cost
150
+ self.auto_instrumentation = auto_instrumentation
151
+ self.external_id = external_id
144
152
 
145
153
  try:
146
154
  response = requests.get(
@@ -458,6 +466,30 @@ class Tracer(AgenticTracing):
458
466
  self.dynamic_exporter._exporter.post_processor = post_processor_func
459
467
  self.dynamic_exporter._post_processor = post_processor_func
460
468
  logger.info("Registered post process as: "+str(post_processor_func))
469
+
470
+
471
+ def set_external_id(self, external_id):
472
+ current_params = {
473
+ 'project_name': self.project_name,
474
+ 'dataset_name': self.dataset_name,
475
+ 'trace_name': self.trace_name,
476
+ 'tracer_type': self.tracer_type,
477
+ 'pipeline': self.pipeline,
478
+ 'metadata': self.metadata,
479
+ 'description': self.description,
480
+ 'timeout': self.timeout,
481
+ 'update_llm_cost': self.update_llm_cost,
482
+ 'auto_instrumentation': self.auto_instrumentation,
483
+ 'interval_time': self.interval_time,
484
+ 'max_upload_workers': self.max_upload_workers
485
+ }
486
+
487
+ # Reinitialize self with new external_id and stored parameters
488
+ self.__init__(
489
+ external_id=external_id,
490
+ **current_params
491
+ )
492
+
461
493
 
462
494
 
463
495
  def set_dataset_name(self, dataset_name):
@@ -483,15 +515,20 @@ class Tracer(AgenticTracing):
483
515
  # Also update the user_details in the dynamic exporter
484
516
  self.dynamic_exporter.user_details = self.user_details
485
517
  else:
486
- # Store current parameters
487
518
  current_params = {
488
- 'project_name': self.project_name,
489
- 'tracer_type': self.tracer_type,
490
- 'pipeline': self.pipeline,
491
- 'metadata': self.metadata,
492
- 'description': self.description,
493
- 'timeout': self.timeout
494
- }
519
+ 'project_name': self.project_name,
520
+ 'trace_name': self.trace_name,
521
+ 'tracer_type': self.tracer_type,
522
+ 'pipeline': self.pipeline,
523
+ 'metadata': self.metadata,
524
+ 'description': self.description,
525
+ 'timeout': self.timeout,
526
+ 'update_llm_cost': self.update_llm_cost,
527
+ 'auto_instrumentation': self.auto_instrumentation,
528
+ 'interval_time': self.interval_time,
529
+ 'max_upload_workers': self.max_upload_workers,
530
+ 'external_id': self.external_id
531
+ }
495
532
 
496
533
  # Reinitialize self with new dataset_name and stored parameters
497
534
  self.__init__(
@@ -501,7 +538,7 @@ class Tracer(AgenticTracing):
501
538
 
502
539
  def _improve_metadata(self, metadata, tracer_type):
503
540
  if metadata is None:
504
- metadata = {}
541
+ metadata = {"metadata": {}}
505
542
  metadata.setdefault("log_source", f"{tracer_type}_tracer")
506
543
  metadata.setdefault("recorded_on", str(datetime.datetime.now()))
507
544
  return metadata
@@ -763,7 +800,10 @@ class Tracer(AgenticTracing):
763
800
  base_url=self.base_url,
764
801
  custom_model_cost=self.model_custom_cost,
765
802
  timeout = self.timeout,
766
- post_processor= self.post_processor
803
+ post_processor= self.post_processor,
804
+ max_upload_workers = self.max_upload_workers,
805
+ user_context = self.user_context,
806
+ external_id=self.external_id
767
807
  )
768
808
 
769
809
  # Set up tracer provider
@@ -772,7 +812,15 @@ class Tracer(AgenticTracing):
772
812
 
773
813
  # Instrument all specified instrumentors
774
814
  for instrumentor_class, args in instrumentors:
775
- instrumentor_class().instrument(tracer_provider=tracer_provider, *args)
815
+ # Create an instance of the instrumentor
816
+ instrumentor = instrumentor_class()
817
+
818
+ # Uninstrument only if it is already instrumented
819
+ if isinstance(instrumentor, LangChainInstrumentor) and instrumentor._is_instrumented_by_opentelemetry:
820
+ instrumentor.uninstrument()
821
+
822
+ # Instrument with the provided tracer provider and arguments
823
+ instrumentor.instrument(tracer_provider=tracer_provider, *args)
776
824
 
777
825
  def update_file_list(self):
778
826
  """
@@ -807,6 +855,7 @@ class Tracer(AgenticTracing):
807
855
 
808
856
  # Convert string context to string if needed
809
857
  if isinstance(context, str):
858
+ self.dynamic_exporter.user_context = context
810
859
  self.user_context = context
811
860
  else:
812
861
  raise TypeError("context must be a string")
@@ -11,9 +11,8 @@ logging_level = (
11
11
  logger.setLevel(logging.DEBUG) if os.getenv("DEBUG") == "1" else logging.INFO
12
12
  )
13
13
 
14
- def rag_trace_json_converter(input_trace, custom_model_cost, trace_id, user_details, tracer_type):
14
+ def rag_trace_json_converter(input_trace, custom_model_cost, trace_id, user_details, tracer_type,user_context):
15
15
  trace_aggregate = {}
16
-
17
16
  def get_prompt(input_trace):
18
17
  if tracer_type == "langchain":
19
18
  for span in input_trace:
@@ -46,7 +45,9 @@ def rag_trace_json_converter(input_trace, custom_model_cost, trace_id, user_deta
46
45
  return None
47
46
 
48
47
  def get_context(input_trace):
49
- if tracer_type == "langchain":
48
+ if user_context.strip():
49
+ return user_context
50
+ elif tracer_type == "langchain":
50
51
  for span in input_trace:
51
52
  if span["name"] == "VectorStoreRetriever":
52
53
  return span["attributes"].get("retrieval.documents.1.document.content")
@@ -82,6 +83,7 @@ def rag_trace_json_converter(input_trace, custom_model_cost, trace_id, user_deta
82
83
  else:
83
84
  additional_metadata = get_additional_metadata(input_trace, custom_model_cost, model_cost)
84
85
 
86
+ trace_aggregate["metadata"] = user_details.get("trace_user_detail", {}).get("metadata")
85
87
  trace_aggregate["metadata"].update(additional_metadata)
86
88
  additional_metadata.pop("total_cost")
87
89
  additional_metadata.pop("total_latency")
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragaai_catalyst
3
- Version: 2.1.7b0
3
+ Version: 2.1.7.1
4
4
  Summary: RAGA AI CATALYST
5
5
  Author-email: Kiran Scaria <kiran.scaria@raga.ai>, Kedar Gaikwad <kedar.gaikwad@raga.ai>, Dushyant Mahajan <dushyant.mahajan@raga.ai>, Siddhartha Kosti <siddhartha.kosti@raga.ai>, Ritika Goel <ritika.goel@raga.ai>, Vijay Chaurasia <vijay.chaurasia@raga.ai>, Tushar Kumar <tushar.kumar@raga.ai>
6
- Requires-Python: <3.13,>=3.10
6
+ Requires-Python: <=3.13.2,>=3.10
7
7
  Description-Content-Type: text/markdown
8
8
  License-File: LICENSE
9
9
  Requires-Dist: aiohttp>=3.10.2
@@ -45,7 +45,7 @@ Requires-Dist: opentelemetry-sdk
45
45
  Requires-Dist: opentelemetry-exporter-otlp
46
46
  Requires-Dist: opentelemetry-proto>=1.12.0
47
47
  Provides-Extra: dev
48
- Requires-Dist: pytest; extra == "dev"
48
+ Requires-Dist: pytest>=8.3.5; extra == "dev"
49
49
  Requires-Dist: pytest-cov; extra == "dev"
50
50
  Requires-Dist: black; extra == "dev"
51
51
  Requires-Dist: isort; extra == "dev"
@@ -31,7 +31,7 @@ ragaai_catalyst/tracers/distributed.py,sha256=MwlBwIxCAng-OI-7Ove_rkE1mTLeuW4Jw-
31
31
  ragaai_catalyst/tracers/langchain_callback.py,sha256=CB75zzG3-DkYTELj0vI1MOHQTY0MuQJfoHIXz9Cl8S8,34568
32
32
  ragaai_catalyst/tracers/llamaindex_callback.py,sha256=ZY0BJrrlz-P9Mg2dX-ZkVKG3gSvzwqBtk7JL_05MiYA,14028
33
33
  ragaai_catalyst/tracers/llamaindex_instrumentation.py,sha256=Ys_jLkvVqo12bKgXDmkp4TxJu9HkBATrFE8cIcTYxWw,14329
34
- ragaai_catalyst/tracers/tracer.py,sha256=16fu4zAPP8N8xzBtcbvXlWaR8g2GIC8BhOJwcDrp4vo,36993
34
+ ragaai_catalyst/tracers/tracer.py,sha256=LHRd35rTFgYovxsI4tyXHgsCCdccO1_O1txFLFyLUKc,39069
35
35
  ragaai_catalyst/tracers/upload_traces.py,sha256=PEE_JhAmOAMKyb-pl4ZoFWhIePxJm1zs93crrk94iEg,5887
36
36
  ragaai_catalyst/tracers/agentic_tracing/README.md,sha256=X4QwLb7-Jg7GQMIXj-SerZIgDETfw-7VgYlczOR8ZeQ,4508
37
37
  ragaai_catalyst/tracers/agentic_tracing/__init__.py,sha256=yf6SKvOPSpH-9LiKaoLKXwqj5sez8F_5wkOb91yp0oE,260
@@ -74,10 +74,10 @@ ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py,sha256=W7Nw-IpugejI
74
74
  ragaai_catalyst/tracers/agentic_tracing/utils/unique_decorator.py,sha256=G027toV-Km20JjKrc-Y_PilQ8ABEKrBvvzgLTnqVg7I,5819
75
75
  ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py,sha256=4TeCGsFF26249fV6dJHLTZDrRa93SG9oer4rudoF8Y4,19443
76
76
  ragaai_catalyst/tracers/exporters/__init__.py,sha256=wQbaqyeIjVZxYprHCKZ9BeiqxeXYBKjzEgP79LWNxCU,293
77
- ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=l5wYX80lmMa39iOgZ7wopcH5km8t-koERL7B9wFy8Hg,5433
77
+ ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=v2V-y1l9t9gQQbqoi2jlEhm1xRQjR5yTyr6rxSriXCE,6303
78
78
  ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=RgGteu-NVGprXKkynvyIO5yOjpbtA41R3W_NzCjnkwE,6445
79
79
  ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=6xvjWXyh8XPkHKSLLmAZUQSvwuyY17ov8pv2VdfI0qA,17875
80
- ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=5TJfwD5LBLD3D9i_mrvkx2-Jp8JtWUgKTqnmAo2toCw,11364
80
+ ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=BzL5u7yOcWHHtPueoJclXcvexBQo1SFu5lHY8ANnzP8,12998
81
81
  ragaai_catalyst/tracers/instrumentators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
82
  ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
83
83
  ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py,sha256=e0URuRWCdzpxuBLfL82FOTMjbRuDAkW8aIRi7s7Nocc,1655
@@ -85,11 +85,11 @@ ragaai_catalyst/tracers/utils/convert_llama_instru_callback.py,sha256=8qLo7x4Zsn
85
85
  ragaai_catalyst/tracers/utils/extraction_logic_llama_index.py,sha256=ZhPs0YhVtB82-Pq9o1BvCinKE_WPvVxPTEcZjlJbFYM,2371
86
86
  ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py,sha256=XS2_x2qneqEx9oAighLg-LRiueWcESLwIC2r7eJT-Ww,3117
87
87
  ragaai_catalyst/tracers/utils/model_prices_and_context_window_backup.json,sha256=C3uwkibJ08C9sOX-54kulZYmJlIpZ-SQpfE6HNGrjbM,343502
88
- ragaai_catalyst/tracers/utils/rag_trace_json_converter.py,sha256=XSanJ3ChRn_Nqj5mlJhy-jFUCAhkw6lBuhhzUx6Mo9k,11239
88
+ ragaai_catalyst/tracers/utils/rag_trace_json_converter.py,sha256=sIUWwzXlEGU8wkVVL0w944tXxsOVdUHHV9UCImvBVOU,11406
89
89
  ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256=E0_QfciQMMpCtQYrNB4l8HJhlaFalr5bkMqkVRgQahY,14073
90
90
  ragaai_catalyst/tracers/utils/utils.py,sha256=ViygfJ7vZ7U0CTSA1lbxVloHp4NSlmfDzBRNCJuMhis,2374
91
- ragaai_catalyst-2.1.7b0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
92
- ragaai_catalyst-2.1.7b0.dist-info/METADATA,sha256=Ccfgxo8Ehm7CeGQRZrFsDYPb_RsTymn6B0oG_y9JuZE,22139
93
- ragaai_catalyst-2.1.7b0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
94
- ragaai_catalyst-2.1.7b0.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
95
- ragaai_catalyst-2.1.7b0.dist-info/RECORD,,
91
+ ragaai_catalyst-2.1.7.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
92
+ ragaai_catalyst-2.1.7.1.dist-info/METADATA,sha256=oQG1fW2asI1Jxz-Oglbns-GknOOBxpMsQK8SNieowsk,22149
93
+ ragaai_catalyst-2.1.7.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
94
+ ragaai_catalyst-2.1.7.1.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
95
+ ragaai_catalyst-2.1.7.1.dist-info/RECORD,,