| # Psy 6.9M Model Card |
|
|
| ## Model |
|
|
| - Name: Psy |
| - Bundle version: v0.1 |
| - Model type: byte-level, zero-language cyber artifact encoder (classification-only) |
| - License: Apache-2.0 (see `LICENSE`) |
| - Checkpoint: `checkpoints/psy_6.9m_encoder.pt` |
| - Encoder parameters: 6,904,064 |
| - Exported encoder SHA256: `2d0a15792bcdfbebfbf689ca0dddd39f9259525bbe9bee9d491289af4e590dbc` |
|
|
| ## Who Psy is for (practical use) |
|
|
| Psy is a tiny (6.9M params / ~27MB / CPU-only / fully offline) instrument that reads |
| a cyber artifact in its **raw bytes** and returns a coarse severity/verdict. Nothing |
| leaves your machine. Two doors to the same tool: |
|
|
| **1 — The defender who's drowning** (SOC analyst, solo admin, small team with no SOC). |
| You get buried in CVEs, detection-rule hits, and network flows — more than any human |
| can assess, and the dangerous one hides in the noise. Psy reads each artifact and |
| **prioritizes the queue** so you look at the scary stuff first. It runs airgapped, on |
| your own hardware — good for orgs that *can't* send data to a cloud API (defense, |
| healthcare, critical infra, privacy-sensitive) or simply can't afford enterprise tooling. |
|
|
| **2 — The vibe coder who's blind** (ships fast, AI-assisted, not a security person). |
| You pulled in 400 dependencies you never read and have no idea which CVE is scary or |
| whether a compromised package is beaconing out. Psy is the **judgment layer on tools |
| you already run**: pipe your `npm/pip/cargo audit` CVE records in → *"fix these 3, |
| ignore the wall of yellow."* It reads the bytes so you don't have to understand them — |
| tiny enough to drop in a pre-ship checklist or a git hook. |
|
|
| **Honest boundary (this is the feature, not a caveat):** Psy is a **scorer that sits on |
| top of feeds you already have** (audit output, captured flows) — *not* a one-click |
| "scan my repo" scanner. It **prioritizes and flags; it does not decide, fix, or |
| guarantee**, and it returns `PSY_UNCERTAIN` when it isn't sure instead of bluffing. |
| An instrument for a human in the loop, not an oracle. |
|
|
| ## Quickstart (run it — verified output) |
|
|
| ```bash |
| python3 scripts/validate_bundle.py # expect status PASSED (1 network_flow warning) |
| python3 scripts/run_demo.py --artifact demo_artifacts/rule_ast_sample.jsonl |
| ``` |
|
|
| Feed it a detection-rule AST → Psy reads the bytes and returns one strict-JSON verdict: |
|
|
| ```json |
| {"psy_frame":{"magic":[80,83,89],"version":1,"sender":2,"receiver":1,"intent":5, |
| "opcode":69,"confidence":0.8381}, |
| "status":"PSY_ANOMALY_FOUND", |
| "verdict":{"family":"RULE_AST","action":"BLOCK","label":2,"class_index":2,"artifact_type":5, |
| "confidence":0.8381,"mode":"encoder_plus_probe_head","head_status":"loaded", |
| "status":"PSY_ANOMALY_FOUND","artifact_hash":"e0a7780dd5ad7c080d0ead87f5cace38", |
| "embedding_norm":28.4617,"display":"Psy anomaly found."}} |
| ``` |
|
|
| That's the whole contract: bytes in, one honest structured verdict out. (The `CVE_RECORD` |
| demo returns a confident `PSY_UNCERTAIN`/`ABSTAIN` — a real "investigate" call, explained |
| below; `NETWORK_FLOW` runs encoder-only in v0.1 — see the head table.) |
|
|
| ## Defensive-Use Statement |
|
|
| Psy is a **defensive** research instrument. It reads already-structured cyber |
| artifacts (a sanitized CVE record, a detection-rule AST, a network-flow header) |
| and emits a coarse severity/verdict frame. It has **no generative, executive, or |
| remediation capability**: verified by reading and running the code, there is no |
| code path that generates text, generates code, executes an artifact, patches a |
| system, or emits an exploit. The runtime only encodes an artifact to a 256-dim |
| embedding, applies a small linear probe head, and reports a severity class. |
| It must not be used as, or represented as, a production security scanner, and it |
| cannot detect malware or exploits. Do not feed it untrusted executable content |
| expecting containment — it does not run anything, but it also does not defend |
| anything on its own. |
|
|
| ## Architecture (as implemented, verified from tensor shapes) |
|
|
| Byte-level pre-LN Transformer encoder backbone. |
|
|
| - 6 transformer layers (`MultiheadAttention`, 8 heads, `batch_first`; GELU FFN 256 -> 1024 -> 256) |
| - Hidden size (d_model): 256 |
| - Byte vocabulary: 257 (`byte_emb`, shape [257, 256]) |
| - Field vocabulary: 8192 (`field_emb`, shape [8192, 256], **shared** across field keys, field values, and seq) |
| - Artifact-type vocabulary: 8 (`type_emb`, shape [8, 256]) |
| - **No positional embeddings.** |
| - Input assembly per artifact: `[ type(1) + field_key + field_val(32) + seq(64) + bytes(512) ] = 609 tokens`. |
| - Pooling: the artifact-type token at position 0 acts as a CLS token; the model returns the pooled `[:, 0]` vector = a 256-dim embedding. |
| - Final LayerNorm before pooling. |
|
|
| The exported checkpoint contains **only the encoder backbone** (77 tensors, |
| 6,904,064 params, loads with 0 missing / 0 unexpected keys via the bundle's |
| `load_encoder`, which uses `weights_only=True` and treats any missing/unexpected |
| key as an error). Masked-training prediction heads were stripped at export so the |
| bundle ships Psy purely as the 6.9M artifact-encoder instrument, plus the two |
| small probe heads described below. |
|
|
| ## Probe Heads (what actually ships) |
|
|
| The encoder is task-agnostic. Per-family severity is produced by a tiny linear |
| probe head (`nn.Linear(256, num_classes)`, loaded `strict=True`) placed on the |
| pooled embedding, followed by softmax + argmax. |
|
|
| This bundle ships **two** trained probe heads (CVE_RECORD and RULE_AST are fully |
| functional end-to-end; NETWORK_FLOW is encoder-only in v0.1): |
| |
| | Family | Head file | Shape | SHA256 | Ships? | |
| |---------------|----------------------------------------|---------------|-------------------------------------------------------------------|--------| |
| | CVE_RECORD | `checkpoints/heads/cve_sanitized_head.pt` | Linear(256->3) | `b6c9cfae96b3b22414e2f956e3cfa657a9160e092652c0cc48eeac14c244760f` | Yes | |
| | RULE_AST | `checkpoints/heads/rule_ast_head.pt` | Linear(256->3) | `bc6a96c03a987a8819cd055b69828ce71817a5cc94b33e6cedcdbb52d5d64d27` | Yes | |
| | NETWORK_FLOW | `checkpoints/heads/network_flow_head.pt` | Linear(256->2) | (not shipped) | **No** | |
|
|
| If a family's head is absent, the runtime does not fabricate a verdict: it runs |
| the encoder only, returns `head_status: "probe_head_not_present"`, |
| `mode: "encoder_only"`, and `PSY_UNCERTAIN` / `ABSTAIN` at confidence 0.0. |
|
|
| ## Inputs |
|
|
| Psy consumes structured JSON cyber artifacts with: |
|
|
| - `artifact_type` or `artifact_family` |
| - `payload_bytes_b64` or `payload_bytes` |
| - `field_ids` |
| - `field_values` |
| - `seq` |
|
|
| ## Outputs |
|
|
| The runtime emits one strict-JSON status/verdict frame per artifact containing: |
|
|
| - a Psy contact/status frame (`magic`, `version`, `sender`, `receiver`, `intent`, `opcode`, `confidence`) |
| - artifact family and artifact hash (BLAKE2b-128 of the canonical JSON) |
| - encoder statistics (`embedding_norm`) |
| - `mode` (`encoder_plus_probe_head` or `encoder_only`), `head_status`, `class_index`, `label`, `confidence` |
| - a status + action |
|
|
| ### Class -> opcode -> action mapping |
|
|
| | Probe label | Opcode | Status | Action | |
| |-------------|---------------------|---------------------|---------| |
| | 0 | `PSY_SAFE` | `PSY_SAFE` | ALLOW | |
| | 1 | `PSY_UNCERTAIN` | `PSY_UNCERTAIN` | ABSTAIN | |
| | 2 | `PSY_ANOMALY_FOUND` | `PSY_ANOMALY_FOUND` | BLOCK | |
|
|
| Note on the two meanings of `PSY_UNCERTAIN`: it is emitted both when the probe |
| head **confidently predicts the middle (investigate) class** (a real, high- |
| confidence label-1 prediction) and when there is **no head available** (encoder- |
| only). Disambiguate using `mode` / `head_status` / `confidence`, not the status |
| string alone. This is why the CVE demo can read `PSY_UNCERTAIN` at confidence |
| 0.9996 — it is a confident label-1 (MEDIUM/INVESTIGATE) prediction the opcode |
| layer maps to ABSTAIN, not a malfunction. |
|
|
| ## What each family does end-to-end (verified by running) |
|
|
| | Family | Mode | Demo result | Notes | |
| |---------------|--------------------------|--------------------------------------------|-------| |
| | RULE_AST | encoder + probe head | label 2 -> `PSY_ANOMALY_FOUND` / BLOCK, conf 0.8381 | Decisive verdict path. | |
| | CVE_RECORD | encoder + probe head | label 1 -> `PSY_UNCERTAIN` / ABSTAIN, conf 0.9996 | Head runs; demo sample lands on the investigate class. | |
| | NETWORK_FLOW | encoder only (no head) | `PSY_UNCERTAIN` / ABSTAIN, conf 0.0 | Head not shipped in v0.1; encoder-only by design. | |
|
|
| ## Probe metrics (sanitized training-run summaries) |
|
|
| These are summaries carried from the local metric log; the full training logs, |
| shards, and held-out reproduction are **not** included in this bundle. They |
| describe the trained probes, not an in-bundle re-evaluation. |
|
|
| | Family | Baseline (majority) | Test accuracy | Macro-F1 | Status | Head shipped | |
| |---------------|---------------------|---------------|----------|----------|--------------| |
| | CVE_RECORD | 0.6424 | 0.8684 | 0.7706 | SIGNAL | Yes | |
| | RULE_AST | 0.5129 | 0.7847 | 0.7013 | SIGNAL | Yes | |
| | NETWORK_FLOW | 0.9952 | 1.0000 | 0.9989 | MARGINAL | No | |
| |
| The CVE probe is trained on sanitized records with direct CVSS/severity fields |
| removed, so it reflects structural signal rather than a copied severity field. |
| |
| ## Limitations |
| |
| - Not a production security scanner. Not malware/exploit detection. |
| - Does not generate code or patches, does not execute artifacts, does not chat. |
| - Does not contain the training corpus, shards, or logs. |
| - A scorer on top of existing feeds, not a repo/network scanner — you supply the artifacts. |
| - Only two of three advertised families produce a probe verdict in v0.1; |
| NETWORK_FLOW ships encoder-only (no head weights). |
| - NETWORK_FLOW metrics are dominated by extreme class imbalance |
| (train class 0:2 = 896,107:4,327). Test accuracy 1.0 is not meaningful on its |
| own; the family is marked MARGINAL and would require class-wise validation |
| before any head is treated as a real signal. This is the reason its head is |
| held back from v0.1 rather than shipped. |
| - Probe metrics above are training-run summaries, not reproduced inside the |
| bundle; treat them as reported-not-reverified. |
| |
| ## Provenance / integrity |
| |
| - Verify the encoder: `sha256sum checkpoints/psy_6.9m_encoder.pt` must equal the SHA above. |
| - Verify the heads: the two head SHAs above. |
| - `python3 scripts/validate_bundle.py` re-derives the param count (must == 6,904,064), checks required files, scans for secrets/non-loopback IPs, and confirms no forbidden path components. Expected result on a clean release: `status: PASSED` with a single warning for the intentionally-absent `network_flow_head.pt`. |
|
|
| ## This isn't only for developers |
|
|
| The two use cases above assume some technical context, but the need isn't limited |
| to people who write code. A nonprofit running a donated laptop fleet, a small |
| business owner handed a vendor's CVE list with no security staff to read it, a |
| student trying to understand what "severity" actually means in a disclosure — none |
| of that requires a job title. The floor to use Psy is a correctly-shaped JSON |
| record, not a background in security or software. If you can get your artifact |
| into that shape (yourself, with a script someone wrote for you, or by asking an AI |
| assistant to format it), Psy will read it the same way for anyone. |
|
|