Every AI service asks for the same thing: send us your data and trust us with it. We wanted to know if a model could learn from data its host never sees.
So we ran an experiment and played both parts. One machine is the data owner. It holds the data and the only secret key. The other is the AI provider, the host. It trains the model, stores it and answers questions. From the owner it gets the encrypted data, the public keys it needs to compute and the size of the job. Nothing else.
The data is one sentence: “The cat sat on the mat.” That is on purpose. With one sentence we can check every number by hand. It means we are measuring whether the model learns the sequence, not whether it understands cats.
Drag the key
One model. Two worlds.
Left of the line is what our server holds. Right of it is the same model, opened with the owner’s key. Real bytes, real weights.
What we proved
- A computer can train an AI model on data it can’t read. The host trained a small language model for 242 steps from encrypted data and public keys. It never had the secret key.
- The model never handled a readable word. On the host, the training data, the questions, the answers and, from the first update on, the weights were ciphertext the whole time. Every time the host tried to decrypt with a key of its own, it failed.
- It learned for real. The owner decrypted the checkpoints and compared them with the same model trained in the open. They match at every check, to within one character, and given “The cat” it writes “sat on the mat”.
- The owner chooses how to use it. Ask it sealed questions on the host, about 15 seconds per character. Or decrypt it and run it locally, under a millisecond.
- It runs on ordinary hardware. One GPU trained it in about an hour, with encryption built to withstand quantum computers.
It learned, step for step
Correct next characters out of 120, encrypted run next to the same model trained in the open:
| Step | Encrypted | In the open |
|---|
At step 242 the two differ by one character: the encryption adds a little rounding noise, and the encrypted run happened to land one better. 115 is the ceiling for this sentence, because a short start like “t” can be followed by a space, an “h” or a full stop.
Try it. Right now.
First a replay of a real sealed question, start to finish. Then the owner’s decrypted copy runs right here in your browser: for this demo we are also the owner, so we opened the model and put it on this page. Nothing you type leaves your device.
The model only knows these characters: T h e c a t s o n m . and space.
How a Private Model gets made
- YouYou lock itYour computer makes the key and encrypts your data. The secret key never leaves it.
- Us, sealedWe train it blindOur server trains on ciphertext. Every add and multiply happens on encrypted numbers. It starts from random numbers of its own, encrypted under your public key; after the first update they depend on your data, so only your key can read them.
- Us, sealedIt stays sealedThe trained model is ciphertext. Break into our servers and you get noise.
- YouYou use itAsk it sealed questions on our side, or decrypt it and run it yourself at full speed.
The encryption is CKKS, a lattice-based scheme, with OpenFHE’s 128-bit post-quantum parameters. Lattice problems are the same family behind the new post-quantum standards. Each ciphertext carries 32,768 numbers.
What we had to change in the model
We started from our own SIMPLE LLM, a small transformer written in NumPy. Encrypted numbers can be added and multiplied. They can’t be compared, exponentiated or divided. So everything else had to go:
| Softmax attention | (1 + score)², averaged over the positions seen so far. Like softmax, it starts as an even average. |
|---|---|
| ReLU | 0.5x + 0.25x², which matches ReLU at −2, 0 and 2 |
| Cross-entropy loss | Squared error against the right next character |
| Gradient clipping | Removed. It needs a square root and a division. |
Then the layout. Every tensor lives in one ciphertext as a grid of 128 rows by 16 by 16. Layers alternate between two arrangements, so nothing is ever transposed, and each weight’s gradient lands in that weight’s own arrangement. One training step is 89 encrypted multiplies, 364 rotations and 6 to 20 refreshes, called bootstraps.
Scrambled isn’t private. Here’s the proof.
Before the real encryption, we ran two controls on the original SIMPLE LLM. They are there to stop us, and anyone else, from fooling ourselves.
| Plaintext | Shuffled letters | AES-256 bytes | |
|---|---|---|---|
| Final loss | 0.0795 | 0.0803 | 0.0237 |
| Accuracy | 95.8% | 95.8% | 98.8% |
| Reusable patterns in the input | 41% | 41% | 0% |
Shuffling the letters changes nothing. The model never sees letters anyway, only numbers. Started from matching weights, the shuffled run ends within 3×10−15 of the plaintext run on every weight. It hides which letter is which and keeps every pattern: word lengths, the three words ending in “at”.
Ordinary encryption gives the best score and learns nothing. Fed AES-256 ciphertext, the model scores better than on plaintext. Random bytes never repeat, so there is nothing ambiguous to get wrong, and 39 bytes are easy to memorize. Its view of the sentence has no structure left. A falling loss is not proof of learning.
What it costs
| Keys the owner sends | 26.2 GB of public keys, made in 83 s |
|---|---|
| One encrypted training step | about 16 s on one GPU (72 to 207 s on CPU) |
| The training run | 242 steps in about 65 minutes on one GPU |
| One refresh (bootstrap) | 0.7 s on GPU (10 to 14 s on CPU) |
| One sealed answer | about 15 s per character, end to end |
| The owner running their own copy | under 1 ms per character |
The model is small on purpose: 2,048 weights. Encrypted math is heavy, so the first Private Models are small, focused models, where it already works. Speed is an engineering problem, and more GPUs are the next step.
Update, 13 Oct: long runs fixed
The refresh that broke at step 243 had a cause we could fix. Every encrypted number has two halves. The real half holds our values. The other half only collects noise, and nothing in training cleared it, so over hundreds of steps it grew until the owner could no longer decrypt.
Now, once per step, the host clears that half on every weight. It is a small extra step per weight, it needs no new keys, and the host still reads nothing. From the exact state that used to break, training ran on to step 300: every step decrypted, scoring 110 to 113 of 120. The model on this page is still the one from step 242. Long runs were the gate for bigger models, and that gate is open.
What’s next
- Bigger models, built from the ground up. The next run trains a model of our own on real text, across a rack of GPUs.
- Hide the shape too. The host still sees the model’s size, how long the data is and when questions arrive. Padding and batching are the plan to close that.
- Prove the host did the work. Encryption keeps the data secret. Our Optima Prime receipts are built to show a computation was done as claimed. Together: privacy and proof.
New from the lab · Private Model
Your data. Your model. Your key.
Bring the data you can’t hand to anyone. We train a model on it without ever seeing it. You walk away with the only key.
Trained sealed
Your data is encrypted on your machine before it leaves. We train on ciphertext. We never see a word of it.
Not even the model reads it
On our side the model runs on encrypted weights, encrypted questions and encrypted answers. Your key is the only way in.
Run it your way
Ask it questions while it stays sealed with us. Or decrypt it and run it on your own machine, at full speed.
Built for the data that never leaves the building: case files, patient records, ledgers, player data, internal playbooks. We start with small, focused models.