Skip to main content
AI tutorials

Build and Connect WERM: A C. elegans Neural Network for Local AI Steering

Learn how to install WERM, simulate its 302-neuron C. elegans network, apply touch stimuli, connect it to Ollama or an OpenAI-compatible local server, and use its neural state to influence language-model sampling settings.

Build and Connect WERM: A C. elegans Neural Network for Local AI Steering
WERM project visualization

What WERM does

WERM, short for Wiring-Encoded Recurrent Modulator, is a small neural simulation based on the real wiring diagram of the adult hermaphrodite Caenorhabditis elegans. Its 302-neuron rate network runs in a browser, in Node.js, or alongside a language model running locally on your computer.

The model uses the connectome to process simulated sensory stimuli. A steering layer reads the resulting worm state and converts it into language-model settings such as temperature, top-p, token limits, and a one-line tone mode. WERM does not send data to a remote service when used with a local model.

What is based on biological data?

The repository includes the adult hermaphrodite network from Cook et al. 2019, provided through the OpenWorm Connectome Toolbox. It contains 302 neurons, 3,709 directed chemical connections, and 1,105 gap-junction pairs. Connection weights represent the number of electron microscope sections in which two cells were observed joined, rather than a direct synapse count.

The project also contains genome-derived maps. The reference genome is NCBI RefSeq GCF_000002985.6, also known as WBcel235, and the gene annotation comes from WormBase WS298. The included measurements cover 100,272,607 bases across six chromosomes, with 35.4 percent GC content and 19,971 protein-coding genes.

WERM uses a rate network with a gate inspired by liquid time constant networks. The 28 neurons known to make and release GABA are treated as inhibitory; the remaining neurons are treated as excitatory.

Understand the modeling choices

The connectome does not specify the sign of every synapse. WERM therefore uses the GABA-based rule as a simplifying assumption. The model parameters were selected by scripts/sweep.mjs from 1,470 settings using a rule fixed before the results were examined. This makes WERM a tuned model, not a fit to neural recordings.

The steering mapping is also an explicit design choice. The worm state controls sampling parameters and tone through code that you can inspect and change. The neuroscience data does not determine these language-model settings.

Install and run the first simulation

Clone the repository and enter its directory:

git clone https://github.com/Henryfud/werm
cd werm

WERM requires Node.js 20 or newer. The model has no runtime dependencies, so you can run the unit tests without installing packages:

npm test

Run a three-second simulation using the tail-touch stimulus:

node src/cli.mjs sim --stim touch-tail --seconds 3

The command runs the network with the selected sensory input. The command-line interface also supports the connect command for local language-model integration and the steer command for inspecting the settings WERM would produce.

Connect WERM to Ollama

First install Ollama from ollama.com/download and start it. You can launch the service directly with ollama serve if necessary. Download a local model, then connect WERM to it:

ollama pull llama3.2
node src/cli.mjs connect --model llama3.2

Replace llama3.2 with the name of any model installed in Ollama. If Ollama is not running or the model is unavailable, WERM reports the problem and suggests what to run. Use --host when the Ollama service is hosted somewhere other than http://localhost:11434.

During a conversation, WERM first converts the message into sensory stimuli, runs the worm for a short period, and then uses the resulting state to configure the model request. Messages remain on your computer when both WERM and the model server are local.

Use another OpenAI-compatible local server

WERM can connect to any local engine that serves the OpenAI chat completions API. Start the server, then provide its base URL and model name:

node src/cli.mjs connect --base-url http://localhost:1234/v1 --model YOUR_MODEL

Common server configurations include:

  • LM Studio: start the local server from its Developer tab and use http://localhost:1234/v1.
  • llama.cpp: run llama-server -m your-model.gguf and use http://localhost:8080/v1.
  • vLLM: run vllm serve your-model and use http://localhost:8000/v1.
  • Ollama's OpenAI-style endpoint: use http://localhost:11434/v1.

For these servers, WERM sends temperature, top_p, and max_tokens. The OpenAI-style API does not include the repeat penalty used by the Ollama client, so that option is omitted. If your server requires authentication, set the WERM_API_KEY environment variable.

Inspect steering without contacting a model

Use the steer command to see how WERM interprets a message:

node src/cli.mjs steer "why is my code broken?"

The command prints the inferred stimuli, the current mode, model-specific options, and a system prompt. A result can include stimuli such as nose-touch and noxious, a reversing mode, and sampling values for Ollama and OpenAI-compatible clients.

This offline command is useful when you are developing an integration, because it lets you inspect the steering behavior without starting a model server.

Use WERM from JavaScript

The core network and steering helpers are available as ES modules. The following example loads the connectome, settles the network, applies stimuli derived from a message, and reads the resulting steering parameters:

