ai-lib-python 0.5.0__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.
- ai_lib_python/__init__.py +43 -0
- ai_lib_python/batch/__init__.py +15 -0
- ai_lib_python/batch/collector.py +244 -0
- ai_lib_python/batch/executor.py +224 -0
- ai_lib_python/cache/__init__.py +26 -0
- ai_lib_python/cache/backends.py +380 -0
- ai_lib_python/cache/key.py +237 -0
- ai_lib_python/cache/manager.py +332 -0
- ai_lib_python/client/__init__.py +37 -0
- ai_lib_python/client/builder.py +528 -0
- ai_lib_python/client/cancel.py +368 -0
- ai_lib_python/client/core.py +433 -0
- ai_lib_python/client/response.py +134 -0
- ai_lib_python/embeddings/__init__.py +36 -0
- ai_lib_python/embeddings/client.py +339 -0
- ai_lib_python/embeddings/types.py +234 -0
- ai_lib_python/embeddings/vectors.py +246 -0
- ai_lib_python/errors/__init__.py +41 -0
- ai_lib_python/errors/base.py +316 -0
- ai_lib_python/errors/classification.py +210 -0
- ai_lib_python/guardrails/__init__.py +35 -0
- ai_lib_python/guardrails/base.py +336 -0
- ai_lib_python/guardrails/filters.py +583 -0
- ai_lib_python/guardrails/validators.py +475 -0
- ai_lib_python/pipeline/__init__.py +55 -0
- ai_lib_python/pipeline/accumulate.py +248 -0
- ai_lib_python/pipeline/base.py +240 -0
- ai_lib_python/pipeline/decode.py +281 -0
- ai_lib_python/pipeline/event_map.py +506 -0
- ai_lib_python/pipeline/fan_out.py +284 -0
- ai_lib_python/pipeline/select.py +297 -0
- ai_lib_python/plugins/__init__.py +32 -0
- ai_lib_python/plugins/base.py +294 -0
- ai_lib_python/plugins/hooks.py +296 -0
- ai_lib_python/plugins/middleware.py +285 -0
- ai_lib_python/plugins/registry.py +294 -0
- ai_lib_python/protocol/__init__.py +71 -0
- ai_lib_python/protocol/loader.py +317 -0
- ai_lib_python/protocol/manifest.py +385 -0
- ai_lib_python/protocol/validator.py +460 -0
- ai_lib_python/py.typed +1 -0
- ai_lib_python/resilience/__init__.py +102 -0
- ai_lib_python/resilience/backpressure.py +225 -0
- ai_lib_python/resilience/circuit_breaker.py +318 -0
- ai_lib_python/resilience/executor.py +343 -0
- ai_lib_python/resilience/fallback.py +341 -0
- ai_lib_python/resilience/preflight.py +413 -0
- ai_lib_python/resilience/rate_limiter.py +291 -0
- ai_lib_python/resilience/retry.py +299 -0
- ai_lib_python/resilience/signals.py +283 -0
- ai_lib_python/routing/__init__.py +118 -0
- ai_lib_python/routing/manager.py +593 -0
- ai_lib_python/routing/strategy.py +345 -0
- ai_lib_python/routing/types.py +397 -0
- ai_lib_python/structured/__init__.py +33 -0
- ai_lib_python/structured/json_mode.py +281 -0
- ai_lib_python/structured/schema.py +316 -0
- ai_lib_python/structured/validator.py +334 -0
- ai_lib_python/telemetry/__init__.py +127 -0
- ai_lib_python/telemetry/exporters/__init__.py +9 -0
- ai_lib_python/telemetry/exporters/prometheus.py +111 -0
- ai_lib_python/telemetry/feedback.py +446 -0
- ai_lib_python/telemetry/health.py +409 -0
- ai_lib_python/telemetry/logger.py +389 -0
- ai_lib_python/telemetry/metrics.py +496 -0
- ai_lib_python/telemetry/tracer.py +473 -0
- ai_lib_python/tokens/__init__.py +25 -0
- ai_lib_python/tokens/counter.py +282 -0
- ai_lib_python/tokens/estimator.py +286 -0
- ai_lib_python/transport/__init__.py +34 -0
- ai_lib_python/transport/auth.py +141 -0
- ai_lib_python/transport/http.py +364 -0
- ai_lib_python/transport/pool.py +425 -0
- ai_lib_python/types/__init__.py +41 -0
- ai_lib_python/types/events.py +343 -0
- ai_lib_python/types/message.py +332 -0
- ai_lib_python/types/tool.py +191 -0
- ai_lib_python/utils/__init__.py +21 -0
- ai_lib_python/utils/tool_call_assembler.py +317 -0
- ai_lib_python-0.5.0.dist-info/METADATA +837 -0
- ai_lib_python-0.5.0.dist-info/RECORD +84 -0
- ai_lib_python-0.5.0.dist-info/WHEEL +4 -0
- ai_lib_python-0.5.0.dist-info/licenses/LICENSE-APACHE +201 -0
- ai_lib_python-0.5.0.dist-info/licenses/LICENSE-MIT +21 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
"""
|
|
2
|
+
High-level validators for content safety and compliance.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from ai_lib_python.guardrails.base import (
|
|
10
|
+
CompositeGuardrail,
|
|
11
|
+
Guardrail,
|
|
12
|
+
GuardrailResult,
|
|
13
|
+
GuardrailSeverity,
|
|
14
|
+
)
|
|
15
|
+
from ai_lib_python.guardrails.filters import (
|
|
16
|
+
EmailFilter,
|
|
17
|
+
KeywordFilter,
|
|
18
|
+
LengthFilter,
|
|
19
|
+
ProfanityFilter,
|
|
20
|
+
RegexFilter,
|
|
21
|
+
UrlFilter,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from collections.abc import Sequence
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ContentValidator:
|
|
29
|
+
"""High-level content validator with pre-configured guardrails.
|
|
30
|
+
|
|
31
|
+
Provides ready-to-use validators for common use cases.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
>>> validator = ContentValidator.create_input_validator()
|
|
35
|
+
>>> result = validator.check("User input here")
|
|
36
|
+
>>> if not result.is_safe:
|
|
37
|
+
... print(f"Violations: {[v.message for v in result.violations]}")
|
|
38
|
+
>>>
|
|
39
|
+
>>> # Filter content
|
|
40
|
+
>>> filtered = validator.filter("Input with sensitive data")
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, guardrails: Sequence[Guardrail]) -> None:
|
|
44
|
+
"""Initialize content validator.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
guardrails: List of guardrails to apply
|
|
48
|
+
"""
|
|
49
|
+
self._composite = CompositeGuardrail(
|
|
50
|
+
rule_id="content-validator",
|
|
51
|
+
guardrails=list(guardrails),
|
|
52
|
+
severity=GuardrailSeverity.WARNING,
|
|
53
|
+
stop_on_first=False,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def check(self, content: str) -> GuardrailResult:
|
|
57
|
+
"""Check content against all guardrails.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
content: Text content to validate
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
GuardrailResult with all violations
|
|
64
|
+
"""
|
|
65
|
+
return self._composite.check(content)
|
|
66
|
+
|
|
67
|
+
def filter(self, content: str) -> str:
|
|
68
|
+
"""Filter content by applying all guardrails.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
content: Text content to filter
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Filtered content
|
|
75
|
+
"""
|
|
76
|
+
return self._composite.filter(content)
|
|
77
|
+
|
|
78
|
+
def add_guardrail(self, guardrail: Guardrail) -> None:
|
|
79
|
+
"""Add a guardrail to the validator."""
|
|
80
|
+
self._composite.add_guardrail(guardrail)
|
|
81
|
+
|
|
82
|
+
def remove_guardrail(self, rule_id: str) -> bool:
|
|
83
|
+
"""Remove a guardrail by rule ID."""
|
|
84
|
+
return self._composite.remove_guardrail(rule_id)
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def create_input_validator(
|
|
88
|
+
cls,
|
|
89
|
+
severity: GuardrailSeverity = GuardrailSeverity.WARNING,
|
|
90
|
+
) -> "ContentValidator":
|
|
91
|
+
"""Create a validator for user input.
|
|
92
|
+
|
|
93
|
+
Filters for common input issues:
|
|
94
|
+
- Length limits
|
|
95
|
+
- Profanity
|
|
96
|
+
- URLs
|
|
97
|
+
- Emails
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
severity: Severity level for violations
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Configured ContentValidator
|
|
104
|
+
"""
|
|
105
|
+
guardrails = [
|
|
106
|
+
LengthFilter(
|
|
107
|
+
rule_id="input-length",
|
|
108
|
+
min_length=1,
|
|
109
|
+
max_length=10000,
|
|
110
|
+
severity=severity,
|
|
111
|
+
count_mode="chars",
|
|
112
|
+
),
|
|
113
|
+
ProfanityFilter(
|
|
114
|
+
rule_id="input-profanity",
|
|
115
|
+
severity=severity,
|
|
116
|
+
),
|
|
117
|
+
UrlFilter(
|
|
118
|
+
rule_id="input-urls",
|
|
119
|
+
action="allow",
|
|
120
|
+
severity=severity,
|
|
121
|
+
allowed_domains=["example.com"], # Add your allowed domains
|
|
122
|
+
),
|
|
123
|
+
EmailFilter(
|
|
124
|
+
rule_id="input-emails",
|
|
125
|
+
action="allow",
|
|
126
|
+
severity=severity,
|
|
127
|
+
allowed_domains=["example.com"], # Add your allowed domains
|
|
128
|
+
),
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
return cls(guardrails)
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def create_output_validator(
|
|
135
|
+
cls,
|
|
136
|
+
severity: GuardrailSeverity = GuardrailSeverity.WARNING,
|
|
137
|
+
) -> "ContentValidator":
|
|
138
|
+
"""Create a validator for AI model output.
|
|
139
|
+
|
|
140
|
+
Filters for common output issues:
|
|
141
|
+
- Excessive length
|
|
142
|
+
- Profanity
|
|
143
|
+
- Malicious URLs
|
|
144
|
+
- PII patterns
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
severity: Severity level for violations
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Configured ContentValidator
|
|
151
|
+
"""
|
|
152
|
+
guardrails = [
|
|
153
|
+
LengthFilter(
|
|
154
|
+
rule_id="output-length",
|
|
155
|
+
min_length=1,
|
|
156
|
+
max_length=50000,
|
|
157
|
+
severity=severity,
|
|
158
|
+
count_mode="chars",
|
|
159
|
+
),
|
|
160
|
+
ProfanityFilter(
|
|
161
|
+
rule_id="output-profanity",
|
|
162
|
+
severity=severity,
|
|
163
|
+
),
|
|
164
|
+
UrlFilter(
|
|
165
|
+
rule_id="output-urls",
|
|
166
|
+
action="deny",
|
|
167
|
+
severity=severity,
|
|
168
|
+
blocked_domains=["malicious.example.com", "spam.example.com"],
|
|
169
|
+
),
|
|
170
|
+
# Block common PII patterns
|
|
171
|
+
RegexFilter(
|
|
172
|
+
rule_id="output-credit-card",
|
|
173
|
+
pattern=r"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b",
|
|
174
|
+
severity=GuardrailSeverity.CRITICAL,
|
|
175
|
+
replacement="[CARD REDECTED]",
|
|
176
|
+
),
|
|
177
|
+
RegexFilter(
|
|
178
|
+
rule_id="output-ssn",
|
|
179
|
+
pattern=r"\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b",
|
|
180
|
+
severity=GuardrailSeverity.CRITICAL,
|
|
181
|
+
replacement="[SSN REDECTED]",
|
|
182
|
+
),
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
return cls(guardrails)
|
|
186
|
+
|
|
187
|
+
@classmethod
|
|
188
|
+
def create_pii_validator(
|
|
189
|
+
cls,
|
|
190
|
+
severity: GuardrailSeverity = GuardrailSeverity.CRITICAL,
|
|
191
|
+
) -> "ContentValidator":
|
|
192
|
+
"""Create a validator focusing on PII detection.
|
|
193
|
+
|
|
194
|
+
Detects and blocks Personally Identifiable Information.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
severity: Severity level for violations
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Configured ContentValidator
|
|
201
|
+
"""
|
|
202
|
+
guardrails = [
|
|
203
|
+
# Email addresses
|
|
204
|
+
EmailFilter(
|
|
205
|
+
rule_id="pii-email",
|
|
206
|
+
action="block",
|
|
207
|
+
severity=severity,
|
|
208
|
+
),
|
|
209
|
+
# Phone numbers (various formats)
|
|
210
|
+
RegexFilter(
|
|
211
|
+
rule_id="pii-phone",
|
|
212
|
+
pattern=r"\b\d{3}[-\s.]?\d{3}[-\s.]?\d{4}\b",
|
|
213
|
+
severity=severity,
|
|
214
|
+
replacement="[PHONE REDACTED]",
|
|
215
|
+
),
|
|
216
|
+
# Credit card numbers
|
|
217
|
+
RegexFilter(
|
|
218
|
+
rule_id="pii-credit-card",
|
|
219
|
+
pattern=r"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b",
|
|
220
|
+
severity=severity,
|
|
221
|
+
replacement="[CARD REDACTED]",
|
|
222
|
+
),
|
|
223
|
+
# Social Security Number
|
|
224
|
+
RegexFilter(
|
|
225
|
+
rule_id="pii-ssn",
|
|
226
|
+
pattern=r"\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b",
|
|
227
|
+
severity=severity,
|
|
228
|
+
replacement="[SSN REDACTED]",
|
|
229
|
+
),
|
|
230
|
+
# IP addresses
|
|
231
|
+
RegexFilter(
|
|
232
|
+
rule_id="pii-ip",
|
|
233
|
+
pattern=r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b",
|
|
234
|
+
severity=severity,
|
|
235
|
+
replacement="[IP REDACTED]",
|
|
236
|
+
),
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
return cls(guardrails)
|
|
240
|
+
|
|
241
|
+
@classmethod
|
|
242
|
+
def create_custom_validator(
|
|
243
|
+
cls,
|
|
244
|
+
forbidden_keywords: list[str] | None = None,
|
|
245
|
+
allowed_domains: list[str] | None = None,
|
|
246
|
+
max_length: int | None = None,
|
|
247
|
+
severity: GuardrailSeverity = GuardrailSeverity.WARNING,
|
|
248
|
+
) -> "ContentValidator":
|
|
249
|
+
"""Create a custom validator with specific rules.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
forbidden_keywords: List of keywords to block
|
|
253
|
+
allowed_domains: List of allowed URL/email domains
|
|
254
|
+
max_length: Maximum content length
|
|
255
|
+
severity: Severity level for violations
|
|
256
|
+
|
|
257
|
+
Returns:
|
|
258
|
+
Configured ContentValidator
|
|
259
|
+
"""
|
|
260
|
+
guardrails = []
|
|
261
|
+
|
|
262
|
+
if forbidden_keywords:
|
|
263
|
+
guardrails.append(
|
|
264
|
+
KeywordFilter(
|
|
265
|
+
rule_id="custom-keywords",
|
|
266
|
+
keywords=forbidden_keywords,
|
|
267
|
+
severity=severity,
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if allowed_domains:
|
|
272
|
+
guardrails.extend([
|
|
273
|
+
UrlFilter(
|
|
274
|
+
rule_id="custom-urls",
|
|
275
|
+
action="allow",
|
|
276
|
+
severity=severity,
|
|
277
|
+
allowed_domains=allowed_domains,
|
|
278
|
+
),
|
|
279
|
+
EmailFilter(
|
|
280
|
+
rule_id="custom-emails",
|
|
281
|
+
action="allow",
|
|
282
|
+
severity=severity,
|
|
283
|
+
allowed_domains=allowed_domains,
|
|
284
|
+
),
|
|
285
|
+
])
|
|
286
|
+
|
|
287
|
+
if max_length:
|
|
288
|
+
guardrails.append(
|
|
289
|
+
LengthFilter(
|
|
290
|
+
rule_id="custom-length",
|
|
291
|
+
max_length=max_length,
|
|
292
|
+
severity=severity,
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
return cls(guardrails)
|
|
297
|
+
|
|
298
|
+
@classmethod
|
|
299
|
+
def create_code_validator(
|
|
300
|
+
cls,
|
|
301
|
+
severity: GuardrailSeverity = GuardrailSeverity.INFO,
|
|
302
|
+
) -> "ContentValidator":
|
|
303
|
+
"""Create a validator for code snippets.
|
|
304
|
+
|
|
305
|
+
Less strict validation suitable for code-related content.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
severity: Severity level for violations
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
Configured ContentValidator
|
|
312
|
+
"""
|
|
313
|
+
guardrails = [
|
|
314
|
+
# Allow URLs (useful for code examples)
|
|
315
|
+
UrlFilter(
|
|
316
|
+
rule_id="code-urls",
|
|
317
|
+
action="allow",
|
|
318
|
+
severity=severity,
|
|
319
|
+
allowed_domains=[], # Allow all domains
|
|
320
|
+
),
|
|
321
|
+
# Allow emails (common in code)
|
|
322
|
+
EmailFilter(
|
|
323
|
+
rule_id="code-emails",
|
|
324
|
+
action="allow",
|
|
325
|
+
severity=severity,
|
|
326
|
+
allowed_domains=[], # Allow all domains
|
|
327
|
+
),
|
|
328
|
+
# Length limit for code snippets
|
|
329
|
+
LengthFilter(
|
|
330
|
+
rule_id="code-length",
|
|
331
|
+
min_length=1,
|
|
332
|
+
max_length=100000,
|
|
333
|
+
severity=severity,
|
|
334
|
+
count_mode="chars",
|
|
335
|
+
),
|
|
336
|
+
]
|
|
337
|
+
|
|
338
|
+
return cls(guardrails)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
class SafetyValidator(ContentValidator):
|
|
342
|
+
"""Validator focused specifically on content safety.
|
|
343
|
+
|
|
344
|
+
Detects potentially harmful or inappropriate content.
|
|
345
|
+
|
|
346
|
+
Example:
|
|
347
|
+
>>> validator = SafetyValidator()
|
|
348
|
+
>>> result = validator.check("Input to check")
|
|
349
|
+
>>> if not result.is_safe:
|
|
350
|
+
... print("Content flagged as unsafe")
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
# Potentially harmful keywords
|
|
354
|
+
_HARMFUL_KEYWORDS = [
|
|
355
|
+
"bomb", "drug", "weapon", "kill",
|
|
356
|
+
"illegal", "hack", "steal",
|
|
357
|
+
]
|
|
358
|
+
|
|
359
|
+
# Self-harm indicators
|
|
360
|
+
_SELF_HARM_KEYWORDS = [
|
|
361
|
+
"suicide", "end it all", "kill myself",
|
|
362
|
+
"want to die", "don't want to live",
|
|
363
|
+
]
|
|
364
|
+
|
|
365
|
+
def __init__(
|
|
366
|
+
self,
|
|
367
|
+
severity: GuardrailSeverity = GuardrailSeverity.CRITICAL,
|
|
368
|
+
block_self_harm: bool = True,
|
|
369
|
+
block_harmful: bool = True,
|
|
370
|
+
block_profane: bool = True,
|
|
371
|
+
) -> None:
|
|
372
|
+
"""Initialize safety validator.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
severity: Severity level for violations
|
|
376
|
+
block_self_harm: Block self-harm related content
|
|
377
|
+
block_harmful: Block harmful content
|
|
378
|
+
block_profane: Block profane content
|
|
379
|
+
"""
|
|
380
|
+
guardrails = []
|
|
381
|
+
|
|
382
|
+
if block_self_harm:
|
|
383
|
+
guardrails.append(
|
|
384
|
+
KeywordFilter(
|
|
385
|
+
rule_id="safety-self-harm",
|
|
386
|
+
keywords=self._SELF_HARM_KEYWORDS,
|
|
387
|
+
severity=severity,
|
|
388
|
+
case_sensitive=False,
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
if block_harmful:
|
|
393
|
+
guardrails.append(
|
|
394
|
+
KeywordFilter(
|
|
395
|
+
rule_id="safety-harmful",
|
|
396
|
+
keywords=self._HARMFUL_KEYWORDS,
|
|
397
|
+
severity=severity,
|
|
398
|
+
case_sensitive=False,
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
if block_profane:
|
|
403
|
+
guardrails.append(
|
|
404
|
+
ProfanityFilter(
|
|
405
|
+
rule_id="safety-profanity",
|
|
406
|
+
severity=severity,
|
|
407
|
+
)
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
super().__init__(guardrails)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
class ComplianceValidator(ContentValidator):
|
|
414
|
+
"""Validator for regulatory compliance.
|
|
415
|
+
|
|
416
|
+
Helps enforce compliance with data protection regulations.
|
|
417
|
+
|
|
418
|
+
Example:
|
|
419
|
+
>>> validator = ComplianceValidator(
|
|
420
|
+
... gdpr_mode=True,
|
|
421
|
+
... hipaa_mode=False,
|
|
422
|
+
... )
|
|
423
|
+
>>> result = validator.check("Content to check")
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
PII_PATTERNS = {
|
|
427
|
+
"email": r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b",
|
|
428
|
+
"phone": r"\b\d{3}[-\s.]?\d{3}[-\s.]?\d{4}\b",
|
|
429
|
+
"ssn": r"\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b",
|
|
430
|
+
"credit_card": r"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b",
|
|
431
|
+
"ip_address": r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b",
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
def __init__(
|
|
435
|
+
self,
|
|
436
|
+
gdpr_mode: bool = True,
|
|
437
|
+
hipaa_mode: bool = False,
|
|
438
|
+
severity: GuardrailSeverity = GuardrailSeverity.CRITICAL,
|
|
439
|
+
) -> None:
|
|
440
|
+
"""Initialize compliance validator.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
gdpr_mode: Enable GDPR compliance (detect PII)
|
|
444
|
+
hipaa_mode: Enable HIPAA compliance (detect PHI)
|
|
445
|
+
severity: Severity level for violations
|
|
446
|
+
"""
|
|
447
|
+
guardrails = []
|
|
448
|
+
|
|
449
|
+
if gdpr_mode:
|
|
450
|
+
# GDPR: Detect and block PII
|
|
451
|
+
for name, pattern in self.PII_PATTERNS.items():
|
|
452
|
+
guardrails.append(
|
|
453
|
+
RegexFilter(
|
|
454
|
+
rule_id=f"gdpr-{name}",
|
|
455
|
+
pattern=pattern,
|
|
456
|
+
severity=severity,
|
|
457
|
+
replacement=f"[{name.upper()} REDACTED]",
|
|
458
|
+
message=f"GDPR violation: {name} detected",
|
|
459
|
+
)
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
if hipaa_mode:
|
|
463
|
+
# HIPAA: Additional protected health information patterns
|
|
464
|
+
# (Additional patterns can be added based on requirements)
|
|
465
|
+
guardrails.extend([
|
|
466
|
+
RegexFilter(
|
|
467
|
+
rule_id="hipaa-medical-record",
|
|
468
|
+
pattern=r"\bMR[A-Z]?\d{6,}\b",
|
|
469
|
+
severity=severity,
|
|
470
|
+
replacement="[MRN REDACTED]",
|
|
471
|
+
message="HIPAA violation: Medical record number detected",
|
|
472
|
+
),
|
|
473
|
+
])
|
|
474
|
+
|
|
475
|
+
super().__init__(guardrails)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pipeline layer - Stream processing operators.
|
|
3
|
+
|
|
4
|
+
This module implements the operator pipeline for processing streaming responses:
|
|
5
|
+
- Decoder: Parses raw bytes into frames (SSE, JSON Lines)
|
|
6
|
+
- Selector: Filters frames using JSONPath expressions
|
|
7
|
+
- Accumulator: Accumulates stateful data (tool call arguments)
|
|
8
|
+
- EventMapper: Converts frames to unified streaming events
|
|
9
|
+
- FanOut: Expands arrays into separate events
|
|
10
|
+
|
|
11
|
+
The pipeline is constructed dynamically from protocol manifests.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from ai_lib_python.pipeline.accumulate import ToolCallAccumulator
|
|
15
|
+
from ai_lib_python.pipeline.base import Decoder, EventMapper, Pipeline, Transform
|
|
16
|
+
from ai_lib_python.pipeline.decode import (
|
|
17
|
+
AnthropicSSEDecoder,
|
|
18
|
+
JsonLinesDecoder,
|
|
19
|
+
SSEDecoder,
|
|
20
|
+
)
|
|
21
|
+
from ai_lib_python.pipeline.event_map import (
|
|
22
|
+
AnthropicEventMapper,
|
|
23
|
+
DefaultEventMapper,
|
|
24
|
+
ProtocolEventMapper,
|
|
25
|
+
)
|
|
26
|
+
from ai_lib_python.pipeline.fan_out import (
|
|
27
|
+
FanOutTransform,
|
|
28
|
+
ReplicateTransform,
|
|
29
|
+
SplitTransform,
|
|
30
|
+
create_fan_out,
|
|
31
|
+
)
|
|
32
|
+
from ai_lib_python.pipeline.select import JsonPathSelector, PassThroughSelector
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
# Base abstractions
|
|
36
|
+
"AnthropicEventMapper",
|
|
37
|
+
"AnthropicSSEDecoder",
|
|
38
|
+
"Decoder",
|
|
39
|
+
"DefaultEventMapper",
|
|
40
|
+
"EventMapper",
|
|
41
|
+
# FanOut
|
|
42
|
+
"FanOutTransform",
|
|
43
|
+
# Implementations
|
|
44
|
+
"JsonLinesDecoder",
|
|
45
|
+
"JsonPathSelector",
|
|
46
|
+
"PassThroughSelector",
|
|
47
|
+
"Pipeline",
|
|
48
|
+
"ProtocolEventMapper",
|
|
49
|
+
"ReplicateTransform",
|
|
50
|
+
"SSEDecoder",
|
|
51
|
+
"SplitTransform",
|
|
52
|
+
"ToolCallAccumulator",
|
|
53
|
+
"Transform",
|
|
54
|
+
"create_fan_out",
|
|
55
|
+
]
|