Skip to content

3.2 Defining the Blueprint Schema

Zhoumy303 edited this page Sep 27, 2026 · 2 revisions

In this task, you will write the blueprint JSON Schema and prepare example blueprints to constrain the structured output generated by the LLM. After completing this task, you will have a verifiable, constrainable, example-backed blueprint specification, laying the foundation for the subsequent generator modules.


Prerequisites

  • Completed Task 1: Project initialization and environment setup.
  • Virtual environment activated.
  • jsonschema installed (already declared in pyproject.toml).

Step 1: Write the complete modsmith/blueprint/schema.json

This Schema acts as a "contract" that constrains what the AI generates. It defines the global configuration, the type enum, and the conditional fields required by different types.

Write the following content into modsmith/blueprint/schema.json:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "ModSmith Blueprint",
  "type": "object",
  "required": [
    "mod_id",
    "package_name",
    "minecraft_version",
    "fabric_loader_version",
    "items"
  ],
  "properties": {
    "mod_id": {
      "type": "string",
      "description": "Unique identifier of the mod. Only lowercase letters, digits, and hyphens, e.g. example-mod",
      "pattern": "^[a-z][a-z0-9-]*$"
    },
    "package_name": {
      "type": "string",
      "description": "Java package name, e.g. com.example",
      "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$"
    },
    "minecraft_version": {
      "type": "string",
      "description": "Target Minecraft version, determined by system configuration"
    },
    "fabric_loader_version": {
      "type": "string",
      "description": "Fabric Loader version, determined by system configuration"
    },
    "items": {
      "type": "array",
      "description": "List of items to generate",
      "items": {
        "type": "object",
        "required": ["id", "type", "display_name_en"],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique item ID. Only lowercase letters, digits, and underscores, e.g. healing_apple",
            "pattern": "^[a-z][a-z0-9_]*$"
          },
          "type": {
            "type": "string",
            "enum": ["basic", "food", "fuel", "tool"],
            "description": "Item type"
          },
          "display_name_en": {
            "type": "string",
            "description": "English display name"
          },
          "display_name_zh": {
            "type": "string",
            "description": "Chinese display name"
          },
          "texture": {
            "type": "string",
            "description": "Texture path; 'auto' means auto-generate",
            "default": "auto"
          },
          "nutrition": {
            "type": "integer",
            "minimum": 0,
            "description": "Hunger restored by the food (required only when type=food)"
          },
          "saturation": {
            "type": "number",
            "minimum": 0,
            "description": "Saturation added by the food (required only when type=food)"
          },
          "always_edible": {
            "type": "boolean",
            "description": "Whether always edible (effective only when type=food)",
            "default": false
          },
          "effects": {
            "type": "array",
            "description": "Status effects applied on consumption (effective only when type=food)",
            "items": {
              "type": "object",
              "required": ["effect", "duration_ticks", "amplifier"],
              "properties": {
                "effect": {
                  "type": "string",
                  "description": "Effect ID, e.g. regeneration, speed"
                },
                "duration_ticks": {
                  "type": "integer",
                  "minimum": 1,
                  "description": "Duration (in ticks; 20 ticks = 1 second)"
                },
                "amplifier": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Effect level; 0 means level I, 1 means level II"
                }
              }
            }
          },
          "burn_time": {
            "type": "integer",
            "minimum": 1,
            "description": "Burn time (in ticks; required only when type=fuel)"
          },
          "tool_type": {
            "type": "string",
            "enum": ["sword", "axe", "pickaxe", "shovel", "hoe"],
            "description": "Tool type (required only when type=tool)"
          },
          "durability": {
            "type": "integer",
            "minimum": 1,
            "description": "Durability (required only when type=tool)"
          },
          "mining_speed": {
            "type": "number",
            "minimum": 0.1,
            "description": "Mining speed (required only when type=tool)"
          },
          "attack_damage": {
            "type": "number",
            "minimum": 0,
            "description": "Attack damage (required only when type=tool)"
          }
        },
        "allOf": [
          {
            "if": {
              "properties": { "type": { "const": "food" } }
            },
            "then": {
              "required": ["nutrition", "saturation", "always_edible"]
            }
          },
          {
            "if": {
              "properties": { "type": { "const": "fuel" } }
            },
            "then": {
              "required": ["burn_time"]
            }
          },
          {
            "if": {
              "properties": { "type": { "const": "tool" } }
            },
            "then": {
              "required": ["tool_type", "durability", "mining_speed", "attack_damage"]
            }
          }
        ]
      }
    }
  }
}

Notes:

  • pattern restricts the naming format of mod_id and item id, preventing the AI from inventing names.
  • allOf + if-then implements conditional required fields: nutrition and similar fields are only required when the type is food.
  • effects is an array, supporting multiple status effects on a food item.

Step 2: Write the example blueprints

