kalibr 1.2.1__py3-none-any.whl → 1.2.3__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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: kalibr
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Unified LLM Observability & Multi-Model AI Integration Framework - Deploy to GPT, Claude, Gemini, Copilot with full telemetry.
5
5
  Author-email: Kalibr Team <support@kalibr.systems>
6
6
  License: Apache-2.0
@@ -64,7 +64,6 @@ Requires-Dist: pytest>=7.4.0; extra == "dev"
64
64
  Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
65
65
  Requires-Dist: black>=23.0.0; extra == "dev"
66
66
  Requires-Dist: ruff>=0.1.0; extra == "dev"
67
- Dynamic: license-file
68
67
 
69
68
  # Kalibr Python SDK
70
69
 
@@ -33,17 +33,17 @@ kalibr/instrumentation/openai_instr.py,sha256=UU0Pi1Gq1FqgetYWDacQhNFdjemuPrc0hR
33
33
  kalibr/instrumentation/registry.py,sha256=sfQnXhbPOI5LVon2kFhe8KcXQwWmuKW1XUe50B2AaBc,4749
34
34
  kalibr/middleware/__init__.py,sha256=qyDUn_irAX67MS-IkuDVxg4RmFnJHDf_BfIT3qfGoBI,115
35
35
  kalibr/middleware/auto_tracer.py,sha256=ZBSBM0O3a6rwVzfik1n5NUmQDah8_iaf86rU64aPYT4,13037
36
- kalibr-1.2.1.dist-info/licenses/LICENSE,sha256=5mwAnB38l3_PjmOQn6_L6cZnJvus143DUjMBPIH1yso,10768
37
36
  kalibr_crewai/__init__.py,sha256=b0HFTiE80eArtSMBOIEKu1JM6KU0tCjEylKCVVVF29Q,1796
38
37
  kalibr_crewai/callbacks.py,sha256=_d1M4J-6XfKqrVIxnOgOQu57jpFKVv-VIsmPV0HNgZ4,20419
39
- kalibr_crewai/instrumentor.py,sha256=MbGELxjAQxy4o7BiNL8ik79avl0hXYxECvDzWi-fdsE,21993
38
+ kalibr_crewai/instrumentor.py,sha256=-G_-xaqE3Op70MSEIaZjPYioGDxKRagwLbZmcmmvzFg,26793
40
39
  kalibr_langchain/__init__.py,sha256=O4XYVyhLp1v-Y1kGZw3zD-tUK9wp0UX8Jt6oN0QTHN4,1373
41
40
  kalibr_langchain/async_callback.py,sha256=_Mj_YrKbULNtfxixZ7iwiHyWEV9l178ZA5Oy5A5Pakk,27748
42
41
  kalibr_langchain/callback.py,sha256=SNM1aHOXdG55grHmGyTwbXOeM6hjZTub2REiZD2H-d8,35216
43
42
  kalibr_openai_agents/__init__.py,sha256=wL59LzGstptKigfQDrKKt_7hcMO1JGVQtVAsE0lz-Zw,1367
44
43
  kalibr_openai_agents/processor.py,sha256=F550sdRf3rpguP1yOlgAUQWDLPBy4hSACV3-zOyCpOU,18257
