ragaai-catalyst 2.1.4.1b1__py3-none-any.whl → 2.1.5b1__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/dataset.py +330 -0
- ragaai_catalyst/tracers/__init__.py +17 -1
- ragaai_catalyst/tracers/agentic_tracing/tracers/agent_tracer.py +20 -4
- ragaai_catalyst/tracers/agentic_tracing/tracers/base.py +85 -52
- ragaai_catalyst/tracers/agentic_tracing/tracers/custom_tracer.py +17 -2
- ragaai_catalyst/tracers/agentic_tracing/tracers/llm_tracer.py +17 -2
- ragaai_catalyst/tracers/agentic_tracing/tracers/main_tracer.py +32 -20
- ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py +3 -3
- ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py +37 -3
- ragaai_catalyst/tracers/agentic_tracing/utils/model_costs.json +17 -1
- ragaai_catalyst/tracers/agentic_tracing/utils/zip_list_of_unique_files.py +6 -6
- ragaai_catalyst/tracers/distributed.py +313 -0
- ragaai_catalyst/tracers/tracer.py +2 -2
- {ragaai_catalyst-2.1.4.1b1.dist-info → ragaai_catalyst-2.1.5b1.dist-info}/METADATA +1 -2
- {ragaai_catalyst-2.1.4.1b1.dist-info → ragaai_catalyst-2.1.5b1.dist-info}/RECORD +19 -18
- {ragaai_catalyst-2.1.4.1b1.dist-info → ragaai_catalyst-2.1.5b1.dist-info}/LICENSE +0 -0
- {ragaai_catalyst-2.1.4.1b1.dist-info → ragaai_catalyst-2.1.5b1.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.1.4.1b1.dist-info → ragaai_catalyst-2.1.5b1.dist-info}/top_level.txt +0 -0
@@ -61,6 +61,7 @@ class LLMTracerMixin:
|
|
61
61
|
# Add auto_instrument options
|
62
62
|
self.auto_instrument_llm = False
|
63
63
|
self.auto_instrument_user_interaction = False
|
64
|
+
self.auto_instrument_file_io = False
|
64
65
|
self.auto_instrument_network = False
|
65
66
|
|
66
67
|
def instrument_llm_calls(self):
|
@@ -117,6 +118,10 @@ class LLMTracerMixin:
|
|
117
118
|
def instrument_network_calls(self):
|
118
119
|
"""Enable network instrumentation for LLM calls"""
|
119
120
|
self.auto_instrument_network = True
|
121
|
+
|
122
|
+
def instrument_file_io_calls(self):
|
123
|
+
"""Enable file IO instrumentation for LLM calls"""
|
124
|
+
self.auto_instrument_file_io = True
|
120
125
|
|
121
126
|
def patch_openai_methods(self, module):
|
122
127
|
try:
|
@@ -334,7 +339,17 @@ class LLMTracerMixin:
|
|
334
339
|
|
335
340
|
interactions = []
|
336
341
|
if self.auto_instrument_user_interaction:
|
337
|
-
|
342
|
+
input_output_interactions = []
|
343
|
+
for interaction in self.component_user_interaction.get(component_id, []):
|
344
|
+
if interaction["interaction_type"] in ["input", "output"]:
|
345
|
+
input_output_interactions.append(interaction)
|
346
|
+
interactions.extend(input_output_interactions)
|
347
|
+
if self.auto_instrument_file_io:
|
348
|
+
file_io_interactions = []
|
349
|
+
for interaction in self.component_user_interaction.get(component_id, []):
|
350
|
+
if interaction["interaction_type"] in ["file_read", "file_write"]:
|
351
|
+
file_io_interactions.append(interaction)
|
352
|
+
interactions.extend(file_io_interactions)
|
338
353
|
|
339
354
|
parameters_to_display = {}
|
340
355
|
if "run_manager" in parameters:
|
@@ -475,7 +490,7 @@ class LLMTracerMixin:
|
|
475
490
|
parameters=parameters,
|
476
491
|
)
|
477
492
|
|
478
|
-
|
493
|
+
self.add_component(llm_component)
|
479
494
|
self.llm_data = llm_component
|
480
495
|
|
481
496
|
return result
|
@@ -84,27 +84,23 @@ class AgenticTracing(
|
|
84
84
|
self.auto_instrument_custom = True
|
85
85
|
else:
|
86
86
|
# Set global active state
|
87
|
-
self.is_active =
|
88
|
-
any(auto_instrumentation.values())
|
89
|
-
if isinstance(auto_instrumentation, dict)
|
90
|
-
else bool(auto_instrumentation)
|
91
|
-
)
|
87
|
+
self.is_active = True
|
92
88
|
|
93
89
|
# Set individual components
|
94
90
|
if isinstance(auto_instrumentation, dict):
|
95
|
-
self.auto_instrument_llm = auto_instrumentation.get("llm",
|
96
|
-
self.auto_instrument_tool = auto_instrumentation.get("tool",
|
97
|
-
self.auto_instrument_agent = auto_instrumentation.get("agent",
|
91
|
+
self.auto_instrument_llm = auto_instrumentation.get("llm", True)
|
92
|
+
self.auto_instrument_tool = auto_instrumentation.get("tool", True)
|
93
|
+
self.auto_instrument_agent = auto_instrumentation.get("agent", True)
|
98
94
|
self.auto_instrument_user_interaction = auto_instrumentation.get(
|
99
|
-
"user_interaction",
|
95
|
+
"user_interaction", True
|
100
96
|
)
|
101
97
|
self.auto_instrument_file_io = auto_instrumentation.get(
|
102
|
-
"file_io",
|
98
|
+
"file_io", True
|
103
99
|
)
|
104
100
|
self.auto_instrument_network = auto_instrumentation.get(
|
105
|
-
"network",
|
101
|
+
"network", True
|
106
102
|
)
|
107
|
-
self.auto_instrument_custom = auto_instrumentation.get("custom",
|
103
|
+
self.auto_instrument_custom = auto_instrumentation.get("custom", True)
|
108
104
|
else:
|
109
105
|
# If boolean provided, apply to all components
|
110
106
|
self.auto_instrument_llm = bool(auto_instrumentation)
|
@@ -137,13 +133,28 @@ class AgenticTracing(
|
|
137
133
|
self.network_tracer.network_calls.copy()
|
138
134
|
)
|
139
135
|
self.network_tracer.network_calls = [] # Reset for next component
|
140
|
-
|
136
|
+
|
137
|
+
# Store user interactions for the component
|
141
138
|
for interaction in self.user_interaction_tracer.interactions:
|
142
139
|
interaction_component_id = interaction.get("component_id")
|
143
140
|
if interaction_component_id not in self.component_user_interaction:
|
144
141
|
self.component_user_interaction[interaction_component_id] = []
|
145
142
|
if interaction not in self.component_user_interaction[interaction_component_id]:
|
146
143
|
self.component_user_interaction[interaction_component_id].append(interaction)
|
144
|
+
|
145
|
+
# Only reset component_id if it matches the current one
|
146
|
+
# This ensures we don't reset a parent's component_id when a child component ends
|
147
|
+
if self.current_component_id.get() == component_id:
|
148
|
+
# Get the parent agent's component_id if it exists
|
149
|
+
parent_agent_id = self.current_agent_id.get()
|
150
|
+
# If there's a parent agent, set the component_id back to the parent's
|
151
|
+
if parent_agent_id:
|
152
|
+
self.current_component_id.set(parent_agent_id)
|
153
|
+
self.user_interaction_tracer.component_id.set(parent_agent_id)
|
154
|
+
else:
|
155
|
+
# Only reset to None if there's no parent
|
156
|
+
self.current_component_id.set(None)
|
157
|
+
self.user_interaction_tracer.component_id.set(None)
|
147
158
|
|
148
159
|
def start(self):
|
149
160
|
"""Start tracing"""
|
@@ -155,9 +166,6 @@ class AgenticTracing(
|
|
155
166
|
self.user_interaction_tracer.trace_id.set(self.trace_id)
|
156
167
|
self.user_interaction_tracer.tracer = self
|
157
168
|
self.user_interaction_tracer.component_id.set(self.current_component_id.get())
|
158
|
-
builtins.print = self.user_interaction_tracer.traced_print
|
159
|
-
builtins.input = self.user_interaction_tracer.traced_input
|
160
|
-
builtins.open = self.user_interaction_tracer.traced_open
|
161
169
|
|
162
170
|
# Start base tracer (includes system info and resource monitoring)
|
163
171
|
super().start()
|
@@ -179,11 +187,12 @@ class AgenticTracing(
|
|
179
187
|
self.instrument_custom_calls()
|
180
188
|
|
181
189
|
if self.auto_instrument_user_interaction:
|
182
|
-
|
183
190
|
ToolTracerMixin.instrument_user_interaction_calls(self)
|
184
191
|
LLMTracerMixin.instrument_user_interaction_calls(self)
|
185
192
|
AgentTracerMixin.instrument_user_interaction_calls(self)
|
186
193
|
CustomTracerMixin.instrument_user_interaction_calls(self)
|
194
|
+
builtins.print = self.user_interaction_tracer.traced_print
|
195
|
+
builtins.input = self.user_interaction_tracer.traced_input
|
187
196
|
|
188
197
|
if self.auto_instrument_network:
|
189
198
|
ToolTracerMixin.instrument_network_calls(self)
|
@@ -191,9 +200,12 @@ class AgenticTracing(
|
|
191
200
|
AgentTracerMixin.instrument_network_calls(self)
|
192
201
|
CustomTracerMixin.instrument_network_calls(self)
|
193
202
|
|
194
|
-
|
195
|
-
|
196
|
-
|
203
|
+
if self.auto_instrument_file_io:
|
204
|
+
ToolTracerMixin.instrument_file_io_calls(self)
|
205
|
+
LLMTracerMixin.instrument_file_io_calls(self)
|
206
|
+
AgentTracerMixin.instrument_file_io_calls(self)
|
207
|
+
CustomTracerMixin.instrument_file_io_calls(self)
|
208
|
+
builtins.open = self.user_interaction_tracer.traced_open
|
197
209
|
|
198
210
|
def stop(self):
|
199
211
|
"""Stop tracing and save results"""
|
@@ -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
|
}
|
@@ -32,6 +32,7 @@ class ToolTracerMixin:
|
|
32
32
|
# add auto_instrument option
|
33
33
|
self.auto_instrument_tool = False
|
34
34
|
self.auto_instrument_user_interaction = False
|
35
|
+
self.auto_instrument_file_io = False
|
35
36
|
self.auto_instrument_network = False
|
36
37
|
|
37
38
|
# take care of auto_instrument
|
@@ -40,6 +41,9 @@ class ToolTracerMixin:
|
|
40
41
|
|
41
42
|
def instrument_user_interaction_calls(self):
|
42
43
|
self.auto_instrument_user_interaction = True
|
44
|
+
|
45
|
+
def instrument_file_io_calls(self):
|
46
|
+
self.auto_instrument_file_io = True
|
43
47
|
|
44
48
|
def instrument_network_calls(self):
|
45
49
|
self.auto_instrument_network = True
|
@@ -133,6 +137,10 @@ class ToolTracerMixin:
|
|
133
137
|
component_id = str(uuid.uuid4())
|
134
138
|
hash_id = generate_unique_hash_simple(func)
|
135
139
|
|
140
|
+
# Set current tool name and store the token
|
141
|
+
name_token = self.current_tool_name.set(name)
|
142
|
+
id_token = self.current_tool_id.set(component_id)
|
143
|
+
|
136
144
|
# Start tracking network calls for this component
|
137
145
|
self.start_component(component_id)
|
138
146
|
|
@@ -191,6 +199,12 @@ class ToolTracerMixin:
|
|
191
199
|
self.add_component(tool_component)
|
192
200
|
|
193
201
|
raise
|
202
|
+
finally:
|
203
|
+
# Reset the tool name and id context
|
204
|
+
if name_token:
|
205
|
+
self.current_tool_name.reset(name_token)
|
206
|
+
if id_token:
|
207
|
+
self.current_tool_id.reset(id_token)
|
194
208
|
|
195
209
|
async def _trace_tool_execution(
|
196
210
|
self, func, name, tool_type, version, *args, **kwargs
|
@@ -207,6 +221,10 @@ class ToolTracerMixin:
|
|
207
221
|
component_id = str(uuid.uuid4())
|
208
222
|
hash_id = generate_unique_hash_simple(func)
|
209
223
|
|
224
|
+
# Set current tool name and store the token
|
225
|
+
name_token = self.current_tool_name.set(name)
|
226
|
+
id_token = self.current_tool_id.set(component_id)
|
227
|
+
|
210
228
|
self.start_component(component_id)
|
211
229
|
try:
|
212
230
|
# Execute the tool
|
@@ -256,6 +274,12 @@ class ToolTracerMixin:
|
|
256
274
|
self.add_component(tool_component)
|
257
275
|
|
258
276
|
raise
|
277
|
+
finally:
|
278
|
+
# Reset the tool name and id context
|
279
|
+
if name_token:
|
280
|
+
self.current_tool_name.reset(name_token)
|
281
|
+
if id_token:
|
282
|
+
self.current_tool_id.reset(id_token)
|
259
283
|
|
260
284
|
def create_tool_component(self, **kwargs):
|
261
285
|
"""Create a tool component according to the data structure"""
|
@@ -264,9 +288,19 @@ class ToolTracerMixin:
|
|
264
288
|
network_calls = self.component_network_calls.get(kwargs["component_id"], [])
|
265
289
|
interactions = []
|
266
290
|
if self.auto_instrument_user_interaction:
|
267
|
-
|
268
|
-
|
269
|
-
|
291
|
+
input_output_interactions = []
|
292
|
+
for interaction in self.component_user_interaction.get(kwargs["component_id"], []):
|
293
|
+
if interaction["interaction_type"] in ["input", "output"]:
|
294
|
+
input_output_interactions.append(interaction)
|
295
|
+
if input_output_interactions!=[]:
|
296
|
+
interactions.extend(input_output_interactions)
|
297
|
+
if self.auto_instrument_file_io:
|
298
|
+
file_io_interactions = []
|
299
|
+
for interaction in self.component_user_interaction.get(kwargs["component_id"], []):
|
300
|
+
if interaction["interaction_type"] in ["file_read", "file_write"]:
|
301
|
+
file_io_interactions.append(interaction)
|
302
|
+
if file_io_interactions!=[]:
|
303
|
+
interactions.extend(file_io_interactions)
|
270
304
|
|
271
305
|
# Get tags, metrics
|
272
306
|
name = kwargs["name"]
|
@@ -2063,7 +2063,9 @@
|
|
2063
2063
|
"input_cost_per_token": 5.9e-07,
|
2064
2064
|
"output_cost_per_token": 7.9e-07,
|
2065
2065
|
"litellm_provider": "groq",
|
2066
|
-
"mode": "chat"
|
2066
|
+
"mode": "chat",
|
2067
|
+
"supports_function_calling": true,
|
2068
|
+
"supports_response_schema": true
|
2067
2069
|
},
|
2068
2070
|
"groq/llama-3.3-70b-specdec": {
|
2069
2071
|
"max_tokens": 8192,
|
@@ -4605,6 +4607,20 @@
|
|
4605
4607
|
"litellm_provider": "replicate",
|
4606
4608
|
"mode": "chat"
|
4607
4609
|
},
|
4610
|
+
"openrouter/deepseek/deepseek-r1": {
|
4611
|
+
"max_tokens": 8192,
|
4612
|
+
"max_input_tokens": 64000,
|
4613
|
+
"max_output_tokens": 8192,
|
4614
|
+
"input_cost_per_token": 5.5e-07,
|
4615
|
+
"input_cost_per_token_cache_hit": 1.4e-07,
|
4616
|
+
"output_cost_per_token": 2.19e-06,
|
4617
|
+
"litellm_provider": "openrouter",
|
4618
|
+
"mode": "chat",
|
4619
|
+
"supports_function_calling": true,
|
4620
|
+
"supports_assistant_prefill": true,
|
4621
|
+
"supports_tool_choice": true,
|
4622
|
+
"supports_prompt_caching": true
|
4623
|
+
},
|
4608
4624
|
"openrouter/deepseek/deepseek-chat": {
|
4609
4625
|
"max_tokens": 8192,
|
4610
4626
|
"max_input_tokens": 66000,
|
@@ -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,313 @@
|
|
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
|
+
span_name = name or func.__name__
|
195
|
+
|
196
|
+
@wraps(func)
|
197
|
+
async def async_wrapper(*args, **kwargs):
|
198
|
+
tracer = get_current_tracer()
|
199
|
+
if not tracer:
|
200
|
+
return await func(*args, **kwargs)
|
201
|
+
|
202
|
+
# Set current tool name and store the token
|
203
|
+
name_token = tracer.current_tool_name.set(span_name)
|
204
|
+
|
205
|
+
try:
|
206
|
+
# Use async tool tracing
|
207
|
+
return await tracer._trace_tool_execution(
|
208
|
+
func,
|
209
|
+
span_name,
|
210
|
+
tool_type,
|
211
|
+
version,
|
212
|
+
*args,
|
213
|
+
**kwargs
|
214
|
+
)
|
215
|
+
finally:
|
216
|
+
# Reset using the stored token
|
217
|
+
if name_token:
|
218
|
+
tracer.current_tool_name.reset(name_token)
|
219
|
+
|
220
|
+
@wraps(func)
|
221
|
+
def sync_wrapper(*args, **kwargs):
|
222
|
+
tracer = get_current_tracer()
|
223
|
+
if not tracer:
|
224
|
+
return func(*args, **kwargs)
|
225
|
+
|
226
|
+
# Set current tool name and store the token
|
227
|
+
name_token = tracer.current_tool_name.set(span_name)
|
228
|
+
|
229
|
+
try:
|
230
|
+
# Use synchronous tool tracing
|
231
|
+
return tracer._trace_sync_tool_execution(
|
232
|
+
func,
|
233
|
+
span_name,
|
234
|
+
tool_type,
|
235
|
+
version,
|
236
|
+
*args,
|
237
|
+
**kwargs
|
238
|
+
)
|
239
|
+
finally:
|
240
|
+
# Reset using the stored token
|
241
|
+
if name_token:
|
242
|
+
tracer.current_tool_name.reset(name_token)
|
243
|
+
|
244
|
+
return async_wrapper if is_async else sync_wrapper
|
245
|
+
return decorator
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
def trace_custom(name: str = None, custom_type: str = "generic", version: str = "1.0.0", trace_variables: bool = False, **kwargs):
|
250
|
+
"""Decorator for tracing custom functions."""
|
251
|
+
def decorator(func):
|
252
|
+
is_async = asyncio.iscoroutinefunction(func)
|
253
|
+
|
254
|
+
@wraps(func)
|
255
|
+
async def async_wrapper(*args, **kwargs):
|
256
|
+
tracer = get_current_tracer()
|
257
|
+
if not tracer:
|
258
|
+
return await func(*args, **kwargs)
|
259
|
+
|
260
|
+
# Use async tool tracing
|
261
|
+
return await tracer._trace_custom_execution(
|
262
|
+
func,
|
263
|
+
name or func.__name__,
|
264
|
+
custom_type,
|
265
|
+
version,
|
266
|
+
trace_variables,
|
267
|
+
*args,
|
268
|
+
**kwargs
|
269
|
+
)
|
270
|
+
|
271
|
+
@wraps(func)
|
272
|
+
def sync_wrapper(*args, **kwargs):
|
273
|
+
tracer = get_current_tracer()
|
274
|
+
if not tracer:
|
275
|
+
return func(*args, **kwargs)
|
276
|
+
|
277
|
+
# Use synchronous tool tracing
|
278
|
+
return tracer._trace_sync_custom_execution(
|
279
|
+
func,
|
280
|
+
name or func.__name__,
|
281
|
+
custom_type,
|
282
|
+
version,
|
283
|
+
trace_variables,
|
284
|
+
*args,
|
285
|
+
**kwargs
|
286
|
+
)
|
287
|
+
|
288
|
+
return async_wrapper if is_async else sync_wrapper
|
289
|
+
return decorator
|
290
|
+
|
291
|
+
|
292
|
+
def current_span():
|
293
|
+
"""Get the current active span for adding metrics."""
|
294
|
+
tracer = get_current_tracer()
|
295
|
+
if not tracer:
|
296
|
+
return None
|
297
|
+
|
298
|
+
# First check for LLM context
|
299
|
+
llm_name = tracer.current_llm_call_name.get()
|
300
|
+
if llm_name:
|
301
|
+
return tracer.span(llm_name)
|
302
|
+
|
303
|
+
# Then check for tool context
|
304
|
+
tool_name = tracer.current_tool_name.get()
|
305
|
+
if tool_name:
|
306
|
+
return tracer.span(tool_name)
|
307
|
+
|
308
|
+
# Finally fall back to agent context
|
309
|
+
agent_name = tracer.current_agent_name.get()
|
310
|
+
if not agent_name:
|
311
|
+
raise ValueError("No active span found. Make sure you're calling this within a traced function.")
|
312
|
+
|
313
|
+
return tracer.span(agent_name)
|
@@ -98,10 +98,10 @@ class Tracer(AgenticTracing):
|
|
98
98
|
"custom": False
|
99
99
|
}
|
100
100
|
elif isinstance(auto_instrumentation, dict):
|
101
|
-
auto_instrumentation = {k: v for k, v in auto_instrumentation.items()
|
101
|
+
auto_instrumentation = {k: v for k, v in auto_instrumentation.items()}
|
102
102
|
for key in ["llm", "tool", "agent", "user_interaction", "file_io", "network", "custom"]:
|
103
103
|
if key not in auto_instrumentation:
|
104
|
-
auto_instrumentation[key] =
|
104
|
+
auto_instrumentation[key] = True
|
105
105
|
|
106
106
|
super().__init__(user_detail=user_detail, auto_instrumentation=auto_instrumentation)
|
107
107
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.5b1
|
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"
|