_load_examples() automatically reads every .json file under modsmith/blueprint/examples/ and sends them to the AI as few-shot examples. We prepare 3 examples covering different type values.

Example 1: modsmith/blueprint/examples/01_basic_item.json

This is the simplest item example.

{
  "mod_id": "example-mod",
  "package_name": "com.example",
  "minecraft_version": "26.1.2",
  "fabric_loader_version": "0.19.5",
  "items": [
    {
      "id": "ruby",
      "type": "basic",
      "display_name_en": "Ruby",
      "display_name_zh": "Red Ruby",
      "texture": "auto"
    }
  ]
}

Example 2: modsmith/blueprint/examples/02_food_item.json

This is a food example with a consumption effect.

{
  "mod_id": "example-mod",
  "package_name": "com.example",
  "minecraft_version": "26.1.2",
  "fabric_loader_version": "0.19.5",
  "items": [
    {
      "id": "healing_apple",
      "type": "food",
      "display_name_en": "Healing Apple",
      "display_name_zh": "Healing Apple",
      "nutrition": 4,
      "saturation": 0.3,
      "always_edible": true,
      "effects": [
        {
          "effect": "regeneration",
          "duration_ticks": 200,
          "amplifier": 0
        }
      ],
      "texture": "auto"
    }
  ]
}

Example 3: modsmith/blueprint/examples/03_tool_item.json

This is a tool example showing the fields required by the tool type.

{
  "mod_id": "example-mod",
  "package_name": "com.example",
  "minecraft_version": "26.1.2",
  "fabric_loader_version": "0.19.5",
  "items": [
    {
      "id": "guidite_sword",
      "type": "tool",
      "display_name_en": "Guidite Sword",
      "display_name_zh": "Guidite Sword",
      "tool_type": "sword",
      "durability": 455,
      "mining_speed": 5.0,
      "attack_damage": 1.5,
      "texture": "auto"
    }
  ]
}

Step 3: Validate the Schema and examples

We need to ensure:

  1. The Schema itself is a valid JSON Schema.
  2. All examples conform to this Schema.

Write a simple validation script test_schema.py (place it at the project root):

"""Validate that the Schema is legal and that examples conform to it."""

import json
from pathlib import Path

import jsonschema

# Path definitions
SCHEMA_PATH = Path("modsmith/blueprint/schema.json")
EXAMPLES_DIR = Path("modsmith/blueprint/examples")


def main() -> None:
    # 1. Load the Schema
    with open(SCHEMA_PATH, "r", encoding="utf-8") as f:
        schema = json.load(f)

    # 2. Validate the Schema itself
    try:
        jsonschema.Draft7Validator.check_schema(schema)
        print("✅ The Schema itself is a valid JSON Schema.")
    except jsonschema.SchemaError as e:
        print(f"❌ The Schema itself is invalid: {e}")
        return

    # 3. Validate each example against the Schema
    validator = jsonschema.Draft7Validator(schema)
    all_passed = True

    for example_path in sorted(EXAMPLES_DIR.glob("*.json")):
        with open(example_path, "r", encoding="utf-8") as f:
            example = json.load(f)

        errors = list(validator.iter_errors(example))
        if errors:
            all_passed = False
            print(f"❌ {example_path.name} does not conform to the Schema:")
            for error in errors:
                print(f"   - {error.message}")
        else:
            print(f"✅ {example_path.name} conforms to the Schema.")

    if all_passed:
        print("\n🎉 All examples passed validation!")
    else:
        print("\n⚠️ Some examples did not pass validation. Please check.")


if __name__ == "__main__":
    main()

Run:

python test_schema.py

Expected output:

✅ The Schema itself is a valid JSON Schema.
✅ 01_basic_item.json conforms to the Schema.
✅ 02_food_item.json conforms to the Schema.
✅ 03_tool_item.json conforms to the Schema.

🎉 All examples passed validation!

Step 4: Verify that the LLM can use these examples

After completing the steps above, re-run the previous LLM test script:

python test_llm.py

This time, the System Prompt sent to the AI contains the complete Schema and the 3 examples. The AI should be able to generate more regular and complete blueprints. For example, if you input "create an apple that restores 4 hunger points when eaten," the JSON it outputs should automatically include effects: [], always_edible: true, and similar fields.


✅ Task 2 Acceptance Criteria

  • schema.json includes global configuration, the item array, and conditional validation (allOf + if-then).
  • The examples/ directory contains 3 examples covering basic, food, and tool types.
  • test_schema.py runs successfully and all examples pass validation.
  • Re-running test_llm.py, the LLM produces more regular blueprints based on the new Schema and examples.

After completing these steps, ModSmith will have a verifiable, constrainable, example-backed blueprint specification. This is the foundation for the subsequent generator modules (Tasks 6, 7, 8).

Clone this wiki locally