45
- kalibr-1.2.1.dist-info/METADATA,sha256=sv6H2efZMRiHxGJZLnHtBaI6NurzfV7UFv62kQNRyV4,11223
46
- kalibr-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- kalibr-1.2.1.dist-info/entry_points.txt,sha256=Kojlc6WRX8V1qS9lOMdDPZpTUVHCtzGtHqXusErgmLY,47
48
- kalibr-1.2.1.dist-info/top_level.txt,sha256=dIfBOWUnnHGFDwgz5zfIx5_0bU3wOUgAbYr4JcFHZmo,59
49
- kalibr-1.2.1.dist-info/RECORD,,
44
+ kalibr-1.2.3.dist-info/LICENSE,sha256=5mwAnB38l3_PjmOQn6_L6cZnJvus143DUjMBPIH1yso,10768
45
+ kalibr-1.2.3.dist-info/METADATA,sha256=x6_p6pRthFdGcHYRMXeKCmf0WRwMU5xE9FT142ce4ts,11201
46
+ kalibr-1.2.3.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
47
+ kalibr-1.2.3.dist-info/entry_points.txt,sha256=Kojlc6WRX8V1qS9lOMdDPZpTUVHCtzGtHqXusErgmLY,47
48
+ kalibr-1.2.3.dist-info/top_level.txt,sha256=dIfBOWUnnHGFDwgz5zfIx5_0bU3wOUgAbYr4JcFHZmo,59
49
+ kalibr-1.2.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (76.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -12,6 +12,8 @@ from datetime import datetime, timezone
12
12
  from functools import wraps
13
13
  from typing import Any, Callable, Dict, List, Optional
14
14
 
15
+ from opentelemetry import trace as otel_trace
16
+
15
17
  from .callbacks import EventBatcher, _count_tokens, _get_provider_from_model
16
18
 
17
19
  # Import Kalibr cost adapters
@@ -150,6 +152,10 @@ class KalibrCrewAIInstrumentor:
150
152
  # Instrumentation state
151
153
  self._is_instrumented = False
152
154
 
155
+ # Accumulated metrics for crew-level aggregation
156
+ self._accumulated_tokens = {"input": 0, "output": 0}
157
+ self._accumulated_cost = 0.0
158
+
153
159
  def instrument(self) -> bool:
154
160
  """Instrument CrewAI classes.
155
161
 
@@ -236,11 +242,22 @@ class KalibrCrewAIInstrumentor:
236
242
  start_time = time.time()
237
243
  ts_start = datetime.now(timezone.utc)
238
244
 
245
+ # Reset accumulators before crew execution
246
+ instrumentor._accumulated_tokens = {"input": 0, "output": 0}
247
+ instrumentor._accumulated_cost = 0.0
248
+
239
249
  # Capture crew info
240
250
  crew_name = getattr(crew_self, "name", None) or "unnamed_crew"
241
- agent_count = len(getattr(crew_self, "agents", []))
251
+ agents = getattr(crew_self, "agents", [])
252
+ agent_count = len(agents)
242
253
  task_count = len(getattr(crew_self, "tasks", []))
243
254
 
255
+ # Extract model from first agent if available
256
+ model_name = "unknown"
257
+ provider = "crewai"
258
+ if agents:
259
+ model_name, provider = _extract_model_from_agent(agents[0])
260
+
244
261
  status = "success"
245
262
  error_type = None
246
263
  error_message = None
@@ -260,12 +277,33 @@ class KalibrCrewAIInstrumentor:
260
277
  duration_ms = int((time.time() - start_time) * 1000)
261
278
  ts_end = datetime.now(timezone.utc)
262
279
 
280
+ # Enrich CrewAI's OTel span with Kalibr telemetry
281
+ try:
282
+ current_span = otel_trace.get_current_span()
283
+ if current_span and current_span.is_recording():
284
+ current_span.set_attribute("kalibr.cost_usd", instrumentor._accumulated_cost)
285
+ current_span.set_attribute("kalibr.input_tokens", instrumentor._accumulated_tokens["input"])
286
+ current_span.set_attribute("kalibr.output_tokens", instrumentor._accumulated_tokens["output"])
287
+ current_span.set_attribute("kalibr.total_tokens", instrumentor._accumulated_tokens["input"] + instrumentor._accumulated_tokens["output"])
288
+ current_span.set_attribute("kalibr.model_id", model_name)
289
+ current_span.set_attribute("kalibr.provider", provider)
290
+ current_span.set_attribute("kalibr.duration_ms", duration_ms)
291
+ current_span.set_attribute("kalibr.tenant_id", instrumentor.tenant_id)
292
+ except Exception:
293
+ pass # Don't fail if span enrichment fails
294
+
263
295
  # Build output info
264
296
  output_preview = None
265
297
  if instrumentor.capture_output and result is not None:
266
298
  output_preview = str(result)[:500]
267
299
 
268
- # Create event
300
+ # Get accumulated metrics from child agent/task executions
301
+ input_tokens = instrumentor._accumulated_tokens["input"]
302
+ output_tokens = instrumentor._accumulated_tokens["output"]
303
+ total_tokens = input_tokens + output_tokens
304
+ cost_usd = instrumentor._accumulated_cost
305
+
306
+ # Create event with aggregated metrics
269
307
  event = {
270
308
  "schema_version": "1.0",
271
309
  "trace_id": trace_id,
@@ -273,18 +311,18 @@ class KalibrCrewAIInstrumentor:
273
311
  "parent_span_id": None,
274
312
  "tenant_id": instrumentor.tenant_id,
275
313
  "workflow_id": instrumentor.workflow_id,
276
- "provider": "crewai",
277
- "model_id": "crew",
278
- "model_name": crew_name,
314
+ "provider": provider,
315
+ "model_id": model_name,
316
+ "model_name": model_name,
279
317
  "operation": f"crew:{crew_name}",
280
318
  "endpoint": "crew.kickoff",
281
319
  "duration_ms": duration_ms,
282
320
  "latency_ms": duration_ms,
283
- "input_tokens": 0,
284
- "output_tokens": 0,
285
- "total_tokens": 0,
286
- "cost_usd": 0.0,
287
- "total_cost_usd": 0.0,
321
+ "input_tokens": input_tokens,
322
+ "output_tokens": output_tokens,
323
+ "total_tokens": total_tokens,
324
+ "cost_usd": cost_usd,
325
+ "total_cost_usd": cost_usd,
288
326
  "status": status,
289
327
  "error_type": error_type,
290
328
  "error_message": error_message,
@@ -321,10 +359,21 @@ class KalibrCrewAIInstrumentor:
321
359
  start_time = time.time()
322
360
  ts_start = datetime.now(timezone.utc)
323
361
 
362
+ # Reset accumulators before crew execution
363
+ instrumentor._accumulated_tokens = {"input": 0, "output": 0}
364
+ instrumentor._accumulated_cost = 0.0
365
+
324
366
  crew_name = getattr(crew_self, "name", None) or "unnamed_crew"
325
- agent_count = len(getattr(crew_self, "agents", []))
367
+ agents = getattr(crew_self, "agents", [])
368
+ agent_count = len(agents)
326
369
  task_count = len(getattr(crew_self, "tasks", []))
327
370
 
371
+ # Extract model from first agent if available
372
+ model_name = "unknown"
373
+ provider = "crewai"
374
+ if agents:
375
+ model_name, provider = _extract_model_from_agent(agents[0])
376
+
328
377
  status = "success"
329
378
  error_type = None
330
379
  error_message = None
@@ -344,10 +393,32 @@ class KalibrCrewAIInstrumentor:
344
393
  duration_ms = int((time.time() - start_time) * 1000)
345
394
  ts_end = datetime.now(timezone.utc)
346
395
 
396
+ # Enrich CrewAI's OTel span with Kalibr telemetry
397
+ try:
398
+ current_span = otel_trace.get_current_span()
399
+ if current_span and current_span.is_recording():
400
+ current_span.set_attribute("kalibr.cost_usd", instrumentor._accumulated_cost)
401
+ current_span.set_attribute("kalibr.input_tokens", instrumentor._accumulated_tokens["input"])
402
+ current_span.set_attribute("kalibr.output_tokens", instrumentor._accumulated_tokens["output"])
403
+ current_span.set_attribute("kalibr.total_tokens", instrumentor._accumulated_tokens["input"] + instrumentor._accumulated_tokens["output"])
404
+ current_span.set_attribute("kalibr.model_id", model_name)
405
+ current_span.set_attribute("kalibr.provider", provider)
406
+ current_span.set_attribute("kalibr.duration_ms", duration_ms)
407
+ current_span.set_attribute("kalibr.tenant_id", instrumentor.tenant_id)
408
+ except Exception:
409
+ pass # Don't fail if span enrichment fails
410
+
347
411
  output_preview = None
348
412
  if instrumentor.capture_output and result is not None:
349
413
  output_preview = str(result)[:500]
350
414
 
415
+ # Get accumulated metrics from child agent/task executions
416
+ input_tokens = instrumentor._accumulated_tokens["input"]
417
+ output_tokens = instrumentor._accumulated_tokens["output"]
418
+ total_tokens = input_tokens + output_tokens
419
+ cost_usd = instrumentor._accumulated_cost
420
+
421
+ # Create event with aggregated metrics
351
422
  event = {
352
423
  "schema_version": "1.0",
353
424
  "trace_id": trace_id,
@@ -355,18 +426,18 @@ class KalibrCrewAIInstrumentor:
355
426
  "parent_span_id": None,
356
427
  "tenant_id": instrumentor.tenant_id,
357
428
  "workflow_id": instrumentor.workflow_id,
358
- "provider": "crewai",
359
- "model_id": "crew",
360
- "model_name": crew_name,
429
+ "provider": provider,
430
+ "model_id": model_name,
431
+ "model_name": model_name,
361
432
  "operation": f"crew:{crew_name}",
362
433
  "endpoint": "crew.kickoff_async",
363
434
  "duration_ms": duration_ms,
364
435
  "latency_ms": duration_ms,
365
- "input_tokens": 0,
366
- "output_tokens": 0,
367
- "total_tokens": 0,
368
- "cost_usd": 0.0,
369
- "total_cost_usd": 0.0,
436
+ "input_tokens": input_tokens,
437
+ "output_tokens": output_tokens,
438
+ "total_tokens": total_tokens,
439
+ "cost_usd": cost_usd,
440
+ "total_cost_usd": cost_usd,
370
441
  "status": status,
371
442
  "error_type": error_type,
372
443
  "error_message": error_message,
@@ -445,6 +516,11 @@ class KalibrCrewAIInstrumentor:
445
516
  # Calculate cost using CostAdapterFactory
446
517
  cost_usd = _calculate_cost(provider, model_name, input_tokens, output_tokens)
447
518
 
519
+ # Accumulate metrics for crew-level aggregation
520
+ instrumentor._accumulated_tokens["input"] += input_tokens
521
+ instrumentor._accumulated_tokens["output"] += output_tokens
522
+ instrumentor._accumulated_cost += cost_usd
523
+
448
524
  event = {
449
525
  "schema_version": "1.0",
450
526
  "trace_id": str(uuid.uuid4()), # TODO: Link to crew trace
@@ -541,6 +617,11 @@ class KalibrCrewAIInstrumentor:
541
617
  # Calculate cost using CostAdapterFactory
542
618
  cost_usd = _calculate_cost(provider, model_name, input_tokens, output_tokens)
543
619
 
620
+ # Accumulate metrics for crew-level aggregation
621
+ instrumentor._accumulated_tokens["input"] += input_tokens
622
+ instrumentor._accumulated_tokens["output"] += output_tokens
623
+ instrumentor._accumulated_cost += cost_usd
624
+
544
625
  event = {
545
626
  "schema_version": "1.0",
546
627
  "trace_id": str(uuid.uuid4()),