kalibr 1.0.25__py3-none-any.whl → 1.1.2a0__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.
- kalibr/__init__.py +170 -3
- kalibr/__main__.py +3 -203
- kalibr/capsule_middleware.py +108 -0
- kalibr/cli/__init__.py +5 -0
- kalibr/cli/capsule_cmd.py +174 -0
- kalibr/cli/deploy_cmd.py +114 -0
- kalibr/cli/main.py +67 -0
- kalibr/cli/run.py +203 -0
- kalibr/cli/serve.py +59 -0
- kalibr/client.py +293 -0
- kalibr/collector.py +173 -0
- kalibr/context.py +132 -0
- kalibr/cost_adapter.py +222 -0
- kalibr/decorators.py +140 -0
- kalibr/instrumentation/__init__.py +13 -0
- kalibr/instrumentation/anthropic_instr.py +282 -0
- kalibr/instrumentation/base.py +108 -0
- kalibr/instrumentation/google_instr.py +281 -0
- kalibr/instrumentation/openai_instr.py +265 -0
- kalibr/instrumentation/registry.py +153 -0
- kalibr/kalibr.py +144 -230
- kalibr/kalibr_app.py +53 -314
- kalibr/middleware/__init__.py +5 -0
- kalibr/middleware/auto_tracer.py +356 -0
- kalibr/models.py +41 -0
- kalibr/redaction.py +44 -0
- kalibr/schemas.py +116 -0
- kalibr/simple_tracer.py +258 -0
- kalibr/tokens.py +52 -0
- kalibr/trace_capsule.py +296 -0
- kalibr/trace_models.py +201 -0
- kalibr/tracer.py +354 -0
- kalibr/types.py +25 -93
- kalibr/utils.py +198 -0
- kalibr-1.1.2a0.dist-info/METADATA +236 -0
- kalibr-1.1.2a0.dist-info/RECORD +48 -0
- kalibr-1.1.2a0.dist-info/entry_points.txt +2 -0
- kalibr-1.1.2a0.dist-info/licenses/LICENSE +21 -0
- kalibr-1.1.2a0.dist-info/top_level.txt +4 -0
- kalibr_crewai/__init__.py +65 -0
- kalibr_crewai/callbacks.py +539 -0
- kalibr_crewai/instrumentor.py +513 -0
- kalibr_langchain/__init__.py +47 -0
- kalibr_langchain/async_callback.py +850 -0
- kalibr_langchain/callback.py +1064 -0
- kalibr_openai_agents/__init__.py +43 -0
- kalibr_openai_agents/processor.py +554 -0
- kalibr/deployment.py +0 -41
- kalibr/packager.py +0 -43
- kalibr/runtime_router.py +0 -138
- kalibr/schema_generators.py +0 -159
- kalibr/validator.py +0 -70
- kalibr-1.0.25.data/data/examples/README.md +0 -173
- kalibr-1.0.25.data/data/examples/basic_kalibr_example.py +0 -66
- kalibr-1.0.25.data/data/examples/enhanced_kalibr_example.py +0 -347
- kalibr-1.0.25.dist-info/METADATA +0 -231
- kalibr-1.0.25.dist-info/RECORD +0 -19
- kalibr-1.0.25.dist-info/entry_points.txt +0 -2
- kalibr-1.0.25.dist-info/licenses/LICENSE +0 -11
- kalibr-1.0.25.dist-info/top_level.txt +0 -1
- {kalibr-1.0.25.dist-info → kalibr-1.1.2a0.dist-info}/WHEEL +0 -0
kalibr/utils.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Utility functions for Kalibr SDK.
|
|
2
|
+
|
|
3
|
+
Helper functions for:
|
|
4
|
+
- Environment configuration
|
|
5
|
+
- Event validation
|
|
6
|
+
- JSON serialization
|
|
7
|
+
- Logging
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from datetime import date, datetime, time
|
|
13
|
+
from typing import Any, Dict, Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_config_from_env() -> Dict[str, str]:
|
|
17
|
+
"""Load Kalibr configuration from environment variables.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Configuration dict with keys:
|
|
21
|
+
- clickhouse_url: ClickHouse connection URL
|
|
22
|
+
- project_name: Project/service name
|
|
23
|
+
- auth_token: API authentication token
|
|
24
|
+
- environment: Environment (prod/staging/dev)
|
|
25
|
+
- tenant_id: Tenant identifier
|
|
26
|
+
- workflow_id: Workflow identifier
|
|
27
|
+
- sandbox_id: Sandbox/VM identifier
|
|
28
|
+
- runtime_env: Runtime environment
|
|
29
|
+
- collector_url: Collector endpoint URL
|
|
30
|
+
"""
|
|
31
|
+
config = {
|
|
32
|
+
"clickhouse_url": os.getenv("CLICKHOUSE_URL", "http://localhost:8123"),
|
|
33
|
+
"project_name": os.getenv("KALIBR_PROJECT_NAME", "kalibr-app"),
|
|
34
|
+
"auth_token": os.getenv("KALIBR_AUTH_TOKEN", ""),
|
|
35
|
+
"api_key": os.getenv("KALIBR_API_KEY", ""),
|
|
36
|
+
"environment": os.getenv("KALIBR_ENVIRONMENT", "prod"),
|
|
37
|
+
"tenant_id": os.getenv("KALIBR_TENANT_ID", "default"),
|
|
38
|
+
"workflow_id": os.getenv("KALIBR_WORKFLOW_ID", "default-workflow"),
|
|
39
|
+
"sandbox_id": os.getenv("SANDBOX_ID", "local"),
|
|
40
|
+
"runtime_env": os.getenv("RUNTIME_ENV", "local"),
|
|
41
|
+
"api_endpoint": os.getenv("KALIBR_API_ENDPOINT", "http://localhost:8001/api/v1/traces"),
|
|
42
|
+
"collector_url": os.getenv("KALIBR_COLLECTOR_URL", "http://localhost:8080/api/ingest"),
|
|
43
|
+
}
|
|
44
|
+
return config
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def validate_event(event: Dict[str, Any]) -> bool:
|
|
48
|
+
"""Validate that event has required fields.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
event: Event dictionary
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
True if valid, False otherwise
|
|
55
|
+
"""
|
|
56
|
+
required_fields = [
|
|
57
|
+
"trace_id",
|
|
58
|
+
"span_id",
|
|
59
|
+
"timestamp",
|
|
60
|
+
"service",
|
|
61
|
+
"vendor",
|
|
62
|
+
"operation",
|
|
63
|
+
"latency_ms",
|
|
64
|
+
"status",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
for field in required_fields:
|
|
68
|
+
if field not in event:
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def serialize_event(event: Dict[str, Any]) -> str:
|
|
75
|
+
"""Serialize event to JSON string.
|
|
76
|
+
|
|
77
|
+
Handles special types like datetime, date, time.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
event: Event dictionary
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
JSON string
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def default_handler(obj):
|
|
87
|
+
"""Handle non-serializable types."""
|
|
88
|
+
if isinstance(obj, (datetime, date, time)):
|
|
89
|
+
return obj.isoformat()
|
|
90
|
+
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
|
|
91
|
+
|
|
92
|
+
return json.dumps(event, default=default_handler)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def safe_get_nested(data: Dict, keys: list, default: Any = None) -> Any:
|
|
96
|
+
"""Safely get nested dictionary value.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
data: Dictionary to query
|
|
100
|
+
keys: List of nested keys
|
|
101
|
+
default: Default value if key path doesn't exist
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Value at nested key path, or default
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
>>> data = {"a": {"b": {"c": 123}}}
|
|
108
|
+
>>> safe_get_nested(data, ["a", "b", "c"])
|
|
109
|
+
123
|
|
110
|
+
>>> safe_get_nested(data, ["a", "x", "y"], default=0)
|
|
111
|
+
0
|
|
112
|
+
"""
|
|
113
|
+
current = data
|
|
114
|
+
for key in keys:
|
|
115
|
+
if isinstance(current, dict) and key in current:
|
|
116
|
+
current = current[key]
|
|
117
|
+
else:
|
|
118
|
+
return default
|
|
119
|
+
return current
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def truncate_string(s: str, max_length: int = 1000) -> str:
|
|
123
|
+
"""Truncate string to max length with ellipsis.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
s: String to truncate
|
|
127
|
+
max_length: Maximum length
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Truncated string
|
|
131
|
+
"""
|
|
132
|
+
if len(s) <= max_length:
|
|
133
|
+
return s
|
|
134
|
+
return s[: max_length - 3] + "..."
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def format_cost(cost_usd: float) -> str:
|
|
138
|
+
"""Format cost in USD for display.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
cost_usd: Cost in USD
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Formatted string (e.g., "$0.0123")
|
|
145
|
+
"""
|
|
146
|
+
if cost_usd < 0.0001:
|
|
147
|
+
return "$0.0000"
|
|
148
|
+
elif cost_usd < 0.01:
|
|
149
|
+
return f"${cost_usd:.4f}"
|
|
150
|
+
elif cost_usd < 1.0:
|
|
151
|
+
return f"${cost_usd:.3f}"
|
|
152
|
+
else:
|
|
153
|
+
return f"${cost_usd:.2f}"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def format_latency(latency_ms: int) -> str:
|
|
157
|
+
"""Format latency for display.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
latency_ms: Latency in milliseconds
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Formatted string (e.g., "420ms" or "2.3s")
|
|
164
|
+
"""
|
|
165
|
+
if latency_ms < 1000:
|
|
166
|
+
return f"{latency_ms}ms"
|
|
167
|
+
else:
|
|
168
|
+
seconds = latency_ms / 1000
|
|
169
|
+
return f"{seconds:.1f}s"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def get_log_prefix() -> str:
|
|
173
|
+
"""Get log prefix for Kalibr SDK messages.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Log prefix string
|
|
177
|
+
"""
|
|
178
|
+
return "[Kalibr SDK]"
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def log_info(message: str):
|
|
182
|
+
"""Log info message."""
|
|
183
|
+
print(f"{get_log_prefix()} ℹ️ {message}")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def log_warning(message: str):
|
|
187
|
+
"""Log warning message."""
|
|
188
|
+
print(f"{get_log_prefix()} ⚠️ {message}")
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def log_error(message: str):
|
|
192
|
+
"""Log error message."""
|
|
193
|
+
print(f"{get_log_prefix()} ❌ {message}")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def log_success(message: str):
|
|
197
|
+
"""Log success message."""
|
|
198
|
+
print(f"{get_log_prefix()} ✅ {message}")
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kalibr
|
|
3
|
+
Version: 1.1.2a0
|
|
4
|
+
Summary: Unified LLM Observability & Multi-Model AI Integration Framework - Deploy to GPT, Claude, Gemini, Copilot with full telemetry
|
|
5
|
+
Author-email: Kalibr Team <team@kalibr.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kalibr-systems/kalibr-sdk-python
|
|
8
|
+
Project-URL: Documentation, https://docs.kalibr.systems
|
|
9
|
+
Project-URL: Repository, https://github.com/kalibr-systems/kalibr-sdk-python
|
|
10
|
+
Project-URL: Issues, https://github.com/kalibr-systems/kalibr-sdk-python/issues
|
|
11
|
+
Keywords: ai,mcp,gpt,claude,gemini,copilot,openai,anthropic,google,microsoft,observability,telemetry,tracing,llm,schema-generation,api,multi-model,langchain,crewai
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: httpx>=0.27.0
|
|
27
|
+
Requires-Dist: tiktoken>=0.8.0
|
|
28
|
+
Requires-Dist: fastapi>=0.110.1
|
|
29
|
+
Requires-Dist: uvicorn>=0.25.0
|
|
30
|
+
Requires-Dist: pydantic>=2.6.4
|
|
31
|
+
Requires-Dist: typer>=0.9.0
|
|
32
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
33
|
+
Requires-Dist: rich>=10.0.0
|
|
34
|
+
Requires-Dist: requests>=2.31.0
|
|
35
|
+
Requires-Dist: opentelemetry-api>=1.20.0
|
|
36
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0
|
|
37
|
+
Requires-Dist: opentelemetry-exporter-otlp>=1.20.0
|
|
38
|
+
Provides-Extra: langchain
|
|
39
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
|
|
40
|
+
Provides-Extra: langchain-openai
|
|
41
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain-openai"
|
|
42
|
+
Requires-Dist: langchain-openai>=0.1.0; extra == "langchain-openai"
|
|
43
|
+
Provides-Extra: langchain-anthropic
|
|
44
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain-anthropic"
|
|
45
|
+
Requires-Dist: langchain-anthropic>=0.1.0; extra == "langchain-anthropic"
|
|
46
|
+
Provides-Extra: langchain-google
|
|
47
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain-google"
|
|
48
|
+
Requires-Dist: langchain-google-genai>=0.0.10; extra == "langchain-google"
|
|
49
|
+
Provides-Extra: langchain-all
|
|
50
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "langchain-all"
|
|
51
|
+
Requires-Dist: langchain-openai>=0.1.0; extra == "langchain-all"
|
|
52
|
+
Requires-Dist: langchain-anthropic>=0.1.0; extra == "langchain-all"
|
|
53
|
+
Requires-Dist: langchain-google-genai>=0.0.10; extra == "langchain-all"
|
|
54
|
+
Provides-Extra: crewai
|
|
55
|
+
Requires-Dist: crewai>=0.28.0; extra == "crewai"
|
|
56
|
+
Provides-Extra: openai-agents
|
|
57
|
+
Requires-Dist: openai-agents>=0.0.3; extra == "openai-agents"
|
|
58
|
+
Provides-Extra: integrations
|
|
59
|
+
Requires-Dist: langchain-core>=0.1.0; extra == "integrations"
|
|
60
|
+
Requires-Dist: crewai>=0.28.0; extra == "integrations"
|
|
61
|
+
Requires-Dist: openai-agents>=0.0.3; extra == "integrations"
|
|
62
|
+
Provides-Extra: dev
|
|
63
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
64
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
65
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
66
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
67
|
+
Dynamic: license-file
|
|
68
|
+
|
|
69
|
+
# Kalibr Python SDK
|
|
70
|
+
|
|
71
|
+
Production-grade observability for LLM applications. Automatically instrument OpenAI, Anthropic, and Google AI SDKs with zero code changes.
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
- **Zero-code instrumentation** - Automatic tracing for OpenAI, Anthropic, and Google AI
|
|
76
|
+
- **Cost tracking** - Real-time cost calculation for all LLM calls
|
|
77
|
+
- **Token monitoring** - Track input/output tokens across providers
|
|
78
|
+
- **Parent-child traces** - Automatic trace relationship management
|
|
79
|
+
- **Multi-provider support** - Works with GPT-4, Claude, Gemini, and more
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install kalibr
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Quick Start
|
|
88
|
+
|
|
89
|
+
### Auto-instrumentation (Recommended)
|
|
90
|
+
|
|
91
|
+
Simply import `kalibr` at the start of your application - all LLM calls are automatically traced:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import kalibr # Enable auto-instrumentation
|
|
95
|
+
import openai
|
|
96
|
+
|
|
97
|
+
# Set your Kalibr API key
|
|
98
|
+
import os
|
|
99
|
+
os.environ["KALIBR_API_KEY"] = "your-kalibr-api-key"
|
|
100
|
+
|
|
101
|
+
# All OpenAI calls are now automatically traced
|
|
102
|
+
client = openai.OpenAI()
|
|
103
|
+
response = client.chat.completions.create(
|
|
104
|
+
model="gpt-4o",
|
|
105
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Manual Tracing with Decorator
|
|
110
|
+
|
|
111
|
+
For more control, use the `@trace` decorator:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from kalibr import trace
|
|
115
|
+
import openai
|
|
116
|
+
|
|
117
|
+
@trace(operation="summarize", provider="openai", model="gpt-4o")
|
|
118
|
+
def summarize_text(text: str) -> str:
|
|
119
|
+
client = openai.OpenAI()
|
|
120
|
+
response = client.chat.completions.create(
|
|
121
|
+
model="gpt-4o",
|
|
122
|
+
messages=[
|
|
123
|
+
{"role": "system", "content": "Summarize the following text."},
|
|
124
|
+
{"role": "user", "content": text}
|
|
125
|
+
]
|
|
126
|
+
)
|
|
127
|
+
return response.choices[0].message.content
|
|
128
|
+
|
|
129
|
+
result = summarize_text("Your long text here...")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Multi-Provider Example
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import kalibr
|
|
136
|
+
import openai
|
|
137
|
+
import anthropic
|
|
138
|
+
|
|
139
|
+
# OpenAI call - automatically traced
|
|
140
|
+
openai_client = openai.OpenAI()
|
|
141
|
+
gpt_response = openai_client.chat.completions.create(
|
|
142
|
+
model="gpt-4o",
|
|
143
|
+
messages=[{"role": "user", "content": "Explain quantum computing"}]
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Anthropic call - automatically traced
|
|
147
|
+
anthropic_client = anthropic.Anthropic()
|
|
148
|
+
claude_response = anthropic_client.messages.create(
|
|
149
|
+
model="claude-sonnet-4-20250514",
|
|
150
|
+
max_tokens=1024,
|
|
151
|
+
messages=[{"role": "user", "content": "Explain machine learning"}]
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Configuration
|
|
156
|
+
|
|
157
|
+
Configure the SDK using environment variables:
|
|
158
|
+
|
|
159
|
+
| Variable | Description | Default |
|
|
160
|
+
|----------|-------------|---------|
|
|
161
|
+
| `KALIBR_API_KEY` | API key for authentication | *Required* |
|
|
162
|
+
| `KALIBR_COLLECTOR_URL` | Collector endpoint URL | `http://localhost:8001/api/ingest` |
|
|
163
|
+
| `KALIBR_TENANT_ID` | Tenant identifier for multi-tenant setups | `default` |
|
|
164
|
+
| `KALIBR_WORKFLOW_ID` | Workflow identifier for grouping traces | `default` |
|
|
165
|
+
| `KALIBR_SERVICE_NAME` | Service name for OpenTelemetry spans | `kalibr-app` |
|
|
166
|
+
| `KALIBR_ENVIRONMENT` | Environment (prod, staging, dev) | `prod` |
|
|
167
|
+
| `KALIBR_AUTO_INSTRUMENT` | Enable/disable auto-instrumentation | `true` |
|
|
168
|
+
| `KALIBR_CONSOLE_EXPORT` | Enable console span export for debugging | `false` |
|
|
169
|
+
|
|
170
|
+
## CLI Tools
|
|
171
|
+
|
|
172
|
+
The SDK includes command-line tools for running and deploying applications:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Run your app locally with tracing
|
|
176
|
+
kalibr serve myapp.py
|
|
177
|
+
|
|
178
|
+
# Run with managed runtime lifecycle
|
|
179
|
+
kalibr run myapp.py --port 8000
|
|
180
|
+
|
|
181
|
+
# Deploy to cloud platforms
|
|
182
|
+
kalibr deploy myapp.py --runtime fly.io
|
|
183
|
+
|
|
184
|
+
# Fetch trace data by ID
|
|
185
|
+
kalibr capsule <trace-id>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Supported Providers
|
|
189
|
+
|
|
190
|
+
| Provider | Models | Auto-Instrumentation |
|
|
191
|
+
|----------|--------|---------------------|
|
|
192
|
+
| OpenAI | GPT-4, GPT-4o, GPT-3.5 | Yes |
|
|
193
|
+
| Anthropic | Claude 3 Opus, Sonnet, Haiku | Yes |
|
|
194
|
+
| Google | Gemini Pro, Gemini Flash | Yes |
|
|
195
|
+
|
|
196
|
+
## Examples
|
|
197
|
+
|
|
198
|
+
See the [`examples/`](./examples) directory for complete examples:
|
|
199
|
+
|
|
200
|
+
- `basic_example.py` - Simple tracing example
|
|
201
|
+
- `basic_agent.py` - Agent with auto-instrumentation
|
|
202
|
+
- `advanced_example.py` - Advanced tracing patterns
|
|
203
|
+
- `cross_vendor.py` - Multi-provider workflows
|
|
204
|
+
- `test_mas.py` - Multi-agent system demonstration
|
|
205
|
+
|
|
206
|
+
## Development
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Clone the repository
|
|
210
|
+
git clone https://github.com/kalibr-systems/kalibr-sdk-python.git
|
|
211
|
+
cd kalibr-sdk-python
|
|
212
|
+
|
|
213
|
+
# Install in development mode
|
|
214
|
+
pip install -e ".[dev]"
|
|
215
|
+
|
|
216
|
+
# Run tests
|
|
217
|
+
pytest
|
|
218
|
+
|
|
219
|
+
# Format code
|
|
220
|
+
black kalibr/
|
|
221
|
+
ruff check kalibr/
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Contributing
|
|
225
|
+
|
|
226
|
+
We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
MIT License - see [LICENSE](./LICENSE) for details.
|
|
231
|
+
|
|
232
|
+
## Links
|
|
233
|
+
|
|
234
|
+
- [Documentation](https://docs.kalibr.systems)
|
|
235
|
+
- [GitHub Issues](https://github.com/kalibr-systems/kalibr-sdk-python/issues)
|
|
236
|
+
- [PyPI Package](https://pypi.org/project/kalibr/)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
kalibr/__init__.py,sha256=V65LyTow2l1RHR7RVDclJ6kWYypmleu3K1hV-shz7g0,5912
|
|
2
|
+
kalibr/__main__.py,sha256=jO96I4pqinwHg7ONRvNVKbySBh5pSIhOAiNrgSQrNlY,110
|
|
3
|
+
kalibr/capsule_middleware.py,sha256=pXG_wORgCqo3wHjtkn_zY4doLyiDmTwJtB7XiZNnbPk,3163
|
|
4
|
+
kalibr/client.py,sha256=t6_vZn_juHrsCg-7QFrkl-pzlqV7ZesQLCh8fnF808Q,9727
|
|
5
|
+
kalibr/collector.py,sha256=rtTKQLe6NkDSblBIfFooQ-ESFcP0Q1HUp4Bcqqg8JFo,5818
|
|
6
|
+
kalibr/context.py,sha256=hBxWXZx0gcmeGqDMS1rstke_DmrujoRBIsfrG26WKUY,3755
|
|
7
|
+
kalibr/cost_adapter.py,sha256=NerJ7ywaJjBn97gVFr7qKX7318e3Kmy2qqeNlGl9nPE,6439
|
|
8
|
+
kalibr/decorators.py,sha256=m-XBXxWMDVrzaNsljACiGmeGhgiHj_MqSfj6OGK3L5I,4380
|
|
9
|
+
kalibr/kalibr.py,sha256=cNXC3W_TX5SvGsy1lRopkwFqsHOpyd1kkVjEMOz1Yr4,6084
|
|
10
|
+
kalibr/kalibr_app.py,sha256=ItZwEh0FZPx9_BE-zPQajC2yxI2y9IHYwJD0k9tbHvY,2773
|
|
11
|
+
kalibr/models.py,sha256=HwD_-iysZMSnCzMQYO1Qcf0aeXySupY7yJeBwl_dLS0,1024
|
|
12
|
+
kalibr/redaction.py,sha256=XibxX4Lv1Ci0opE6Tb5ZI2GLbO0a8E9U66MAg60llnc,1139
|
|
13
|
+
kalibr/schemas.py,sha256=XLZNLkXca6jbj9AF6gDIyGVnIcr1SVOsNYaKvW-wbgE,3669
|
|
14
|
+
kalibr/simple_tracer.py,sha256=XwVI7h25vUok7I3AIiFm1TGBvDM--lzl-xAhTiv7d4o,9775
|
|
15
|
+
kalibr/tokens.py,sha256=istjgaxi9S4dMddjuGtoQaTnZYcWLCqdnxRjV86yNXA,1297
|
|
16
|
+
kalibr/trace_capsule.py,sha256=CPMUz5D-fVfao-MozNtSDbgOQKdDAJxTN5KQL6w2Xp8,10154
|
|
17
|
+
kalibr/trace_models.py,sha256=9o7VJQk3gCrvdfXPrNh3Ptkq5sRgA9_qrLLE3jNkSBg,7304
|
|
18
|
+
kalibr/tracer.py,sha256=jwWBpZbGXn6fEv4pw25BLFCH-22QUbyzofPWp1Iwdkk,11911
|
|
19
|
+
kalibr/types.py,sha256=cna4-akpdwfHXfOJCtVIq5lO_jaoG2Am3BRrXi0Vo34,895
|
|
20
|
+
kalibr/utils.py,sha256=IbAgw-Bwxdy9Kc0fm2yIDt2RxWU0gRCzffuz3GRUSnE,5042
|
|
21
|
+
kalibr/cli/__init__.py,sha256=FmRGaDMhM9DhrKg1ONkF0emIrJcjFWjlFBl_oenvpsk,77
|
|
22
|
+
kalibr/cli/capsule_cmd.py,sha256=htxUtRpos_dLs-LnJm6WeGtLYCCc1h7H3WXz7i6DVWc,6082
|
|
23
|
+
kalibr/cli/deploy_cmd.py,sha256=kV4uqCN2IdQev1vPBY5qqIHsEhjGBZ7y_rLx8RGAL_4,5178
|
|
24
|
+
kalibr/cli/main.py,sha256=Ob0Vpg8KPnHluP_23pgbEZpDb_iKnjoN7mW52-2Qr44,1939
|
|
25
|
+
kalibr/cli/run.py,sha256=T3oQ0aSfBMyOlwjJ8hGojmkrAr6EuzpzPXDUNK4amW0,6423
|
|
26
|
+
kalibr/cli/serve.py,sha256=71Xha35qrBNkcQxuUkwC-ixbOriHGUIEgxl7C_qERQo,2085
|
|
27
|
+
kalibr/instrumentation/__init__.py,sha256=YnUJ4gUH8WNxdVv5t1amn0l2WUULJG2MuQIL2ZZhn04,354
|
|
28
|
+
kalibr/instrumentation/anthropic_instr.py,sha256=ozXHr8BPMafIbvgaxunskQi9YX5_Gpoiekye77oRc2E,10058
|
|
29
|
+
kalibr/instrumentation/base.py,sha256=eMFBTIQXtG2bZD5st6vzN72ooeHCANZ3SapYzrdijgk,3109
|
|
30
|
+
kalibr/instrumentation/google_instr.py,sha256=f2um7MB2QCT2u9CFV4-vKke-8M0dSXSpZHTcbdxMZyI,10476
|
|
31
|
+
kalibr/instrumentation/openai_instr.py,sha256=UU0Pi1Gq1FqgetYWDacQhNFdjemuPrc0hRTKd-LIDHI,9250
|
|
32
|
+
kalibr/instrumentation/registry.py,sha256=sfQnXhbPOI5LVon2kFhe8KcXQwWmuKW1XUe50B2AaBc,4749
|
|
33
|
+
kalibr/middleware/__init__.py,sha256=qyDUn_irAX67MS-IkuDVxg4RmFnJHDf_BfIT3qfGoBI,115
|
|
34
|
+
kalibr/middleware/auto_tracer.py,sha256=oevrhWBAM4el_F5jFc28ZBFLEklx7XGd40dNFe5VQ8Q,13032
|
|
35
|
+
kalibr-1.1.2a0.dist-info/licenses/LICENSE,sha256=BYlEPoDdYD3iHuAjt2JYGoxDYQaI1gxab2pR4acoz04,1063
|
|
36
|
+
kalibr_crewai/__init__.py,sha256=ClbyRwZ9K3VabYg3RnjnCNQtv1z7UNyCAlMSo0tCGYQ,1791
|
|
37
|
+
kalibr_crewai/callbacks.py,sha256=jP-eJcLzk9gpdG5uDwn_XVhZbUUV8GtUQc3qHSgpm3A,17152
|
|
38
|
+
kalibr_crewai/instrumentor.py,sha256=IbKVTlxrZhFP8ykqyS4w7RfS3zGMA1K80dEUGaWBlNg,19460
|
|
39
|
+
kalibr_langchain/__init__.py,sha256=BPj6JZgWDh3wNQCnIfdC24gupzBjVPxbq3zBsfn7yCY,1368
|
|
40
|
+
kalibr_langchain/async_callback.py,sha256=sAJIhysNGDz53R5ueoNmgElfSr8_V97eW-0-8dVaqik,27743
|
|
41
|
+
kalibr_langchain/callback.py,sha256=NW6pWtd9j9RBSN4v69Rhmo6RN1lsYYo_QTPYz7HJ65c,34260
|
|
42
|
+
kalibr_openai_agents/__init__.py,sha256=ToKJ1Krwc38ADZO0HCWo1_ZMGi4VRIEgym2Avkg0CyQ,1362
|
|
43
|
+
kalibr_openai_agents/processor.py,sha256=CT7llzbljrIYeVbUWM9N5yXCnPJMujB_AmhA__Xte9Q,18252
|
|
44
|
+
kalibr-1.1.2a0.dist-info/METADATA,sha256=W7T3HAPs441LUIdTINo20KTQNAFUHYwRoPSjCnLVqFg,7864
|
|
45
|
+
kalibr-1.1.2a0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
46
|
+
kalibr-1.1.2a0.dist-info/entry_points.txt,sha256=Kojlc6WRX8V1qS9lOMdDPZpTUVHCtzGtHqXusErgmLY,47
|
|
47
|
+
kalibr-1.1.2a0.dist-info/top_level.txt,sha256=dIfBOWUnnHGFDwgz5zfIx5_0bU3wOUgAbYr4JcFHZmo,59
|
|
48
|
+
kalibr-1.1.2a0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kalibr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Kalibr CrewAI Integration - Observability for CrewAI applications.
|
|
2
|
+
|
|
3
|
+
This package provides callbacks and auto-instrumentation for CrewAI,
|
|
4
|
+
capturing:
|
|
5
|
+
- Agent step execution with tool calls
|
|
6
|
+
- Task completion with outputs
|
|
7
|
+
- Crew execution lifecycle
|
|
8
|
+
- Token usage and costs
|
|
9
|
+
- Error tracking
|
|
10
|
+
|
|
11
|
+
Usage with Callbacks:
|
|
12
|
+
from kalibr_crewai import KalibrAgentCallback, KalibrTaskCallback
|
|
13
|
+
from crewai import Agent, Task, Crew
|
|
14
|
+
|
|
15
|
+
# Create callbacks
|
|
16
|
+
agent_callback = KalibrAgentCallback(tenant_id="my-tenant")
|
|
17
|
+
task_callback = KalibrTaskCallback(tenant_id="my-tenant")
|
|
18
|
+
|
|
19
|
+
# Use with Agent
|
|
20
|
+
agent = Agent(
|
|
21
|
+
role="Researcher",
|
|
22
|
+
goal="Find information",
|
|
23
|
+
step_callback=agent_callback,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Use with Task
|
|
27
|
+
task = Task(
|
|
28
|
+
description="Research AI trends",
|
|
29
|
+
agent=agent,
|
|
30
|
+
callback=task_callback,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
Usage with Auto-Instrumentation:
|
|
34
|
+
from kalibr_crewai import KalibrCrewAIInstrumentor
|
|
35
|
+
|
|
36
|
+
# Instrument CrewAI (call before creating crews)
|
|
37
|
+
instrumentor = KalibrCrewAIInstrumentor(tenant_id="my-tenant")
|
|
38
|
+
instrumentor.instrument()
|
|
39
|
+
|
|
40
|
+
# Now all CrewAI operations are automatically traced
|
|
41
|
+
crew = Crew(agents=[...], tasks=[...])
|
|
42
|
+
result = crew.kickoff()
|
|
43
|
+
|
|
44
|
+
# Optionally uninstrument
|
|
45
|
+
instrumentor.uninstrument()
|
|
46
|
+
|
|
47
|
+
Environment Variables:
|
|
48
|
+
KALIBR_API_KEY: API key for authentication
|
|
49
|
+
KALIBR_ENDPOINT: Backend endpoint URL
|
|
50
|
+
KALIBR_TENANT_ID: Tenant identifier
|
|
51
|
+
KALIBR_ENVIRONMENT: Environment (prod/staging/dev)
|
|
52
|
+
KALIBR_SERVICE: Service name
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
__version__ = "0.1.0"
|
|
56
|
+
|
|
57
|
+
from .callbacks import KalibrAgentCallback, KalibrTaskCallback
|
|
58
|
+
from .instrumentor import KalibrCrewAIInstrumentor
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"KalibrAgentCallback",
|
|
62
|
+
"KalibrTaskCallback",
|
|
63
|
+
"KalibrCrewAIInstrumentor",
|
|
64
|
+
"__version__",
|
|
65
|
+
]
|