ragaai-catalyst 2.2.4b4__py3-none-any.whl → 2.2.4.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.
- ragaai_catalyst/tracers/agentic_tracing/upload/session_manager.py +156 -0
- ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py +122 -34
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py +46 -32
- ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py +80 -42
- ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py +1 -0
- ragaai_catalyst/tracers/utils/trace_json_converter.py +2 -2
- {ragaai_catalyst-2.2.4b4.dist-info → ragaai_catalyst-2.2.4.1.dist-info}/METADATA +1 -1
- {ragaai_catalyst-2.2.4b4.dist-info → ragaai_catalyst-2.2.4.1.dist-info}/RECORD +11 -10
- {ragaai_catalyst-2.2.4b4.dist-info → ragaai_catalyst-2.2.4.1.dist-info}/WHEEL +0 -0
- {ragaai_catalyst-2.2.4b4.dist-info → ragaai_catalyst-2.2.4.1.dist-info}/licenses/LICENSE +0 -0
- {ragaai_catalyst-2.2.4b4.dist-info → ragaai_catalyst-2.2.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import threading
|
4
|
+
|
5
|
+
from requests.adapters import HTTPAdapter
|
6
|
+
from urllib3.util.retry import Retry
|
7
|
+
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
|
+
from requests.exceptions import ConnectionError, Timeout
|
9
|
+
from http.client import RemoteDisconnected
|
10
|
+
from ragaai_catalyst import RagaAICatalyst
|
11
|
+
import requests
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class SessionManager:
|
17
|
+
"""Shared session manager with connection pooling for HTTP requests"""
|
18
|
+
_instance = None
|
19
|
+
_session = None
|
20
|
+
_lock = threading.Lock()
|
21
|
+
|
22
|
+
def __new__(cls):
|
23
|
+
if cls._instance is None:
|
24
|
+
with cls._lock: # Thread-safe singleton
|
25
|
+
if cls._instance is None: # Double-check locking
|
26
|
+
logger.info("Creating new SessionManager singleton instance")
|
27
|
+
cls._instance = super(SessionManager, cls).__new__(cls)
|
28
|
+
cls._instance._initialize_session()
|
29
|
+
else:
|
30
|
+
logger.debug("SessionManager instance already exists, returning existing instance")
|
31
|
+
else:
|
32
|
+
logger.debug("SessionManager instance exists, returning existing instance")
|
33
|
+
return cls._instance
|
34
|
+
|
35
|
+
def _initialize_session(self):
|
36
|
+
"""Initialize session with connection pooling and retry strategy"""
|
37
|
+
logger.info("Initializing HTTP session with connection pooling and retry strategy")
|
38
|
+
self._session = requests.Session()
|
39
|
+
|
40
|
+
retry_strategy = Retry(
|
41
|
+
total=3, # number of retries
|
42
|
+
connect=3, # number of retries for connection-related errors
|
43
|
+
read=3, # number of retries for read-related errors
|
44
|
+
backoff_factor=0.5, # wait 0.5, 1, 2... seconds between retries
|
45
|
+
status_forcelist=[500, 502, 503, 504] # HTTP status codes to retry on
|
46
|
+
)
|
47
|
+
|
48
|
+
adapter = HTTPAdapter(
|
49
|
+
max_retries=retry_strategy,
|
50
|
+
pool_connections=5, # number of connection pools to cache (per host)
|
51
|
+
pool_maxsize=50, # maximum number of connections in each pool
|
52
|
+
pool_block=True # Block/wait when pool is full rather than raising error
|
53
|
+
)
|
54
|
+
|
55
|
+
self._session.mount("http://", adapter)
|
56
|
+
self._session.mount("https://", adapter)
|
57
|
+
|
58
|
+
# Set session-level configuration to handle connection issues
|
59
|
+
self._session.headers.update({
|
60
|
+
'Connection': 'keep-alive',
|
61
|
+
'User-Agent': 'RagaAI-Catalyst/1.0'
|
62
|
+
})
|
63
|
+
|
64
|
+
logger.info("HTTP session initialized successfully with adapters mounted for http:// and https://")
|
65
|
+
|
66
|
+
# Warm up connection pool using RagaAICatalyst.BASE_URL
|
67
|
+
if os.getenv("RAGAAI_CATALYST_BASE_URL") is not None:
|
68
|
+
base_url = os.getenv("RAGAAI_CATALYST_BASE_URL")
|
69
|
+
logger.info(f"Warming up connection pool using RagaAICatalyst.BASE_URL: {base_url}")
|
70
|
+
self.warm_up_connections(base_url)
|
71
|
+
else:
|
72
|
+
logger.warning(f"RAGAAI_CATALYST_BASE_URL not available, skipping connection warmup")
|
73
|
+
|
74
|
+
@property
|
75
|
+
def session(self):
|
76
|
+
if self._session is None:
|
77
|
+
logger.warning("Session accessed but not initialized, reinitializing...")
|
78
|
+
self._initialize_session()
|
79
|
+
return self._session
|
80
|
+
|
81
|
+
def warm_up_connections(self, base_url, num_connections=3):
|
82
|
+
"""
|
83
|
+
Warm up the connection pool by making lightweight requests to healthcheck endpoint.
|
84
|
+
This can help prevent RemoteDisconnected errors on initial requests.
|
85
|
+
"""
|
86
|
+
if not self._session:
|
87
|
+
return
|
88
|
+
|
89
|
+
# Construct healthcheck URL
|
90
|
+
healthcheck_url = f"{base_url.rstrip('/')}/healthcheck"
|
91
|
+
logger.info(f"Warming up connection pool with {num_connections} connections to {healthcheck_url}")
|
92
|
+
|
93
|
+
for i in range(num_connections):
|
94
|
+
try:
|
95
|
+
# Make a lightweight HEAD request to the healthcheck endpoint to warm up the connection
|
96
|
+
response = self._session.head(healthcheck_url, timeout=10)
|
97
|
+
logger.info(f"Warmup connection {i+1}: Status {response.status_code}")
|
98
|
+
except Exception as e:
|
99
|
+
logger.warning(f"Warmup connection {i+1} failed (this may be normal): {e}")
|
100
|
+
# Ignore other failures during warmup as they're expected
|
101
|
+
continue
|
102
|
+
|
103
|
+
logger.info("Connection pool warmup completed")
|
104
|
+
|
105
|
+
def close(self):
|
106
|
+
"""Close the session"""
|
107
|
+
if self._session:
|
108
|
+
logger.info("Closing HTTP session")
|
109
|
+
self._session.close()
|
110
|
+
self._session = None
|
111
|
+
logger.info("HTTP session closed successfully")
|
112
|
+
else:
|
113
|
+
logger.debug("Close called but session was already None")
|
114
|
+
|
115
|
+
def handle_request_exceptions(self, e, operation_name):
|
116
|
+
"""Handle common request exceptions with appropriate logging"""
|
117
|
+
logger.error(f"Exception occurred during {operation_name}")
|
118
|
+
if isinstance(e, (PoolError, MaxRetryError)):
|
119
|
+
logger.error(f"Connection pool exhausted during {operation_name}: {e}")
|
120
|
+
elif isinstance(e, NewConnectionError):
|
121
|
+
logger.error(f"Failed to establish new connection during {operation_name}: {e}")
|
122
|
+
elif isinstance(e, RemoteDisconnected):
|
123
|
+
logger.error(f"Remote connection closed unexpectedly during {operation_name}: {e}")
|
124
|
+
elif isinstance(e, ConnectionError):
|
125
|
+
logger.error(f"Connection error during {operation_name}: {e}")
|
126
|
+
elif isinstance(e, Timeout):
|
127
|
+
logger.error(f"Request timeout during {operation_name}: {e}")
|
128
|
+
else:
|
129
|
+
logger.error(f"Unexpected error during {operation_name}: {e}")
|
130
|
+
|
131
|
+
def make_request_with_retry(self, method, url, **kwargs):
|
132
|
+
"""
|
133
|
+
Make HTTP request with additional retry logic for RemoteDisconnected errors
|
134
|
+
that may not be caught by urllib3's retry mechanism.
|
135
|
+
"""
|
136
|
+
max_retries = 3
|
137
|
+
for attempt in range(max_retries):
|
138
|
+
try:
|
139
|
+
response = self._session.request(method, url, **kwargs)
|
140
|
+
return response
|
141
|
+
except (RemoteDisconnected, ConnectionError) as e:
|
142
|
+
logger.warning(f"Connection error on attempt {attempt + 1}/{max_retries}: {e}")
|
143
|
+
if attempt == max_retries - 1:
|
144
|
+
# Re-raise the exception on the last attempt
|
145
|
+
raise
|
146
|
+
# Wait before retrying (exponential backoff)
|
147
|
+
import time
|
148
|
+
wait_time = 2 ** attempt
|
149
|
+
logger.info(f"Retrying in {wait_time} seconds...")
|
150
|
+
time.sleep(wait_time)
|
151
|
+
|
152
|
+
|
153
|
+
# Global session manager instance
|
154
|
+
logger.info("Creating global SessionManager instance")
|
155
|
+
session_manager = SessionManager()
|
156
|
+
logger.info(f"Global SessionManager instance created with ID: {id(session_manager)}")
|
@@ -22,6 +22,7 @@ from typing import Dict, Any, Optional
|
|
22
22
|
import threading
|
23
23
|
import uuid
|
24
24
|
|
25
|
+
|
25
26
|
# Set up logging
|
26
27
|
log_dir = os.path.join(tempfile.gettempdir(), "ragaai_logs")
|
27
28
|
os.makedirs(log_dir, exist_ok=True)
|
@@ -49,11 +50,13 @@ try:
|
|
49
50
|
from ragaai_catalyst.tracers.agentic_tracing.upload.upload_code import upload_code
|
50
51
|
# from ragaai_catalyst.tracers.agentic_tracing.upload.upload_trace_metric import upload_trace_metric
|
51
52
|
from ragaai_catalyst.tracers.agentic_tracing.utils.create_dataset_schema import create_dataset_schema_with_trace
|
53
|
+
from ragaai_catalyst.tracers.agentic_tracing.upload.session_manager import session_manager
|
52
54
|
from ragaai_catalyst import RagaAICatalyst
|
53
55
|
IMPORTS_AVAILABLE = True
|
54
56
|
except ImportError:
|
55
57
|
logger.warning("RagaAI Catalyst imports not available - running in test mode")
|
56
58
|
IMPORTS_AVAILABLE = False
|
59
|
+
session_manager = None
|
57
60
|
|
58
61
|
# Define task queue directory
|
59
62
|
QUEUE_DIR = os.path.join(tempfile.gettempdir(), "ragaai_tasks")
|
@@ -72,6 +75,10 @@ _executor_lock = threading.Lock()
|
|
72
75
|
_futures: Dict[str, Any] = {}
|
73
76
|
_futures_lock = threading.Lock()
|
74
77
|
|
78
|
+
# Dataset creation cache to avoid redundant API calls
|
79
|
+
_dataset_cache: Dict[str, Dict[str, Any]] = {}
|
80
|
+
_dataset_cache_lock = threading.Lock()
|
81
|
+
DATASET_CACHE_DURATION = 600 # 10 minutes in seconds
|
75
82
|
|
76
83
|
_cleanup_lock = threading.Lock()
|
77
84
|
_last_cleanup = 0
|
@@ -88,7 +95,7 @@ def get_executor(max_workers=None):
|
|
88
95
|
if _executor is None:
|
89
96
|
# Calculate optimal worker count
|
90
97
|
if max_workers is None:
|
91
|
-
max_workers = min(
|
98
|
+
max_workers = min(8, (os.cpu_count() or 1) * 4)
|
92
99
|
|
93
100
|
logger.info(f"Creating ThreadPoolExecutor with {max_workers} workers")
|
94
101
|
_executor = concurrent.futures.ThreadPoolExecutor(
|
@@ -110,9 +117,57 @@ def generate_unique_task_id():
|
|
110
117
|
unique_id = str(uuid.uuid4())[:8] # Short UUID
|
111
118
|
return f"task_{int(time.time())}_{os.getpid()}_{counter}_{unique_id}"
|
112
119
|
|
120
|
+
def _generate_dataset_cache_key(dataset_name: str, project_name: str, base_url: str) -> str:
|
121
|
+
"""Generate a unique cache key for dataset creation"""
|
122
|
+
return f"{dataset_name}#{project_name}#{base_url}"
|
123
|
+
|
124
|
+
def _is_dataset_cached(cache_key: str) -> bool:
|
125
|
+
"""Check if dataset creation is cached and still valid"""
|
126
|
+
with _dataset_cache_lock:
|
127
|
+
if cache_key not in _dataset_cache:
|
128
|
+
return False
|
129
|
+
|
130
|
+
cache_entry = _dataset_cache[cache_key]
|
131
|
+
cache_time = cache_entry.get('timestamp', 0)
|
132
|
+
current_time = time.time()
|
133
|
+
|
134
|
+
# Check if cache is still valid (within 10 minutes)
|
135
|
+
if current_time - cache_time <= DATASET_CACHE_DURATION:
|
136
|
+
logger.info(f"Dataset creation cache hit for key: {cache_key}")
|
137
|
+
return True
|
138
|
+
else:
|
139
|
+
# Cache expired, remove it
|
140
|
+
logger.info(f"Dataset creation cache expired for key: {cache_key}")
|
141
|
+
del _dataset_cache[cache_key]
|
142
|
+
return False
|
143
|
+
|
144
|
+
def _cache_dataset_creation(cache_key: str, response: Any) -> None:
|
145
|
+
"""Cache successful dataset creation"""
|
146
|
+
with _dataset_cache_lock:
|
147
|
+
_dataset_cache[cache_key] = {
|
148
|
+
'timestamp': time.time(),
|
149
|
+
'response': response
|
150
|
+
}
|
151
|
+
|
152
|
+
def _cleanup_expired_cache_entries() -> None:
|
153
|
+
"""Remove expired cache entries"""
|
154
|
+
current_time = time.time()
|
155
|
+
with _dataset_cache_lock:
|
156
|
+
expired_keys = []
|
157
|
+
for cache_key, cache_entry in _dataset_cache.items():
|
158
|
+
cache_time = cache_entry.get('timestamp', 0)
|
159
|
+
if current_time - cache_time > DATASET_CACHE_DURATION:
|
160
|
+
expired_keys.append(cache_key)
|
161
|
+
|
162
|
+
for key in expired_keys:
|
163
|
+
del _dataset_cache[key]
|
164
|
+
|
165
|
+
if expired_keys:
|
166
|
+
logger.info(f"Cleaned up {len(expired_keys)} expired dataset cache entries")
|
167
|
+
|
113
168
|
def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
114
169
|
project_name: str, project_id: str, dataset_name: str,
|
115
|
-
user_details: Dict[str, Any], base_url: str, timeout=120, fail_on_trace_error=True) -> Dict[str, Any]:
|
170
|
+
user_details: Dict[str, Any], base_url: str, tracer_type, timeout=120, fail_on_trace_error=True) -> Dict[str, Any]:
|
116
171
|
"""
|
117
172
|
Process a single upload task
|
118
173
|
|
@@ -165,20 +220,36 @@ def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
|
165
220
|
save_task_status(result)
|
166
221
|
return result
|
167
222
|
|
168
|
-
# Step 1: Create dataset schema
|
223
|
+
# Step 1: Create dataset schema (with caching)
|
169
224
|
logger.info(f"Creating dataset schema for {dataset_name} with base_url: {base_url} and timeout: {timeout}")
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
225
|
+
|
226
|
+
# Generate cache key and check if dataset creation is already cached
|
227
|
+
cache_key = _generate_dataset_cache_key(dataset_name, project_name, base_url)
|
228
|
+
|
229
|
+
if _is_dataset_cached(cache_key):
|
230
|
+
logger.info(f"Dataset schema creation skipped (cached) for {dataset_name}")
|
231
|
+
else:
|
232
|
+
try:
|
233
|
+
# Clean up expired cache entries periodically
|
234
|
+
# _cleanup_expired_cache_entries()
|
235
|
+
|
236
|
+
response = create_dataset_schema_with_trace(
|
237
|
+
dataset_name=dataset_name,
|
238
|
+
project_name=project_name,
|
239
|
+
base_url=base_url,
|
240
|
+
user_details=user_details,
|
241
|
+
timeout=timeout
|
242
|
+
)
|
243
|
+
logger.info(f"Dataset schema created: {response}")
|
244
|
+
|
245
|
+
# Cache the response only if status code is 200
|
246
|
+
if response and hasattr(response, 'status_code') and response.status_code in [200, 201]:
|
247
|
+
_cache_dataset_creation(cache_key, response)
|
248
|
+
logger.info(f"Response cached successfully for dataset: {dataset_name} and key: {cache_key}")
|
249
|
+
|
250
|
+
except Exception as e:
|
251
|
+
logger.error(f"Error creating dataset schema: {e}")
|
252
|
+
# Continue with other steps
|
182
253
|
|
183
254
|
# Step 2: Upload trace metrics
|
184
255
|
# if filepath and os.path.exists(filepath):
|
@@ -238,28 +309,34 @@ def process_upload(task_id: str, filepath: str, hash_id: str, zip_path: str,
|
|
238
309
|
logger.error(error_msg)
|
239
310
|
|
240
311
|
# Step 4: Upload code hash
|
241
|
-
if
|
242
|
-
logger.info(f"
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
312
|
+
if tracer_type.startswith("agentic/"):
|
313
|
+
logger.info(f"Tracer type '{tracer_type}' matches agentic pattern, proceeding with code upload")
|
314
|
+
if hash_id and zip_path and os.path.exists(zip_path):
|
315
|
+
logger.info(f"Uploading code hash {hash_id} with base_url: {base_url} and timeout: {timeout}")
|
316
|
+
try:
|
317
|
+
response = upload_code(
|
318
|
+
hash_id=hash_id,
|
319
|
+
zip_path=zip_path,
|
320
|
+
project_name=project_name,
|
321
|
+
dataset_name=dataset_name,
|
322
|
+
base_url=base_url,
|
323
|
+
timeout=timeout
|
324
|
+
)
|
325
|
+
if response is None:
|
326
|
+
error_msg = "Code hash not uploaded"
|
327
|
+
logger.error(error_msg)
|
328
|
+
else:
|
329
|
+
logger.info(f"Code hash uploaded successfully: {response}")
|
330
|
+
except Exception as e:
|
331
|
+
logger.error(f"Error uploading code hash: {e}")
|
332
|
+
else:
|
333
|
+
logger.warning(f"Code zip {zip_path} not found, skipping code upload")
|
334
|
+
|
258
335
|
# Mark task as completed
|
259
336
|
result["status"] = STATUS_COMPLETED
|
260
337
|
result["end_time"] = datetime.now().isoformat()
|
261
338
|
logger.info(f"Task {task_id} completed successfully")
|
262
|
-
|
339
|
+
|
263
340
|
except Exception as e:
|
264
341
|
logger.error(f"Error processing task {task_id}: {e}")
|
265
342
|
result["status"] = STATUS_FAILED
|
@@ -302,7 +379,8 @@ def save_task_status(task_status: Dict[str, Any]):
|
|
302
379
|
with open(status_path, "w") as f:
|
303
380
|
json.dump(task_status, f, indent=2)
|
304
381
|
|
305
|
-
def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, dataset_name, user_details, base_url,
|
382
|
+
def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, dataset_name, user_details, base_url,
|
383
|
+
tracer_type, timeout=120):
|
306
384
|
"""
|
307
385
|
Submit a new upload task using futures.
|
308
386
|
|
@@ -349,6 +427,7 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
|
|
349
427
|
dataset_name=dataset_name,
|
350
428
|
user_details=user_details,
|
351
429
|
base_url=base_url,
|
430
|
+
tracer_type = tracer_type,
|
352
431
|
timeout=timeout,
|
353
432
|
fail_on_trace_error=True
|
354
433
|
)
|
@@ -379,6 +458,7 @@ def submit_upload_task(filepath, hash_id, zip_path, project_name, project_id, da
|
|
379
458
|
dataset_name=dataset_name,
|
380
459
|
user_details=user_details,
|
381
460
|
base_url=base_url,
|
461
|
+
tracer_type=tracer_type,
|
382
462
|
timeout=timeout,
|
383
463
|
fail_on_trace_error=True
|
384
464
|
)
|
@@ -550,6 +630,14 @@ def shutdown(timeout=120):
|
|
550
630
|
|
551
631
|
_executor = None
|
552
632
|
|
633
|
+
# Close the session manager to clean up HTTP connections
|
634
|
+
if session_manager is not None:
|
635
|
+
try:
|
636
|
+
session_manager.close()
|
637
|
+
logger.info("Session manager closed successfully")
|
638
|
+
except Exception as e:
|
639
|
+
logger.error(f"Error closing session manager: {e}")
|
640
|
+
|
553
641
|
# Register shutdown handler
|
554
642
|
atexit.register(shutdown)
|
555
643
|
|
@@ -4,6 +4,10 @@ import os
|
|
4
4
|
import re
|
5
5
|
import time
|
6
6
|
from urllib.parse import urlparse, urlunparse
|
7
|
+
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
|
+
from requests.exceptions import ConnectionError, Timeout, RequestException
|
9
|
+
from http.client import RemoteDisconnected
|
10
|
+
from .session_manager import session_manager
|
7
11
|
|
8
12
|
import requests
|
9
13
|
|
@@ -48,7 +52,7 @@ class UploadAgenticTraces:
|
|
48
52
|
start_time = time.time()
|
49
53
|
endpoint = f"{self.base_url}/v1/llm/presigned-url"
|
50
54
|
# Changed to POST from GET
|
51
|
-
response =
|
55
|
+
response = session_manager.make_request_with_retry(
|
52
56
|
"POST", endpoint, headers=headers, data=payload, timeout=self.timeout
|
53
57
|
)
|
54
58
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -62,7 +66,7 @@ class UploadAgenticTraces:
|
|
62
66
|
return presignedurl
|
63
67
|
else:
|
64
68
|
# If POST fails, try GET
|
65
|
-
response =
|
69
|
+
response = session_manager.make_request_with_retry(
|
66
70
|
"GET", endpoint, headers=headers, data=payload, timeout=self.timeout
|
67
71
|
)
|
68
72
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -83,7 +87,7 @@ class UploadAgenticTraces:
|
|
83
87
|
"Authorization": f"Bearer {token}",
|
84
88
|
"X-Project-Name": self.project_name,
|
85
89
|
}
|
86
|
-
response =
|
90
|
+
response = session_manager.make_request_with_retry(
|
87
91
|
"POST",
|
88
92
|
endpoint,
|
89
93
|
headers=headers,
|
@@ -110,8 +114,10 @@ class UploadAgenticTraces:
|
|
110
114
|
f"Error while getting presigned url: {response.json()['message']}"
|
111
115
|
)
|
112
116
|
return None
|
113
|
-
|
114
|
-
|
117
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
118
|
+
session_manager.handle_request_exceptions(e, "getting presigned URL")
|
119
|
+
return None
|
120
|
+
except RequestException as e:
|
115
121
|
logger.error(f"Error while getting presigned url: {e}")
|
116
122
|
return None
|
117
123
|
|
@@ -138,16 +144,16 @@ class UploadAgenticTraces:
|
|
138
144
|
|
139
145
|
if "blob.core.windows.net" in presignedUrl: # Azure
|
140
146
|
headers["x-ms-blob-type"] = "BlockBlob"
|
141
|
-
|
147
|
+
logger.info("Uploading agentic traces to presigned URL...")
|
142
148
|
try:
|
143
149
|
with open(filename) as f:
|
144
150
|
payload = f.read().replace("\n", "").replace("\r", "").encode()
|
145
151
|
except Exception as e:
|
146
|
-
|
152
|
+
logger.error(f"Error while reading file: {e}")
|
147
153
|
return False
|
148
154
|
try:
|
149
155
|
start_time = time.time()
|
150
|
-
response =
|
156
|
+
response = session_manager.make_request_with_retry(
|
151
157
|
"PUT", presignedUrl, headers=headers, data=payload, timeout=self.timeout
|
152
158
|
)
|
153
159
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -157,8 +163,11 @@ class UploadAgenticTraces:
|
|
157
163
|
if response.status_code != 200 or response.status_code != 201:
|
158
164
|
return response, response.status_code
|
159
165
|
return True
|
160
|
-
except
|
161
|
-
|
166
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
167
|
+
session_manager.handle_request_exceptions(e, "uploading trace to presigned URL")
|
168
|
+
return False
|
169
|
+
except RequestException as e:
|
170
|
+
logger.error(f"Error while uploading trace to presigned url: {e}")
|
162
171
|
return False
|
163
172
|
|
164
173
|
def insert_traces(self, presignedUrl):
|
@@ -177,16 +186,16 @@ class UploadAgenticTraces:
|
|
177
186
|
try:
|
178
187
|
start_time = time.time()
|
179
188
|
endpoint = f"{self.base_url}/v1/llm/insert/trace"
|
180
|
-
response =
|
189
|
+
response = session_manager.make_request_with_retry(
|
181
190
|
"POST", endpoint, headers=headers, data=payload, timeout=self.timeout
|
182
191
|
)
|
183
192
|
elapsed_ms = (time.time() - start_time) * 1000
|
184
193
|
logger.debug(
|
185
194
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
186
195
|
)
|
187
|
-
if response.status_code
|
188
|
-
|
189
|
-
return
|
196
|
+
if response.status_code in [200, 201]:
|
197
|
+
logger.info(f"Traces inserted successfully: {response.json()['message']}")
|
198
|
+
return True
|
190
199
|
elif response.status_code == 401:
|
191
200
|
logger.warning("Received 401 error. Attempting to refresh token.")
|
192
201
|
token = RagaAICatalyst.get_token(force_refresh=True)
|
@@ -195,7 +204,7 @@ class UploadAgenticTraces:
|
|
195
204
|
"Content-Type": "application/json",
|
196
205
|
"X-Project-Name": self.project_name,
|
197
206
|
}
|
198
|
-
response =
|
207
|
+
response = session_manager.make_request_with_retry(
|
199
208
|
"POST",
|
200
209
|
endpoint,
|
201
210
|
headers=headers,
|
@@ -206,17 +215,21 @@ class UploadAgenticTraces:
|
|
206
215
|
logger.debug(
|
207
216
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
208
217
|
)
|
209
|
-
if response.status_code
|
210
|
-
|
211
|
-
return
|
218
|
+
if response.status_code in [200, 201]:
|
219
|
+
logger.info(f"Traces inserted successfully: {response.json()['message']}")
|
220
|
+
return True
|
212
221
|
else:
|
213
|
-
|
222
|
+
logger.error(f"Error while inserting traces after 401: {response.json()['message']}")
|
214
223
|
return False
|
215
224
|
else:
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
225
|
+
logger.error(f"Error while inserting traces: {response.json()['message']}")
|
226
|
+
return False
|
227
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
228
|
+
session_manager.handle_request_exceptions(e, "inserting traces")
|
229
|
+
return False
|
230
|
+
except RequestException as e:
|
231
|
+
logger.error(f"Error while inserting traces: {e}")
|
232
|
+
return False
|
220
233
|
|
221
234
|
def _get_dataset_spans(self):
|
222
235
|
try:
|
@@ -245,26 +258,26 @@ class UploadAgenticTraces:
|
|
245
258
|
continue
|
246
259
|
return dataset_spans
|
247
260
|
except Exception as e:
|
248
|
-
|
261
|
+
logger.error(f"Error while reading dataset spans: {e}")
|
249
262
|
return None
|
250
263
|
|
251
264
|
def upload_agentic_traces(self):
|
252
265
|
try:
|
253
266
|
presigned_url = self._get_presigned_url()
|
254
267
|
if presigned_url is None:
|
255
|
-
|
268
|
+
logger.warning("Warning: Failed to obtain presigned URL")
|
256
269
|
return False
|
257
270
|
|
258
271
|
# Upload the file using the presigned URL
|
259
272
|
upload_result = self._put_presigned_url(presigned_url, self.json_file_path)
|
260
273
|
if not upload_result:
|
261
|
-
|
274
|
+
logger.error("Error: Failed to upload file to presigned URL")
|
262
275
|
return False
|
263
276
|
elif isinstance(upload_result, tuple):
|
264
277
|
response, status_code = upload_result
|
265
278
|
if status_code not in [200, 201]:
|
266
|
-
|
267
|
-
f"Error:
|
279
|
+
logger.error(
|
280
|
+
f"Error: Uploading agentic traces failed with status code {status_code}: {response.text if hasattr(response, 'text') else 'Unknown error'}")
|
268
281
|
return False
|
269
282
|
# Insert trace records
|
270
283
|
insert_success = self.insert_traces(presigned_url)
|
@@ -272,13 +285,14 @@ class UploadAgenticTraces:
|
|
272
285
|
print("Error: Failed to insert trace records")
|
273
286
|
return False
|
274
287
|
|
275
|
-
|
288
|
+
logger.info("Successfully uploaded agentic traces")
|
276
289
|
return True
|
277
290
|
except FileNotFoundError:
|
278
|
-
|
291
|
+
logger.error(f"Error: Trace file not found at {self.json_file_path}")
|
279
292
|
return False
|
280
293
|
except ConnectionError as e:
|
281
|
-
|
294
|
+
logger.error(f"Error: Network connection failed while uploading traces: {e}")
|
282
295
|
return False
|
283
296
|
except Exception as e:
|
284
|
-
|
297
|
+
logger.error(f"Error while uploading agentic traces: {e}")
|
298
|
+
return False
|
@@ -1,15 +1,19 @@
|
|
1
|
-
import json
|
2
1
|
import logging
|
3
2
|
import os
|
4
3
|
import time
|
4
|
+
import re
|
5
|
+
import json
|
6
|
+
from urllib.parse import urlparse, urlunparse
|
7
|
+
from urllib3.exceptions import PoolError, MaxRetryError, NewConnectionError
|
8
|
+
from requests.exceptions import ConnectionError, Timeout, RequestException
|
9
|
+
from http.client import RemoteDisconnected
|
5
10
|
|
6
11
|
import requests
|
7
12
|
|
8
13
|
from ragaai_catalyst.ragaai_catalyst import RagaAICatalyst
|
14
|
+
from .session_manager import session_manager
|
9
15
|
|
10
16
|
logger = logging.getLogger(__name__)
|
11
|
-
import re
|
12
|
-
from urllib.parse import urlparse, urlunparse
|
13
17
|
|
14
18
|
|
15
19
|
def upload_code(
|
@@ -19,11 +23,26 @@ def upload_code(
|
|
19
23
|
project_name, dataset_name, base_url, timeout=timeout
|
20
24
|
)
|
21
25
|
|
26
|
+
# Handle None case during exceptions - do not proceed
|
27
|
+
if code_hashes_list is None:
|
28
|
+
logger.error("Failed to fetch existing code hashes, cannot proceed with upload")
|
29
|
+
return None
|
30
|
+
|
22
31
|
if hash_id not in code_hashes_list:
|
23
32
|
presigned_url = _fetch_presigned_url(
|
24
33
|
project_name, dataset_name, base_url, timeout=timeout
|
25
34
|
)
|
26
|
-
|
35
|
+
# Handle None case for presigned URL
|
36
|
+
if presigned_url is None:
|
37
|
+
logger.error("Failed to fetch presigned URL, cannot proceed with upload")
|
38
|
+
return None
|
39
|
+
|
40
|
+
upload_result = _put_zip_presigned_url(project_name, presigned_url, zip_path, timeout=timeout)
|
41
|
+
|
42
|
+
# Handle upload failure
|
43
|
+
if upload_result is False or (isinstance(upload_result, tuple) and upload_result[1] not in [200, 201]):
|
44
|
+
logger.error("Failed to upload zip file")
|
45
|
+
return None
|
27
46
|
|
28
47
|
response = _insert_code(
|
29
48
|
dataset_name,
|
@@ -33,6 +52,10 @@ def upload_code(
|
|
33
52
|
base_url,
|
34
53
|
timeout=timeout,
|
35
54
|
)
|
55
|
+
# Handle None response from insert_code
|
56
|
+
if response is None:
|
57
|
+
logger.error("Failed to insert code metadata")
|
58
|
+
return None
|
36
59
|
return response
|
37
60
|
else:
|
38
61
|
return "Code already exists"
|
@@ -49,7 +72,7 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
49
72
|
url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
|
50
73
|
start_time = time.time()
|
51
74
|
endpoint = f"{url_base}/v2/llm/dataset/code?datasetName={dataset_name}"
|
52
|
-
response =
|
75
|
+
response = session_manager.make_request_with_retry(
|
53
76
|
"GET", endpoint, headers=headers, data=payload, timeout=timeout
|
54
77
|
)
|
55
78
|
elapsed_ms = (time.time() - start_time) * 1000
|
@@ -57,7 +80,7 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
57
80
|
f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
58
81
|
)
|
59
82
|
|
60
|
-
if response.status_code
|
83
|
+
if response.status_code in [200, 201]:
|
61
84
|
return response.json()["data"]["codeHashes"]
|
62
85
|
elif response.status_code == 401:
|
63
86
|
logger.warning("Received 401 error. Attempting to refresh token.")
|
@@ -66,22 +89,25 @@ def _fetch_dataset_code_hashes(project_name, dataset_name, base_url=None, timeou
|
|
66
89
|
"Authorization": f"Bearer {os.getenv('RAGAAI_CATALYST_TOKEN')}",
|
67
90
|
"X-Project-Name": project_name,
|
68
91
|
}
|
69
|
-
response =
|
92
|
+
response = session_manager.make_request_with_retry(
|
70
93
|
"GET", endpoint, headers=headers, data=payload, timeout=timeout
|
71
94
|
)
|
72
95
|
elapsed_ms = (time.time() - start_time) * 1000
|
73
|
-
logger.debug(
|
74
|
-
|
75
|
-
)
|
76
|
-
if response.status_code == 200:
|
96
|
+
logger.debug(f"API Call: [GET] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms")
|
97
|
+
if response.status_code in [200, 201]:
|
77
98
|
return response.json()["data"]["codeHashes"]
|
78
99
|
else:
|
79
|
-
logger.error(
|
80
|
-
|
81
|
-
|
82
|
-
|
100
|
+
logger.error(f"Failed to fetch code hashes: {response.json()['message']}")
|
101
|
+
return None
|
102
|
+
else:
|
103
|
+
logger.error(f"Error while fetching dataset code hashes: {response.json()['message']}")
|
104
|
+
return None
|
105
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
106
|
+
session_manager.handle_request_exceptions(e, "fetching dataset code hashes")
|
107
|
+
return None
|
108
|
+
except RequestException as e:
|
83
109
|
logger.error(f"Failed to list datasets: {e}")
|
84
|
-
|
110
|
+
return None
|
85
111
|
|
86
112
|
|
87
113
|
def update_presigned_url(presigned_url, base_url):
|
@@ -156,7 +182,7 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
|
|
156
182
|
logger.debug(
|
157
183
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
158
184
|
)
|
159
|
-
if response.status_code
|
185
|
+
if response.status_code in [200, 201]:
|
160
186
|
presigned_url = response.json()["data"]["presignedUrls"][0]
|
161
187
|
presigned_url = update_presigned_url(presigned_url, url_base)
|
162
188
|
return presigned_url
|
@@ -168,9 +194,10 @@ def _fetch_presigned_url(project_name, dataset_name, base_url=None, timeout=120)
|
|
168
194
|
logger.error(
|
169
195
|
f"Failed to fetch code hashes: {response.json()['message']}"
|
170
196
|
)
|
197
|
+
return None
|
171
198
|
except requests.exceptions.RequestException as e:
|
172
199
|
logger.error(f"Failed to list datasets: {e}")
|
173
|
-
|
200
|
+
return None
|
174
201
|
|
175
202
|
|
176
203
|
def _put_zip_presigned_url(project_name, presignedUrl, filename, timeout=120):
|
@@ -181,21 +208,28 @@ def _put_zip_presigned_url(project_name, presignedUrl, filename, timeout=120):
|
|
181
208
|
|
182
209
|
if "blob.core.windows.net" in presignedUrl: # Azure
|
183
210
|
headers["x-ms-blob-type"] = "BlockBlob"
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
start_time = time.time()
|
189
|
-
response = requests.request(
|
190
|
-
"PUT", presignedUrl, headers=headers, data=payload, timeout=timeout
|
191
|
-
)
|
192
|
-
elapsed_ms = (time.time() - start_time) * 1000
|
193
|
-
logger.debug(
|
194
|
-
f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
195
|
-
)
|
196
|
-
if response.status_code != 200 or response.status_code != 201:
|
197
|
-
return response, response.status_code
|
211
|
+
logger.info("Uploading code to presigned URL...")
|
212
|
+
try:
|
213
|
+
with open(filename, "rb") as f:
|
214
|
+
payload = f.read()
|
198
215
|
|
216
|
+
start_time = time.time()
|
217
|
+
response = session_manager.make_request_with_retry(
|
218
|
+
"PUT", presignedUrl, headers=headers, data=payload, timeout=timeout
|
219
|
+
)
|
220
|
+
elapsed_ms = (time.time() - start_time) * 1000
|
221
|
+
logger.debug(
|
222
|
+
f"API Call: [PUT] {presignedUrl} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
223
|
+
)
|
224
|
+
if response.status_code not in [200, 201]:
|
225
|
+
return response, response.status_code
|
226
|
+
return True
|
227
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
228
|
+
session_manager.handle_request_exceptions(e, "uploading zip to presigned URL")
|
229
|
+
return False
|
230
|
+
except RequestException as e:
|
231
|
+
logger.error(f"Failed to upload zip: {e}")
|
232
|
+
return False
|
199
233
|
|
200
234
|
def _insert_code(
|
201
235
|
dataset_name, hash_id, presigned_url, project_name, base_url=None, timeout=120
|
@@ -218,39 +252,43 @@ def _insert_code(
|
|
218
252
|
url_base = base_url if base_url is not None else RagaAICatalyst.BASE_URL
|
219
253
|
start_time = time.time()
|
220
254
|
endpoint = f"{url_base}/v2/llm/dataset/code"
|
221
|
-
response =
|
255
|
+
response = session_manager.make_request_with_retry(
|
222
256
|
"POST", endpoint, headers=headers, data=payload, timeout=timeout
|
223
257
|
)
|
224
258
|
elapsed_ms = (time.time() - start_time) * 1000
|
225
259
|
logger.debug(
|
226
260
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
227
261
|
)
|
228
|
-
if response.status_code
|
262
|
+
if response.status_code in [200, 201]:
|
229
263
|
return response.json()["message"]
|
230
264
|
|
231
265
|
elif response.status_code == 401:
|
232
|
-
logger.warning("Received 401 error. Attempting to refresh token.")
|
266
|
+
logger.warning("Received 401 error during inserting code. Attempting to refresh token.")
|
233
267
|
token = RagaAICatalyst.get_token(force_refresh=True)
|
234
268
|
headers = {
|
235
269
|
"X-Project-Name": project_name,
|
236
270
|
"Content-Type": "application/json",
|
237
271
|
"Authorization": f"Bearer {token}",
|
238
272
|
}
|
239
|
-
response =
|
273
|
+
response = session_manager.make_request_with_retry(
|
240
274
|
"POST", endpoint, headers=headers, data=payload, timeout=timeout
|
241
275
|
)
|
242
276
|
elapsed_ms = (time.time() - start_time) * 1000
|
243
277
|
logger.debug(
|
244
278
|
f"API Call: [POST] {endpoint} | Status: {response.status_code} | Time: {elapsed_ms:.2f}ms"
|
245
279
|
)
|
246
|
-
if response.status_code
|
280
|
+
if response.status_code in [200, 201]:
|
281
|
+
logger.info(f"Code inserted successfully after 401: {response.json()['message']}")
|
247
282
|
return response.json()["message"]
|
248
283
|
else:
|
249
|
-
logger.error(f"Failed to insert code: {response.json()['message']}")
|
250
|
-
|
284
|
+
logger.error(f"Failed to insert code after 401: {response.json()['message']}")
|
285
|
+
return None
|
251
286
|
else:
|
252
287
|
logger.error(f"Failed to insert code: {response.json()['message']}")
|
253
|
-
|
254
|
-
except
|
288
|
+
return None
|
289
|
+
except (PoolError, MaxRetryError, NewConnectionError, ConnectionError, Timeout, RemoteDisconnected) as e:
|
290
|
+
session_manager.handle_request_exceptions(e, "inserting code")
|
291
|
+
return None
|
292
|
+
except RequestException as e:
|
255
293
|
logger.error(f"Failed to insert code: {e}")
|
256
|
-
|
294
|
+
return None
|
@@ -156,14 +156,14 @@ def convert_json_format(
|
|
156
156
|
|
157
157
|
# If prompt tokens or/and completion tokens are not present, will calculate it using tiktoken
|
158
158
|
try:
|
159
|
-
if prompt_tokens == 0:
|
159
|
+
if prompt_tokens == 0 and span["attributes"].get("openinference.span.kind") == "LLM" and span["status"].get("status_code") != "ERROR":
|
160
160
|
prompt_value = span["attributes"].get("input.value")
|
161
161
|
if prompt_value:
|
162
162
|
prompt_tokens = count_tokens(prompt_value)
|
163
163
|
logger.debug(
|
164
164
|
f"Prompt tokens not present, calculated it: {prompt_tokens}"
|
165
165
|
)
|
166
|
-
if completion_tokens == 0:
|
166
|
+
if completion_tokens == 0 and span["attributes"].get("openinference.span.kind") == "LLM" and span["status"].get("status_code") != "ERROR" :
|
167
167
|
completion_value = span["attributes"].get("output.value")
|
168
168
|
if completion_value:
|
169
169
|
completion_tokens = count_tokens(completion_value)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ragaai_catalyst
|
3
|
-
Version: 2.2.
|
3
|
+
Version: 2.2.4.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>, Rishabh Pandey <rishabh.pandey@raga.ai>, Jyotsana C G <jyotsana@raga.ai>
|
6
6
|
Requires-Python: <=3.13.2,>=3.10
|
@@ -54,9 +54,10 @@ ragaai_catalyst/tracers/agentic_tracing/tracers/network_tracer.py,sha256=m8CxYkl
|
|
54
54
|
ragaai_catalyst/tracers/agentic_tracing/tracers/tool_tracer.py,sha256=xxrliKPfdfbIZRZqMnUewsaTD8_Hv0dbuoBivNZGD4U,21674
|
55
55
|
ragaai_catalyst/tracers/agentic_tracing/tracers/user_interaction_tracer.py,sha256=bhSUhNQCuJXKjgJAXhjKEYjnHMpYN90FSZdR84fNIKU,4614
|
56
56
|
ragaai_catalyst/tracers/agentic_tracing/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
58
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
59
|
-
ragaai_catalyst/tracers/agentic_tracing/upload/
|
57
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/session_manager.py,sha256=sOlxeIYIP8tycaTtZC9xkZosi6EDJUxvDw0_rc_NLI8,6823
|
58
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/trace_uploader.py,sha256=Ujbu0KDl7oDr-cFtLwrQK_i7ghMuPV92mFnRfobJ1aI,24822
|
59
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_agentic_traces.py,sha256=0u4GWgqtaBz9cnr_KuqVIWDvhHWkgTAOTtiy0w8RPuk,13017
|
60
|
+
ragaai_catalyst/tracers/agentic_tracing/upload/upload_code.py,sha256=CbTx2vBAPIat5bdIClv9szOo4i33YL_1v04mkUjNG2c,12170
|
60
61
|
ragaai_catalyst/tracers/agentic_tracing/upload/upload_local_metric.py,sha256=m1O8lKpxKwtHofXLW3fTHX5yfqDW5GxoveARlg5cTw4,2571
|
61
62
|
ragaai_catalyst/tracers/agentic_tracing/utils/__init__.py,sha256=XdB3X_ufe4RVvGorxSqAiB9dYv4UD7Hvvuw3bsDUppY,60
|
62
63
|
ragaai_catalyst/tracers/agentic_tracing/utils/api_utils.py,sha256=ZduFA7MmTnWfQ2FzSD0hxMAAfNNTgBs4CXcHZdXJv6k,749
|
@@ -76,7 +77,7 @@ ragaai_catalyst/tracers/exporters/__init__.py,sha256=wQbaqyeIjVZxYprHCKZ9BeiqxeX
|
|
76
77
|
ragaai_catalyst/tracers/exporters/dynamic_trace_exporter.py,sha256=Rm-QaLv1qMAKpHKcFOcK_HWaKHwFBoUH45_4QYipE-g,6843
|
77
78
|
ragaai_catalyst/tracers/exporters/file_span_exporter.py,sha256=NZsD3rShUiC3rO9y3Y2vqEtS3MO51FXZy0p3q9cdDNY,6403
|
78
79
|
ragaai_catalyst/tracers/exporters/raga_exporter.py,sha256=l-RfysTIXYxtvYkVlJbRvg-AzJbT4Fdb-YiZh0mfuDs,17868
|
79
|
-
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=
|
80
|
+
ragaai_catalyst/tracers/exporters/ragaai_trace_exporter.py,sha256=VxO96ldBpG5mCncrN5mXErIZMlxQ1ewhNoMLfCrzegM,9025
|
80
81
|
ragaai_catalyst/tracers/instrumentators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
81
82
|
ragaai_catalyst/tracers/utils/__init__.py,sha256=KeMaZtYaTojilpLv65qH08QmpYclfpacDA0U3wg6Ybw,64
|
82
83
|
ragaai_catalyst/tracers/utils/convert_langchain_callbacks_output.py,sha256=SehrD7q8ytAiUYoWr406b4mWs3Lk0Rcy6Ekkihh22TI,1703
|
@@ -86,10 +87,10 @@ ragaai_catalyst/tracers/utils/langchain_tracer_extraction_logic.py,sha256=XS2_x2
|
|
86
87
|
ragaai_catalyst/tracers/utils/model_prices_and_context_window_backup.json,sha256=WlZCZeOQ54aMVjYS8BAeka2uaFC3ftBTMZ8zzzA8TAI,495947
|
87
88
|
ragaai_catalyst/tracers/utils/rag_extraction_logic_final.py,sha256=3ygkRT__lLDRflRttjzPu28tIA8cTCiGQVMQjqMItqQ,11309
|
88
89
|
ragaai_catalyst/tracers/utils/rag_trace_json_converter.py,sha256=54IEZO-YRjUAahV5nw8KClXqTF1LhfDry_TsZ4KGow4,20467
|
89
|
-
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256
|
90
|
+
ragaai_catalyst/tracers/utils/trace_json_converter.py,sha256=-HZVmijeUFLO7e9OAvi1RJdWVTxPRUHPd1MkKQlCD54,11785
|
90
91
|
ragaai_catalyst/tracers/utils/utils.py,sha256=o-p9n2ZuophdrV0wrixu-BqRHCkovup_klc3mS8mU8g,2374
|
91
|
-
ragaai_catalyst-2.2.
|
92
|
-
ragaai_catalyst-2.2.
|
93
|
-
ragaai_catalyst-2.2.
|
94
|
-
ragaai_catalyst-2.2.
|
95
|
-
ragaai_catalyst-2.2.
|
92
|
+
ragaai_catalyst-2.2.4.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
93
|
+
ragaai_catalyst-2.2.4.1.dist-info/METADATA,sha256=m3lK6boDHhoDHZhhrnIF1ZUsxzdoXQI8jgJxn2NxP_g,17679
|
94
|
+
ragaai_catalyst-2.2.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
95
|
+
ragaai_catalyst-2.2.4.1.dist-info/top_level.txt,sha256=HpgsdRgEJMk8nqrU6qdCYk3di7MJkDL0B19lkc7dLfM,16
|
96
|
+
ragaai_catalyst-2.2.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|