driftrail 2.0.0__tar.gz → 2.1.0__tar.gz
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.
- driftrail-2.1.0/PKG-INFO +469 -0
- driftrail-2.1.0/README.md +429 -0
- driftrail-2.1.0/driftrail/__init__.py +203 -0
- driftrail-2.1.0/driftrail/client.py +666 -0
- driftrail-2.1.0/driftrail/types.py +828 -0
- driftrail-2.1.0/driftrail.egg-info/PKG-INFO +469 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/pyproject.toml +2 -2
- driftrail-2.0.0/PKG-INFO +0 -226
- driftrail-2.0.0/README.md +0 -186
- driftrail-2.0.0/driftrail/__init__.py +0 -19
- driftrail-2.0.0/driftrail/client.py +0 -478
- driftrail-2.0.0/driftrail/types.py +0 -187
- driftrail-2.0.0/driftrail.egg-info/PKG-INFO +0 -226
- {driftrail-2.0.0 → driftrail-2.1.0}/LICENSE +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/driftrail/py.typed +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/driftrail.egg-info/SOURCES.txt +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/driftrail.egg-info/dependency_links.txt +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/driftrail.egg-info/requires.txt +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/driftrail.egg-info/top_level.txt +0 -0
- {driftrail-2.0.0 → driftrail-2.1.0}/setup.cfg +0 -0
driftrail-2.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: driftrail
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: DriftRail SDK - Complete AI Safety & Observability Platform with enterprise features for LLM monitoring, guardrails, drift detection, tracing, evaluations, and compliance
|
|
5
|
+
Author-email: DriftRail <support@driftrail.com>
|
|
6
|
+
Maintainer-email: DriftRail <support@driftrail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://driftrail.com
|
|
9
|
+
Project-URL: Documentation, https://docs.driftrail.com
|
|
10
|
+
Project-URL: Repository, https://github.com/cutmob/DriftRail-Python
|
|
11
|
+
Project-URL: Changelog, https://github.com/cutmob/DriftRail-Python/blob/main/CHANGELOG.md
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/cutmob/DriftRail-Python/issues
|
|
13
|
+
Keywords: ai,llm,observability,safety,monitoring,audit,guardrails,compliance,openai,anthropic,gemini,machine-learning,mlops
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
27
|
+
Classifier: Topic :: System :: Monitoring
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.8
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Provides-Extra: async
|
|
33
|
+
Requires-Dist: aiohttp>=3.8.0; extra == "async"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# DriftRail Python SDK
|
|
42
|
+
|
|
43
|
+
Official Python SDK for [DriftRail](https://driftrail.com) - AI Safety & Observability Platform.
|
|
44
|
+
|
|
45
|
+
[](https://badge.fury.io/py/driftrail)
|
|
46
|
+
[](https://www.python.org/downloads/)
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install driftrail
|
|
52
|
+
|
|
53
|
+
# With async support
|
|
54
|
+
pip install driftrail[async]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from driftrail import DriftRail
|
|
61
|
+
|
|
62
|
+
client = DriftRail(
|
|
63
|
+
api_key="dr_live_...",
|
|
64
|
+
app_id="my-app"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Log an LLM interaction
|
|
68
|
+
response = client.ingest(
|
|
69
|
+
model="gpt-4o",
|
|
70
|
+
provider="openai",
|
|
71
|
+
input={"prompt": "What is the capital of France?"},
|
|
72
|
+
output={"text": "The capital of France is Paris."},
|
|
73
|
+
metadata={"latency_ms": 250, "tokens_in": 10, "tokens_out": 8}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
print(f"Event ID: {response.event_id}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Inline Guardrails
|
|
80
|
+
|
|
81
|
+
Block dangerous outputs before they reach users:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
result = client.guard(
|
|
85
|
+
output=llm_response,
|
|
86
|
+
input=user_prompt,
|
|
87
|
+
mode="strict" # or "permissive"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if result.allowed:
|
|
91
|
+
return result.output # May be redacted
|
|
92
|
+
else:
|
|
93
|
+
return "Sorry, I can't help with that."
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Async Client
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from driftrail import DriftRailAsync
|
|
100
|
+
|
|
101
|
+
async with DriftRailAsync(api_key="...", app_id="my-app") as client:
|
|
102
|
+
response = await client.ingest(
|
|
103
|
+
model="gpt-4o",
|
|
104
|
+
provider="openai",
|
|
105
|
+
input={"prompt": "Hello"},
|
|
106
|
+
output={"text": "Hi there!"}
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Enterprise Features
|
|
111
|
+
|
|
112
|
+
The `DriftRailEnterprise` client provides access to all dashboard features:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from driftrail import DriftRailEnterprise
|
|
116
|
+
|
|
117
|
+
client = DriftRailEnterprise(api_key="dr_live_...", app_id="my-app")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Incidents
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
# List incidents
|
|
124
|
+
incidents = client.list_incidents(
|
|
125
|
+
status=["open", "investigating"],
|
|
126
|
+
severity=["high", "critical"]
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Create incident
|
|
130
|
+
incident = client.create_incident(
|
|
131
|
+
title="High risk outputs detected",
|
|
132
|
+
severity="high",
|
|
133
|
+
incident_type="safety",
|
|
134
|
+
description="Multiple high-risk outputs in production"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Get stats
|
|
138
|
+
stats = client.get_incident_stats()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Compliance
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
# Get compliance status
|
|
145
|
+
status = client.get_compliance_status()
|
|
146
|
+
|
|
147
|
+
# Generate compliance report
|
|
148
|
+
report = client.generate_compliance_report(
|
|
149
|
+
framework="soc2",
|
|
150
|
+
format="pdf",
|
|
151
|
+
include_evidence=True
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Get compliance score
|
|
155
|
+
score = client.get_compliance_score()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Drift Detection
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# Get drift metrics
|
|
162
|
+
metrics = client.get_drift_metrics()
|
|
163
|
+
|
|
164
|
+
# Get drift alerts
|
|
165
|
+
alerts = client.get_drift_alerts(severity="critical", unresolved=True)
|
|
166
|
+
|
|
167
|
+
# Acknowledge/resolve alerts
|
|
168
|
+
client.acknowledge_alert(alert_id)
|
|
169
|
+
client.resolve_alert(alert_id, notes="Fixed in v2.1")
|
|
170
|
+
|
|
171
|
+
# Get drift score
|
|
172
|
+
score = client.get_drift_score()
|
|
173
|
+
|
|
174
|
+
# Get predictions
|
|
175
|
+
predictions = client.get_drift_predictions()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Distributed Tracing
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
# Start a trace
|
|
182
|
+
trace = client.start_trace(
|
|
183
|
+
app_id="my-app",
|
|
184
|
+
name="chat-completion",
|
|
185
|
+
user_id="user-123",
|
|
186
|
+
metadata={"session": "abc"}
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Add spans
|
|
190
|
+
span = client.start_span(
|
|
191
|
+
trace_id=trace["trace_id"],
|
|
192
|
+
name="llm-call",
|
|
193
|
+
span_type="llm",
|
|
194
|
+
model="gpt-4o"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# End span with results
|
|
198
|
+
client.end_span(
|
|
199
|
+
span_id=span["span_id"],
|
|
200
|
+
output={"text": "Response"},
|
|
201
|
+
tokens_in=100,
|
|
202
|
+
tokens_out=50
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# End trace
|
|
206
|
+
client.end_trace(trace["trace_id"])
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Prompt Management
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
# Create prompt
|
|
213
|
+
prompt = client.create_prompt(
|
|
214
|
+
name="customer-support",
|
|
215
|
+
content="You are a helpful assistant...",
|
|
216
|
+
variables=["customer_name", "issue"],
|
|
217
|
+
tags=["support", "production"]
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Create version
|
|
221
|
+
version = client.create_prompt_version(
|
|
222
|
+
prompt_id=prompt["prompt_id"],
|
|
223
|
+
content="Updated prompt content...",
|
|
224
|
+
commit_message="Improved tone"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Deploy to environment
|
|
228
|
+
client.deploy_prompt_version(
|
|
229
|
+
version_id=version["version_id"],
|
|
230
|
+
environment="prod"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Get deployed prompt
|
|
234
|
+
deployed = client.get_deployed_prompt(prompt["prompt_id"], "prod")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Evaluations
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
# Create dataset
|
|
241
|
+
dataset = client.create_dataset(
|
|
242
|
+
name="qa-test-set",
|
|
243
|
+
schema_type="qa"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Add items
|
|
247
|
+
client.add_dataset_items(dataset["dataset_id"], [
|
|
248
|
+
{"input": {"question": "What is 2+2?"}, "expected_output": {"answer": "4"}},
|
|
249
|
+
{"input": {"question": "Capital of Japan?"}, "expected_output": {"answer": "Tokyo"}}
|
|
250
|
+
])
|
|
251
|
+
|
|
252
|
+
# Run evaluation
|
|
253
|
+
run = client.create_eval_run(
|
|
254
|
+
dataset_id=dataset["dataset_id"],
|
|
255
|
+
model="gpt-4o",
|
|
256
|
+
evaluators=[
|
|
257
|
+
{"name": "correctness", "type": "llm_judge"},
|
|
258
|
+
{"name": "exact_match", "type": "exact_match"}
|
|
259
|
+
]
|
|
260
|
+
)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Semantic Caching
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
# Check cache
|
|
267
|
+
result = client.cache_lookup(input="What is the weather?", model="gpt-4o")
|
|
268
|
+
|
|
269
|
+
if result["hit"]:
|
|
270
|
+
return result["output"]
|
|
271
|
+
else:
|
|
272
|
+
# Call LLM and store
|
|
273
|
+
response = call_llm(...)
|
|
274
|
+
client.cache_store(
|
|
275
|
+
input="What is the weather?",
|
|
276
|
+
output=response,
|
|
277
|
+
model="gpt-4o"
|
|
278
|
+
)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Agent Simulations
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
# Create simulation
|
|
285
|
+
sim = client.create_simulation(
|
|
286
|
+
name="booking-flow",
|
|
287
|
+
scenario="User wants to book a flight to Paris",
|
|
288
|
+
persona={"name": "Traveler", "traits": ["impatient", "budget-conscious"]},
|
|
289
|
+
success_criteria=[
|
|
290
|
+
{"name": "booking_complete", "description": "Flight successfully booked"}
|
|
291
|
+
],
|
|
292
|
+
max_turns=20
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
# Run simulation
|
|
296
|
+
run = client.run_simulation(sim["simulation_id"])
|
|
297
|
+
|
|
298
|
+
# Get results
|
|
299
|
+
results = client.get_simulation_run(run["run_id"])
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Integrations
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
# Create Slack integration
|
|
306
|
+
client.create_integration(
|
|
307
|
+
type="slack",
|
|
308
|
+
webhook_url="https://hooks.slack.com/...",
|
|
309
|
+
channel_name="#alerts",
|
|
310
|
+
events=["high_risk", "incident", "drift_alert"]
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
# Test integration
|
|
314
|
+
client.test_integration(webhook_url, "slack")
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Model Analytics
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
# Get summary
|
|
321
|
+
summary = client.get_model_analytics_summary()
|
|
322
|
+
|
|
323
|
+
# Get historical logs
|
|
324
|
+
logs = client.get_historical_logs(
|
|
325
|
+
model="gpt-4o",
|
|
326
|
+
min_risk_score=0.7,
|
|
327
|
+
limit=100
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
# Get model benchmarks
|
|
331
|
+
benchmarks = client.get_model_benchmarks(model="gpt-4o")
|
|
332
|
+
|
|
333
|
+
# Record model switch
|
|
334
|
+
client.record_model_switch(
|
|
335
|
+
app_id="my-app",
|
|
336
|
+
new_model="gpt-4o",
|
|
337
|
+
new_provider="openai",
|
|
338
|
+
previous_model="gpt-4",
|
|
339
|
+
switch_reason="Cost optimization"
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Executive Dashboard
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
# Get executive metrics
|
|
347
|
+
metrics = client.get_executive_metrics(period="7d")
|
|
348
|
+
|
|
349
|
+
# Get/update KPI targets
|
|
350
|
+
targets = client.get_kpi_targets()
|
|
351
|
+
client.update_kpi_targets({
|
|
352
|
+
"max_high_risk_percent": 5.0,
|
|
353
|
+
"target_latency_ms": 500
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
# Export metrics
|
|
357
|
+
export = client.export_executive_metrics(period="30d", format="pdf")
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Guardrails
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
# List guardrails
|
|
364
|
+
guardrails = client.get_guardrails()
|
|
365
|
+
|
|
366
|
+
# Create guardrail
|
|
367
|
+
client.create_guardrail(
|
|
368
|
+
name="block-competitors",
|
|
369
|
+
rule_type="blocked_terms",
|
|
370
|
+
action="block",
|
|
371
|
+
config={"terms": ["competitor1", "competitor2"]}
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# Get stats
|
|
375
|
+
stats = client.get_guardrail_stats()
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Custom Detections
|
|
379
|
+
|
|
380
|
+
```python
|
|
381
|
+
# Create custom detection
|
|
382
|
+
client.create_custom_detection(
|
|
383
|
+
name="financial-advice",
|
|
384
|
+
detection_type="semantic",
|
|
385
|
+
config={"description": "Detects unauthorized financial advice"},
|
|
386
|
+
severity="high"
|
|
387
|
+
)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Benchmarks
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
# Get industry benchmark report
|
|
394
|
+
report = client.get_benchmark_report(industry="fintech")
|
|
395
|
+
|
|
396
|
+
# Set your industry
|
|
397
|
+
client.set_tenant_industry("fintech")
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Exports
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
# Create export
|
|
404
|
+
export = client.create_export(
|
|
405
|
+
export_type="events",
|
|
406
|
+
format="csv",
|
|
407
|
+
date_from="2024-01-01",
|
|
408
|
+
date_to="2024-01-31"
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# Check status
|
|
412
|
+
status = client.get_export_status(export["export_id"])
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Configuration
|
|
416
|
+
|
|
417
|
+
| Parameter | Default | Description |
|
|
418
|
+
|-----------|---------|-------------|
|
|
419
|
+
| `api_key` | Required | Your DriftRail API key |
|
|
420
|
+
| `app_id` | Required | Your application identifier |
|
|
421
|
+
| `base_url` | `https://api.driftrail.com` | API base URL |
|
|
422
|
+
| `timeout` | `30` | Request timeout in seconds |
|
|
423
|
+
| `fail_open` | `True` | Don't raise on errors |
|
|
424
|
+
| `guard_mode` | `fail_open` | Guard behavior on block |
|
|
425
|
+
|
|
426
|
+
## Error Handling
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
from driftrail import GuardBlockedError
|
|
430
|
+
|
|
431
|
+
client = DriftRail(
|
|
432
|
+
api_key="...",
|
|
433
|
+
app_id="my-app",
|
|
434
|
+
guard_mode="fail_closed" # Raise on blocked content
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
try:
|
|
438
|
+
result = client.guard(output=response)
|
|
439
|
+
except GuardBlockedError as e:
|
|
440
|
+
print(f"Blocked: {e.result.triggered}")
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Type Hints
|
|
444
|
+
|
|
445
|
+
Full type hints are available for all methods and responses:
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
from driftrail import (
|
|
449
|
+
DriftRail,
|
|
450
|
+
IngestResponse,
|
|
451
|
+
GuardResult,
|
|
452
|
+
Incident,
|
|
453
|
+
DriftAlert,
|
|
454
|
+
Trace,
|
|
455
|
+
Span,
|
|
456
|
+
# ... and many more
|
|
457
|
+
)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Links
|
|
461
|
+
|
|
462
|
+
- [Documentation](https://driftrail.com/docs)
|
|
463
|
+
- [API Reference](https://driftrail.com/api-reference)
|
|
464
|
+
- [Dashboard](https://app.driftrail.com)
|
|
465
|
+
- [GitHub](https://github.com/driftrail/driftrail-python)
|
|
466
|
+
|
|
467
|
+
## License
|
|
468
|
+
|
|
469
|
+
MIT
|