ragaai-catalyst 2.1.4.1b0__py3-none-any.whl → 2.1.5b0__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.
- ragaai_catalyst/__init__.py +19 -2
- ragaai_catalyst/tracers/__init__.py +17 -1
- ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py +4 -2
- ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +163 -42
- ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +1 -1
- ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +16 -1
- ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +3 -3
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py +7 -0
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +6 -6
- ragaai_catalyst/tracers/distributed.py +286 -0
- {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5b0.dist-info}/METADATA +1 -2
- {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5b0.dist-info}/RECORD +15 -14
- {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5b0.dist-info}/LICENSE +0 -0
- {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5b0.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.1.4.1b0.dist-info → ragaai_catalyst-2.1.5b0.dist-info}/top_level.txt +0 -0
ragaai_catalyst/__init__.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from .experiment import Experiment
|
2
2
|
from .ragaai_catalyst import RagaAICatalyst
|
3
|
-
from .tracers import Tracer
|
4
3
|
from .utils import response_checker
|
5
4
|
from .dataset import Dataset
|
6
5
|
from .prompt_manager import PromptManager
|
@@ -8,6 +7,24 @@ from .evaluation import Evaluation
|
|
8
7
|
from .synthetic_data_generation import SyntheticDataGeneration
|
9
8
|
from .guardrails_manager import GuardrailsManager
|
10
9
|
from .guard_executor import GuardExecutor
|
10
|
+
from .tracers import Tracer, init_tracing, trace_agent, trace_llm, trace_tool, current_span, trace_custom
|
11
11
|
|
12
12
|
|
13
|
-
|
13
|
+
|
14
|
+
|
15
|
+
__all__ = [
|
16
|
+
"Experiment",
|
17
|
+
"RagaAICatalyst",
|
18
|
+
"Tracer",
|
19
|
+
"PromptManager",
|
20
|
+
"Evaluation",
|
21
|
+
"SyntheticDataGeneration",
|
22
|
+
"GuardrailsManager",
|
23
|
+
"GuardExecutor",
|
24
|
+
"init_tracing",
|
25
|
+
"trace_agent",
|
26
|
+
"trace_llm",
|
27
|
+
"trace_tool",
|
28
|
+
"current_span",
|
29
|
+
"trace_custom"
|
30
|
+
]
|
@@ -1,3 +1,19 @@
|
|
1
1
|
from .tracer import Tracer
|
2
|
+
from .distributed import (
|
3
|
+
init_tracing,
|
4
|
+
trace_agent,
|
5
|
+
trace_llm,
|
6
|
+
trace_tool,
|
7
|
+
current_span,
|
8
|
+
trace_custom,
|
9
|
+
)
|
2
10
|
|
3
|
-
__all__ = [
|
11
|
+
__all__ = [
|
12
|
+
"Tracer",
|
13
|
+
"init_tracing",
|
14
|
+
"trace_agent",
|
15
|
+
"trace_llm",
|
16
|
+
"trace_tool",
|
17
|
+
"current_span",
|
18
|
+
"trace_custom"
|
19
|
+
]
|
@@ -271,7 +271,7 @@ class ComponentInfo:
|
|
271
271
|
cost: Optional[Dict[str, float]] = None
|
272
272
|
|
273
273
|
class Trace:
|
274
|
-
def __init__(self, id: str, trace_name: str, project_name: str, start_time: str, end_time: str, metadata: Optional[Metadata] = None, data: Optional[List[Dict[str, Any]]] = None, replays: Optional[Dict[str, Any]] = None):
|
274
|
+
def __init__(self, id: str, trace_name: str, project_name: str, start_time: str, end_time: str, metadata: Optional[Metadata] = None, data: Optional[List[Dict[str, Any]]] = None, replays: Optional[Dict[str, Any]] = None, metrics: Optional[List[Dict[str, Any]]] = None):
|
275
275
|
self.id = id
|
276
276
|
self.trace_name = trace_name
|
277
277
|
self.project_name = project_name
|
@@ -280,6 +280,7 @@ class Trace:
|
|
280
280
|
self.metadata = metadata or Metadata()
|
281
281
|
self.data = data or []
|
282
282
|
self.replays = replays
|
283
|
+
self.metrics = metrics or []
|
283
284
|
|
284
285
|
def to_dict(self):
|
285
286
|
return {
|
@@ -288,7 +289,8 @@ class Trace:
|
|
288
289
|
"project_name": self.project_name,
|
289
290
|
"start_time": self.start_time,
|
290
291
|
"end_time": self.end_time,
|
291
|
-
"metadata": self.metadata
|
292
|
+
"metadata": self.metadata,
|
292
293
|
"data": self.data,
|
293
294
|
"replays": self.replays,
|
295
|
+
"metrics": self.metrics
|
294
296
|
}
|
@@ -5,7 +5,7 @@ import psutil
|
|
5
5
|
import pkg_resources
|
6
6
|
from datetime import datetime
|
7
7
|
from pathlib import Path
|
8
|
-
from typing import List, Any
|
8
|
+
from typing import List, Any, Dict
|
9
9
|
import uuid
|
10
10
|
import sys
|
11
11
|
import tempfile
|
@@ -81,6 +81,7 @@ class BaseTracer:
|
|
81
81
|
self.project_id = self.user_details["project_id"] # Access the project_id
|
82
82
|
self.trace_name = self.user_details["trace_name"] # Access the trace_name
|
83
83
|
self.visited_metrics = []
|
84
|
+
self.trace_metrics = [] # Store metrics here
|
84
85
|
|
85
86
|
# Initialize trace data
|
86
87
|
self.trace_id = None
|
@@ -211,6 +212,10 @@ class BaseTracer:
|
|
211
212
|
threading.Thread(target=self._track_disk_usage).start()
|
212
213
|
threading.Thread(target=self._track_network_usage).start()
|
213
214
|
|
215
|
+
# Reset metrics
|
216
|
+
self.visited_metrics = []
|
217
|
+
self.trace_metrics = []
|
218
|
+
|
214
219
|
metadata = Metadata(
|
215
220
|
cost={},
|
216
221
|
tokens={},
|
@@ -241,6 +246,7 @@ class BaseTracer:
|
|
241
246
|
metadata=metadata,
|
242
247
|
data=self.data_key,
|
243
248
|
replays={"source": None},
|
249
|
+
metrics=[] # Initialize empty metrics list
|
244
250
|
)
|
245
251
|
|
246
252
|
def stop(self):
|
@@ -300,13 +306,16 @@ class BaseTracer:
|
|
300
306
|
# replace source code with zip_path
|
301
307
|
self.trace.metadata.system_info.source_code = hash_id
|
302
308
|
|
309
|
+
# Add metrics to trace before saving
|
310
|
+
trace_data = self.trace.to_dict()
|
311
|
+
trace_data["metrics"] = self.trace_metrics
|
312
|
+
|
303
313
|
# Clean up trace_data before saving
|
304
|
-
trace_data = self.trace.__dict__
|
305
314
|
cleaned_trace_data = self._clean_trace(trace_data)
|
306
315
|
|
307
316
|
# Format interactions and add to trace
|
308
317
|
interactions = self.format_interactions()
|
309
|
-
|
318
|
+
trace_data["workflow"] = interactions["workflow"]
|
310
319
|
|
311
320
|
with open(filepath, "w") as f:
|
312
321
|
json.dump(cleaned_trace_data, f, cls=TracerJSONEncoder, indent=2)
|
@@ -424,38 +433,44 @@ class BaseTracer:
|
|
424
433
|
def _extract_cost_tokens(self, trace):
|
425
434
|
cost = {}
|
426
435
|
tokens = {}
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
436
|
+
|
437
|
+
def process_span_info(info):
|
438
|
+
if not isinstance(info, dict):
|
439
|
+
return
|
440
|
+
cost_info = info.get("cost", {})
|
441
|
+
for key, value in cost_info.items():
|
442
|
+
if key not in cost:
|
443
|
+
cost[key] = 0
|
444
|
+
cost[key] += value
|
445
|
+
token_info = info.get("tokens", {})
|
446
|
+
for key, value in token_info.items():
|
447
|
+
if key not in tokens:
|
448
|
+
tokens[key] = 0
|
449
|
+
tokens[key] += value
|
450
|
+
|
451
|
+
def process_spans(spans):
|
452
|
+
for span in spans:
|
453
|
+
# Get span type, handling both span objects and dictionaries
|
454
|
+
span_type = span.type if hasattr(span, 'type') else span.get('type')
|
455
|
+
span_info = span.info if hasattr(span, 'info') else span.get('info', {})
|
456
|
+
span_data = span.data if hasattr(span, 'data') else span.get('data', {})
|
457
|
+
|
458
|
+
# Process direct LLM spans
|
459
|
+
if span_type == "llm":
|
460
|
+
process_span_info(span_info)
|
461
|
+
# Process agent spans recursively
|
462
|
+
elif span_type == "agent":
|
463
|
+
# Process LLM children in the current agent span
|
464
|
+
children = span_data.get("children", [])
|
465
|
+
for child in children:
|
466
|
+
child_type = child.get("type")
|
467
|
+
if child_type == "llm":
|
468
|
+
process_span_info(child.get("info", {}))
|
469
|
+
# Recursively process nested agent spans
|
470
|
+
elif child_type == "agent":
|
471
|
+
process_spans([child])
|
472
|
+
|
473
|
+
process_spans(trace.data[0]["spans"])
|
459
474
|
trace.metadata.cost = cost
|
460
475
|
trace.metadata.tokens = tokens
|
461
476
|
return trace
|
@@ -609,9 +624,7 @@ class BaseTracer:
|
|
609
624
|
"span_id": child.get("id"),
|
610
625
|
"interaction_type": "llm_call_end",
|
611
626
|
"name": child.get("name"),
|
612
|
-
"content": {
|
613
|
-
"response": child.get("data", {}).get("output")
|
614
|
-
},
|
627
|
+
"content": {"response": child.get("data", {}).get("output")},
|
615
628
|
"timestamp": child.get("end_time"),
|
616
629
|
"error": child.get("error"),
|
617
630
|
}
|
@@ -657,7 +670,7 @@ class BaseTracer:
|
|
657
670
|
{
|
658
671
|
"id": str(interaction_id),
|
659
672
|
"span_id": child.get("id"),
|
660
|
-
"interaction_type": child_type,
|
673
|
+
"interaction_type": f"{child_type}_call_start",
|
661
674
|
"name": child.get("name"),
|
662
675
|
"content": child.get("data", {}),
|
663
676
|
"timestamp": child.get("start_time"),
|
@@ -665,6 +678,19 @@ class BaseTracer:
|
|
665
678
|
}
|
666
679
|
)
|
667
680
|
interaction_id += 1
|
681
|
+
|
682
|
+
interactions.append(
|
683
|
+
{
|
684
|
+
"id": str(interaction_id),
|
685
|
+
"span_id": child.get("id"),
|
686
|
+
"interaction_type": f"{child_type}_call_end",
|
687
|
+
"name": child.get("name"),
|
688
|
+
"content": child.get("data", {}),
|
689
|
+
"timestamp": child.get("end_time"),
|
690
|
+
"error": child.get("error"),
|
691
|
+
}
|
692
|
+
)
|
693
|
+
interaction_id += 1
|
668
694
|
|
669
695
|
# Process additional interactions and network calls
|
670
696
|
if "interactions" in child:
|
@@ -825,7 +851,7 @@ class BaseTracer:
|
|
825
851
|
{
|
826
852
|
"id": str(interaction_id),
|
827
853
|
"span_id": span.id,
|
828
|
-
"interaction_type": span.type,
|
854
|
+
"interaction_type": f"{span.type}_call_start",
|
829
855
|
"name": span.name,
|
830
856
|
"content": span.data,
|
831
857
|
"timestamp": span.start_time,
|
@@ -833,6 +859,19 @@ class BaseTracer:
|
|
833
859
|
}
|
834
860
|
)
|
835
861
|
interaction_id += 1
|
862
|
+
|
863
|
+
interactions.append(
|
864
|
+
{
|
865
|
+
"id": str(interaction_id),
|
866
|
+
"span_id": span.id,
|
867
|
+
"interaction_type": f"{span.type}_call_end",
|
868
|
+
"name": span.name,
|
869
|
+
"content": span.data,
|
870
|
+
"timestamp": span.end_time,
|
871
|
+
"error": span.error,
|
872
|
+
}
|
873
|
+
)
|
874
|
+
interaction_id += 1
|
836
875
|
|
837
876
|
# Process interactions from span.data if they exist
|
838
877
|
if span.interactions:
|
@@ -882,8 +921,90 @@ class BaseTracer:
|
|
882
921
|
|
883
922
|
return {"workflow": sorted_interactions}
|
884
923
|
|
924
|
+
def add_metrics(
|
925
|
+
self,
|
926
|
+
name: str | List[Dict[str, Any]] | Dict[str, Any] = None,
|
927
|
+
score: float | int = None,
|
928
|
+
reasoning: str = "",
|
929
|
+
cost: float = None,
|
930
|
+
latency: float = None,
|
931
|
+
metadata: Dict[str, Any] = None,
|
932
|
+
config: Dict[str, Any] = None,
|
933
|
+
):
|
934
|
+
"""Add metrics at the trace level.
|
935
|
+
|
936
|
+
Can be called in two ways:
|
937
|
+
1. With individual parameters:
|
938
|
+
tracer.add_metrics(name="metric_name", score=0.9, reasoning="Good performance")
|
939
|
+
|
940
|
+
2. With a dictionary or list of dictionaries:
|
941
|
+
tracer.add_metrics({"name": "metric_name", "score": 0.9})
|
942
|
+
tracer.add_metrics([{"name": "metric1", "score": 0.9}, {"name": "metric2", "score": 0.8}])
|
943
|
+
|
944
|
+
Args:
|
945
|
+
name: Either the metric name (str) or a metric dictionary/list of dictionaries
|
946
|
+
score: Score value (float or int) when using individual parameters
|
947
|
+
reasoning: Optional explanation for the score
|
948
|
+
cost: Optional cost associated with the metric
|
949
|
+
latency: Optional latency measurement
|
950
|
+
metadata: Optional additional metadata as key-value pairs
|
951
|
+
config: Optional configuration parameters
|
952
|
+
"""
|
953
|
+
if not hasattr(self, 'trace'):
|
954
|
+
logger.warning("Cannot add metrics before trace is initialized. Call start() first.")
|
955
|
+
return
|
956
|
+
|
957
|
+
# Convert individual parameters to metric dict if needed
|
958
|
+
if isinstance(name, str):
|
959
|
+
metrics = [{
|
960
|
+
"name": name,
|
961
|
+
"score": score,
|
962
|
+
"reasoning": reasoning,
|
963
|
+
"cost": cost,
|
964
|
+
"latency": latency,
|
965
|
+
"metadata": metadata or {},
|
966
|
+
"config": config or {}
|
967
|
+
}]
|
968
|
+
else:
|
969
|
+
# Handle dict or list input
|
970
|
+
metrics = name if isinstance(name, list) else [name] if isinstance(name, dict) else []
|
971
|
+
|
972
|
+
try:
|
973
|
+
for metric in metrics:
|
974
|
+
if not isinstance(metric, dict):
|
975
|
+
raise ValueError(f"Expected dict, got {type(metric)}")
|
976
|
+
|
977
|
+
if "name" not in metric or "score" not in metric:
|
978
|
+
raise ValueError("Metric must contain 'name' and 'score' fields")
|
979
|
+
|
980
|
+
# Handle duplicate metric names
|
981
|
+
metric_name = metric["name"]
|
982
|
+
if metric_name in self.visited_metrics:
|
983
|
+
count = sum(1 for m in self.visited_metrics if m.startswith(metric_name))
|
984
|
+
metric_name = f"{metric_name}_{count + 1}"
|
985
|
+
self.visited_metrics.append(metric_name)
|
986
|
+
|
987
|
+
formatted_metric = {
|
988
|
+
"name": metric_name,
|
989
|
+
"score": metric["score"],
|
990
|
+
"reason": metric.get("reasoning", ""),
|
991
|
+
"source": "user",
|
992
|
+
"cost": metric.get("cost"),
|
993
|
+
"latency": metric.get("latency"),
|
994
|
+
"metadata": metric.get("metadata", {}),
|
995
|
+
"mappings": [],
|
996
|
+
"config": metric.get("config", {})
|
997
|
+
}
|
998
|
+
|
999
|
+
self.trace_metrics.append(formatted_metric)
|
1000
|
+
logger.debug(f"Added trace-level metric: {formatted_metric}")
|
1001
|
+
|
1002
|
+
except ValueError as e:
|
1003
|
+
logger.error(f"Validation Error: {e}")
|
1004
|
+
except Exception as e:
|
1005
|
+
logger.error(f"Error adding metric: {e}")
|
1006
|
+
|
885
1007
|
def span(self, span_name):
|
886
1008
|
if span_name not in self.span_attributes_dict:
|
887
1009
|
self.span_attributes_dict[span_name] = SpanAttributes(span_name)
|
888
|
-
return self.span_attributes_dict[span_name]
|
889
|
-
|
1010
|
+
return self.span_attributes_dict[span_name]
|
@@ -137,13 +137,28 @@ class AgenticTracing(
|
|
137
137
|
self.network_tracer.network_calls.copy()
|
138
138
|
)
|
139
139
|
self.network_tracer.network_calls = [] # Reset for next component
|
140
|
-
|
140
|
+
|
141
|
+
# Store user interactions for the component
|
141
142
|
for interaction in self.user_interaction_tracer.interactions:
|
142
143
|
interaction_component_id = interaction.get("component_id")
|
143
144
|
if interaction_component_id not in self.component_user_interaction:
|
144
145
|
self.component_user_interaction[interaction_component_id] = []
|
145
146
|
if interaction not in self.component_user_interaction[interaction_component_id]:
|
146
147
|
self.component_user_interaction[interaction_component_id].append(interaction)
|
148
|
+
|
149
|
+
# Only reset component_id if it matches the current one
|
150
|
+
# This ensures we don't reset a parent's component_id when a child component ends
|
151
|
+
if self.current_component_id.get() == component_id:
|
152
|
+
# Get the parent agent's component_id if it exists
|
153
|
+
parent_agent_id = self.current_agent_id.get()
|
154
|
+
# If there's a parent agent, set the component_id back to the parent's
|
155
|
+
if parent_agent_id:
|
156
|
+
self.current_component_id.set(parent_agent_id)
|
157
|
+
self.user_interaction_tracer.component_id.set(parent_agent_id)
|
158
|
+
else:
|
159
|
+
# Only reset to None if there's no parent
|
160
|
+
self.current_component_id.set(None)
|
161
|
+
self.user_interaction_tracer.component_id.set(None)
|
147
162
|
|
148
163
|
def start(self):
|
149
164
|
"""Start tracing"""
|
@@ -41,7 +41,7 @@ class NetworkTracer:
|
|
41
41
|
|
42
42
|
# Extract protocol from URL
|
43
43
|
protocol = "https" if url.startswith("https") else "http"
|
44
|
-
|
44
|
+
|
45
45
|
self.network_calls.append(
|
46
46
|
{
|
47
47
|
"url": url,
|
@@ -57,11 +57,11 @@ class NetworkTracer:
|
|
57
57
|
"parent_id": None, # Will be set by the component
|
58
58
|
"request": {
|
59
59
|
"headers": request_headers,
|
60
|
-
"body": request_body
|
60
|
+
"body": request_body if request_body else None,
|
61
61
|
},
|
62
62
|
"response": {
|
63
63
|
"headers": response_headers,
|
64
|
-
"body": response_body
|
64
|
+
"body": response_body if response_body else None,
|
65
65
|
},
|
66
66
|
"error": str(error) if error else None,
|
67
67
|
}
|
@@ -59,6 +59,13 @@ def _get_children_metrics_of_agent(children_traces):
|
|
59
59
|
|
60
60
|
def get_trace_metrics_from_trace(traces):
|
61
61
|
metrics = []
|
62
|
+
|
63
|
+
# get trace level metrics
|
64
|
+
if "metrics" in traces.keys():
|
65
|
+
if len(traces["metrics"]) > 0:
|
66
|
+
metrics.extend(traces["metrics"])
|
67
|
+
|
68
|
+
# get span level metrics
|
62
69
|
for span in traces["data"][0]["spans"]:
|
63
70
|
if span["type"] == "agent":
|
64
71
|
children_metric = _get_children_metrics_of_agent(span["data"]["children"])
|
@@ -5,7 +5,6 @@ import re
|
|
5
5
|
import ast
|
6
6
|
import importlib.util
|
7
7
|
import json
|
8
|
-
import astor
|
9
8
|
import ipynbname
|
10
9
|
import sys
|
11
10
|
|
@@ -74,12 +73,14 @@ class PackageUsageRemover(ast.NodeTransformer):
|
|
74
73
|
def remove_package_code(source_code: str, package_name: str) -> str:
|
75
74
|
try:
|
76
75
|
tree = ast.parse(source_code)
|
77
|
-
|
78
|
-
modified_tree =
|
79
|
-
modified_code =
|
76
|
+
remover = PackageUsageRemover(package_name)
|
77
|
+
modified_tree = remover.visit(tree)
|
78
|
+
modified_code = ast.unparse(modified_tree)
|
79
|
+
|
80
80
|
return modified_code
|
81
81
|
except Exception as e:
|
82
|
-
|
82
|
+
logger.error(f"Error in remove_package_code: {e}")
|
83
|
+
return source_code
|
83
84
|
|
84
85
|
class JupyterNotebookHandler:
|
85
86
|
@staticmethod
|
@@ -452,4 +453,3 @@ if __name__ == "__main__":
|
|
452
453
|
hash_id, zip_path = zip_list_of_unique_files(filepaths)
|
453
454
|
print(f"Created zip file: {zip_path}")
|
454
455
|
print(f"Hash ID: {hash_id}")
|
455
|
-
|
@@ -0,0 +1,286 @@
|
|
1
|
+
"""
|
2
|
+
Distributed tracing functionality for RagaAI Catalyst.
|
3
|
+
Provides simplified initialization and decorator-based tracing.
|
4
|
+
"""
|
5
|
+
|
6
|
+
import os
|
7
|
+
import threading
|
8
|
+
from typing import Optional, Dict, Any, List
|
9
|
+
from functools import wraps
|
10
|
+
from contextlib import contextmanager
|
11
|
+
import uuid
|
12
|
+
from datetime import datetime
|
13
|
+
import asyncio
|
14
|
+
|
15
|
+
from .tracer import Tracer
|
16
|
+
from ..ragaai_catalyst import RagaAICatalyst
|
17
|
+
|
18
|
+
# Global state
|
19
|
+
_global_tracer: Optional[Tracer] = None
|
20
|
+
_global_catalyst: Optional[RagaAICatalyst] = None
|
21
|
+
_tracer_lock = threading.Lock()
|
22
|
+
_active_spans = threading.local()
|
23
|
+
|
24
|
+
def get_current_tracer() -> Optional[Tracer]:
|
25
|
+
"""Get the current global tracer instance."""
|
26
|
+
return _global_tracer
|
27
|
+
|
28
|
+
def get_current_catalyst() -> Optional[RagaAICatalyst]:
|
29
|
+
"""Get the current global catalyst instance."""
|
30
|
+
return _global_catalyst
|
31
|
+
|
32
|
+
def init_tracing(
|
33
|
+
project_name: str = None,
|
34
|
+
dataset_name: str = None,
|
35
|
+
access_key: str = None,
|
36
|
+
secret_key: str = None,
|
37
|
+
base_url: str = None,
|
38
|
+
tracer: Tracer = None,
|
39
|
+
catalyst: RagaAICatalyst = None,
|
40
|
+
**kwargs
|
41
|
+
) -> None:
|
42
|
+
"""Initialize distributed tracing.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
project_name: Project name for new tracer
|
46
|
+
dataset_name: Dataset name for new tracer
|
47
|
+
access_key: RagaAI Catalyst access key
|
48
|
+
secret_key: RagaAI Catalyst secret key
|
49
|
+
base_url: RagaAI Catalyst API base URL
|
50
|
+
tracer: Existing Tracer instance
|
51
|
+
catalyst: Existing RagaAICatalyst instance
|
52
|
+
**kwargs: Additional tracer configuration
|
53
|
+
"""
|
54
|
+
global _global_tracer, _global_catalyst
|
55
|
+
|
56
|
+
with _tracer_lock:
|
57
|
+
if tracer and catalyst:
|
58
|
+
_global_tracer = tracer
|
59
|
+
_global_catalyst = catalyst
|
60
|
+
else:
|
61
|
+
# Use env vars as fallback
|
62
|
+
access_key = access_key or os.getenv("RAGAAI_CATALYST_ACCESS_KEY")
|
63
|
+
secret_key = secret_key or os.getenv("RAGAAI_CATALYST_SECRET_KEY")
|
64
|
+
base_url = base_url or os.getenv("RAGAAI_CATALYST_BASE_URL")
|
65
|
+
|
66
|
+
if not all([access_key, secret_key]):
|
67
|
+
raise ValueError(
|
68
|
+
"Missing required credentials. Either provide access_key and secret_key "
|
69
|
+
"or set RAGAAI_CATALYST_ACCESS_KEY and RAGAAI_CATALYST_SECRET_KEY environment variables."
|
70
|
+
)
|
71
|
+
|
72
|
+
_global_catalyst = RagaAICatalyst(
|
73
|
+
access_key=access_key,
|
74
|
+
secret_key=secret_key,
|
75
|
+
base_url=base_url
|
76
|
+
)
|
77
|
+
|
78
|
+
_global_tracer = Tracer(
|
79
|
+
project_name=project_name,
|
80
|
+
dataset_name=dataset_name,
|
81
|
+
**kwargs
|
82
|
+
)
|
83
|
+
|
84
|
+
def trace_agent(name: str = None, agent_type: str = "generic", version: str = "1.0.0", **kwargs):
|
85
|
+
"""Decorator for tracing agent functions."""
|
86
|
+
def decorator(func):
|
87
|
+
is_async = asyncio.iscoroutinefunction(func)
|
88
|
+
span_name = name or func.__name__
|
89
|
+
|
90
|
+
@wraps(func)
|
91
|
+
async def async_wrapper(*args, **kwargs):
|
92
|
+
tracer = get_current_tracer()
|
93
|
+
if not tracer:
|
94
|
+
return await func(*args, **kwargs)
|
95
|
+
|
96
|
+
# Set current agent name and store the token
|
97
|
+
name_token = tracer.current_agent_name.set(span_name)
|
98
|
+
|
99
|
+
try:
|
100
|
+
# Use async agent tracing
|
101
|
+
return await tracer._trace_agent_execution(
|
102
|
+
func,
|
103
|
+
span_name,
|
104
|
+
agent_type,
|
105
|
+
version,
|
106
|
+
None, # capabilities
|
107
|
+
str(uuid.uuid4()), # hash_id
|
108
|
+
*args,
|
109
|
+
**kwargs
|
110
|
+
)
|
111
|
+
finally:
|
112
|
+
# Reset using the stored token
|
113
|
+
if name_token:
|
114
|
+
tracer.current_agent_name.reset(name_token)
|
115
|
+
|
116
|
+
@wraps(func)
|
117
|
+
def sync_wrapper(*args, **kwargs):
|
118
|
+
tracer = get_current_tracer()
|
119
|
+
if not tracer:
|
120
|
+
return func(*args, **kwargs)
|
121
|
+
|
122
|
+
# Set current agent name and store the token
|
123
|
+
name_token = tracer.current_agent_name.set(span_name)
|
124
|
+
|
125
|
+
try:
|
126
|
+
# Use synchronous agent tracing
|
127
|
+
return tracer._trace_sync_agent_execution(
|
128
|
+
func,
|
129
|
+
span_name,
|
130
|
+
agent_type,
|
131
|
+
version,
|
132
|
+
None, # capabilities
|
133
|
+
*args,
|
134
|
+
**kwargs
|
135
|
+
)
|
136
|
+
finally:
|
137
|
+
# Reset using the stored token
|
138
|
+
if name_token:
|
139
|
+
tracer.current_agent_name.reset(name_token)
|
140
|
+
|
141
|
+
return async_wrapper if is_async else sync_wrapper
|
142
|
+
return decorator
|
143
|
+
|
144
|
+
def trace_llm(name: str = None, model: str = None, **kwargs):
|
145
|
+
"""Decorator for tracing LLM calls."""
|
146
|
+
def decorator(func):
|
147
|
+
is_async = asyncio.iscoroutinefunction(func)
|
148
|
+
span_name = name or func.__name__
|
149
|
+
|
150
|
+
@wraps(func)
|
151
|
+
async def async_wrapper(*args, **kwargs):
|
152
|
+
tracer = get_current_tracer()
|
153
|
+
if not tracer:
|
154
|
+
return await func(*args, **kwargs)
|
155
|
+
|
156
|
+
# Set current LLM name and store the token
|
157
|
+
name_token = tracer.current_llm_call_name.set(span_name)
|
158
|
+
|
159
|
+
try:
|
160
|
+
# Just execute the function within the current span
|
161
|
+
result = await func(*args, **kwargs)
|
162
|
+
return result
|
163
|
+
finally:
|
164
|
+
# Reset using the stored token
|
165
|
+
if name_token:
|
166
|
+
tracer.current_llm_call_name.reset(name_token)
|
167
|
+
|
168
|
+
@wraps(func)
|
169
|
+
def sync_wrapper(*args, **kwargs):
|
170
|
+
tracer = get_current_tracer()
|
171
|
+
if not tracer:
|
172
|
+
return func(*args, **kwargs)
|
173
|
+
|
174
|
+
# Set current LLM name and store the token
|
175
|
+
name_token = tracer.current_llm_call_name.set(span_name)
|
176
|
+
|
177
|
+
try:
|
178
|
+
# Just execute the function within the current span
|
179
|
+
result = func(*args, **kwargs)
|
180
|
+
return result
|
181
|
+
finally:
|
182
|
+
# Reset using the stored token
|
183
|
+
if name_token:
|
184
|
+
tracer.current_llm_call_name.reset(name_token)
|
185
|
+
|
186
|
+
return async_wrapper if is_async else sync_wrapper
|
187
|
+
return decorator
|
188
|
+
|
189
|
+
|
190
|
+
def trace_tool(name: str = None, tool_type: str = "generic", version: str = "1.0.0", **kwargs):
|
191
|
+
"""Decorator for tracing tool functions."""
|
192
|
+
def decorator(func):
|
193
|
+
is_async = asyncio.iscoroutinefunction(func)
|
194
|
+
|
195
|
+
@wraps(func)
|
196
|
+
async def async_wrapper(*args, **kwargs):
|
197
|
+
tracer = get_current_tracer()
|
198
|
+
if not tracer:
|
199
|
+
return await func(*args, **kwargs)
|
200
|
+
|
201
|
+
# Use async tool tracing
|
202
|
+
return await tracer._trace_tool_execution(
|
203
|
+
func,
|
204
|
+
name or func.__name__,
|
205
|
+
tool_type,
|
206
|
+
version,
|
207
|
+
*args,
|
208
|
+
**kwargs
|
209
|
+
)
|
210
|
+
|
211
|
+
@wraps(func)
|
212
|
+
def sync_wrapper(*args, **kwargs):
|
213
|
+
tracer = get_current_tracer()
|
214
|
+
if not tracer:
|
215
|
+
return func(*args, **kwargs)
|
216
|
+
|
217
|
+
# Use synchronous tool tracing
|
218
|
+
return tracer._trace_sync_tool_execution(
|
219
|
+
func,
|
220
|
+
name or func.__name__,
|
221
|
+
tool_type,
|
222
|
+
version,
|
223
|
+
*args,
|
224
|
+
**kwargs
|
225
|
+
)
|
226
|
+
|
227
|
+
return async_wrapper if is_async else sync_wrapper
|
228
|
+
return decorator
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
def trace_custom(name: str = None, custom_type: str = "generic", version: str = "1.0.0", trace_variables: bool = False, **kwargs):
|
233
|
+
"""Decorator for tracing custom functions."""
|
234
|
+
def decorator(func):
|
235
|
+
is_async = asyncio.iscoroutinefunction(func)
|
236
|
+
|
237
|
+
@wraps(func)
|
238
|
+
async def async_wrapper(*args, **kwargs):
|
239
|
+
tracer = get_current_tracer()
|
240
|
+
if not tracer:
|
241
|
+
return await func(*args, **kwargs)
|
242
|
+
|
243
|
+
# Use async tool tracing
|
244
|
+
return await tracer._trace_custom_execution(
|
245
|
+
func,
|
246
|
+
name or func.__name__,
|
247
|
+
custom_type,
|
248
|
+
version,
|
249
|
+
trace_variables,
|
250
|
+
*args,
|
251
|
+
**kwargs
|
252
|
+
)
|
253
|
+
|
254
|
+
@wraps(func)
|
255
|
+
def sync_wrapper(*args, **kwargs):
|
256
|
+
tracer = get_current_tracer()
|
257
|
+
if not tracer:
|
258
|
+
return func(*args, **kwargs)
|
259
|
+
|
260
|
+
# Use synchronous tool tracing
|
261
|
+
return tracer._trace_sync_custom_execution(
|
262
|
+
func,
|
263
|
+
name or func.__name__,
|
264
|
+
custom_type,
|
265
|
+
version,
|
266
|
+
trace_variables,
|
267
|
+
*args,
|
268
|
+
**kwargs
|
269
|
+
)
|
270
|
+
|
271
|
+
return async_wrapper if is_async else sync_wrapper
|
272
|
+
return decorator
|
273
|
+
|
274
|
+
|
275
|
+
def current_span():
|
276
|
+
"""Get the current active span for adding metrics."""
|
277
|
+
tracer = get_current_tracer()
|
278
|
+
if not tracer:
|
279
|
+
return None
|
280
|
+
|
281
|
+
# Get the current agent name from context
|
282
|
+
agent_name = tracer.current_agent_name.get()
|
283
|
+
if not agent_name:
|
284
|
+
raise ValueError("No active span found. Make sure you're calling this within a traced function.")
|
285
|
+
|
286
|
+
return tracer.span(agent_name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.5b0
|
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>
|
6
6
|
Requires-Python: <3.13,>=3.9
|
@@ -34,7 +34,6 @@ Requires-Dist: psutil~=6.0.0
|
|
34
34
|
Requires-Dist: py-cpuinfo~=9.0.0
|
35
35
|
Requires-Dist: requests~=2.32.3
|
36
36
|
Requires-Dist: GPUtil~=1.4.0
|
37
|
-
Requires-Dist: astor>=0.8.1
|
38
37
|
Requires-Dist: ipynbname
|
39
38
|
Provides-Extra: dev
|
40
39
|
Requires-Dist: pytest; extra == "dev"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
ragaai_catalyst/__init__.py,sha256=
|
1
|
+
ragaai_catalyst/__init__.py,sha256=tvESV8UuVtth14E89wQxgf0WvQZSApWfDeLiIdmMhkE,791
|
2
2
|
ragaai_catalyst/_version.py,sha256=JKt9KaVNOMVeGs8ojO6LvIZr7ZkMzNN-gCcvryy4x8E,460
|
3
3
|
ragaai_catalyst/dataset.py,sha256=aTRvZicAXmrC0KdmmsoJH_rtEJrxbqYmf1P806c1Wg0,10521
|
4
4
|
ragaai_catalyst/evaluation.py,sha256=34H2bYZNSrcu0jMQgDZw1OLVbQU80PaVLo2avju8POM,20311
|
@@ -11,14 +11,15 @@ ragaai_catalyst/proxy_call.py,sha256=CHxldeceZUaLU-to_hs_Kf1z_b2vHMssLS_cOBedu78
|
|
11
11
|
ragaai_catalyst/ragaai_catalyst.py,sha256=FdqMzwuQLqS2-3JJDsTQ8uh2itllOxfPrRUjb8Kwmn0,17428
|
12
12
|
ragaai_catalyst/synthetic_data_generation.py,sha256=uDV9tNwto2xSkWg5XHXUvjErW-4P34CTrxaJpRfezyA,19250
|
13
13
|
ragaai_catalyst/utils.py,sha256=TlhEFwLyRU690HvANbyoRycR3nQ67lxVUQoUOfTPYQ0,3772
|
14
|
-
ragaai_catalyst/tracers/__init__.py,sha256=
|
14
|
+
ragaai_catalyst/tracers/__init__.py,sha256=LfgTes-nHpazssbGKnn8kyLZNr49kIPrlkrqqoTFTfc,301
|
15
|
+
ragaai_catalyst/tracers/distributed.py,sha256=_KO7swUDoPErbfahxNSRpxQk22rstQItfPGP8e4l7E4,9334
|
15
16
|
ragaai_catalyst/tracers/llamaindex_callback.py,sha256=ZY0BJrrlz-P9Mg2dX-ZkVKG3gSvzwqBtk7JL_05MiYA,14028
|
16
17
|
ragaai_catalyst/tracers/tracer.py,sha256=UX-01NYWcH2y4UW1W287Cn-jy760rgaFqu8llJbeMdg,15654
|
17
18
|
ragaai_catalyst/tracers/upload_traces.py,sha256=mT5rverNUL5Rcal9VR5_c75wHBAUrm2pvYetTZqP3ok,4796
|
18
19
|
ragaai_catalyst/tracers/agentic_tracing/README.md,sha256=X4QwLb7-Jg7GQMIXj-SerZIgDETfw-7VgYlczOR8ZeQ,4508
|
19
20
|
ragaai_catalyst/tracers/agentic_tracing/__init__.py,sha256=yf6SKvOPSpH-9LiKaoLKXwqj5sez8F_5wkOb91yp0oE,260
|
20
21
|
ragaai_catalyst/tracers/agentic_tracing/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py,sha256=
|
22
|
+
ragaai_catalyst/tracers/agentic_tracing/data/data_structure.py,sha256=icAtNzKN_I0YtfuJ3RF8BdZJK3ohqxkVZIdvM5_YugY,9327
|
22
23
|
ragaai_catalyst/tracers/agentic_tracing/tests/FinancialAnalysisSystem.ipynb,sha256=0qZxjWqYCTAVvdo3Tsp544D8Am48wfeMQ9RKpKgAL8g,34291
|
23
24
|
ragaai_catalyst/tracers/agentic_tracing/tests/GameActivityEventPlanner.ipynb,sha256=QCMFJYbGX0fd9eMW4PqyQLZjyWuTXo7n1nqO_hMLf0s,4225
|
24
25
|
ragaai_catalyst/tracers/agentic_tracing/tests/TravelPlanner.ipynb,sha256=fU3inXoemJbdTkGAQl_N1UwVEZ10LrKv4gCEpbQ4ISg,43481
|
@@ -27,18 +28,18 @@ ragaai_catalyst/tracers/agentic_tracing/tests/ai_travel_agent.py,sha256=S4rCcKzU
|
|
27
28
|
ragaai_catalyst/tracers/agentic_tracing/tests/unique_decorator_test.py,sha256=Xk1cLzs-2A3dgyBwRRnCWs7Eubki40FVonwd433hPN8,4805
|
28
29
|
ragaai_catalyst/tracers/agentic_tracing/tracers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
30
|
ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py,sha256=aLiq5nPie5TT61QYtvAtvErsxjPFYiUxjayn5aCX1_k,25543
|
30
|
-
ragaai_catalyst/tracers/agentic_tracing/tracers/base.py,sha256=
|
31
|
+
ragaai_catalyst/tracers/agentic_tracing/tracers/base.py,sha256=XZH5qi8eMIHG_qjedRHa3lGYp0NiAtCUxN9P_uW_NMo,39981
|
31
32
|
ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py,sha256=uay8lU7T-CKsVu8KvWX31qfMqufK9S3Ive7XKo2Ksmk,12252
|
32
33
|
ragaai_catalyst/tracers/agentic_tracing/tracers/langgraph_tracer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
-
ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py,sha256=
|
34
|
-
ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py,sha256=
|
35
|
-
ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py,sha256=
|
34
|
+
ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py,sha256=hU97LWEdqFL-tnIb_Qlk6VJdS6yVPH0QVzVzg1yuCB0,29341
|
35
|
+
ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py,sha256=9K1swf0IOEEzgpkO2A_k_Yxk6ybLRXDcVoQAzm-_fWs,15889
|
36
|
+
ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py,sha256=m8CxYkl7iMiFya_lNwN1ykBc3Pmo-2pR_2HmpptwHWQ,10352
|
36
37
|
ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py,sha256=4h6epgRHPVRfTrCznwc6KPK6xevwBaZwE-q0Zj-4Kkk,12160
|
37
38
|
ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py,sha256=bhSUhNQCuJXKjgJAXhjKEYjnHMpYN90FSZdR84fNIKU,4614
|
38
39
|
ragaai_catalyst/tracers/agentic_tracing/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
40
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=1MDKXAAPzOEdxFKWWQrRgrmM3kz--DGXSywGXQmR3lQ,6041
|
40
41
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=HgpMgI-JTWZrizcM7GGUIaAgaZF4aRT3D0dJXVEkblY,4271
|
41
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py,sha256=
|
42
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_trace_metric.py,sha256=id66gfx-XYj_zsAmicBKojBOqJQ__FJLSoZ0db56aes,3493
|
42
43
|
ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py,sha256=XdB3X_ufe4RVvGorxSqAiB9dYv4UD7Hvvuw3bsDUppY,60
|
43
44
|
ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py,sha256=JyNCbfpW-w4O9CjtemTqmor2Rh1WGpQwhRaDSRmBxw8,689
|
44
45
|
ragaai_catalyst/tracers/agentic_tracing/utils/create_dataset_schema.py,sha256=lgvJL0cakJrX8WGsnU05YGvotequSj6HgSohyR4OJNE,804
|
@@ -50,7 +51,7 @@ ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json,sha256=weznWpRd6N
|
|
50
51
|
ragaai_catalyst/tracers/agentic_tracing/utils/span_attributes.py,sha256=MqeRNGxzeuh9qTK0NbYMftl9V9Z0V7gMgBoHkrXP56k,1592
|
51
52
|
ragaai_catalyst/tracers/agentic_tracing/utils/trace_utils.py,sha256=RciiDdo2riibEoM8X0FKHaXi78y3bWwNkV8U0leqigk,3508
|
52
53
|
ragaai_catalyst/tracers/agentic_tracing/utils/unique_decorator.py,sha256=DQHjcEuqEKsNSWaNs7SoOaq50yK4Jsl966S7mBnV-zA,5723
|
53
|
-
ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py,sha256=
|
54
|
+
ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py,sha256=8SAN4pjA3XKBWlUZiDGXGh26ve1qRH_fv0VwewsfCFc,18818
|
54
55
|
ragaai_catalyst/tracers/exporters/__init__.py,sha256=kVA8zp05h3phu4e-iHSlnznp_PzMRczB7LphSsZgUjg,138
|
55
56
|
ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=RgGteu-NVGprXKkynvyIO5yOjpbtA41R3W_NzCjnkwE,6445
|
56
57
|
ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=6xvjWXyh8XPkHKSLLmAZUQSvwuyY17ov8pv2VdfI0qA,17875
|
@@ -60,8 +61,8 @@ ragaai_catalyst/tracers/instrumentators/llamaindex.py,sha256=SMrRlR4xM7k9HK43hak
|
|
60
61
|
ragaai_catalyst/tracers/instrumentators/openai.py,sha256=14R4KW9wQCR1xysLfsP_nxS7cqXrTPoD8En4MBAaZUU,379
|
61
62
|
ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
|
62
63
|
ragaai_catalyst/tracers/utils/utils.py,sha256=ViygfJ7vZ7U0CTSA1lbxVloHp4NSlmfDzBRNCJuMhis,2374
|
63
|
-
ragaai_catalyst-2.1.
|
64
|
-
ragaai_catalyst-2.1.
|
65
|
-
ragaai_catalyst-2.1.
|
66
|
-
ragaai_catalyst-2.1.
|
67
|
-
ragaai_catalyst-2.1.
|
64
|
+
ragaai_catalyst-2.1.5b0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
65
|
+
ragaai_catalyst-2.1.5b0.dist-info/METADATA,sha256=R0r0eV49WTeIO0O1NlkFk99eIbAPnvqf0urcA-GpF48,12764
|
66
|
+
ragaai_catalyst-2.1.5b0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
67
|
+
ragaai_catalyst-2.1.5b0.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
68
|
+
ragaai_catalyst-2.1.5b0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|