python-rerouting-library 0.2.1__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.
- python_rerouting_library-0.2.1/LICENSE +21 -0
- python_rerouting_library-0.2.1/PKG-INFO +624 -0
- python_rerouting_library-0.2.1/README.md +590 -0
- python_rerouting_library-0.2.1/pyproject.toml +80 -0
- python_rerouting_library-0.2.1/setup.cfg +4 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/__init__.py +25 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/backends/__init__.py +30 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/backends/cloud.py +58 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/backends/local_llama.py +74 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/config.py +128 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/dispatcher.py +200 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/exceptions.py +18 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/privacy.py +171 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/router.py +227 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library/training.py +177 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library.egg-info/PKG-INFO +624 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library.egg-info/SOURCES.txt +23 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library.egg-info/dependency_links.txt +1 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library.egg-info/requires.txt +13 -0
- python_rerouting_library-0.2.1/src/python_rerouting_library.egg-info/top_level.txt +1 -0
- python_rerouting_library-0.2.1/tests/test_classifier_artifact.py +99 -0
- python_rerouting_library-0.2.1/tests/test_dispatcher.py +354 -0
- python_rerouting_library-0.2.1/tests/test_privacy.py +134 -0
- python_rerouting_library-0.2.1/tests/test_router_decision.py +56 -0
- python_rerouting_library-0.2.1/tests/test_router_thresholds.py +88 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Deepa Patil
|
|
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,624 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-rerouting-library
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Privacy-aware semantic routing between local and cloud LLM backends
|
|
5
|
+
Author: Deepa793
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Deepa793/python-rerouting-library
|
|
8
|
+
Project-URL: Repository, https://github.com/Deepa793/python-rerouting-library
|
|
9
|
+
Project-URL: Issues, https://github.com/Deepa793/python-rerouting-library/issues
|
|
10
|
+
Keywords: llm,routing,semantic-routing,local-llm,privacy,llama,openai,machine-learning,generative-ai
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=1.24
|
|
23
|
+
Requires-Dist: scikit-learn>=1.1
|
|
24
|
+
Requires-Dist: sentence-transformers>=3.0
|
|
25
|
+
Requires-Dist: joblib>=1.4
|
|
26
|
+
Requires-Dist: openai>=1.0
|
|
27
|
+
Provides-Extra: local-llama
|
|
28
|
+
Requires-Dist: llama-cpp-python>=0.3; extra == "local-llama"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
32
|
+
Requires-Dist: twine>=6; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# Python Rerouting Library
|
|
36
|
+
|
|
37
|
+
A lightweight Python library that routes user queries between a local Llama model and a cloud LLM using privacy rules and semantic complexity classification.
|
|
38
|
+
|
|
39
|
+
## What Changed in v0.2.0
|
|
40
|
+
|
|
41
|
+
Version 0.2 adds a **privacy-first routing layer** in front of the semantic complexity router.
|
|
42
|
+
|
|
43
|
+
The key rule is:
|
|
44
|
+
|
|
45
|
+
> Privacy policy takes precedence over complexity routing.
|
|
46
|
+
|
|
47
|
+
If a query contains detected sensitive information, the query is routed directly to the local model and is never sent to the cloud.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Routing Architecture
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Query
|
|
55
|
+
↓
|
|
56
|
+
Privacy Detector
|
|
57
|
+
↓
|
|
58
|
+
Sensitive data detected?
|
|
59
|
+
│
|
|
60
|
+
├── YES
|
|
61
|
+
│ ↓
|
|
62
|
+
│ privacy_override
|
|
63
|
+
│ ↓
|
|
64
|
+
│ Local Llama only
|
|
65
|
+
│ ↓
|
|
66
|
+
│ if local fails → DispatchError
|
|
67
|
+
│
|
|
68
|
+
│ NEVER cloud
|
|
69
|
+
│
|
|
70
|
+
└── NO
|
|
71
|
+
↓
|
|
72
|
+
MiniLM Semantic Router
|
|
73
|
+
↓
|
|
74
|
+
Logistic Regression
|
|
75
|
+
↓
|
|
76
|
+
simple / uncertain / complex
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
For clean queries, normal routing continues:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
simple
|
|
83
|
+
↓
|
|
84
|
+
Local Llama
|
|
85
|
+
↓
|
|
86
|
+
if local fails → Cloud fallback
|
|
87
|
+
|
|
88
|
+
uncertain
|
|
89
|
+
↓
|
|
90
|
+
Cloud
|
|
91
|
+
|
|
92
|
+
complex
|
|
93
|
+
↓
|
|
94
|
+
Cloud
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Privacy-First Routing
|
|
100
|
+
|
|
101
|
+
Before complexity scoring, every query is checked by `PrivacyDetector`.
|
|
102
|
+
|
|
103
|
+
The current detector looks for common patterns including:
|
|
104
|
+
|
|
105
|
+
* Email addresses
|
|
106
|
+
* US-style phone numbers
|
|
107
|
+
* Social Security numbers
|
|
108
|
+
* Common API-key formats
|
|
109
|
+
* Credit-card numbers
|
|
110
|
+
|
|
111
|
+
Credit-card candidates are additionally validated using the **Luhn checksum** to reduce false positives.
|
|
112
|
+
|
|
113
|
+
If sensitive information is detected:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
Query
|
|
117
|
+
↓
|
|
118
|
+
PrivacyDetector
|
|
119
|
+
↓
|
|
120
|
+
privacy_override
|
|
121
|
+
↓
|
|
122
|
+
Local Llama
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The MiniLM semantic router is not called.
|
|
126
|
+
|
|
127
|
+
The cloud backend is not called.
|
|
128
|
+
|
|
129
|
+
If the local backend fails:
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
privacy_override
|
|
133
|
+
↓
|
|
134
|
+
Local backend failure
|
|
135
|
+
↓
|
|
136
|
+
DispatchError
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
There is intentionally **no cloud fallback** for privacy-sensitive queries.
|
|
140
|
+
|
|
141
|
+
The detector reports only privacy categories such as:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
email
|
|
145
|
+
phone
|
|
146
|
+
ssn
|
|
147
|
+
api_key
|
|
148
|
+
credit_card
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
It does not return the matched sensitive value.
|
|
152
|
+
|
|
153
|
+
> The privacy detector is a lightweight policy layer based on known patterns. It is not intended to replace a full Data Loss Prevention, compliance, or enterprise sensitive-data classification system.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Semantic Router
|
|
158
|
+
|
|
159
|
+
Queries that pass the privacy check continue to the semantic router.
|
|
160
|
+
|
|
161
|
+
The router uses:
|
|
162
|
+
|
|
163
|
+
* `sentence-transformers/all-MiniLM-L6-v2`
|
|
164
|
+
* 384-dimensional semantic embeddings
|
|
165
|
+
* Logistic Regression
|
|
166
|
+
* Configurable uncertainty thresholds
|
|
167
|
+
|
|
168
|
+
The query is converted into an embedding and passed to the trained classifier.
|
|
169
|
+
|
|
170
|
+
The classifier produces:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
P(complex)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This probability is then used by the routing policy.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Default Complexity Routing Policy
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
P(complex) < 0.40
|
|
184
|
+
→ simple
|
|
185
|
+
→ local Llama
|
|
186
|
+
|
|
187
|
+
0.40 ≤ P(complex) ≤ 0.60
|
|
188
|
+
→ uncertain
|
|
189
|
+
→ cloud
|
|
190
|
+
|
|
191
|
+
P(complex) > 0.60
|
|
192
|
+
→ complex
|
|
193
|
+
→ cloud
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The thresholds are configurable.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Routing Priority
|
|
201
|
+
|
|
202
|
+
The system now contains two routing layers:
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
1. Privacy policy
|
|
206
|
+
↓
|
|
207
|
+
2. Complexity policy
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Privacy always wins.
|
|
211
|
+
|
|
212
|
+
For example, a query such as:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
Design a multi-region database architecture
|
|
216
|
+
for alice@example.com with automatic failover.
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
looks like a complex query.
|
|
220
|
+
|
|
221
|
+
In v0.1 it would likely be routed to the cloud.
|
|
222
|
+
|
|
223
|
+
In v0.2:
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
email detected
|
|
227
|
+
↓
|
|
228
|
+
privacy_override
|
|
229
|
+
↓
|
|
230
|
+
local only
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
The semantic complexity classifier is not called.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Failure Policy
|
|
238
|
+
|
|
239
|
+
### Privacy-sensitive query
|
|
240
|
+
|
|
241
|
+
```text
|
|
242
|
+
Local Llama
|
|
243
|
+
↓ failure
|
|
244
|
+
DispatchError
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Cloud fallback is prohibited.
|
|
248
|
+
|
|
249
|
+
### Clean simple query
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
Local Llama
|
|
253
|
+
↓ failure
|
|
254
|
+
Cloud fallback
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Clean uncertain query
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
Cloud
|
|
261
|
+
↓ failure
|
|
262
|
+
DispatchError
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Clean complex query
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
Cloud
|
|
269
|
+
↓ failure
|
|
270
|
+
DispatchError
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Complex and uncertain queries are not silently downgraded to the local model.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Project Structure
|
|
278
|
+
|
|
279
|
+
```text
|
|
280
|
+
python-rerouting-library/
|
|
281
|
+
├── src/
|
|
282
|
+
│ └── python_rerouting_library/
|
|
283
|
+
│ ├── __init__.py
|
|
284
|
+
│ ├── router.py
|
|
285
|
+
│ ├── privacy.py
|
|
286
|
+
│ ├── dispatcher.py
|
|
287
|
+
│ ├── training.py
|
|
288
|
+
│ ├── config.py
|
|
289
|
+
│ ├── exceptions.py
|
|
290
|
+
│ └── backends/
|
|
291
|
+
│ ├── __init__.py
|
|
292
|
+
│ ├── local_llama.py
|
|
293
|
+
│ └── cloud.py
|
|
294
|
+
├── tests/
|
|
295
|
+
│ ├── test_dispatcher.py
|
|
296
|
+
│ ├── test_privacy.py
|
|
297
|
+
│ ├── test_router_decision.py
|
|
298
|
+
│ └── test_router_thresholds.py
|
|
299
|
+
├── examples/
|
|
300
|
+
├── benchmarks/
|
|
301
|
+
├── pyproject.toml
|
|
302
|
+
├── .env.example
|
|
303
|
+
├── .gitignore
|
|
304
|
+
├── LICENSE
|
|
305
|
+
└── README.md
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The generated router classifier is stored under:
|
|
309
|
+
|
|
310
|
+
```text
|
|
311
|
+
artifacts/
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
and is intentionally excluded from Git.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Requirements
|
|
319
|
+
|
|
320
|
+
* Python 3.10+
|
|
321
|
+
* Router classifier artifact
|
|
322
|
+
* Local GGUF model for local Llama inference
|
|
323
|
+
* OpenAI-compatible cloud API for cloud routing
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Installation
|
|
328
|
+
|
|
329
|
+
From the project folder:
|
|
330
|
+
|
|
331
|
+
```powershell
|
|
332
|
+
python -m pip install -e ".[dev]"
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
If using the local Llama backend:
|
|
336
|
+
|
|
337
|
+
```powershell
|
|
338
|
+
python -m pip install -e ".[local-llama]"
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`llama-cpp-python` is an optional dependency.
|
|
342
|
+
|
|
343
|
+
Cloud-only users do not need to install it.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Configuration
|
|
348
|
+
|
|
349
|
+
The library reads runtime settings from environment variables.
|
|
350
|
+
|
|
351
|
+
Example:
|
|
352
|
+
|
|
353
|
+
```powershell
|
|
354
|
+
$env:LLAMA_MODEL_PATH="C:\models\llama3.2\model.gguf"
|
|
355
|
+
|
|
356
|
+
$env:ROUTER_CLASSIFIER_PATH="artifacts\router_classifier.joblib"
|
|
357
|
+
|
|
358
|
+
$env:CLOUD_BASE_URL="https://api.openai.com/v1"
|
|
359
|
+
$env:CLOUD_MODEL="gpt-5.4-nano"
|
|
360
|
+
$env:CLOUD_API_KEY="YOUR_API_KEY"
|
|
361
|
+
|
|
362
|
+
$env:LOCAL_MAX_TOKENS="128"
|
|
363
|
+
$env:CLOUD_MAX_TOKENS="256"
|
|
364
|
+
|
|
365
|
+
$env:ROUTER_SIMPLE_THRESHOLD="0.40"
|
|
366
|
+
$env:ROUTER_COMPLEX_THRESHOLD="0.60"
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
See `.env.example` for the available settings.
|
|
370
|
+
|
|
371
|
+
Never commit real API keys or credentials.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Classifier Artifact
|
|
376
|
+
|
|
377
|
+
The package does not ship with a default production complexity classifier.
|
|
378
|
+
|
|
379
|
+
Complexity classification is workload-dependent. What should be considered a simple or complex query can vary depending on:
|
|
380
|
+
|
|
381
|
+
- the local model being used
|
|
382
|
+
- the cloud model being used
|
|
383
|
+
- application domain
|
|
384
|
+
- latency requirements
|
|
385
|
+
- cost policy
|
|
386
|
+
- desired routing behavior
|
|
387
|
+
|
|
388
|
+
Users should therefore train or provide a compatible classifier artifact.
|
|
389
|
+
|
|
390
|
+
When using `Router` directly:
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
from python_rerouting_library import Router
|
|
394
|
+
|
|
395
|
+
router = Router(
|
|
396
|
+
classifier_path="path/to/router_classifier.joblib"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
## Train the Router
|
|
400
|
+
|
|
401
|
+
The current example training dataset is:
|
|
402
|
+
|
|
403
|
+
```text
|
|
404
|
+
benchmarks/router_queries_50.csv
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Train and save the classifier with:
|
|
408
|
+
|
|
409
|
+
```powershell
|
|
410
|
+
python -m python_rerouting_library.training `
|
|
411
|
+
--csv benchmarks\router_queries_50.csv `
|
|
412
|
+
--output artifacts\router_classifier.joblib
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
The training pipeline uses MiniLM embeddings and Logistic Regression.
|
|
416
|
+
|
|
417
|
+
The router thresholds are runtime routing policy and are not stored as a training-time decision threshold.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Run the Full Example
|
|
422
|
+
|
|
423
|
+
After configuring the environment and training the router:
|
|
424
|
+
|
|
425
|
+
```powershell
|
|
426
|
+
python .\examples\test_full_dispatcher.py
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
A clean simple query should normally route to:
|
|
430
|
+
|
|
431
|
+
```text
|
|
432
|
+
Backend: local-llama
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
A clean complex query should normally route to:
|
|
436
|
+
|
|
437
|
+
```text
|
|
438
|
+
Backend: cloud-api
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
A detected privacy-sensitive query should route to:
|
|
442
|
+
|
|
443
|
+
```text
|
|
444
|
+
Route: privacy_override
|
|
445
|
+
Backend: local-llama
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Run Tests
|
|
451
|
+
|
|
452
|
+
```powershell
|
|
453
|
+
python -m pytest -v
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Current v0.2 regression suite:
|
|
457
|
+
|
|
458
|
+
```text
|
|
459
|
+
26 passed
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
The tests cover:
|
|
463
|
+
|
|
464
|
+
* simple → local
|
|
465
|
+
* complex → cloud
|
|
466
|
+
* uncertain → cloud
|
|
467
|
+
* clean simple local failure → cloud fallback
|
|
468
|
+
* cloud failure handling
|
|
469
|
+
* uncertainty threshold boundaries
|
|
470
|
+
* structured route decisions
|
|
471
|
+
* email detection
|
|
472
|
+
* phone-number detection
|
|
473
|
+
* SSN detection
|
|
474
|
+
* API-key detection
|
|
475
|
+
* credit-card detection
|
|
476
|
+
* Luhn validation
|
|
477
|
+
* multiple privacy categories
|
|
478
|
+
* privacy override before semantic routing
|
|
479
|
+
* verification that privacy queries do not call the router
|
|
480
|
+
* verification that privacy queries do not fall back to cloud
|
|
481
|
+
|
|
482
|
+
The automated unit tests do not call the OpenAI API.
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Route Decision Behavior
|
|
487
|
+
|
|
488
|
+
Normal semantic routes contain complexity information:
|
|
489
|
+
|
|
490
|
+
```text
|
|
491
|
+
label
|
|
492
|
+
confidence
|
|
493
|
+
complex_probability
|
|
494
|
+
latency_ms
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
For a privacy override:
|
|
498
|
+
|
|
499
|
+
```text
|
|
500
|
+
label = privacy_override
|
|
501
|
+
confidence = None
|
|
502
|
+
complex_probability = None
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
This is intentional.
|
|
506
|
+
|
|
507
|
+
The complexity classifier never ran, so the library does not invent a complexity probability.
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Privacy Override Example
|
|
512
|
+
|
|
513
|
+
Conceptually:
|
|
514
|
+
|
|
515
|
+
```python
|
|
516
|
+
result = dispatcher.run(
|
|
517
|
+
"Please review account details for alice@example.com"
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
print(result.route.label)
|
|
521
|
+
print(result.backend_name)
|
|
522
|
+
print(result.privacy_categories)
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Expected behavior:
|
|
526
|
+
|
|
527
|
+
```text
|
|
528
|
+
privacy_override
|
|
529
|
+
local-llama
|
|
530
|
+
('email',)
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
The query is not sent to the cloud.
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Version History
|
|
538
|
+
|
|
539
|
+
### v0.2.0
|
|
540
|
+
|
|
541
|
+
Adds:
|
|
542
|
+
|
|
543
|
+
* Privacy-first routing
|
|
544
|
+
* `PrivacyDetector`
|
|
545
|
+
* `PrivacyDecision`
|
|
546
|
+
* `privacy_override`
|
|
547
|
+
* Local-only processing for detected sensitive data
|
|
548
|
+
* No cloud fallback for privacy-sensitive queries
|
|
549
|
+
* Email detection
|
|
550
|
+
* Phone-number detection
|
|
551
|
+
* SSN detection
|
|
552
|
+
* API-key pattern detection
|
|
553
|
+
* Credit-card detection with Luhn validation
|
|
554
|
+
* Privacy-category observability
|
|
555
|
+
* Expanded regression tests
|
|
556
|
+
|
|
557
|
+
### v0.1.0
|
|
558
|
+
|
|
559
|
+
Introduced:
|
|
560
|
+
|
|
561
|
+
* MiniLM semantic query embeddings
|
|
562
|
+
* Logistic Regression complexity classifier
|
|
563
|
+
* Simple / uncertain / complex routing
|
|
564
|
+
* Local Llama backend
|
|
565
|
+
* Cloud LLM backend
|
|
566
|
+
* Local-to-cloud fallback for simple queries
|
|
567
|
+
* Custom backend exceptions
|
|
568
|
+
* Centralized configuration
|
|
569
|
+
* Automated regression tests
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Design Principle
|
|
574
|
+
|
|
575
|
+
The library separates three concerns:
|
|
576
|
+
|
|
577
|
+
```text
|
|
578
|
+
Policy
|
|
579
|
+
↓
|
|
580
|
+
Routing
|
|
581
|
+
↓
|
|
582
|
+
Execution
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
In v0.2:
|
|
586
|
+
|
|
587
|
+
```text
|
|
588
|
+
Privacy Detector
|
|
589
|
+
↓
|
|
590
|
+
Semantic Router
|
|
591
|
+
↓
|
|
592
|
+
Dispatcher
|
|
593
|
+
↓
|
|
594
|
+
Local / Cloud Backend
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
This means model-selection optimization happens only after the privacy policy allows the query to continue through the normal routing pipeline.
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
## Current Limitations
|
|
602
|
+
|
|
603
|
+
The current privacy detector is intentionally lightweight.
|
|
604
|
+
|
|
605
|
+
It does not yet provide:
|
|
606
|
+
|
|
607
|
+
* Named-entity recognition
|
|
608
|
+
* Address detection
|
|
609
|
+
* Medical-record detection
|
|
610
|
+
* International identity-number detection
|
|
611
|
+
* Context-aware secret detection
|
|
612
|
+
* Configurable privacy policies
|
|
613
|
+
* User-defined sensitive-data patterns
|
|
614
|
+
* Enterprise DLP integration
|
|
615
|
+
|
|
616
|
+
These are possible future extensions.
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## License
|
|
621
|
+
|
|
622
|
+
This project is licensed under the MIT License.
|
|
623
|
+
|
|
624
|
+
See the `LICENSE` file for details.
|