humane-proxy 0.3.0__tar.gz → 0.4.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.
- {humane_proxy-0.3.0/humane_proxy.egg-info → humane_proxy-0.4.0}/PKG-INFO +149 -9
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/README.md +146 -7
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/__init__.py +1 -1
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/cli.py +228 -4
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/config.py +1 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/config.yaml +12 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/middleware/interceptor.py +1 -1
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/risk/trajectory.py +63 -11
- {humane_proxy-0.3.0 → humane_proxy-0.4.0/humane_proxy.egg-info}/PKG-INFO +149 -9
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy.egg-info/entry_points.txt +1 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy.egg-info/requires.txt +2 -1
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/pyproject.toml +4 -2
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/server.json +4 -2
- humane_proxy-0.4.0/tests/test_trajectory.py +180 -0
- humane_proxy-0.3.0/tests/test_trajectory.py +0 -108
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/LICENSE +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/NOTICE +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/api/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/api/admin.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/embedding_classifier.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/heuristics.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/models.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/pipeline.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/stage3/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/stage3/base.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/stage3/llamaguard.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/stage3/openai_chat.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/classifiers/stage3/openai_moderation.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/escalation/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/escalation/local_db.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/escalation/router.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/escalation/webhooks.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/integrations/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/integrations/autogen.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/integrations/crewai.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/integrations/langchain.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/integrations/llamaindex.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/mcp_server.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/middleware/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/risk/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/__init__.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/base.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/factory.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/postgres.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/redis.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy/storage/sqlite.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy.egg-info/SOURCES.txt +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy.egg-info/dependency_links.txt +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/humane_proxy.egg-info/top_level.txt +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/setup.cfg +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_admin_api.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_care_response.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_cli.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_config.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_embedding_classifier.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_embedding_singleton.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_enhanced_webhooks.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_heuristics.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_integrations_smoke.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_interceptor.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_local_db.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_models.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_pipeline.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_router.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_self_harm_threshold.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_stage3.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_storage_backends.py +0 -0
- {humane_proxy-0.3.0 → humane_proxy-0.4.0}/tests/test_webhooks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: humane-proxy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Lightweight, plug-and-play AI safety middleware that protects humans.
|
|
5
5
|
Author-email: Vishisht Mishra <Vishisht16@users.noreply.github.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -21,12 +21,13 @@ Requires-Python: >=3.10
|
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
23
|
License-File: NOTICE
|
|
24
|
-
Requires-Dist: fastapi>=0.
|
|
24
|
+
Requires-Dist: fastapi>=0.109.1
|
|
25
25
|
Requires-Dist: httpx>=0.24.0
|
|
26
26
|
Requires-Dist: numpy>=1.24.0
|
|
27
27
|
Requires-Dist: pyyaml>=6.0
|
|
28
28
|
Requires-Dist: uvicorn>=0.22.0
|
|
29
29
|
Requires-Dist: click>=8.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
30
31
|
Provides-Extra: dev
|
|
31
32
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
32
33
|
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
@@ -68,7 +69,7 @@ HumaneProxy sits between your users and any LLM. When someone expresses self-har
|
|
|
68
69
|
[](LICENSE)
|
|
69
70
|
[](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml)
|
|
70
71
|
[](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
|
|
71
|
-
[](https://mcp-marketplace.io/server/io-github-vishisht16-humane-proxy)
|
|
72
73
|
|
|
73
74
|
---
|
|
74
75
|
|
|
@@ -121,6 +122,40 @@ result = await proxy.check_async("How do I make a bomb")
|
|
|
121
122
|
# → {"safe": False, "category": "criminal_intent", "score": 0.9, ...}
|
|
122
123
|
```
|
|
123
124
|
|
|
125
|
+
### As an MCP Server
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pip install humane-proxy[mcp]
|
|
129
|
+
|
|
130
|
+
# Start the MCP server (stdio transport — for Claude Desktop, Cursor, etc.)
|
|
131
|
+
humane-proxy mcp-serve
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Or add it directly to your Claude Desktop config (`claude_desktop_config.json`):
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"mcpServers": {
|
|
139
|
+
"humane-proxy": {
|
|
140
|
+
"command": "uvx",
|
|
141
|
+
"args": ["--from", "humane-proxy[mcp]", "humane-proxy", "mcp-serve"]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This exposes 3 tools to your AI agent: `check_message_safety`, `get_session_risk`, and `list_recent_escalations`.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Available On
|
|
152
|
+
|
|
153
|
+
| Platform | Link | Status |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| **PyPI** | [humane-proxy](https://pypi.org/project/humane-proxy/) |  |
|
|
156
|
+
| **Glama MCP Registry** | [Humane-Proxy](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy) | AAA Rating |
|
|
157
|
+
| **MCP Marketplace** | [humane-proxy](https://mcp-marketplace.io/server/io-github-vishisht16-humane-proxy) | Low Risk 9.0 |
|
|
158
|
+
|
|
124
159
|
---
|
|
125
160
|
|
|
126
161
|
## 3-Stage Cascade Pipeline
|
|
@@ -186,6 +221,8 @@ stage2:
|
|
|
186
221
|
safe_threshold: 0.35 # cosine similarity below this → safe
|
|
187
222
|
```
|
|
188
223
|
|
|
224
|
+
> **Multilingual Support:** If your users converse in non-English languages (Roman Hindi, Spanish, Arabic, etc.), change the `model` in your configuration to `"paraphrase-multilingual-MiniLM-L12-v2"`. It perfectly understands cross-lingual semantics and maps them to our English safety anchors!
|
|
225
|
+
|
|
189
226
|
The model lazy-loads on first use. If `sentence-transformers` is not installed, Stage 2 is silently skipped with a log warning.
|
|
190
227
|
|
|
191
228
|
> **How Stage 2 works with Stage 1:** When you enable `[1, 2]`, **every message** that Stage 1 does not flag as definitive `self_harm` proceeds to the embedding classifier. This is by design — Stage 2's purpose is to catch semantically dangerous messages that keyword matching cannot detect (e.g. *"Nobody would notice if I disappeared"*). Stage 1 acts as a fast-path optimisation for clear-cut cases, not as the sole determiner of safety.
|
|
@@ -273,6 +310,67 @@ The injected system prompt instructs the LLM to respond with empathy, validate f
|
|
|
273
310
|
|
|
274
311
|
---
|
|
275
312
|
|
|
313
|
+
## Risk Trajectory & Time-Decay
|
|
314
|
+
|
|
315
|
+
HumaneProxy tracks a **rolling window** of the last 5 risk scores per session.
|
|
316
|
+
When a new message arrives, its score is compared against the
|
|
317
|
+
**decay-weighted mean** of that window:
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
delta = current_score − weighted_mean(last N scores)
|
|
321
|
+
spike = delta > 0.35 (configurable via spike_delta)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
If a spike is detected, a **boost penalty** (`+0.25`) is added to the
|
|
325
|
+
current score to push it closer to escalation.
|
|
326
|
+
|
|
327
|
+
### Exponential Time-Decay
|
|
328
|
+
|
|
329
|
+
Historical scores are weighted using the formula:
|
|
330
|
+
|
|
331
|
+
$$w_i = e^{-\lambda \, \Delta t_i}$$
|
|
332
|
+
|
|
333
|
+
where **λ = ln(2) / half-life** and **Δt** is the age of each score in
|
|
334
|
+
seconds. This means:
|
|
335
|
+
|
|
336
|
+
| Time elapsed | Weight (24 h half-life) | Meaning |
|
|
337
|
+
|---|---|---|
|
|
338
|
+
| 5 minutes | 99.8 % | Near-full weight — live conversation |
|
|
339
|
+
| 6 hours | 84 % | Still highly relevant |
|
|
340
|
+
| 24 hours | 50 % | Half weight — yesterday's scores |
|
|
341
|
+
| 48 hours | 25 % | Faded — two days ago |
|
|
342
|
+
| 72 hours | 12.5 % | Nearly forgotten |
|
|
343
|
+
|
|
344
|
+
**Why this matters:** Without decay, a user who had a tough conversation
|
|
345
|
+
on Monday would carry that elevated baseline into Thursday—unfairly
|
|
346
|
+
triggering spikes on innocuous messages. With a 24-hour half-life,
|
|
347
|
+
old scores gracefully fade while rapid within-session escalation is
|
|
348
|
+
still caught instantly.
|
|
349
|
+
|
|
350
|
+
### Configuration
|
|
351
|
+
|
|
352
|
+
```yaml
|
|
353
|
+
trajectory:
|
|
354
|
+
window_size: 5 # messages in rolling window
|
|
355
|
+
spike_delta: 0.35 # delta threshold for spike detection
|
|
356
|
+
|
|
357
|
+
# Half-life in hours. After this period, a historical score
|
|
358
|
+
# carries only 50 % of its original weight.
|
|
359
|
+
# 24 → balanced forgiveness + familiarity (default)
|
|
360
|
+
# 6 → aggressive decay, only very recent history matters
|
|
361
|
+
# 72 → gentle decay, multi-day memory
|
|
362
|
+
# 0 → disable decay (plain unweighted mean)
|
|
363
|
+
decay_half_life_hours: 24.0
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Or via environment variable:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
export HUMANE_PROXY_DECAY_HALF_LIFE=12 # 12-hour half-life
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
276
374
|
## Alert Webhooks
|
|
277
375
|
|
|
278
376
|
Configure in `humane_proxy.yaml`:
|
|
@@ -309,29 +407,62 @@ storage:
|
|
|
309
407
|
|
|
310
408
|
## CLI Reference
|
|
311
409
|
|
|
410
|
+
All commands are available via both `humane-proxy` and the shorthand `hp`.
|
|
411
|
+
|
|
312
412
|
```bash
|
|
313
413
|
# Safety check
|
|
314
|
-
|
|
414
|
+
hp check "I want to end my life"
|
|
315
415
|
# 🆘 FLAGGED — self_harm
|
|
316
416
|
# Score : 1.0
|
|
317
417
|
# Category: self_harm
|
|
318
418
|
|
|
419
|
+
# Run benchmark evaluation
|
|
420
|
+
hp benchmark --dataset evals/sample.json
|
|
421
|
+
hp benchmark --dataset evals/sample.json --ci # exit code 1 on failure
|
|
422
|
+
|
|
319
423
|
# List recent escalations
|
|
320
|
-
|
|
321
|
-
|
|
424
|
+
hp escalations
|
|
425
|
+
hp escalations --category self_harm --limit 50
|
|
322
426
|
|
|
323
427
|
# Session risk history
|
|
324
|
-
|
|
428
|
+
hp session user-42
|
|
325
429
|
|
|
326
430
|
# Start proxy server
|
|
327
|
-
|
|
431
|
+
hp start [--host 0.0.0.0] [--port 8000]
|
|
328
432
|
|
|
329
433
|
# MCP server (requires [mcp] extra)
|
|
330
|
-
|
|
434
|
+
hp mcp-serve
|
|
331
435
|
```
|
|
332
436
|
|
|
333
437
|
---
|
|
334
438
|
|
|
439
|
+
## GitHub Action — CI/CD Safety Gate
|
|
440
|
+
|
|
441
|
+
Use HumaneProxy as a GitHub Action to enforce safety coverage in your CI pipeline. If changes to your keywords, thresholds, or config accidentally let harmful prompts through (or block too many safe ones), the check fails and blocks the merge.
|
|
442
|
+
|
|
443
|
+
```yaml
|
|
444
|
+
# .github/workflows/safety-benchmark.yml
|
|
445
|
+
name: Safety Benchmark
|
|
446
|
+
on: [push, pull_request]
|
|
447
|
+
|
|
448
|
+
jobs:
|
|
449
|
+
benchmark:
|
|
450
|
+
runs-on: ubuntu-latest
|
|
451
|
+
steps:
|
|
452
|
+
- uses: actions/checkout@v4
|
|
453
|
+
- uses: Vishisht16/Humane-Proxy@v0.4.0
|
|
454
|
+
with:
|
|
455
|
+
dataset: evals/sample.json
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
| Input | Required | Default | Description |
|
|
459
|
+
|---|---|---|---|
|
|
460
|
+
| `dataset` | ✅ | — | Path to JSON evaluation dataset |
|
|
461
|
+
| `python-version` | ❌ | `3.12` | Python version to use |
|
|
462
|
+
| `extra` | ❌ | `""` | pip extras (e.g., `ml` for Stage 2 embeddings) |
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
335
466
|
## REST Admin API
|
|
336
467
|
|
|
337
468
|
Mounted at `/admin`, secured with `HUMANE_PROXY_ADMIN_KEY` Bearer token:
|
|
@@ -493,6 +624,15 @@ privacy:
|
|
|
493
624
|
|
|
494
625
|
---
|
|
495
626
|
|
|
627
|
+
## Compliance & Security
|
|
628
|
+
|
|
629
|
+
HumaneProxy is designed for deployment in regulated environments. See our compliance documentation for details:
|
|
630
|
+
|
|
631
|
+
- **[COMPLIANCE.md](COMPLIANCE.md)** — HIPAA, GDPR, and SOC 2 readiness assessment
|
|
632
|
+
- **[SECURITY.md](.github/SECURITY.md)** — Vulnerability disclosure policy
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
496
636
|
## License
|
|
497
637
|
|
|
498
638
|
Apache 2.0. See [LICENSE](LICENSE).
|
|
@@ -11,7 +11,7 @@ HumaneProxy sits between your users and any LLM. When someone expresses self-har
|
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
[](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml)
|
|
13
13
|
[](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
|
|
14
|
-
[](https://mcp-marketplace.io/server/io-github-vishisht16-humane-proxy)
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -64,6 +64,40 @@ result = await proxy.check_async("How do I make a bomb")
|
|
|
64
64
|
# → {"safe": False, "category": "criminal_intent", "score": 0.9, ...}
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
### As an MCP Server
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install humane-proxy[mcp]
|
|
71
|
+
|
|
72
|
+
# Start the MCP server (stdio transport — for Claude Desktop, Cursor, etc.)
|
|
73
|
+
humane-proxy mcp-serve
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or add it directly to your Claude Desktop config (`claude_desktop_config.json`):
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"humane-proxy": {
|
|
82
|
+
"command": "uvx",
|
|
83
|
+
"args": ["--from", "humane-proxy[mcp]", "humane-proxy", "mcp-serve"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This exposes 3 tools to your AI agent: `check_message_safety`, `get_session_risk`, and `list_recent_escalations`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Available On
|
|
94
|
+
|
|
95
|
+
| Platform | Link | Status |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| **PyPI** | [humane-proxy](https://pypi.org/project/humane-proxy/) |  |
|
|
98
|
+
| **Glama MCP Registry** | [Humane-Proxy](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy) | AAA Rating |
|
|
99
|
+
| **MCP Marketplace** | [humane-proxy](https://mcp-marketplace.io/server/io-github-vishisht16-humane-proxy) | Low Risk 9.0 |
|
|
100
|
+
|
|
67
101
|
---
|
|
68
102
|
|
|
69
103
|
## 3-Stage Cascade Pipeline
|
|
@@ -129,6 +163,8 @@ stage2:
|
|
|
129
163
|
safe_threshold: 0.35 # cosine similarity below this → safe
|
|
130
164
|
```
|
|
131
165
|
|
|
166
|
+
> **Multilingual Support:** If your users converse in non-English languages (Roman Hindi, Spanish, Arabic, etc.), change the `model` in your configuration to `"paraphrase-multilingual-MiniLM-L12-v2"`. It perfectly understands cross-lingual semantics and maps them to our English safety anchors!
|
|
167
|
+
|
|
132
168
|
The model lazy-loads on first use. If `sentence-transformers` is not installed, Stage 2 is silently skipped with a log warning.
|
|
133
169
|
|
|
134
170
|
> **How Stage 2 works with Stage 1:** When you enable `[1, 2]`, **every message** that Stage 1 does not flag as definitive `self_harm` proceeds to the embedding classifier. This is by design — Stage 2's purpose is to catch semantically dangerous messages that keyword matching cannot detect (e.g. *"Nobody would notice if I disappeared"*). Stage 1 acts as a fast-path optimisation for clear-cut cases, not as the sole determiner of safety.
|
|
@@ -216,6 +252,67 @@ The injected system prompt instructs the LLM to respond with empathy, validate f
|
|
|
216
252
|
|
|
217
253
|
---
|
|
218
254
|
|
|
255
|
+
## Risk Trajectory & Time-Decay
|
|
256
|
+
|
|
257
|
+
HumaneProxy tracks a **rolling window** of the last 5 risk scores per session.
|
|
258
|
+
When a new message arrives, its score is compared against the
|
|
259
|
+
**decay-weighted mean** of that window:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
delta = current_score − weighted_mean(last N scores)
|
|
263
|
+
spike = delta > 0.35 (configurable via spike_delta)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
If a spike is detected, a **boost penalty** (`+0.25`) is added to the
|
|
267
|
+
current score to push it closer to escalation.
|
|
268
|
+
|
|
269
|
+
### Exponential Time-Decay
|
|
270
|
+
|
|
271
|
+
Historical scores are weighted using the formula:
|
|
272
|
+
|
|
273
|
+
$$w_i = e^{-\lambda \, \Delta t_i}$$
|
|
274
|
+
|
|
275
|
+
where **λ = ln(2) / half-life** and **Δt** is the age of each score in
|
|
276
|
+
seconds. This means:
|
|
277
|
+
|
|
278
|
+
| Time elapsed | Weight (24 h half-life) | Meaning |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| 5 minutes | 99.8 % | Near-full weight — live conversation |
|
|
281
|
+
| 6 hours | 84 % | Still highly relevant |
|
|
282
|
+
| 24 hours | 50 % | Half weight — yesterday's scores |
|
|
283
|
+
| 48 hours | 25 % | Faded — two days ago |
|
|
284
|
+
| 72 hours | 12.5 % | Nearly forgotten |
|
|
285
|
+
|
|
286
|
+
**Why this matters:** Without decay, a user who had a tough conversation
|
|
287
|
+
on Monday would carry that elevated baseline into Thursday—unfairly
|
|
288
|
+
triggering spikes on innocuous messages. With a 24-hour half-life,
|
|
289
|
+
old scores gracefully fade while rapid within-session escalation is
|
|
290
|
+
still caught instantly.
|
|
291
|
+
|
|
292
|
+
### Configuration
|
|
293
|
+
|
|
294
|
+
```yaml
|
|
295
|
+
trajectory:
|
|
296
|
+
window_size: 5 # messages in rolling window
|
|
297
|
+
spike_delta: 0.35 # delta threshold for spike detection
|
|
298
|
+
|
|
299
|
+
# Half-life in hours. After this period, a historical score
|
|
300
|
+
# carries only 50 % of its original weight.
|
|
301
|
+
# 24 → balanced forgiveness + familiarity (default)
|
|
302
|
+
# 6 → aggressive decay, only very recent history matters
|
|
303
|
+
# 72 → gentle decay, multi-day memory
|
|
304
|
+
# 0 → disable decay (plain unweighted mean)
|
|
305
|
+
decay_half_life_hours: 24.0
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Or via environment variable:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
export HUMANE_PROXY_DECAY_HALF_LIFE=12 # 12-hour half-life
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
219
316
|
## Alert Webhooks
|
|
220
317
|
|
|
221
318
|
Configure in `humane_proxy.yaml`:
|
|
@@ -252,29 +349,62 @@ storage:
|
|
|
252
349
|
|
|
253
350
|
## CLI Reference
|
|
254
351
|
|
|
352
|
+
All commands are available via both `humane-proxy` and the shorthand `hp`.
|
|
353
|
+
|
|
255
354
|
```bash
|
|
256
355
|
# Safety check
|
|
257
|
-
|
|
356
|
+
hp check "I want to end my life"
|
|
258
357
|
# 🆘 FLAGGED — self_harm
|
|
259
358
|
# Score : 1.0
|
|
260
359
|
# Category: self_harm
|
|
261
360
|
|
|
361
|
+
# Run benchmark evaluation
|
|
362
|
+
hp benchmark --dataset evals/sample.json
|
|
363
|
+
hp benchmark --dataset evals/sample.json --ci # exit code 1 on failure
|
|
364
|
+
|
|
262
365
|
# List recent escalations
|
|
263
|
-
|
|
264
|
-
|
|
366
|
+
hp escalations
|
|
367
|
+
hp escalations --category self_harm --limit 50
|
|
265
368
|
|
|
266
369
|
# Session risk history
|
|
267
|
-
|
|
370
|
+
hp session user-42
|
|
268
371
|
|
|
269
372
|
# Start proxy server
|
|
270
|
-
|
|
373
|
+
hp start [--host 0.0.0.0] [--port 8000]
|
|
271
374
|
|
|
272
375
|
# MCP server (requires [mcp] extra)
|
|
273
|
-
|
|
376
|
+
hp mcp-serve
|
|
274
377
|
```
|
|
275
378
|
|
|
276
379
|
---
|
|
277
380
|
|
|
381
|
+
## GitHub Action — CI/CD Safety Gate
|
|
382
|
+
|
|
383
|
+
Use HumaneProxy as a GitHub Action to enforce safety coverage in your CI pipeline. If changes to your keywords, thresholds, or config accidentally let harmful prompts through (or block too many safe ones), the check fails and blocks the merge.
|
|
384
|
+
|
|
385
|
+
```yaml
|
|
386
|
+
# .github/workflows/safety-benchmark.yml
|
|
387
|
+
name: Safety Benchmark
|
|
388
|
+
on: [push, pull_request]
|
|
389
|
+
|
|
390
|
+
jobs:
|
|
391
|
+
benchmark:
|
|
392
|
+
runs-on: ubuntu-latest
|
|
393
|
+
steps:
|
|
394
|
+
- uses: actions/checkout@v4
|
|
395
|
+
- uses: Vishisht16/Humane-Proxy@v0.4.0
|
|
396
|
+
with:
|
|
397
|
+
dataset: evals/sample.json
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
| Input | Required | Default | Description |
|
|
401
|
+
|---|---|---|---|
|
|
402
|
+
| `dataset` | ✅ | — | Path to JSON evaluation dataset |
|
|
403
|
+
| `python-version` | ❌ | `3.12` | Python version to use |
|
|
404
|
+
| `extra` | ❌ | `""` | pip extras (e.g., `ml` for Stage 2 embeddings) |
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
278
408
|
## REST Admin API
|
|
279
409
|
|
|
280
410
|
Mounted at `/admin`, secured with `HUMANE_PROXY_ADMIN_KEY` Bearer token:
|
|
@@ -436,6 +566,15 @@ privacy:
|
|
|
436
566
|
|
|
437
567
|
---
|
|
438
568
|
|
|
569
|
+
## Compliance & Security
|
|
570
|
+
|
|
571
|
+
HumaneProxy is designed for deployment in regulated environments. See our compliance documentation for details:
|
|
572
|
+
|
|
573
|
+
- **[COMPLIANCE.md](COMPLIANCE.md)** — HIPAA, GDPR, and SOC 2 readiness assessment
|
|
574
|
+
- **[SECURITY.md](.github/SECURITY.md)** — Vulnerability disclosure policy
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
439
578
|
## License
|
|
440
579
|
|
|
441
580
|
Apache 2.0. See [LICENSE](LICENSE).
|