LLMCA (Language Model Cellular Automata) is an experimental project that combines cellular automata with language models (LLM). This project allows simulating a cognitive space where each cell is a cognitive unit evolving based on rules defined by a language model.
Rust
8
104 commits
updated May 30, 2026
LLMCA (Language Model Cellular Automata) is an experimental project that combines cellular automata with large language models (LLMs). It simulates a cognitive space where each cell evolves based on rules defined and interpreted by an LLM, considering the state of its neighbors.
CognitiveUnitPair).LifeManager for managing multiple simulation entities with persistence and lifecycle management.resolvers.toml) or environment variables, allowing heterogeneous API backends.schemars for automatic schema generation, ensuring type-safe communication between the simulation and LLM APIs..life directory), allowing resumption from previous steps.git clone https://github.com/pinsky-three/llmca.gitcd llmca && cargo buildAPI Configuration: Configure LLM resolvers using one of two methods:
Option A: TOML Configuration (Recommended)
Create a resolvers.toml file in the project root:
[[resolvers]]
provider = "ollama"
api_url = "http://localhost:11434"
model_name = "llama3.2"
api_key = "_"
[[resolvers]]
provider = "openrouter"
api_url = "https://openrouter.ai/api/v1"
model_name = "deepseek/deepseek-r1-distill-qwen-1.5b"
api_key = "your_key"
provider is optional for older configs. If omitted, URLs containing
openrouter use the OpenRouter provider; all other URLs default to Ollama.
Ollama URLs may be written as http://localhost:11434 or the legacy
OpenAI-compatible http://localhost:11434/v1; the native Rig adapter will
normalize the latter.
Option B: Environment Variables
Create a .env file in the project root:
OPENAI_API_URL="http://your_api_url:port/v1" # Comma-separated for multiple APIs
OPENAI_MODEL_NAME="your_model_name" # Comma-separated for multiple models
OPENAI_API_KEY="your_api_key" # Comma-separated for multiple keys
OPENAI_PROVIDER="ollama" # Optional, comma-separated: ollama or openrouter
If using multiple APIs, ensure the number of URLs, model names, and API keys match.
Run: cargo run -p minimal-ui
Runtime binaries initialize structured JSON logs with tracing-subscriber.
The default log level is info, which records step-level telemetry without
logging every model response:
RUST_LOG=info cargo run -p minimal-ui
Each completed evolution step logs unit count, resolver count, chunks,
unique-state count, parse failures, LLM transport failures, and elapsed time.
The API also returns the same telemetry from POST /api/entity/:id/evolve.
minimal-ui skips saved entity restore on startup and logs manager/entity setup
duration separately. Slow evolution chunks are logged at info; fast chunks are
logged at debug.
Model calls use Rig
instead of a hand-built chat-completions request. Ollama uses Rig's typed
structured output path, which sends the CognitiveUnitPair JSON schema through
Ollama's native format parameter. OpenRouter uses Rig's extractor/tool path
because Rig 0.36 does not yet map its generic output_schema field to
OpenRouter's native response_format.
Raw model responses are available behind a targeted debug filter so normal runs avoid high-volume logging and formatting overhead:
RUST_LOG=info,llmca::model_response=debug cargo run -p minimal-ui
Do not enable llmca::model_response=debug when prompts or model outputs may
contain sensitive data. API keys are never emitted by the structured logs.
Max in-flight completion requests equals the number of resolvers in
resolvers.toml. For example, 4 resolvers means 4 concurrent completion calls.
The LLM receives a JSON input representing a cell's memory (previous states) and its neighbors' current states. It's instructed to return a JSON object containing the next state and optionally, a new rule following the CognitiveUnitPair schema.
Example LLM System Prompt:
You're a LLM Cognitive Unit and your unique task is to respond with your next (rule, state)
based on your current rule and the states of your neighbors in json format.
Always respond with a plain json compliant with `CognitiveUnitPair` schema.
The user passes your memory and the neighborhood states as a list of 'messages' in json format.
Don't put the json in a code block, don't add explanations, just return the json ready to be parsed.
Only if your rule is empty, you may propose a new rule and return it with the response.
If you think the rule is wrong, you may propose a new rule and return it with the response.
Example of valid response: `{"rule": "rule_1", "state": "state_1"}`
Example LLM Input (Simplified):
[
"self memory",
{"rule": "be red if neighbors are green", "state": "#ff0000"},
{"rule": "be red if neighbors are green", "state": "#ff0000"},
"neighbors",
{"rule": "...", "state": "#00ff00"},
{"rule": "...", "state": "#00ff00"}
]
Example LLM Output:
{"rule": "be red if neighbors are green", "state": "#ff0000"}
The visualization then interprets the state (e.g., #ff0000) as a color. The simulation maintains a temporal memory (configurable size) of past states for each cognitive unit, allowing the LLM to consider historical patterns when determining the next state.
Contributions are welcome! Fork the project and submit pull requests.
This project is licensed under the MIT License. For more details, see the LICENSE file.
104 commits
Rust
96.7%
Shell
3.3%
LLMCA (Language Model Cellular Automata) is an experimental project that combines cellular automata with language models (LLM). This project allows simulating a cognitive space where each cell is a cognitive unit evolving based on rules defined by a language model.
Rust
8
104 commits
updated May 30, 2026
LLMCA (Language Model Cellular Automata) is an experimental project that combines cellular automata with large language models (LLMs). It simulates a cognitive space where each cell evolves based on rules defined and interpreted by an LLM, considering the state of its neighbors.
CognitiveUnitPair).LifeManager for managing multiple simulation entities with persistence and lifecycle management.resolvers.toml) or environment variables, allowing heterogeneous API backends.schemars for automatic schema generation, ensuring type-safe communication between the simulation and LLM APIs..life directory), allowing resumption from previous steps.git clone https://github.com/pinsky-three/llmca.gitcd llmca && cargo buildAPI Configuration: Configure LLM resolvers using one of two methods:
Option A: TOML Configuration (Recommended)
Create a resolvers.toml file in the project root:
[[resolvers]]
provider = "ollama"
api_url = "http://localhost:11434"
model_name = "llama3.2"
api_key = "_"
[[resolvers]]
provider = "openrouter"
api_url = "https://openrouter.ai/api/v1"
model_name = "deepseek/deepseek-r1-distill-qwen-1.5b"
api_key = "your_key"
provider is optional for older configs. If omitted, URLs containing
openrouter use the OpenRouter provider; all other URLs default to Ollama.
Ollama URLs may be written as http://localhost:11434 or the legacy
OpenAI-compatible http://localhost:11434/v1; the native Rig adapter will
normalize the latter.
Option B: Environment Variables
Create a .env file in the project root:
OPENAI_API_URL="http://your_api_url:port/v1" # Comma-separated for multiple APIs
OPENAI_MODEL_NAME="your_model_name" # Comma-separated for multiple models
OPENAI_API_KEY="your_api_key" # Comma-separated for multiple keys
OPENAI_PROVIDER="ollama" # Optional, comma-separated: ollama or openrouter
If using multiple APIs, ensure the number of URLs, model names, and API keys match.
Run: cargo run -p minimal-ui
Runtime binaries initialize structured JSON logs with tracing-subscriber.
The default log level is info, which records step-level telemetry without
logging every model response:
RUST_LOG=info cargo run -p minimal-ui
Each completed evolution step logs unit count, resolver count, chunks,
unique-state count, parse failures, LLM transport failures, and elapsed time.
The API also returns the same telemetry from POST /api/entity/:id/evolve.
minimal-ui skips saved entity restore on startup and logs manager/entity setup
duration separately. Slow evolution chunks are logged at info; fast chunks are
logged at debug.
Model calls use Rig
instead of a hand-built chat-completions request. Ollama uses Rig's typed
structured output path, which sends the CognitiveUnitPair JSON schema through
Ollama's native format parameter. OpenRouter uses Rig's extractor/tool path
because Rig 0.36 does not yet map its generic output_schema field to
OpenRouter's native response_format.
Raw model responses are available behind a targeted debug filter so normal runs avoid high-volume logging and formatting overhead:
RUST_LOG=info,llmca::model_response=debug cargo run -p minimal-ui
Do not enable llmca::model_response=debug when prompts or model outputs may
contain sensitive data. API keys are never emitted by the structured logs.
Max in-flight completion requests equals the number of resolvers in
resolvers.toml. For example, 4 resolvers means 4 concurrent completion calls.
The LLM receives a JSON input representing a cell's memory (previous states) and its neighbors' current states. It's instructed to return a JSON object containing the next state and optionally, a new rule following the CognitiveUnitPair schema.
Example LLM System Prompt:
You're a LLM Cognitive Unit and your unique task is to respond with your next (rule, state)
based on your current rule and the states of your neighbors in json format.
Always respond with a plain json compliant with `CognitiveUnitPair` schema.
The user passes your memory and the neighborhood states as a list of 'messages' in json format.
Don't put the json in a code block, don't add explanations, just return the json ready to be parsed.
Only if your rule is empty, you may propose a new rule and return it with the response.
If you think the rule is wrong, you may propose a new rule and return it with the response.
Example of valid response: `{"rule": "rule_1", "state": "state_1"}`
Example LLM Input (Simplified):
[
"self memory",
{"rule": "be red if neighbors are green", "state": "#ff0000"},
{"rule": "be red if neighbors are green", "state": "#ff0000"},
"neighbors",
{"rule": "...", "state": "#00ff00"},
{"rule": "...", "state": "#00ff00"}
]
Example LLM Output:
{"rule": "be red if neighbors are green", "state": "#ff0000"}
The visualization then interprets the state (e.g., #ff0000) as a color. The simulation maintains a temporal memory (configurable size) of past states for each cognitive unit, allowing the LLM to consider historical patterns when determining the next state.
Contributions are welcome! Fork the project and submit pull requests.
This project is licensed under the MIT License. For more details, see the LICENSE file.
104 commits
Rust
96.7%
Shell
3.3%