| | --- |
| | license: other |
| | license_name: nope-edge-community-license-v1.0 |
| | license_link: LICENSE.md |
| | language: |
| | - en |
| | tags: |
| | - safety |
| | - crisis-detection |
| | - text-classification |
| | - mental-health |
| | - content-safety |
| | - suicide-prevention |
| | base_model: Qwen/Qwen3-1.7B |
| | pipeline_tag: text-generation |
| | library_name: transformers |
| | extra_gated_heading: "Access NOPE Edge" |
| | extra_gated_description: "This model is available for **research, academic, nonprofit, and evaluation use**. Commercial production use requires a separate license. Please read the [license terms below](#nope-edge-community-license-v10) before downloading." |
| | extra_gated_button_content: "Agree and download" |
| | extra_gated_fields: |
| | I am using this for research, academic, nonprofit, personal, or evaluation purposes: |
| | type: checkbox |
| | I agree to the NOPE Edge Community License v1.0: |
| | type: checkbox |
| | --- |
| | |
| | # NOPE Edge Mini - Crisis Classification Model |
| |
|
| | A fine-tuned model for detecting crisis signals in text - suicidal ideation, self-harm, abuse, violence, and other safety-critical content. Features chain-of-thought reasoning that explains its classifications. |
| |
|
| | > **License:** [NOPE Edge Community License v1.0](LICENSE.md) - Free for research, academic, nonprofit, and evaluation use. Commercial production requires a separate license. See [nope.net/edge](https://nope.net/edge) for details. |
| |
|
| | --- |
| |
|
| | ## Model Variants |
| |
|
| | | Model | Parameters | Use Case | |
| | |-------|------------|----------| |
| | | **[nope-edge](https://huggingface.co/nopenet/nope-edge)** | 4B | Maximum accuracy | |
| | | **[nope-edge-mini](https://huggingface.co/nopenet/nope-edge-mini)** | 1.7B | High-volume, cost-sensitive | |
| |
|
| | This is **nope-edge-mini (1.7B)**. |
| |
|
| | --- |
| |
|
| | ## Quick Start |
| |
|
| | ### Requirements |
| |
|
| | - Python 3.10+ |
| | - GPU with 4GB+ VRAM and bfloat16 support (e.g., RTX 3060+, L4, A10G) - or CPU (slower) |
| | - ~4GB disk space |
| |
|
| | ```bash |
| | pip install torch transformers accelerate |
| | ``` |
| |
|
| | ### Usage |
| |
|
| | ```python |
| | from transformers import AutoModelForCausalLM, AutoTokenizer |
| | import torch |
| | import re |
| | |
| | model_id = "nopenet/nope-edge-mini" |
| | |
| | tokenizer = AutoTokenizer.from_pretrained(model_id) |
| | model = AutoModelForCausalLM.from_pretrained( |
| | model_id, |
| | torch_dtype=torch.bfloat16, |
| | device_map="auto" |
| | ) |
| | |
| | def classify(message: str) -> str: |
| | """Returns XML with reflection and risk classification.""" |
| | input_ids = tokenizer.apply_chat_template( |
| | [{"role": "user", "content": message}], |
| | tokenize=True, |
| | return_tensors="pt", |
| | add_generation_prompt=True |
| | ).to(model.device) |
| | |
| | with torch.no_grad(): |
| | output = model.generate(input_ids, max_new_tokens=300, do_sample=False) |
| | |
| | return tokenizer.decode( |
| | output[0][input_ids.shape[1]:], |
| | skip_special_tokens=True |
| | ).strip() |
| | |
| | # Example |
| | result = classify("I want to end it all tonight") |
| | print(result) |
| | ``` |
| |
|
| | **Output:** |
| | ```xml |
| | <reflection>The user directly expresses intent to end their life with a specific timeline ("tonight"), indicating acute suicidal ideation with imminent risk.</reflection> |
| | <risks> |
| | <risk subject="self" type="suicide" severity="high" imminence="urgent"/> |
| | </risks> |
| | ``` |
| |
|
| | --- |
| |
|
| | ## Output Format |
| |
|
| | The model outputs XML with two components: |
| |
|
| | ### 1. Reflection (Chain-of-Thought) |
| |
|
| | ```xml |
| | <reflection>Reasoning about the input...</reflection> |
| | ``` |
| |
|
| | The model explains its classification, including: |
| | - What signals it detected |
| | - Why it chose the risk type and severity |
| | - Any contextual factors considered |
| |
|
| | ### 2. Risk Classification |
| |
|
| | **Crisis detected:** |
| | ```xml |
| | <risks> |
| | <risk subject="self" type="suicide" severity="high" imminence="urgent" features="active_ideation,intent_stated"/> |
| | </risks> |
| | ``` |
| |
|
| | **No crisis:** |
| | ```xml |
| | <risks/> |
| | ``` |
| |
|
| | ### Risk Attributes |
| |
|
| | | Attribute | Values | Description | |
| | |-----------|--------|-------------| |
| | | `subject` | `self`, `other` | Who is at risk | |
| | | `type` | `suicide`, `self_harm`, `self_neglect`, `violence`, `abuse`, `sexual_violence`, `exploitation`, `stalking`, `neglect` | Risk category | |
| | | `severity` | `mild`, `moderate`, `high`, `critical` | Urgency level | |
| | | `imminence` | `chronic`, `acute`, `urgent`, `emergency` | Time sensitivity | |
| | | `features` | comma-separated list | Specific indicators detected | |
| |
|
| | ### Subject Attribution |
| |
|
| | | Subject | Meaning | Example | |
| | |---------|---------|---------| |
| | | `self` | The speaker is at risk | "I want to kill myself" | |
| | | `other` | Reporting concern about someone else | "My friend said she wants to die" | |
| |
|
| | ### Parsing Example |
| |
|
| | ```python |
| | import re |
| | from dataclasses import dataclass |
| | from typing import Optional |
| | |
| | @dataclass |
| | class Risk: |
| | subject: str |
| | type: str |
| | severity: str |
| | imminence: Optional[str] = None |
| | features: Optional[list] = None |
| | |
| | def parse_output(output: str) -> dict: |
| | """Parse model output into structured data.""" |
| | result = { |
| | "reflection": None, |
| | "risks": [], |
| | "is_crisis": False |
| | } |
| | |
| | # Extract reflection |
| | reflection_match = re.search(r'<reflection>(.*?)</reflection>', output, re.DOTALL) |
| | if reflection_match: |
| | result["reflection"] = reflection_match.group(1).strip() |
| | |
| | # Check for empty risks (no crisis) |
| | if '<risks/>' in output or '<risks />' in output: |
| | return result |
| | |
| | # Extract risk elements |
| | risk_pattern = r'<risk\s+([^>]+)/?\s*>' |
| | for match in re.finditer(risk_pattern, output): |
| | attrs = {} |
| | for attr_match in re.finditer(r'(\w+)="([^"]*)"', match.group(1)): |
| | attrs[attr_match.group(1)] = attr_match.group(2) |
| | |
| | if attrs: |
| | risk = Risk( |
| | subject=attrs.get("subject", "self"), |
| | type=attrs.get("type"), |
| | severity=attrs.get("severity"), |
| | imminence=attrs.get("imminence"), |
| | features=attrs.get("features", "").split(",") if attrs.get("features") else None |
| | ) |
| | result["risks"].append(risk) |
| | result["is_crisis"] = True |
| | |
| | return result |
| | |
| | # Usage |
| | output = classify("I want to end it all tonight") |
| | parsed = parse_output(output) |
| | print(f"Crisis: {parsed['is_crisis']}") |
| | print(f"Reasoning: {parsed['reflection']}") |
| | for risk in parsed['risks']: |
| | print(f"Risk: {risk.type}/{risk.severity} ({risk.subject})") |
| | ``` |
| |
|
| | --- |
| |
|
| | ## Examples |
| |
|
| | ### Crisis Detection |
| |
|
| | **Input:** "I want to end it all tonight" |
| | ```xml |
| | <reflection>The user directly expresses intent to end their life with a specific timeline ("tonight"), indicating acute suicidal ideation with imminent risk.</reflection> |
| | <risks> |
| | <risk subject="self" type="suicide" severity="high" imminence="urgent"/> |
| | </risks> |
| | ``` |
| |
|
| | **Input:** "My friend told me she's been cutting herself" |
| | ```xml |
| | <reflection>The user is reporting concern about a friend engaging in self-harm behavior. This is third-party disclosure requiring attention.</reflection> |
| | <risks> |
| | <risk subject="other" type="self_harm" severity="moderate" imminence="chronic"/> |
| | </risks> |
| | ``` |
| |
|
| | ### No Crisis (Correctly Ignored) |
| |
|
| | **Input:** "kms lmao this exam is killing me" |
| | ```xml |
| | <reflection>The user is using hyperbolic internet slang ("kms" = "kill myself") to express frustration about an exam. The "lmao" and casual context indicate this is not genuine suicidal ideation.</reflection> |
| | <risks/> |
| | ``` |
| |
|
| | **Input:** "I used to be suicidal but therapy helped me recover" |
| | ```xml |
| | <reflection>The user is sharing a recovery narrative about past suicidal ideation. They explicitly state therapy helped and they have recovered. No current crisis indicators.</reflection> |
| | <risks/> |
| | ``` |
| |
|
| | --- |
| |
|
| | ## Input Best Practices |
| |
|
| | ### Text Preprocessing |
| |
|
| | **Preserve natural prose.** The model was trained on real conversations with authentic expression: |
| |
|
| | | Keep | Why | |
| | |------|-----| |
| | | Emojis | Emotional signals matter | |
| | | Punctuation intensity | "I can't do this!!!" vs "I can't do this" | |
| | | Slang/algospeak | "kms", "unalive", "catch the bus", "graped" | |
| | | Casual spelling | "im so done" - don't normalize | |
| |
|
| | **Only remove:** Zero-width Unicode, decorative fonts, excessive whitespace. |
| |
|
| | ### Multi-Turn Conversations |
| |
|
| | Serialize into a single user message: |
| |
|
| | ```python |
| | conversation = """User: How are you? |
| | Assistant: I'm here to help. How are you feeling? |
| | User: Not great. I've been thinking about ending it all.""" |
| | |
| | messages = [{"role": "user", "content": conversation}] |
| | ``` |
| |
|
| | --- |
| |
|
| | ## Production Deployment |
| |
|
| | For high-throughput use, deploy with vLLM or SGLang: |
| |
|
| | ```bash |
| | # SGLang (recommended) |
| | pip install sglang |
| | python -m sglang.launch_server \ |
| | --model nopenet/nope-edge-mini \ |
| | --dtype bfloat16 --port 8000 |
| | |
| | # vLLM |
| | pip install vllm |
| | python -m vllm.entrypoints.openai.api_server \ |
| | --model nopenet/nope-edge-mini \ |
| | --dtype bfloat16 --max-model-len 2048 --port 8000 |
| | ``` |
| |
|
| | Then call as OpenAI-compatible API: |
| |
|
| | ```bash |
| | curl http://localhost:8000/v1/chat/completions \ |
| | -H "Content-Type: application/json" \ |
| | -d '{ |
| | "model": "nopenet/nope-edge-mini", |
| | "messages": [{"role": "user", "content": "I want to end it all"}], |
| | "max_tokens": 300, "temperature": 0 |
| | }' |
| | ``` |
| |
|
| | --- |
| |
|
| | ## Model Details |
| |
|
| | | | | |
| | |---|---| |
| | | **Parameters** | 1.7B | |
| | | **Precision** | bfloat16 | |
| | | **Base Model** | Qwen/Qwen3-1.7B | |
| | | **Method** | LoRA fine-tune, merged to full weights | |
| | | **License** | [NOPE Edge Community License v1.0](LICENSE.md) | |
| |
|
| | --- |
| |
|
| | ## Risk Types Detected |
| |
|
| | | Type | Description | Clinical Framework | |
| | |------|-------------|-------------------| |
| | | `suicide` | Suicidal ideation, intent, planning | C-SSRS | |
| | | `self_harm` | Non-suicidal self-injury (NSSI) | - | |
| | | `self_neglect` | Eating disorders, medical neglect | - | |
| | | `violence` | Threats/intent to harm others | HCR-20 | |
| | | `abuse` | Domestic/intimate partner violence | DASH | |
| | | `sexual_violence` | Rape, sexual assault, coercion | - | |
| | | `neglect` | Failing to care for dependent | - | |
| | | `exploitation` | Trafficking, grooming, sextortion | - | |
| | | `stalking` | Persistent unwanted contact | SAM | |
| |
|
| | --- |
| |
|
| | ## Important Limitations |
| |
|
| | - Outputs are **probabilistic signals**, not clinical assessments |
| | - **False negatives and false positives will occur** |
| | - Never use as the **sole basis** for intervention decisions |
| | - Always implement **human review** for flagged content |
| | - This model is **not** a medical device or substitute for professional judgment |
| | - Not validated for all populations, languages, or cultural contexts |
| |
|
| | --- |
| |
|
| | ## Commercial Licensing |
| |
|
| | This model is free for research, academic, nonprofit, and evaluation use. |
| |
|
| | **For commercial production deployment**, contact us: |
| | - Email: support@nope.net |
| | - Website: https://nope.net/edge |
| |
|
| | --- |
| |
|
| | ## About NOPE |
| |
|
| | NOPE provides safety infrastructure for AI applications. Our API helps developers detect mental health crises and harmful AI behavior in real-time. |
| |
|
| | - **Website:** https://nope.net |
| | - **Documentation:** https://docs.nope.net |
| | - **Support:** support@nope.net |
| |
|
| | --- |
| |
|
| | ## NOPE Edge Community License v1.0 |
| |
|
| | Copyright (c) 2026 NopeNet, LLC. All rights reserved. |
| |
|
| | ### Permitted Uses |
| |
|
| | You may use this Model for: |
| |
|
| | - **Research and academic purposes** - published or unpublished studies |
| | - **Personal projects** - non-commercial individual use |
| | - **Nonprofit organizations** - including crisis lines, mental health organizations, and safety-focused NGOs |
| | - **Evaluation and development** - testing integration before commercial licensing |
| | - **Benchmarking** - publishing evaluations with attribution |
| |
|
| | ### Commercial Use |
| |
|
| | **Commercial use requires a separate license.** Commercial use includes production deployment in revenue-generating products or use by for-profit companies beyond evaluation. |
| |
|
| | Contact support@nope.net or visit https://nope.net/edge for commercial licensing. |
| |
|
| | ### Restrictions |
| |
|
| | You may NOT: redistribute or share weights; sublicense, sell, or transfer the Model; create derivative models for redistribution; build a competing crisis classification product. |
| |
|
| | ### No Warranty |
| |
|
| | THE MODEL IS PROVIDED "AS IS" WITHOUT WARRANTIES. False negatives and false positives will occur. This is not a medical device or substitute for professional judgment. |
| |
|
| | ### Limitation of Liability |
| |
|
| | NopeNet shall not be liable for damages arising from use, including classification errors or harm to any person. |
| |
|
| | ### Base Model |
| |
|
| | Built on [Qwen3](https://huggingface.co/Qwen) by Alibaba Cloud (Apache 2.0). See NOTICE.md. |
| |
|