nope-net 0.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.
- nope_net-0.1.0/.env.example +5 -0
- nope_net-0.1.0/.gitignore +36 -0
- nope_net-0.1.0/PKG-INFO +261 -0
- nope_net-0.1.0/README.md +231 -0
- nope_net-0.1.0/pyproject.toml +61 -0
- nope_net-0.1.0/src/nope_net/__init__.py +102 -0
- nope_net-0.1.0/src/nope_net/client.py +434 -0
- nope_net-0.1.0/src/nope_net/errors.py +112 -0
- nope_net-0.1.0/src/nope_net/py.typed +0 -0
- nope_net-0.1.0/src/nope_net/types.py +512 -0
- nope_net-0.1.0/test_integration.py +292 -0
- nope_net-0.1.0/tests/__init__.py +1 -0
- nope_net-0.1.0/tests/test_client.py +259 -0
- nope_net-0.1.0/tests/test_integration.py +230 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
ENV/
|
|
16
|
+
|
|
17
|
+
# IDE
|
|
18
|
+
.idea/
|
|
19
|
+
.vscode/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# Testing
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
.ruff_cache/
|
|
29
|
+
|
|
30
|
+
# Environment
|
|
31
|
+
.env
|
|
32
|
+
.env.local
|
|
33
|
+
|
|
34
|
+
# OS
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
nope_net-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nope-net
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the NOPE safety API - risk classification for conversations
|
|
5
|
+
Project-URL: Homepage, https://nope.net
|
|
6
|
+
Project-URL: Documentation, https://nope.net/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/nope-net/python-sdk
|
|
8
|
+
Author-email: NOPE <support@nope.net>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: ai,classification,crisis,mental-health,risk,safety
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Requires-Dist: httpx>=0.25.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-httpx>=0.21.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# NOPE Python SDK
|
|
32
|
+
|
|
33
|
+
[](https://badge.fury.io/py/nope-net)
|
|
34
|
+
[](https://www.python.org/downloads/)
|
|
35
|
+
[](https://opensource.org/licenses/MIT)
|
|
36
|
+
|
|
37
|
+
Python SDK for the [NOPE](https://nope.net) safety API - risk classification for conversations.
|
|
38
|
+
|
|
39
|
+
NOPE analyzes text conversations for mental-health and safeguarding risk. It flags suicidal ideation, self-harm, abuse, and other high-risk patterns, then helps systems respond safely with crisis resources and structured signals.
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Python 3.9 or higher
|
|
44
|
+
- A NOPE API key ([get one here](https://dashboard.nope.net))
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install nope-net
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from nope_net import NopeClient
|
|
56
|
+
|
|
57
|
+
# Get your API key from https://dashboard.nope.net
|
|
58
|
+
client = NopeClient(api_key="nope_live_...")
|
|
59
|
+
|
|
60
|
+
result = client.evaluate(
|
|
61
|
+
messages=[
|
|
62
|
+
{"role": "user", "content": "I've been feeling really down lately"},
|
|
63
|
+
{"role": "assistant", "content": "I hear you. Can you tell me more?"},
|
|
64
|
+
{"role": "user", "content": "I just don't see the point anymore"}
|
|
65
|
+
],
|
|
66
|
+
config={"user_country": "US"}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
print(f"Severity: {result.summary.speaker_severity}") # e.g., "moderate", "high"
|
|
70
|
+
print(f"Imminence: {result.summary.speaker_imminence}") # e.g., "subacute", "urgent"
|
|
71
|
+
|
|
72
|
+
# Access crisis resources
|
|
73
|
+
for resource in result.crisis_resources:
|
|
74
|
+
print(f" {resource.name}: {resource.phone}")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Async Usage
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from nope_net import AsyncNopeClient
|
|
81
|
+
|
|
82
|
+
async with AsyncNopeClient(api_key="nope_live_...") as client:
|
|
83
|
+
result = await client.evaluate(
|
|
84
|
+
messages=[{"role": "user", "content": "I need help"}],
|
|
85
|
+
config={"user_country": "US"}
|
|
86
|
+
)
|
|
87
|
+
print(f"Severity: {result.summary.speaker_severity}")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
client = NopeClient(
|
|
94
|
+
api_key="nope_live_...", # Required for production
|
|
95
|
+
base_url="https://api.nope.net", # Optional, for self-hosted
|
|
96
|
+
timeout=30.0, # Request timeout in seconds
|
|
97
|
+
)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Evaluate Options
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
result = client.evaluate(
|
|
104
|
+
messages=[...],
|
|
105
|
+
config={
|
|
106
|
+
"user_country": "US", # ISO country code for crisis resources
|
|
107
|
+
"locale": "en-US", # Language/region
|
|
108
|
+
"user_age_band": "adult", # "adult", "minor", or "unknown"
|
|
109
|
+
"dry_run": False, # If True, don't log or trigger webhooks
|
|
110
|
+
},
|
|
111
|
+
user_context="User has history of anxiety", # Optional context
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Response Structure
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
result = client.evaluate(messages=[...], config={"user_country": "US"})
|
|
119
|
+
|
|
120
|
+
# Summary (speaker-focused)
|
|
121
|
+
result.summary.speaker_severity # "none", "mild", "moderate", "high", "critical"
|
|
122
|
+
result.summary.speaker_imminence # "not_applicable", "chronic", "subacute", "urgent", "emergency"
|
|
123
|
+
result.summary.any_third_party_risk # bool
|
|
124
|
+
result.summary.primary_concerns # Narrative summary string
|
|
125
|
+
|
|
126
|
+
# Communication style
|
|
127
|
+
result.communication.styles # [CommunicationStyleAssessment(style="direct", confidence=0.9), ...]
|
|
128
|
+
result.communication.language # "en"
|
|
129
|
+
|
|
130
|
+
# Individual risks (subject + type)
|
|
131
|
+
for risk in result.risks:
|
|
132
|
+
print(f"{risk.subject} {risk.type}: {risk.severity} ({risk.imminence})")
|
|
133
|
+
print(f" Confidence: {risk.confidence}, Subject confidence: {risk.subject_confidence}")
|
|
134
|
+
print(f" Features: {risk.features}")
|
|
135
|
+
|
|
136
|
+
# Crisis resources (matched to user's country)
|
|
137
|
+
for resource in result.crisis_resources:
|
|
138
|
+
print(f"{resource.name}")
|
|
139
|
+
if resource.phone:
|
|
140
|
+
print(f" Phone: {resource.phone}")
|
|
141
|
+
if resource.text_instructions:
|
|
142
|
+
print(f" Text: {resource.text_instructions}")
|
|
143
|
+
|
|
144
|
+
# Recommended reply (if configured)
|
|
145
|
+
if result.recommended_reply:
|
|
146
|
+
print(f"Suggested response: {result.recommended_reply.content}")
|
|
147
|
+
|
|
148
|
+
# Legal/safeguarding flags
|
|
149
|
+
if result.legal_flags:
|
|
150
|
+
if result.legal_flags.ipv and result.legal_flags.ipv.indicated:
|
|
151
|
+
print(f"IPV detected - lethality: {result.legal_flags.ipv.lethality_risk}")
|
|
152
|
+
if result.legal_flags.mandatory_reporting and result.legal_flags.mandatory_reporting.indicated:
|
|
153
|
+
print(f"Mandatory reporting: {result.legal_flags.mandatory_reporting.context}")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Error Handling
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from nope_net import (
|
|
160
|
+
NopeClient,
|
|
161
|
+
NopeAuthError,
|
|
162
|
+
NopeRateLimitError,
|
|
163
|
+
NopeValidationError,
|
|
164
|
+
NopeServerError,
|
|
165
|
+
NopeConnectionError,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
client = NopeClient(api_key="nope_live_...")
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
result = client.evaluate(messages=[...], config={})
|
|
172
|
+
except NopeAuthError:
|
|
173
|
+
print("Invalid API key")
|
|
174
|
+
except NopeRateLimitError as e:
|
|
175
|
+
print(f"Rate limited. Retry after {e.retry_after}s")
|
|
176
|
+
except NopeValidationError as e:
|
|
177
|
+
print(f"Invalid request: {e.message}")
|
|
178
|
+
except NopeServerError:
|
|
179
|
+
print("Server error, try again later")
|
|
180
|
+
except NopeConnectionError:
|
|
181
|
+
print("Could not connect to API")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Plain Text Input
|
|
185
|
+
|
|
186
|
+
For transcripts or session notes without structured messages:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
result = client.evaluate(
|
|
190
|
+
text="Patient expressed feelings of hopelessness and mentioned not wanting to continue.",
|
|
191
|
+
config={"user_country": "US"}
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Risk Taxonomy
|
|
196
|
+
|
|
197
|
+
NOPE uses an orthogonal taxonomy separating WHO is at risk from WHAT type of harm:
|
|
198
|
+
|
|
199
|
+
### Subjects (who is at risk)
|
|
200
|
+
|
|
201
|
+
| Subject | Description |
|
|
202
|
+
|---------|-------------|
|
|
203
|
+
| `self` | The speaker is at risk |
|
|
204
|
+
| `other` | Someone else is at risk (friend, family, stranger) |
|
|
205
|
+
| `unknown` | Ambiguous - "asking for a friend" territory |
|
|
206
|
+
|
|
207
|
+
### Risk Types (what type of harm)
|
|
208
|
+
|
|
209
|
+
| Type | Description |
|
|
210
|
+
|------|-------------|
|
|
211
|
+
| `suicide` | Self-directed lethal intent |
|
|
212
|
+
| `self_harm` | Non-suicidal self-injury (NSSI) |
|
|
213
|
+
| `self_neglect` | Severe self-care failure |
|
|
214
|
+
| `violence` | Harm directed at others |
|
|
215
|
+
| `abuse` | Physical, emotional, sexual, financial abuse |
|
|
216
|
+
| `sexual_violence` | Rape, sexual assault, coerced acts |
|
|
217
|
+
| `neglect` | Failure to provide care for dependents |
|
|
218
|
+
| `exploitation` | Trafficking, forced labor, sextortion |
|
|
219
|
+
| `stalking` | Persistent unwanted contact/surveillance |
|
|
220
|
+
|
|
221
|
+
## Severity & Imminence
|
|
222
|
+
|
|
223
|
+
**Severity** (how serious):
|
|
224
|
+
| Level | Description |
|
|
225
|
+
|-------|-------------|
|
|
226
|
+
| `none` | No concern |
|
|
227
|
+
| `mild` | Low-level concern |
|
|
228
|
+
| `moderate` | Significant concern |
|
|
229
|
+
| `high` | Serious concern |
|
|
230
|
+
| `critical` | Extreme concern |
|
|
231
|
+
|
|
232
|
+
**Imminence** (how soon):
|
|
233
|
+
| Level | Description |
|
|
234
|
+
|-------|-------------|
|
|
235
|
+
| `not_applicable` | No time-based concern |
|
|
236
|
+
| `chronic` | Ongoing, long-term |
|
|
237
|
+
| `subacute` | Days to weeks |
|
|
238
|
+
| `urgent` | Hours to days |
|
|
239
|
+
| `emergency` | Immediate |
|
|
240
|
+
|
|
241
|
+
## API Reference
|
|
242
|
+
|
|
243
|
+
For full API documentation, see [docs.nope.net](https://docs.nope.net).
|
|
244
|
+
|
|
245
|
+
## Versioning
|
|
246
|
+
|
|
247
|
+
This SDK follows [Semantic Versioning](https://semver.org/). While in 0.x.x, breaking changes may occur in minor versions.
|
|
248
|
+
|
|
249
|
+
## Changelog
|
|
250
|
+
|
|
251
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT - see [LICENSE](LICENSE) for details.
|
|
256
|
+
|
|
257
|
+
## Support
|
|
258
|
+
|
|
259
|
+
- Documentation: [docs.nope.net](https://docs.nope.net)
|
|
260
|
+
- Dashboard: [dashboard.nope.net](https://dashboard.nope.net)
|
|
261
|
+
- Issues: [github.com/nope-net/python-sdk/issues](https://github.com/nope-net/python-sdk/issues)
|
nope_net-0.1.0/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# NOPE Python SDK
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/nope-net)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
Python SDK for the [NOPE](https://nope.net) safety API - risk classification for conversations.
|
|
8
|
+
|
|
9
|
+
NOPE analyzes text conversations for mental-health and safeguarding risk. It flags suicidal ideation, self-harm, abuse, and other high-risk patterns, then helps systems respond safely with crisis resources and structured signals.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Python 3.9 or higher
|
|
14
|
+
- A NOPE API key ([get one here](https://dashboard.nope.net))
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install nope-net
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from nope_net import NopeClient
|
|
26
|
+
|
|
27
|
+
# Get your API key from https://dashboard.nope.net
|
|
28
|
+
client = NopeClient(api_key="nope_live_...")
|
|
29
|
+
|
|
30
|
+
result = client.evaluate(
|
|
31
|
+
messages=[
|
|
32
|
+
{"role": "user", "content": "I've been feeling really down lately"},
|
|
33
|
+
{"role": "assistant", "content": "I hear you. Can you tell me more?"},
|
|
34
|
+
{"role": "user", "content": "I just don't see the point anymore"}
|
|
35
|
+
],
|
|
36
|
+
config={"user_country": "US"}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
print(f"Severity: {result.summary.speaker_severity}") # e.g., "moderate", "high"
|
|
40
|
+
print(f"Imminence: {result.summary.speaker_imminence}") # e.g., "subacute", "urgent"
|
|
41
|
+
|
|
42
|
+
# Access crisis resources
|
|
43
|
+
for resource in result.crisis_resources:
|
|
44
|
+
print(f" {resource.name}: {resource.phone}")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Async Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from nope_net import AsyncNopeClient
|
|
51
|
+
|
|
52
|
+
async with AsyncNopeClient(api_key="nope_live_...") as client:
|
|
53
|
+
result = await client.evaluate(
|
|
54
|
+
messages=[{"role": "user", "content": "I need help"}],
|
|
55
|
+
config={"user_country": "US"}
|
|
56
|
+
)
|
|
57
|
+
print(f"Severity: {result.summary.speaker_severity}")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
client = NopeClient(
|
|
64
|
+
api_key="nope_live_...", # Required for production
|
|
65
|
+
base_url="https://api.nope.net", # Optional, for self-hosted
|
|
66
|
+
timeout=30.0, # Request timeout in seconds
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Evaluate Options
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
result = client.evaluate(
|
|
74
|
+
messages=[...],
|
|
75
|
+
config={
|
|
76
|
+
"user_country": "US", # ISO country code for crisis resources
|
|
77
|
+
"locale": "en-US", # Language/region
|
|
78
|
+
"user_age_band": "adult", # "adult", "minor", or "unknown"
|
|
79
|
+
"dry_run": False, # If True, don't log or trigger webhooks
|
|
80
|
+
},
|
|
81
|
+
user_context="User has history of anxiety", # Optional context
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Response Structure
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
result = client.evaluate(messages=[...], config={"user_country": "US"})
|
|
89
|
+
|
|
90
|
+
# Summary (speaker-focused)
|
|
91
|
+
result.summary.speaker_severity # "none", "mild", "moderate", "high", "critical"
|
|
92
|
+
result.summary.speaker_imminence # "not_applicable", "chronic", "subacute", "urgent", "emergency"
|
|
93
|
+
result.summary.any_third_party_risk # bool
|
|
94
|
+
result.summary.primary_concerns # Narrative summary string
|
|
95
|
+
|
|
96
|
+
# Communication style
|
|
97
|
+
result.communication.styles # [CommunicationStyleAssessment(style="direct", confidence=0.9), ...]
|
|
98
|
+
result.communication.language # "en"
|
|
99
|
+
|
|
100
|
+
# Individual risks (subject + type)
|
|
101
|
+
for risk in result.risks:
|
|
102
|
+
print(f"{risk.subject} {risk.type}: {risk.severity} ({risk.imminence})")
|
|
103
|
+
print(f" Confidence: {risk.confidence}, Subject confidence: {risk.subject_confidence}")
|
|
104
|
+
print(f" Features: {risk.features}")
|
|
105
|
+
|
|
106
|
+
# Crisis resources (matched to user's country)
|
|
107
|
+
for resource in result.crisis_resources:
|
|
108
|
+
print(f"{resource.name}")
|
|
109
|
+
if resource.phone:
|
|
110
|
+
print(f" Phone: {resource.phone}")
|
|
111
|
+
if resource.text_instructions:
|
|
112
|
+
print(f" Text: {resource.text_instructions}")
|
|
113
|
+
|
|
114
|
+
# Recommended reply (if configured)
|
|
115
|
+
if result.recommended_reply:
|
|
116
|
+
print(f"Suggested response: {result.recommended_reply.content}")
|
|
117
|
+
|
|
118
|
+
# Legal/safeguarding flags
|
|
119
|
+
if result.legal_flags:
|
|
120
|
+
if result.legal_flags.ipv and result.legal_flags.ipv.indicated:
|
|
121
|
+
print(f"IPV detected - lethality: {result.legal_flags.ipv.lethality_risk}")
|
|
122
|
+
if result.legal_flags.mandatory_reporting and result.legal_flags.mandatory_reporting.indicated:
|
|
123
|
+
print(f"Mandatory reporting: {result.legal_flags.mandatory_reporting.context}")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Error Handling
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from nope_net import (
|
|
130
|
+
NopeClient,
|
|
131
|
+
NopeAuthError,
|
|
132
|
+
NopeRateLimitError,
|
|
133
|
+
NopeValidationError,
|
|
134
|
+
NopeServerError,
|
|
135
|
+
NopeConnectionError,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
client = NopeClient(api_key="nope_live_...")
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
result = client.evaluate(messages=[...], config={})
|
|
142
|
+
except NopeAuthError:
|
|
143
|
+
print("Invalid API key")
|
|
144
|
+
except NopeRateLimitError as e:
|
|
145
|
+
print(f"Rate limited. Retry after {e.retry_after}s")
|
|
146
|
+
except NopeValidationError as e:
|
|
147
|
+
print(f"Invalid request: {e.message}")
|
|
148
|
+
except NopeServerError:
|
|
149
|
+
print("Server error, try again later")
|
|
150
|
+
except NopeConnectionError:
|
|
151
|
+
print("Could not connect to API")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Plain Text Input
|
|
155
|
+
|
|
156
|
+
For transcripts or session notes without structured messages:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
result = client.evaluate(
|
|
160
|
+
text="Patient expressed feelings of hopelessness and mentioned not wanting to continue.",
|
|
161
|
+
config={"user_country": "US"}
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Risk Taxonomy
|
|
166
|
+
|
|
167
|
+
NOPE uses an orthogonal taxonomy separating WHO is at risk from WHAT type of harm:
|
|
168
|
+
|
|
169
|
+
### Subjects (who is at risk)
|
|
170
|
+
|
|
171
|
+
| Subject | Description |
|
|
172
|
+
|---------|-------------|
|
|
173
|
+
| `self` | The speaker is at risk |
|
|
174
|
+
| `other` | Someone else is at risk (friend, family, stranger) |
|
|
175
|
+
| `unknown` | Ambiguous - "asking for a friend" territory |
|
|
176
|
+
|
|
177
|
+
### Risk Types (what type of harm)
|
|
178
|
+
|
|
179
|
+
| Type | Description |
|
|
180
|
+
|------|-------------|
|
|
181
|
+
| `suicide` | Self-directed lethal intent |
|
|
182
|
+
| `self_harm` | Non-suicidal self-injury (NSSI) |
|
|
183
|
+
| `self_neglect` | Severe self-care failure |
|
|
184
|
+
| `violence` | Harm directed at others |
|
|
185
|
+
| `abuse` | Physical, emotional, sexual, financial abuse |
|
|
186
|
+
| `sexual_violence` | Rape, sexual assault, coerced acts |
|
|
187
|
+
| `neglect` | Failure to provide care for dependents |
|
|
188
|
+
| `exploitation` | Trafficking, forced labor, sextortion |
|
|
189
|
+
| `stalking` | Persistent unwanted contact/surveillance |
|
|
190
|
+
|
|
191
|
+
## Severity & Imminence
|
|
192
|
+
|
|
193
|
+
**Severity** (how serious):
|
|
194
|
+
| Level | Description |
|
|
195
|
+
|-------|-------------|
|
|
196
|
+
| `none` | No concern |
|
|
197
|
+
| `mild` | Low-level concern |
|
|
198
|
+
| `moderate` | Significant concern |
|
|
199
|
+
| `high` | Serious concern |
|
|
200
|
+
| `critical` | Extreme concern |
|
|
201
|
+
|
|
202
|
+
**Imminence** (how soon):
|
|
203
|
+
| Level | Description |
|
|
204
|
+
|-------|-------------|
|
|
205
|
+
| `not_applicable` | No time-based concern |
|
|
206
|
+
| `chronic` | Ongoing, long-term |
|
|
207
|
+
| `subacute` | Days to weeks |
|
|
208
|
+
| `urgent` | Hours to days |
|
|
209
|
+
| `emergency` | Immediate |
|
|
210
|
+
|
|
211
|
+
## API Reference
|
|
212
|
+
|
|
213
|
+
For full API documentation, see [docs.nope.net](https://docs.nope.net).
|
|
214
|
+
|
|
215
|
+
## Versioning
|
|
216
|
+
|
|
217
|
+
This SDK follows [Semantic Versioning](https://semver.org/). While in 0.x.x, breaking changes may occur in minor versions.
|
|
218
|
+
|
|
219
|
+
## Changelog
|
|
220
|
+
|
|
221
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT - see [LICENSE](LICENSE) for details.
|
|
226
|
+
|
|
227
|
+
## Support
|
|
228
|
+
|
|
229
|
+
- Documentation: [docs.nope.net](https://docs.nope.net)
|
|
230
|
+
- Dashboard: [dashboard.nope.net](https://dashboard.nope.net)
|
|
231
|
+
- Issues: [github.com/nope-net/python-sdk/issues](https://github.com/nope-net/python-sdk/issues)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "nope-net"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the NOPE safety API - risk classification for conversations"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "NOPE", email = "support@nope.net" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["safety", "ai", "risk", "classification", "mental-health", "crisis"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"httpx>=0.25.0",
|
|
29
|
+
"pydantic>=2.0.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0.0",
|
|
35
|
+
"pytest-asyncio>=0.21.0",
|
|
36
|
+
"pytest-httpx>=0.21.0",
|
|
37
|
+
"ruff>=0.1.0",
|
|
38
|
+
"mypy>=1.0.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://nope.net"
|
|
43
|
+
Documentation = "https://nope.net/docs"
|
|
44
|
+
Repository = "https://github.com/nope-net/python-sdk"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/nope_net"]
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
line-length = 100
|
|
51
|
+
target-version = "py39"
|
|
52
|
+
|
|
53
|
+
[tool.ruff.lint]
|
|
54
|
+
select = ["E", "F", "I", "N", "W"]
|
|
55
|
+
|
|
56
|
+
[tool.mypy]
|
|
57
|
+
python_version = "3.9"
|
|
58
|
+
strict = true
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NOPE Python SDK
|
|
3
|
+
|
|
4
|
+
Safety layer for chat & LLMs. Analyzes conversations for mental-health
|
|
5
|
+
and safeguarding risk.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
```python
|
|
9
|
+
from nope_net import NopeClient
|
|
10
|
+
|
|
11
|
+
client = NopeClient(api_key="nope_live_...")
|
|
12
|
+
result = client.evaluate(
|
|
13
|
+
messages=[{"role": "user", "content": "I'm feeling down"}],
|
|
14
|
+
config={"user_country": "US"}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
print(f"Severity: {result.summary.speaker_severity}")
|
|
18
|
+
for resource in result.crisis_resources:
|
|
19
|
+
print(f" {resource.name}: {resource.phone}")
|
|
20
|
+
```
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .client import AsyncNopeClient, NopeClient
|
|
24
|
+
from .errors import (
|
|
25
|
+
NopeAuthError,
|
|
26
|
+
NopeConnectionError,
|
|
27
|
+
NopeError,
|
|
28
|
+
NopeRateLimitError,
|
|
29
|
+
NopeServerError,
|
|
30
|
+
NopeValidationError,
|
|
31
|
+
)
|
|
32
|
+
from .types import (
|
|
33
|
+
# Request types
|
|
34
|
+
Message,
|
|
35
|
+
EvaluateConfig,
|
|
36
|
+
EvaluateRequest,
|
|
37
|
+
# Core response types
|
|
38
|
+
EvaluateResponse,
|
|
39
|
+
Risk,
|
|
40
|
+
Summary,
|
|
41
|
+
CommunicationAssessment,
|
|
42
|
+
CommunicationStyleAssessment,
|
|
43
|
+
# Supporting types
|
|
44
|
+
CrisisResource,
|
|
45
|
+
LegalFlags,
|
|
46
|
+
IPVFlags,
|
|
47
|
+
MandatoryReportingFlags,
|
|
48
|
+
ThirdPartyThreatFlags,
|
|
49
|
+
ProtectiveFactorsInfo,
|
|
50
|
+
FilterResult,
|
|
51
|
+
PreliminaryRisk,
|
|
52
|
+
RecommendedReply,
|
|
53
|
+
ResponseMetadata,
|
|
54
|
+
# Utility functions
|
|
55
|
+
calculate_speaker_severity,
|
|
56
|
+
calculate_speaker_imminence,
|
|
57
|
+
has_third_party_risk,
|
|
58
|
+
SEVERITY_SCORES,
|
|
59
|
+
IMMINENCE_SCORES,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
__version__ = "0.1.0"
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
# Clients
|
|
66
|
+
"NopeClient",
|
|
67
|
+
"AsyncNopeClient",
|
|
68
|
+
# Errors
|
|
69
|
+
"NopeError",
|
|
70
|
+
"NopeAuthError",
|
|
71
|
+
"NopeRateLimitError",
|
|
72
|
+
"NopeValidationError",
|
|
73
|
+
"NopeServerError",
|
|
74
|
+
"NopeConnectionError",
|
|
75
|
+
# Request types
|
|
76
|
+
"Message",
|
|
77
|
+
"EvaluateConfig",
|
|
78
|
+
"EvaluateRequest",
|
|
79
|
+
# Core response types
|
|
80
|
+
"EvaluateResponse",
|
|
81
|
+
"Risk",
|
|
82
|
+
"Summary",
|
|
83
|
+
"CommunicationAssessment",
|
|
84
|
+
"CommunicationStyleAssessment",
|
|
85
|
+
# Supporting types
|
|
86
|
+
"CrisisResource",
|
|
87
|
+
"LegalFlags",
|
|
88
|
+
"IPVFlags",
|
|
89
|
+
"MandatoryReportingFlags",
|
|
90
|
+
"ThirdPartyThreatFlags",
|
|
91
|
+
"ProtectiveFactorsInfo",
|
|
92
|
+
"FilterResult",
|
|
93
|
+
"PreliminaryRisk",
|
|
94
|
+
"RecommendedReply",
|
|
95
|
+
"ResponseMetadata",
|
|
96
|
+
# Utility functions
|
|
97
|
+
"calculate_speaker_severity",
|
|
98
|
+
"calculate_speaker_imminence",
|
|
99
|
+
"has_third_party_risk",
|
|
100
|
+
"SEVERITY_SCORES",
|
|
101
|
+
"IMMINENCE_SCORES",
|
|
102
|
+
]
|