import fs from "node:fs";
import { WormBrain } from "./src/network.mjs";
import { steer, stimuliFromText, applyStimuli, systemPrompt } from "./src/steer.mjs";

const worm = new WormBrain(
  JSON.parse(fs.readFileSync("data/connectome.json", "utf8"))
);

worm.run(1);
applyStimuli(worm, stimuliFromText("thanks, that helped"), true);
worm.run(1.5);

const { options, mode } = steer(worm.readout());
// Send options and systemPrompt(mode) to your local engine.

The initial worm.run(1) call lets the network settle. After the text is converted into stimuli, applyStimuli changes the sensory state and another run gives the network time to respond. The readout is then passed to steer, which returns sampling options and a mode. Use systemPrompt(mode) to obtain the corresponding tone prompt.

Rerun the experiments

The repository includes scripts for the parameter sweep, null-model comparisons, and a reservoir-style memory benchmark:

npm run sweep
npm run experiments

These commands write results to docs/results/, use every available CPU core, and take a few minutes.

The documented findings report that tail touch strongly pushes the network forward and nose touch pushes it backward, outperforming 100 random pokes of the same size in each test. Head touch produces only a slight backward response, while noxious stimulation is no better than a random poke. Shuffled networks and random networks usually fail to match the real network's head-versus-tail difference, although the real wiring performs slightly worse than shuffled versions on the memory benchmark.

The effect of steering on language-model output has not yet been measured. The evaluation script is available, but its real model run remains to be completed.

Evaluate steering

To preview the planned evaluation without contacting Ollama, run:

node scripts/steer-eval.mjs --dry-run --limit 5

For a real evaluation using a local Ollama model, run:

node scripts/steer-eval.mjs --model llama3.2

The script compares default settings, WERM-generated settings, and random settings across 200 prompts. The dry-run option is useful for checking the planned parameters before starting a model-dependent test.

Rebuild genome and connectome data

Genome maps

To download the reference genome and regenerate the GC and gene-density maps, run:

bash scripts/fetch_genome.sh
node scripts/genome_stats.mjs data/genome/c_elegans.fasta
node scripts/gc_windows.mjs data/genome/c_elegans.fasta
bash scripts/fetch_annotation.sh
node scripts/gene_windows.mjs data/genome/annotation.gff.gz

The genome download is about 100 MB and the annotation download is about 10 MB. Downloaded files are ignored by Git. The site can also read the FASTA file locally to draw the GC map; the data is not uploaded.

Connectome file

To rebuild data/connectome.json, create a Python virtual environment, install the required package archive, unpack it, and run the build script:

python3 -m venv .venv
.venv/bin/pip install openpyxl
.venv/bin/pip download cect==0.3.5 --no-deps -d dl
unzip -q dl/cect-*.whl -d dl/x
.venv/bin/python scripts/build_connectome.py dl/x/cect/data

Build and check the site

The long-scroll site in site/ includes a generative pixel worm field, a live connectome globe, the genome drawn to scale, and explanatory notes. The site uses the same code as the command-line model.

Build the page with:

npm run build:site

This writes site/index.html. Set GITHUB_URL or SITE_URL to customize links on the page. Netlify uses the same build process.

Run the repository checks with:

npm test
npm run check
npm ci && npx playwright install chromium && npm run test:site

The test suite includes 36 unit tests. The additional checks validate project conventions and run a headless-browser smoke test. Continuous integration runs the checks on Node.js 20 and 22.

Explore the project structure

  • data/connectome.json contains the neurons and connections.
  • src/network.mjs implements the neuron model.
  • src/reflex.mjs contains reflex checks and specificity comparisons.
  • src/graphs.mjs creates shuffled and random wiring variants.
  • src/steer.mjs maps worm state to model settings and tone.
  • src/ollama.mjs and src/openai.mjs implement local model clients.
  • src/cli.mjs provides the sim, connect, and steer commands.
  • scripts/ contains data, experiment, validation, and site-build scripts.
  • docs/RESULTS.md records measured outcomes, while docs/ARCHITECTURE.md explains the model and readout.

Important limitations

WERM is intentionally small and is not a complete biological simulation. It has no muscles, body physics, neuropeptides, or learning, and it has not been compared with recordings from real worms. Its behavior should not be interpreted as a prediction of what a real worm would do.

The steering layer also does not give a language model new abilities, and its effect on model responses has not yet been measured. For a more faithful biophysical simulation, the README recommends OpenWorm's c302. WERM is designed to be compact enough to inspect and modify in an afternoon.

Conclusion

WERM provides a practical way to experiment with a real C. elegans wiring diagram without requiring a large simulation stack. Start with the Node.js CLI, test touch stimuli, inspect the generated steering parameters, and then connect the network to Ollama or another local OpenAI-compatible server. From there, the included scripts let you reproduce experiments, rebuild biological data products, and adapt the steering layer to your own local AI workflow.