kalibr 1.1.3a0__py3-none-any.whl → 1.2.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.
- kalibr/__init__.py +39 -3
- kalibr/cli/capsule_cmd.py +1 -1
- kalibr/cli/main.py +3 -3
- kalibr/cli/run.py +1 -1
- kalibr/context.py +42 -0
- kalibr/intelligence.py +650 -0
- kalibr-1.2.1.dist-info/METADATA +385 -0
- {kalibr-1.1.3a0.dist-info → kalibr-1.2.1.dist-info}/RECORD +18 -17
- kalibr-1.2.1.dist-info/licenses/LICENSE +190 -0
- kalibr_crewai/__init__.py +1 -1
- kalibr_crewai/callbacks.py +122 -14
- kalibr_crewai/instrumentor.py +96 -14
- kalibr_langchain/__init__.py +1 -1
- kalibr_langchain/callback.py +26 -0
- kalibr_openai_agents/__init__.py +1 -1
- kalibr-1.1.3a0.dist-info/METADATA +0 -236
- kalibr-1.1.3a0.dist-info/licenses/LICENSE +0 -21
- {kalibr-1.1.3a0.dist-info → kalibr-1.2.1.dist-info}/WHEEL +0 -0
- {kalibr-1.1.3a0.dist-info → kalibr-1.2.1.dist-info}/entry_points.txt +0 -0
- {kalibr-1.1.3a0.dist-info → kalibr-1.2.1.dist-info}/top_level.txt +0 -0
kalibr/intelligence.py
ADDED
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
"""Kalibr Intelligence Client - Query execution intelligence and report outcomes.
|
|
2
|
+
|
|
3
|
+
This module enables the outcome-conditioned routing loop:
|
|
4
|
+
1. Before executing: query get_policy() to get the best path for your goal
|
|
5
|
+
2. After executing: call report_outcome() to teach Kalibr what worked
|
|
6
|
+
|
|
7
|
+
Example - Policy-based routing:
|
|
8
|
+
from kalibr import get_policy, report_outcome
|
|
9
|
+
|
|
10
|
+
# Before executing - get best path
|
|
11
|
+
policy = get_policy(goal="book_meeting")
|
|
12
|
+
model = policy["recommended_model"] # Use this model
|
|
13
|
+
|
|
14
|
+
# After executing - report what happened
|
|
15
|
+
report_outcome(
|
|
16
|
+
trace_id=trace_id,
|
|
17
|
+
goal="book_meeting",
|
|
18
|
+
success=True
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
Example - Path registration and intelligent routing:
|
|
22
|
+
from kalibr import register_path, decide
|
|
23
|
+
|
|
24
|
+
# Register paths for a goal
|
|
25
|
+
register_path(goal="book_meeting", model_id="gpt-4", tool_id="calendar_tool")
|
|
26
|
+
register_path(goal="book_meeting", model_id="claude-3-opus")
|
|
27
|
+
|
|
28
|
+
# Get intelligent routing decision
|
|
29
|
+
decision = decide(goal="book_meeting")
|
|
30
|
+
model = decision["model_id"] # Selected based on outcomes
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import os
|
|
36
|
+
from typing import Any, Optional
|
|
37
|
+
|
|
38
|
+
import httpx
|
|
39
|
+
|
|
40
|
+
# Default intelligence API endpoint
|
|
41
|
+
DEFAULT_INTELLIGENCE_URL = "https://kalibr-intelligence.fly.dev"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class KalibrIntelligence:
|
|
45
|
+
"""Client for Kalibr Intelligence API.
|
|
46
|
+
|
|
47
|
+
Provides methods to query execution policies and report outcomes
|
|
48
|
+
for the outcome-conditioned routing loop.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
api_key: Kalibr API key (or set KALIBR_API_KEY env var)
|
|
52
|
+
tenant_id: Tenant identifier (or set KALIBR_TENANT_ID env var)
|
|
53
|
+
base_url: Intelligence API base URL (or set KALIBR_INTELLIGENCE_URL env var)
|
|
54
|
+
timeout: Request timeout in seconds
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
api_key: str | None = None,
|
|
60
|
+
tenant_id: str | None = None,
|
|
61
|
+
base_url: str | None = None,
|
|
62
|
+
timeout: float = 10.0,
|
|
63
|
+
):
|
|
64
|
+
self.api_key = api_key or os.getenv("KALIBR_API_KEY", "")
|
|
65
|
+
self.tenant_id = tenant_id or os.getenv("KALIBR_TENANT_ID", "")
|
|
66
|
+
self.base_url = (
|
|
67
|
+
base_url
|
|
68
|
+
or os.getenv("KALIBR_INTELLIGENCE_URL", DEFAULT_INTELLIGENCE_URL)
|
|
69
|
+
).rstrip("/")
|
|
70
|
+
self.timeout = timeout
|
|
71
|
+
self._client = httpx.Client(timeout=timeout)
|
|
72
|
+
|
|
73
|
+
def _request(
|
|
74
|
+
self,
|
|
75
|
+
method: str,
|
|
76
|
+
path: str,
|
|
77
|
+
json: dict | None = None,
|
|
78
|
+
params: dict | None = None,
|
|
79
|
+
) -> httpx.Response:
|
|
80
|
+
"""Make authenticated request to intelligence API."""
|
|
81
|
+
headers = {
|
|
82
|
+
"X-API-Key": self.api_key,
|
|
83
|
+
"X-Tenant-ID": self.tenant_id,
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
url = f"{self.base_url}{path}"
|
|
88
|
+
response = self._client.request(method, url, json=json, params=params, headers=headers)
|
|
89
|
+
response.raise_for_status()
|
|
90
|
+
return response
|
|
91
|
+
|
|
92
|
+
def get_policy(
|
|
93
|
+
self,
|
|
94
|
+
goal: str,
|
|
95
|
+
task_type: str | None = None,
|
|
96
|
+
constraints: dict | None = None,
|
|
97
|
+
window_hours: int = 168,
|
|
98
|
+
) -> dict[str, Any]:
|
|
99
|
+
"""Get execution policy for a goal.
|
|
100
|
+
|
|
101
|
+
Returns the historically best-performing path for achieving
|
|
102
|
+
the specified goal, based on outcome data.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
goal: The goal to optimize for (e.g., "book_meeting", "resolve_ticket")
|
|
106
|
+
task_type: Optional task type filter (e.g., "code", "summarize")
|
|
107
|
+
constraints: Optional constraints dict with keys:
|
|
108
|
+
- max_cost_usd: Maximum cost per request
|
|
109
|
+
- max_latency_ms: Maximum latency
|
|
110
|
+
- min_quality: Minimum quality score (0-1)
|
|
111
|
+
- min_confidence: Minimum statistical confidence (0-1)
|
|
112
|
+
- max_risk: Maximum risk score (0-1)
|
|
113
|
+
window_hours: Time window for pattern analysis (default 1 week)
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
dict with:
|
|
117
|
+
- goal: The goal queried
|
|
118
|
+
- recommended_model: Best model for this goal
|
|
119
|
+
- recommended_provider: Provider for the recommended model
|
|
120
|
+
- outcome_success_rate: Historical success rate (0-1)
|
|
121
|
+
- outcome_sample_count: Number of outcomes in the data
|
|
122
|
+
- confidence: Statistical confidence in recommendation
|
|
123
|
+
- risk_score: Risk score (lower is better)
|
|
124
|
+
- reasoning: Human-readable explanation
|
|
125
|
+
- alternatives: List of alternative models
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
policy = intelligence.get_policy(goal="book_meeting")
|
|
132
|
+
print(f"Use {policy['recommended_model']} - {policy['outcome_success_rate']:.0%} success rate")
|
|
133
|
+
"""
|
|
134
|
+
response = self._request(
|
|
135
|
+
"POST",
|
|
136
|
+
"/api/v1/intelligence/policy",
|
|
137
|
+
json={
|
|
138
|
+
"goal": goal,
|
|
139
|
+
"task_type": task_type,
|
|
140
|
+
"constraints": constraints,
|
|
141
|
+
"window_hours": window_hours,
|
|
142
|
+
},
|
|
143
|
+
)
|
|
144
|
+
return response.json()
|
|
145
|
+
|
|
146
|
+
def report_outcome(
|
|
147
|
+
self,
|
|
148
|
+
trace_id: str,
|
|
149
|
+
goal: str,
|
|
150
|
+
success: bool,
|
|
151
|
+
score: float | None = None,
|
|
152
|
+
failure_reason: str | None = None,
|
|
153
|
+
metadata: dict | None = None,
|
|
154
|
+
tool_id: str | None = None,
|
|
155
|
+
execution_params: dict | None = None,
|
|
156
|
+
) -> dict[str, Any]:
|
|
157
|
+
"""Report execution outcome for a goal.
|
|
158
|
+
|
|
159
|
+
This is the feedback loop that teaches Kalibr what works.
|
|
160
|
+
Call this after your agent completes (or fails) a task.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
trace_id: The trace ID from the execution
|
|
164
|
+
goal: The goal this execution was trying to achieve
|
|
165
|
+
success: Whether the goal was achieved
|
|
166
|
+
score: Optional quality score (0-1) for more granular feedback
|
|
167
|
+
failure_reason: Optional reason for failure (helps with debugging)
|
|
168
|
+
metadata: Optional additional context as a dict
|
|
169
|
+
tool_id: Optional tool that was used (e.g., "serper", "browserless")
|
|
170
|
+
execution_params: Optional execution parameters (e.g., {"temperature": 0.3})
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
dict with:
|
|
174
|
+
- status: "accepted" if successful
|
|
175
|
+
- trace_id: The trace ID recorded
|
|
176
|
+
- goal: The goal recorded
|
|
177
|
+
|
|
178
|
+
Raises:
|
|
179
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
180
|
+
|
|
181
|
+
Example:
|
|
182
|
+
# Success case
|
|
183
|
+
report_outcome(trace_id="abc123", goal="book_meeting", success=True)
|
|
184
|
+
|
|
185
|
+
# Failure case with reason
|
|
186
|
+
report_outcome(
|
|
187
|
+
trace_id="abc123",
|
|
188
|
+
goal="book_meeting",
|
|
189
|
+
success=False,
|
|
190
|
+
failure_reason="calendar_conflict"
|
|
191
|
+
)
|
|
192
|
+
"""
|
|
193
|
+
response = self._request(
|
|
194
|
+
"POST",
|
|
195
|
+
"/api/v1/intelligence/report-outcome",
|
|
196
|
+
json={
|
|
197
|
+
"trace_id": trace_id,
|
|
198
|
+
"goal": goal,
|
|
199
|
+
"success": success,
|
|
200
|
+
"score": score,
|
|
201
|
+
"failure_reason": failure_reason,
|
|
202
|
+
"metadata": metadata,
|
|
203
|
+
"tool_id": tool_id,
|
|
204
|
+
"execution_params": execution_params,
|
|
205
|
+
},
|
|
206
|
+
)
|
|
207
|
+
return response.json()
|
|
208
|
+
|
|
209
|
+
def get_recommendation(
|
|
210
|
+
self,
|
|
211
|
+
task_type: str,
|
|
212
|
+
goal: str | None = None,
|
|
213
|
+
optimize_for: str = "balanced",
|
|
214
|
+
constraints: dict | None = None,
|
|
215
|
+
window_hours: int = 168,
|
|
216
|
+
) -> dict[str, Any]:
|
|
217
|
+
"""Get model recommendation for a task type.
|
|
218
|
+
|
|
219
|
+
This is the original recommendation endpoint. For goal-based
|
|
220
|
+
optimization, prefer get_policy() instead.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
task_type: Type of task (e.g., "summarize", "code", "qa")
|
|
224
|
+
goal: Optional goal for outcome-based optimization
|
|
225
|
+
optimize_for: Optimization target - one of:
|
|
226
|
+
- "cost": Minimize cost
|
|
227
|
+
- "quality": Maximize output quality
|
|
228
|
+
- "latency": Minimize response time
|
|
229
|
+
- "balanced": Balance all factors (default)
|
|
230
|
+
- "cost_efficiency": Maximize quality-per-dollar
|
|
231
|
+
- "outcome": Optimize for goal success rate
|
|
232
|
+
constraints: Optional constraints dict
|
|
233
|
+
window_hours: Time window for pattern analysis
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
dict with recommendation, alternatives, stats, reasoning
|
|
237
|
+
"""
|
|
238
|
+
response = self._request(
|
|
239
|
+
"POST",
|
|
240
|
+
"/api/v1/intelligence/recommend",
|
|
241
|
+
json={
|
|
242
|
+
"task_type": task_type,
|
|
243
|
+
"goal": goal,
|
|
244
|
+
"optimize_for": optimize_for,
|
|
245
|
+
"constraints": constraints,
|
|
246
|
+
"window_hours": window_hours,
|
|
247
|
+
},
|
|
248
|
+
)
|
|
249
|
+
return response.json()
|
|
250
|
+
|
|
251
|
+
# =========================================================================
|
|
252
|
+
# ROUTING METHODS
|
|
253
|
+
# =========================================================================
|
|
254
|
+
|
|
255
|
+
def register_path(
|
|
256
|
+
self,
|
|
257
|
+
goal: str,
|
|
258
|
+
model_id: str,
|
|
259
|
+
tool_id: str | None = None,
|
|
260
|
+
params: dict | None = None,
|
|
261
|
+
risk_level: str = "low",
|
|
262
|
+
) -> dict[str, Any]:
|
|
263
|
+
"""Register a new routing path for a goal.
|
|
264
|
+
|
|
265
|
+
Creates a path that maps a goal to a specific model (and optionally tool)
|
|
266
|
+
configuration. This path can then be selected by the decide() method.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
goal: The goal this path is for (e.g., "book_meeting", "resolve_ticket")
|
|
270
|
+
model_id: The model identifier to use (e.g., "gpt-4", "claude-3-opus")
|
|
271
|
+
tool_id: Optional tool identifier if this path uses a specific tool
|
|
272
|
+
params: Optional parameters dict for the path configuration
|
|
273
|
+
risk_level: Risk level for this path - "low", "medium", or "high"
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
dict with the created path including:
|
|
277
|
+
- path_id: Unique identifier for the path
|
|
278
|
+
- goal: The goal
|
|
279
|
+
- model_id: The model
|
|
280
|
+
- tool_id: The tool (if specified)
|
|
281
|
+
- params: The parameters (if specified)
|
|
282
|
+
- risk_level: The risk level
|
|
283
|
+
- created_at: Creation timestamp
|
|
284
|
+
|
|
285
|
+
Raises:
|
|
286
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
287
|
+
|
|
288
|
+
Example:
|
|
289
|
+
path = intelligence.register_path(
|
|
290
|
+
goal="book_meeting",
|
|
291
|
+
model_id="gpt-4",
|
|
292
|
+
tool_id="calendar_tool",
|
|
293
|
+
risk_level="low"
|
|
294
|
+
)
|
|
295
|
+
print(f"Created path: {path['path_id']}")
|
|
296
|
+
"""
|
|
297
|
+
response = self._request(
|
|
298
|
+
"POST",
|
|
299
|
+
"/api/v1/routing/paths",
|
|
300
|
+
json={
|
|
301
|
+
"goal": goal,
|
|
302
|
+
"model_id": model_id,
|
|
303
|
+
"tool_id": tool_id,
|
|
304
|
+
"params": params,
|
|
305
|
+
"risk_level": risk_level,
|
|
306
|
+
},
|
|
307
|
+
)
|
|
308
|
+
return response.json()
|
|
309
|
+
|
|
310
|
+
def list_paths(
|
|
311
|
+
self,
|
|
312
|
+
goal: str | None = None,
|
|
313
|
+
include_disabled: bool = False,
|
|
314
|
+
) -> dict[str, Any]:
|
|
315
|
+
"""List registered routing paths.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
goal: Optional goal to filter paths by
|
|
319
|
+
include_disabled: Whether to include disabled paths (default False)
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
dict with:
|
|
323
|
+
- paths: List of path objects
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
327
|
+
|
|
328
|
+
Example:
|
|
329
|
+
result = intelligence.list_paths(goal="book_meeting")
|
|
330
|
+
for path in result["paths"]:
|
|
331
|
+
print(f"{path['path_id']}: {path['model_id']}")
|
|
332
|
+
"""
|
|
333
|
+
params = {}
|
|
334
|
+
if goal is not None:
|
|
335
|
+
params["goal"] = goal
|
|
336
|
+
if include_disabled:
|
|
337
|
+
params["include_disabled"] = "true"
|
|
338
|
+
|
|
339
|
+
response = self._request(
|
|
340
|
+
"GET",
|
|
341
|
+
"/api/v1/routing/paths",
|
|
342
|
+
params=params if params else None,
|
|
343
|
+
)
|
|
344
|
+
return response.json()
|
|
345
|
+
|
|
346
|
+
def disable_path(self, path_id: str) -> dict[str, Any]:
|
|
347
|
+
"""Disable a routing path.
|
|
348
|
+
|
|
349
|
+
Disables a path so it won't be selected by decide(). The path
|
|
350
|
+
data is retained for historical analysis.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
path_id: The unique identifier of the path to disable
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
dict with:
|
|
357
|
+
- status: "disabled" if successful
|
|
358
|
+
- path_id: The disabled path ID
|
|
359
|
+
|
|
360
|
+
Raises:
|
|
361
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
362
|
+
|
|
363
|
+
Example:
|
|
364
|
+
result = intelligence.disable_path("path_abc123")
|
|
365
|
+
print(f"Status: {result['status']}")
|
|
366
|
+
"""
|
|
367
|
+
response = self._request(
|
|
368
|
+
"DELETE",
|
|
369
|
+
f"/api/v1/routing/paths/{path_id}",
|
|
370
|
+
)
|
|
371
|
+
return response.json()
|
|
372
|
+
|
|
373
|
+
def decide(
|
|
374
|
+
self,
|
|
375
|
+
goal: str,
|
|
376
|
+
task_risk_level: str = "low",
|
|
377
|
+
) -> dict[str, Any]:
|
|
378
|
+
"""Get routing decision for a goal.
|
|
379
|
+
|
|
380
|
+
Uses outcome data and exploration/exploitation strategy to decide
|
|
381
|
+
which path to use for achieving the specified goal.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
goal: The goal to route for (e.g., "book_meeting")
|
|
385
|
+
task_risk_level: Risk tolerance for this task - "low", "medium", or "high"
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
dict with:
|
|
389
|
+
- model_id: The selected model
|
|
390
|
+
- tool_id: The selected tool (if any)
|
|
391
|
+
- params: Additional parameters (if any)
|
|
392
|
+
- reason: Human-readable explanation of the decision
|
|
393
|
+
- confidence: Confidence score (0-1)
|
|
394
|
+
- is_exploration: Whether this is an exploration choice
|
|
395
|
+
- path_id: The selected path ID
|
|
396
|
+
|
|
397
|
+
Raises:
|
|
398
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
399
|
+
|
|
400
|
+
Example:
|
|
401
|
+
decision = intelligence.decide(goal="book_meeting")
|
|
402
|
+
model = decision["model_id"]
|
|
403
|
+
print(f"Using {model} ({decision['reason']})")
|
|
404
|
+
"""
|
|
405
|
+
response = self._request(
|
|
406
|
+
"POST",
|
|
407
|
+
"/api/v1/routing/decide",
|
|
408
|
+
json={
|
|
409
|
+
"goal": goal,
|
|
410
|
+
"task_risk_level": task_risk_level,
|
|
411
|
+
},
|
|
412
|
+
)
|
|
413
|
+
return response.json()
|
|
414
|
+
|
|
415
|
+
def set_exploration_config(
|
|
416
|
+
self,
|
|
417
|
+
goal: str = "*",
|
|
418
|
+
exploration_rate: float = 0.1,
|
|
419
|
+
min_samples_before_exploit: int = 20,
|
|
420
|
+
rollback_threshold: float = 0.3,
|
|
421
|
+
staleness_days: int = 7,
|
|
422
|
+
exploration_on_high_risk: bool = False,
|
|
423
|
+
) -> dict[str, Any]:
|
|
424
|
+
"""Set exploration/exploitation configuration for routing.
|
|
425
|
+
|
|
426
|
+
Configures how the decide() method balances exploring new paths
|
|
427
|
+
vs exploiting known good paths.
|
|
428
|
+
|
|
429
|
+
Args:
|
|
430
|
+
goal: Goal to configure, or "*" for default config
|
|
431
|
+
exploration_rate: Probability of exploring (0-1, default 0.1)
|
|
432
|
+
min_samples_before_exploit: Minimum outcomes before exploiting (default 20)
|
|
433
|
+
rollback_threshold: Performance drop threshold to rollback (default 0.3)
|
|
434
|
+
staleness_days: Days before reexploring stale paths (default 7)
|
|
435
|
+
exploration_on_high_risk: Whether to explore on high-risk tasks (default False)
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
dict with the saved configuration
|
|
439
|
+
|
|
440
|
+
Raises:
|
|
441
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
442
|
+
|
|
443
|
+
Example:
|
|
444
|
+
config = intelligence.set_exploration_config(
|
|
445
|
+
goal="book_meeting",
|
|
446
|
+
exploration_rate=0.2,
|
|
447
|
+
min_samples_before_exploit=10
|
|
448
|
+
)
|
|
449
|
+
"""
|
|
450
|
+
response = self._request(
|
|
451
|
+
"POST",
|
|
452
|
+
"/api/v1/routing/config",
|
|
453
|
+
json={
|
|
454
|
+
"goal": goal,
|
|
455
|
+
"exploration_rate": exploration_rate,
|
|
456
|
+
"min_samples_before_exploit": min_samples_before_exploit,
|
|
457
|
+
"rollback_threshold": rollback_threshold,
|
|
458
|
+
"staleness_days": staleness_days,
|
|
459
|
+
"exploration_on_high_risk": exploration_on_high_risk,
|
|
460
|
+
},
|
|
461
|
+
)
|
|
462
|
+
return response.json()
|
|
463
|
+
|
|
464
|
+
def get_exploration_config(self, goal: str | None = None) -> dict[str, Any]:
|
|
465
|
+
"""Get exploration/exploitation configuration.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
goal: Optional goal to get config for (returns default if not found)
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
dict with configuration values:
|
|
472
|
+
- goal: The goal this config applies to
|
|
473
|
+
- exploration_rate: Exploration probability
|
|
474
|
+
- min_samples_before_exploit: Minimum samples before exploiting
|
|
475
|
+
- rollback_threshold: Rollback threshold
|
|
476
|
+
- staleness_days: Staleness threshold in days
|
|
477
|
+
- exploration_on_high_risk: Whether exploration is allowed on high-risk
|
|
478
|
+
|
|
479
|
+
Raises:
|
|
480
|
+
httpx.HTTPStatusError: If the API returns an error
|
|
481
|
+
|
|
482
|
+
Example:
|
|
483
|
+
config = intelligence.get_exploration_config(goal="book_meeting")
|
|
484
|
+
print(f"Exploration rate: {config['exploration_rate']}")
|
|
485
|
+
"""
|
|
486
|
+
params = {}
|
|
487
|
+
if goal is not None:
|
|
488
|
+
params["goal"] = goal
|
|
489
|
+
|
|
490
|
+
response = self._request(
|
|
491
|
+
"GET",
|
|
492
|
+
"/api/v1/routing/config",
|
|
493
|
+
params=params if params else None,
|
|
494
|
+
)
|
|
495
|
+
return response.json()
|
|
496
|
+
|
|
497
|
+
def close(self):
|
|
498
|
+
"""Close the HTTP client."""
|
|
499
|
+
self._client.close()
|
|
500
|
+
|
|
501
|
+
def __enter__(self):
|
|
502
|
+
return self
|
|
503
|
+
|
|
504
|
+
def __exit__(self, *args):
|
|
505
|
+
self.close()
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
# Module-level singleton for convenience functions
|
|
509
|
+
_intelligence_client: KalibrIntelligence | None = None
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def _get_intelligence_client() -> KalibrIntelligence:
|
|
513
|
+
"""Get or create the singleton intelligence client."""
|
|
514
|
+
global _intelligence_client
|
|
515
|
+
if _intelligence_client is None:
|
|
516
|
+
_intelligence_client = KalibrIntelligence()
|
|
517
|
+
return _intelligence_client
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def get_policy(goal: str, tenant_id: str | None = None, **kwargs) -> dict[str, Any]:
|
|
521
|
+
"""Get execution policy for a goal.
|
|
522
|
+
|
|
523
|
+
Convenience function that uses the default intelligence client.
|
|
524
|
+
See KalibrIntelligence.get_policy for full documentation.
|
|
525
|
+
|
|
526
|
+
Args:
|
|
527
|
+
goal: The goal to optimize for
|
|
528
|
+
tenant_id: Optional tenant ID override (default: uses KALIBR_TENANT_ID env var)
|
|
529
|
+
**kwargs: Additional arguments (task_type, constraints, window_hours)
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
Policy dict with recommended_model, outcome_success_rate, etc.
|
|
533
|
+
|
|
534
|
+
Example:
|
|
535
|
+
from kalibr import get_policy
|
|
536
|
+
|
|
537
|
+
policy = get_policy(goal="book_meeting")
|
|
538
|
+
model = policy["recommended_model"]
|
|
539
|
+
"""
|
|
540
|
+
client = _get_intelligence_client()
|
|
541
|
+
if tenant_id:
|
|
542
|
+
# Create a new client with the specified tenant_id
|
|
543
|
+
client = KalibrIntelligence(tenant_id=tenant_id)
|
|
544
|
+
return client.get_policy(goal, **kwargs)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def report_outcome(trace_id: str, goal: str, success: bool, tenant_id: str | None = None, **kwargs) -> dict[str, Any]:
|
|
548
|
+
"""Report execution outcome for a goal.
|
|
549
|
+
|
|
550
|
+
Convenience function that uses the default intelligence client.
|
|
551
|
+
See KalibrIntelligence.report_outcome for full documentation.
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
trace_id: The trace ID from the execution
|
|
555
|
+
goal: The goal this execution was trying to achieve
|
|
556
|
+
success: Whether the goal was achieved
|
|
557
|
+
tenant_id: Optional tenant ID override (default: uses KALIBR_TENANT_ID env var)
|
|
558
|
+
**kwargs: Additional arguments (score, failure_reason, metadata, tool_id, execution_params)
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
Response dict with status confirmation
|
|
562
|
+
|
|
563
|
+
Example:
|
|
564
|
+
from kalibr import report_outcome
|
|
565
|
+
|
|
566
|
+
report_outcome(trace_id="abc123", goal="book_meeting", success=True)
|
|
567
|
+
"""
|
|
568
|
+
client = _get_intelligence_client()
|
|
569
|
+
if tenant_id:
|
|
570
|
+
# Create a new client with the specified tenant_id
|
|
571
|
+
client = KalibrIntelligence(tenant_id=tenant_id)
|
|
572
|
+
return client.report_outcome(trace_id, goal, success, **kwargs)
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def get_recommendation(task_type: str, **kwargs) -> dict[str, Any]:
|
|
576
|
+
"""Get model recommendation for a task type.
|
|
577
|
+
|
|
578
|
+
Convenience function that uses the default intelligence client.
|
|
579
|
+
See KalibrIntelligence.get_recommendation for full documentation.
|
|
580
|
+
"""
|
|
581
|
+
return _get_intelligence_client().get_recommendation(task_type, **kwargs)
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def register_path(
|
|
585
|
+
goal: str,
|
|
586
|
+
model_id: str,
|
|
587
|
+
tool_id: str | None = None,
|
|
588
|
+
params: dict | None = None,
|
|
589
|
+
risk_level: str = "low",
|
|
590
|
+
tenant_id: str | None = None,
|
|
591
|
+
) -> dict[str, Any]:
|
|
592
|
+
"""Register a new routing path for a goal.
|
|
593
|
+
|
|
594
|
+
Convenience function that uses the default intelligence client.
|
|
595
|
+
See KalibrIntelligence.register_path for full documentation.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
goal: The goal this path is for
|
|
599
|
+
model_id: The model identifier to use
|
|
600
|
+
tool_id: Optional tool identifier
|
|
601
|
+
params: Optional parameters dict
|
|
602
|
+
risk_level: Risk level - "low", "medium", or "high"
|
|
603
|
+
tenant_id: Optional tenant ID override
|
|
604
|
+
|
|
605
|
+
Returns:
|
|
606
|
+
dict with the created path
|
|
607
|
+
|
|
608
|
+
Example:
|
|
609
|
+
from kalibr import register_path
|
|
610
|
+
|
|
611
|
+
path = register_path(
|
|
612
|
+
goal="book_meeting",
|
|
613
|
+
model_id="gpt-4",
|
|
614
|
+
tool_id="calendar_tool"
|
|
615
|
+
)
|
|
616
|
+
"""
|
|
617
|
+
client = _get_intelligence_client()
|
|
618
|
+
if tenant_id:
|
|
619
|
+
client = KalibrIntelligence(tenant_id=tenant_id)
|
|
620
|
+
return client.register_path(goal, model_id, tool_id, params, risk_level)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
def decide(
|
|
624
|
+
goal: str,
|
|
625
|
+
task_risk_level: str = "low",
|
|
626
|
+
tenant_id: str | None = None,
|
|
627
|
+
) -> dict[str, Any]:
|
|
628
|
+
"""Get routing decision for a goal.
|
|
629
|
+
|
|
630
|
+
Convenience function that uses the default intelligence client.
|
|
631
|
+
See KalibrIntelligence.decide for full documentation.
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
goal: The goal to route for
|
|
635
|
+
task_risk_level: Risk tolerance - "low", "medium", or "high"
|
|
636
|
+
tenant_id: Optional tenant ID override
|
|
637
|
+
|
|
638
|
+
Returns:
|
|
639
|
+
dict with model_id, tool_id, params, reason, confidence, etc.
|
|
640
|
+
|
|
641
|
+
Example:
|
|
642
|
+
from kalibr import decide
|
|
643
|
+
|
|
644
|
+
decision = decide(goal="book_meeting")
|
|
645
|
+
model = decision["model_id"]
|
|
646
|
+
"""
|
|
647
|
+
client = _get_intelligence_client()
|
|
648
|
+
if tenant_id:
|
|
649
|
+
client = KalibrIntelligence(tenant_id=tenant_id)
|
|
650
|
+
return client.decide(goal, task_risk_level)
|