Spaces:
Runtime error
Runtime error
File size: 19,818 Bytes
40e814f f0aabd8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | ---
title: WorldSmithAI
emoji: π
colorFrom: pink
colorTo: gray
sdk: gradio
sdk_version: 6.18.0
python_version: '3.13'
app_file: app.py
pinned: false
short_description: Forge ecosystems from small models
---
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
# WorldSmithAI
**Production-Level Agent-Based World Simulation Framework**
WorldSmithAI is a modular Python framework that converts natural language descriptions into generic agent-based worlds and simulates emergent behavior.
The core idea is simple:
```text
Natural language prompt
β WorldSpec JSON DSL
β Pydantic validation
β WorldFactory
β World
β Scheduler
β Agents
β Policies
β Behaviors
β Metrics
β Visualization
β Narration
β Gradio UI
```
WorldSmithAI is intentionally **not hardcoded for any single domain**.
There are no runtime classes like:
```python
class Sheep
class Wolf
class Scientist
class Merchant
class Dragon
```
Instead, every world is composed from generic runtime concepts:
```python
Agent
Behavior
Resource
Event
World
Policy
```
That means the same engine can simulate:
- farm ecosystems
- medieval civilizations
- research ecosystems
- startup economies
- social networks
- fantasy worlds
- transport networks
- power grids
- space colonies
- any DSL-generated ecosystem
---
## Project Status
WorldSmithAI is designed as a hackathon-grade prototype with production-oriented architecture.
Current capabilities include:
- generic agent representation
- behavior abstraction
- concrete behavior modules
- rule-based policies
- contextual bandit policy scaffold
- Pydantic DSL schema
- JSON parser and semantic validator
- WorldFactory for DSL β runtime conversion
- metrics for diversity, entropy, stability, and interestingness
- Matplotlib renderer
- GIF/MP4 animation support
- chart generation
- deterministic narration
- root-level Gradio app
- CLI runner
- example DSL worlds
The system works without an external LLM by using a deterministic fallback world generator. If a model is configured, the model is only responsible for generating JSON DSL, never Python code.
---
## Repository Layout
```text
WorldSmithAI/
βββ app.py
βββ callbacks.py
βββ main.py
βββ README.md
βββ requirements.txt
β
βββ core/
β βββ agent.py
β βββ behavior.py
β βββ resource.py
β βββ event.py
β βββ world.py
β βββ scheduler.py
β
βββ behaviors/
β βββ movement.py
β βββ consume.py
β βββ trade.py
β βββ attack.py
β βββ research.py
β βββ collaboration.py
β βββ transport.py
β βββ construction.py
β βββ governance.py
β βββ market.py
β βββ adoption.py
β βββ planning.py
β βββ memory.py
β
βββ policies/
β βββ base_policy.py
β βββ rule_policy.py
β βββ contextual_bandit.py
β
βββ dsl/
β βββ schema.py
β βββ parser.py
β βββ validator.py
β
βββ factory/
β βββ world_factory.py
β
βββ metrics/
β βββ diversity.py
β βββ entropy.py
β βββ stability.py
β βββ interestingness.py
β
βββ visualization/
β βββ renderer.py
β βββ animation.py
β βββ charts.py
β
βββ llm/
β βββ world_generator.py
β βββ narrator.py
β βββ prompts.py
β
βββ examples/
βββ farm.json
βββ civilization.json
βββ research.json
```
`app.py` is intentionally at the repository root because Hugging Face Gradio Spaces expect the app entry point there.
---
## Core Design Principles
WorldSmithAI follows these principles:
1. **No hardcoded species or domains**
A wolf, scientist, startup founder, train, dragon, or power node is just an `Agent` with a different `type`, `state`, `memory`, `goals`, `behaviors`, and `policy`.
2. **DSL-first world definition**
Worlds are described as JSON using the `WorldSpec` schema.
3. **LLM generates JSON only**
The model never generates Python code. The Python engine remains deterministic.
4. **Composition over inheritance**
Agent behavior comes from behavior objects and policies, not subclass-specific logic.
5. **Strong module boundaries**
Parsing, validation, factory construction, simulation, visualization, metrics, narration, and UI are separate layers.
6. **Gradio app is thin**
`app.py` defines the UI. `callbacks.py` runs the engine pipeline.
---
## Installation
### 1. Clone the repository
```bash
git clone <your-repo-url>
cd WorldSmithAI
```
### 2. Create a virtual environment
Python 3.11 or newer is recommended.
```bash
python -m venv .venv
```
Activate it:
```bash
source .venv/bin/activate
```
On Windows PowerShell:
```powershell
.venv\Scripts\Activate.ps1
```
### 3. Install dependencies
If your project already has a `requirements.txt`, run:
```bash
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```
If you have not created `requirements.txt` yet, use this minimal set:
```bash
python -m pip install --upgrade pip
python -m pip install gradio pydantic numpy matplotlib pillow huggingface_hub
```
Optional development tools:
```bash
python -m pip install pytest ruff mypy
```
Optional MP4 support requires `ffmpeg` installed on the system. GIF output works through Pillow and is the safer default.
---
## Suggested `requirements.txt`
Create this file at the repository root:
```text
gradio
pydantic>=2
numpy
matplotlib
pillow
huggingface_hub
```
Optional dev dependencies can be placed in `requirements-dev.txt`:
```text
pytest
ruff
mypy
```
---
## Can This Be Tested Locally?
Yes. WorldSmithAI can be tested locally without Hugging Face Spaces and without an external LLM.
The deterministic fallback generator allows this command to work even if no model is configured:
```bash
python main.py --prompt "A research ecosystem with scientists, reviewers, funding agents, and knowledge resources" --steps 10 --no-animation
```
For a faster smoke test, disable all visual outputs:
```bash
python main.py \
--prompt "A tiny farm ecosystem with farmers, water, crops, and soil health" \
--steps 5 \
--no-animation \
--no-charts \
--no-final-image \
--no-narrative
```
If that completes, your parser, schema, world generation fallback, validation, factory, scheduler, policies, behaviors, and metrics are at least importable and executable.
---
## Local Smoke Test Checklist
Run these from the repository root.
### 1. Check Python syntax
```bash
python -m compileall .
```
This catches syntax errors across all modules.
### 2. List example worlds
```bash
python main.py --list-examples
```
Expected output should include some or all of:
```text
farm
civilization
research
```
### 3. Validate an example DSL file
```bash
python main.py --example research --validate-only
```
Or directly:
```bash
python main.py --dsl examples/research.json --validate-only
```
This checks:
- JSON parsing
- Pydantic schema validation
- semantic DSL validation
### 4. Run a short simulation without animation
```bash
python main.py --example research --steps 5 --no-animation
```
This checks:
- WorldFactory
- runtime object construction
- policies
- behaviors
- scheduler/world stepping
- metrics
- charts/final image unless disabled
### 5. Run the fastest full-pipeline smoke test
```bash
python main.py \
--example farm \
--steps 5 \
--no-animation \
--no-charts \
--no-final-image \
--no-narrative
```
This is useful when debugging core engine issues.
### 6. Run a full local artifact test
```bash
python main.py --example research --steps 20 --output-dir outputs/research_test
```
Expected outputs:
```text
outputs/research_test/
βββ world_spec.json
βββ validation_report.json
βββ metrics.json
βββ narrative.md
βββ run_summary.json
βββ simulation.gif
βββ population chart image
βββ resource chart image
βββ final world image
```
Exact image filenames may depend on the callback artifact writer.
### 7. Run the Gradio app locally
```bash
python app.py
```
Then open the local URL printed in the terminal, usually something like:
```text
http://127.0.0.1:7860
```
Try the default prompt first. Then try one of:
```text
A medieval civilization with rulers, merchants, artisans, guards, public trust, taxes, and trade.
A startup economy with founders, customers, investors, market adoption, and shifting goals.
A fantasy world with dragons, mages, healers, mana, alliances, and negotiation.
```
---
## CLI Usage
`main.py` is the local command-line entry point.
### Run an example world
```bash
python main.py --example research --steps 60
```
### Run a DSL file
```bash
python main.py --dsl examples/farm.json --steps 80
```
### Generate a world from a prompt
```bash
python main.py \
--prompt "A fantasy kingdom with dragons, mages, merchants, mana, trade, and alliances" \
--steps 70
```
### Validate only
```bash
python main.py --dsl examples/civilization.json --validate-only
```
### Generate DSL only
```bash
python main.py \
--prompt "A transport network with hubs, carriers, queues, chargers, and route planning" \
--generate-only
```
### Disable expensive outputs
```bash
python main.py --example research --steps 20 --no-animation --no-charts
```
### Use MP4 animation
```bash
python main.py --example research --steps 30 --animation-format mp4
```
If MP4 fails, install `ffmpeg` or use GIF:
```bash
python main.py --example research --steps 30 --animation-format gif
```
---
## Gradio App Usage
Start the app:
```bash
python app.py
```
The UI includes:
1. **Generate + Simulate**
Enter a natural-language world prompt. The app generates DSL, builds a world, runs simulation, and returns:
- generated JSON DSL
- validation report
- animation
- population chart
- resource chart
- final world image
- narrative summary
- metrics JSON
2. **Generate DSL only**
Use this to inspect the generated `WorldSpec` before simulation.
3. **Simulate existing DSL**
Paste JSON or load an example from `examples/`.
4. **Validate DSL**
Validate a JSON world spec without running it.
---
## Optional Model Setup
WorldSmithAI works without an LLM by using a deterministic fallback generator.
To enable a Hugging Face model for DSL generation, set:
```bash
export WORLDSMITHAI_MODEL_ID="your-model-id"
```
Optional token:
```bash
export HF_TOKEN="your-hugging-face-token"
```
Then run:
```bash
python app.py
```
The model is only asked to generate WorldSpec JSON. It is not allowed to generate Python code.
If the model fails or returns invalid JSON, WorldSmithAI can fall back to deterministic generation.
---
## Environment Variables
| Variable | Purpose |
|---|---|
| `WORLDSMITHAI_MODEL_ID` | Optional Hugging Face model id for JSON DSL generation |
| `HF_TOKEN` | Optional Hugging Face token |
| `WORLDSMITHAI_OUTPUT_DIR` | Directory for generated artifacts |
| `WORLDSMITHAI_DEFAULT_STEPS` | Default simulation steps in the app |
| `WORLDSMITHAI_MAX_FRAMES` | Maximum animation frames |
| `WORLDSMITHAI_LOG_LEVEL` | Logging level, for example `INFO` or `DEBUG` |
Example:
```bash
export WORLDSMITHAI_DEFAULT_STEPS=60
export WORLDSMITHAI_MAX_FRAMES=80
export WORLDSMITHAI_LOG_LEVEL=INFO
python app.py
```
---
## DSL Example
A minimal world looks like this:
```json
{
"schema_version": "1.0",
"id": "tiny_world",
"name": "Tiny World",
"description": "A minimal generic world.",
"simulation": {
"steps": 10,
"seed": 0,
"scheduler": "sequential",
"activation": "sequential",
"collect_history": true
},
"space": {
"dimensions": 2,
"bounds": [[0, 10], [0, 10]],
"toroidal": false,
"enforce_bounds": true
},
"agents": [
{
"id": "agent_1",
"type": "explorer",
"position": [1, 1],
"state": {
"energy": 10,
"credits": 5
},
"memory": {
"goals": [
{
"id": "learn",
"importance": 1,
"score": 1
}
]
},
"goals": [
{
"id": "learn",
"importance": 1,
"score": 1
}
],
"behaviors": [
{
"name": "prioritize",
"params": {
"source_path": "memory.goals"
}
},
{
"name": "choose_goal",
"params": {}
},
{
"name": "remember",
"params": {
"category": "initial",
"content": {
"note": "hello world"
}
}
}
],
"policy": {
"type": "rule_policy",
"params": {
"rules": [
{
"behavior_name": "choose_goal",
"score_delta": 3
},
{
"behavior_name": "prioritize",
"score_delta": 2
},
{
"behavior_name": "remember",
"score_delta": 1
}
]
}
},
"alive": true,
"metadata": {}
}
],
"resources": [],
"events": [],
"metrics": [
{
"name": "diversity",
"params": {
"collection": "agents",
"group_by_path": "type"
}
}
],
"metadata": {}
}
```
---
## Architecture Notes
### World generation
`llm/world_generator.py` converts prompts into `WorldSpec`.
If no model client is configured, it uses a deterministic fallback builder.
### Parsing and validation
`dsl/parser.py` accepts:
- JSON strings
- dictionaries
- JSON files
- Markdown-fenced JSON
- model responses containing JSON
`dsl/schema.py` performs structural validation.
`dsl/validator.py` performs semantic validation, such as checking behavior names, policy names, constructor parameters, and references.
### Runtime construction
`factory/world_factory.py` turns `WorldSpec` into runtime objects:
```text
WorldSpec
β Agent
β Resource
β Event
β Behavior
β Policy
β World
```
### Simulation
The world and scheduler advance agents. Agents delegate decision-making to policies, and behaviors mutate generic state/memory.
### Visualization
`visualization/renderer.py` renders a single world state.
`visualization/animation.py` renders GIF or MP4 animations.
`visualization/charts.py` renders population and resource curves.
### Metrics
`metrics/` includes:
- diversity
- entropy
- stability
- interestingness
### Narration
`llm/narrator.py` produces deterministic narrative summaries and can optionally use a model client for polished narration.
---
## Testing Strategy
A practical local testing ladder:
### Level 1: Syntax
```bash
python -m compileall .
```
### Level 2: DSL parsing
```bash
python main.py --dsl examples/farm.json --validate-only
python main.py --dsl examples/civilization.json --validate-only
python main.py --dsl examples/research.json --validate-only
```
### Level 3: Fast simulation
```bash
python main.py --example farm --steps 5 --no-animation --no-charts --no-final-image --no-narrative
```
### Level 4: Metrics and narration
```bash
python main.py --example research --steps 10 --no-animation --no-charts --no-final-image
```
### Level 5: Full artifact generation
```bash
python main.py --example civilization --steps 20 --output-dir outputs/civilization_test
```
### Level 6: Gradio UI
```bash
python app.py
```
---
## Troubleshooting
### `ModuleNotFoundError`
Make sure you are running commands from the repository root:
```bash
pwd
```
The current directory should contain:
```text
app.py
callbacks.py
main.py
core/
behaviors/
dsl/
factory/
metrics/
visualization/
llm/
```
Then run:
```bash
python -m compileall .
```
### `ImportError` for a behavior module
Check that the behavior file exists and that the behavior registry includes the expected names.
For example:
```bash
python - <<'PY'
from dsl.validator import load_default_behavior_registry
result = load_default_behavior_registry()
print("Behavior count:", len(result.registry))
print("Import errors:", result.import_errors)
print("Names:", sorted(result.registry.keys())[:50])
PY
```
### Unknown behavior warnings
If semantic validation reports unknown behavior names, check:
1. the behavior file exists
2. it defines a `BEHAVIOR_REGISTRY`
3. the behavior name in JSON matches the registry key
4. `factory/world_factory.py` includes the behavior module in `DEFAULT_BEHAVIOR_MODULES`
### Constructor parameter warnings
If the validator reports unknown constructor parameters, either:
- fix the JSON behavior params, or
- update the behavior dataclass to accept the parameter, or
- run in permissive mode through `callbacks.py`, which is friendlier for hackathon demos.
### MP4 animation fails
Use GIF instead:
```bash
python main.py --example research --steps 30 --animation-format gif
```
MP4 requires `ffmpeg` installed on the host.
### Gradio app starts but generation is slow
Use fewer steps:
```bash
export WORLDSMITHAI_DEFAULT_STEPS=20
export WORLDSMITHAI_MAX_FRAMES=30
python app.py
```
Or disable model usage in the UI and use deterministic fallback generation.
### Model returns invalid JSON
The parser can extract JSON from common model response formats, but small models may still produce invalid JSON.
Use:
- the deterministic fallback generator
- βGenerate DSL onlyβ tab
- βValidate DSLβ tab
- simpler prompts
- fewer agents
---
## Hugging Face Space Notes
For a Gradio Space, keep these files at the repository root:
```text
app.py
callbacks.py
requirements.txt
```
The Space should install dependencies from `requirements.txt`.
Recommended Space hardware for the deterministic version is CPU basic. If you use a larger model locally inside the Space, choose hardware appropriate for that model.
---
## Development Tips
Run formatting and lint checks if you install dev tools:
```bash
ruff check .
```
Run type checks if your environment is ready:
```bash
mypy .
```
Run a quick no-UI smoke test before pushing:
```bash
python main.py --example research --steps 5 --no-animation --no-charts --no-final-image --no-narrative
```
Then run the app:
```bash
python app.py
```
---
## Hackathon Demo Script
A good demo flow:
1. Open the app.
2. Enter a world prompt, for example:
```text
A startup economy where founders, investors, customers, and competitors bid for attention,
adopt strategies, collaborate, forecast demand, and rebalance resources.
```
3. Run simulation for 40 to 60 steps.
4. Show the generated DSL.
5. Show the animation.
6. Show population and resource charts.
7. Show metrics JSON.
8. Read the narrative summary.
9. Explain that the model generated only JSON, while the deterministic Python engine executed the simulation.
---
## Current Limitations
WorldSmithAI is designed as a hackathon-grade but production-oriented framework. Some areas are intentionally extensible:
- event execution is generic and can be expanded
- richer scheduler activation modes can be added
- metric registry integration can be expanded
- behavior parameter schemas can be tightened
- model-specific generation adapters can be added
- graph/network visualization can be added
- multi-run comparison can be added
- unit tests should be expanded as the codebase stabilizes
---
## Acknowledgments
Built for the Hugging Face Build Small Hackathon.
WorldSmithAI explores how small language models can generate compact, validated world DSLs while deterministic Python systems execute and visualize the resulting simulations.
|