feat: a double-blind eval demo on a Tinfoil enclave - #9518
koenvanderveen wants to merge 2 commits into
Conversation
Two Colab notebooks, one per party, that rebuild the tinfoilsh/double-blind-eval flow over PySyft with no dbe involved. A benchmark owner and a model owner each upload half of an evaluation, both attest the enclave against a pinned image digest, both approve the job, and only the benchmark owner reads the results. The benchmark owner submits the job rather than the model owner, because distribute_results always forwards output to the submitter and there is no per-recipient output policy. The model owner approves the run and its copy of the job never reaches done. The prompt set is fetched from OpenMined/double-blind-eval-bench. The model is a PEFT LoRA adapter fetched from HuggingFace; the enclave has no GPU, so the demo runs TinyLlama-1.1B and carries a commented line for the gemma-4-31B adapter the dbe demo uses. SETUP.md covers the operator side: resetting each party's state before deploying, deploying the published v0.1.14 release, and republishing after a config or image change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Found by deploying v0.1.14 and running both notebooks' own cells against it. The eval job failed twice in the enclave before it ran. Plain `torch` on Linux pulls the whole CUDA stack, which overran the enclave's ramdisk and failed the job with "No space left on device"; the enclave has no GPU, so pin the CPU-only wheel by URL instead, 176 MB against several GB. Then float32 weights plus the venv and the downloaded model exceeded the 8 GB of RAM and the OOM killer took the job, so load in bfloat16 with low_cpu_mem_usage and drop the token budget to 16. The job now completes in about two and a half minutes. Reading the model owner's model card could never work. Unlike `jobs` and `peers`, `SyftEnclaveClient.datasets` returns the manager directly rather than through the property that syncs, so re-running that cell pulled nothing however long you waited. The cell syncs explicitly now. Step 7 looped on "wait until the status is done" for a job that had already failed. It now reports a failed job and prints its stderr. `verify_tinfoil.py` never passed the host into the evidence or the policy, so the appraisal raised "no host to reach it on" before running a single check, and main() swallowed the error and exited 1 with no output. The `tinfoil-verify` recipe also ran without the optional extra its own comment requires. Both fixed; the recipe now passes all ten checks against a live enclave. The notebooks and SETUP.md use the enclave accounts from credentials/CLAUDE.md rather than placeholder emails, and both pin the published v0.1.14 and the image digest that release carries. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Tested end to end against a live Tinfoil enclave: deployed published Five fixes came out of it, three of which nothing but a live run would have caught. The job failed twice in the enclave before it ran.
Reading the model card could never have worked. Step 7 asked you to keep waiting for a job that had already failed. It now reports a failed job and prints its stderr — which is how I diagnosed both failures above.
What the run proved
Emails now come from One thing left for you to decide. I fixed the sync in the notebook rather than in Also worth knowing: |
Stacked on #9515. Two Colab notebooks that rebuild the tinfoilsh/double-blind-eval flow over PySyft, with no
dbeinvolved. A benchmark owner and a model owner each upload half of an evaluation, both attest the enclave against a pinned image digest, both approve the job, and only the benchmark owner reads the results. No receipt step.notebooks/enclave/double-blind-eval/1. DO-benchmark-owner-dbe.ipynb2. DO-model-owner-dbe.ipynbSETUP.mdTwo decisions worth reviewing
The benchmark owner submits the job, not the model owner.
distribute_resultsalways forwards output tojob.submitted_by, andshare_results_with_do=Trueforwards to every data owner named indatasets, so there is no way to have the model owner submit without also receiving. Moving the submit step gives the asymmetry the demo is about, and matches dbe's output policy. The model owner approves the run and its copy of the job never reachesdone.The model runs on CPU.
tinfoil-config.ymlsetsgpus: 0, so the demo runs a TinyLlama-1.1B adapter and caps generation at 32 new tokens to stay inside the 600s job timeout. The model owner notebook carries a commentedADAPTER_REPOline for the gemma-4-31B adapter dbe uses; switching to it needsgpus:raised, which is a measured config change.Also here
TINFOIL_TAG=v0.1.14and the digest that release pins, soattest_peeris called the way this branch now requires: with the image digest, the data owners and the enclave email all set.transformersis pinned to4.57.6. Unpinned, the job venv resolved 5.x, whose import chain fails.Verification
pendingafter one approval), 5 prompts evaluated with completions and timings, benchmark owner got the output, model owner got none.pre-commitpasses on all four files.Attestation is not verified against a live enclave — nothing is deployed at
syft-enclave.openmined.containers.tinfoil.devright now. The policy call is the shapedocs/tinfoil_deployment.mdandscripts/tinfoil_e2e_check.pyuse.🤖 Generated with Claude Code