ThongCoding commited on
Commit
deb83c9
·
1 Parent(s): 54433e0
Files changed (10) hide show
  1. .gitignore +1 -0
  2. Dockerfile +13 -0
  3. README.md +5 -5
  4. app.py +56 -0
  5. cache/text.txt +0 -0
  6. data/example_output.json +17 -0
  7. model.py +49 -0
  8. prompt.py +24 -0
  9. requirements.txt +5 -0
  10. structures.json +74 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ pusher.py
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ RUN apt-get update && apt-get install -y \
4
+ build-essential cmake wget git \
5
+ && rm -rf /var/lib/apt/lists/*
6
+
7
+ WORKDIR /code
8
+ COPY . /code
9
+
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+ RUN chmod -R 777 /code
12
+
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,11 +1,11 @@
1
  ---
2
- title: Minecraft Ai Builder Backend
3
- emoji: 📉
4
- colorFrom: green
5
- colorTo: pink
6
  sdk: docker
7
  pinned: false
8
- license: mit
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Gemma 3 1b It
3
+ emoji: 🌖
4
+ colorFrom: yellow
5
+ colorTo: yellow
6
  sdk: docker
7
  pinned: false
8
+ license: gemma
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ from typing import List
4
+ from fastapi import FastAPI, HTTPException
5
+ from fastapi.responses import HTMLResponse
6
+ from pydantic import BaseModel
7
+ from model import generate_structure
8
+
9
+ app = FastAPI()
10
+ STRUCTURE_FILE = "structures.json"
11
+ structure_store = []
12
+
13
+ class Prompt(BaseModel):
14
+ text: str
15
+
16
+ class Structure(BaseModel):
17
+ name: str
18
+ description: str
19
+ required_blocks: List[str]
20
+ tags: List[str]
21
+
22
+ @app.post("/generate")
23
+ def generate(prompt: Prompt):
24
+ result = generate_structure(prompt.text)
25
+ return {"response": result}
26
+
27
+ @app.post("/register_structure")
28
+ def register_structure(structure: Structure):
29
+ # Load existing structures
30
+ structures = []
31
+ if os.path.exists(STRUCTURE_FILE):
32
+ with open(STRUCTURE_FILE, "r") as f:
33
+ try:
34
+ structures = json.load(f)
35
+ except json.JSONDecodeError:
36
+ pass # File was empty or invalid
37
+
38
+ # Check for duplicates
39
+ for s in structures:
40
+ if s["name"] == structure.name:
41
+ raise HTTPException(status_code=400, detail="Structure with this name already exists")
42
+
43
+ # Append and save
44
+ structures.append(structure.dict())
45
+ with open(STRUCTURE_FILE, "w") as f:
46
+ json.dump(structures, f, indent=2)
47
+
48
+ return {"message": "Structure registered successfully"}
49
+
50
+ @app.get("/structures", response_class=HTMLResponse)
51
+ def list_structures():
52
+ html = "<h2>Registered Structures</h2><table border='1'><tr><th>Name</th><th>Description</th><th>Required Blocks</th><th>Tags</th></tr>"
53
+ for structure in structure_store:
54
+ html += f"<tr><td>{structure.name}</td><td>{structure.description}</td><td>{', '.join(structure.required_blocks)}</td><td>{', '.join(structure.tags)}</td></tr>"
55
+ html += "</table>"
56
+ return html
cache/text.txt ADDED
File without changes
data/example_output.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "width": 3,
3
+ "height": 2,
4
+ "depth": 3,
5
+ "layers": [
6
+ [
7
+ ["stone", "stone", "stone"],
8
+ ["stone", "air", "stone"],
9
+ ["stone", "stone", "stone"]
10
+ ],
11
+ [
12
+ ["stone", "glass", "stone"],
13
+ ["glass", "air", "glass"],
14
+ ["stone", "glass", "stone"]
15
+ ]
16
+ ]
17
+ }
model.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from huggingface_hub import hf_hub_download, HfApi
4
+ from llama_cpp import Llama
5
+
6
+ HF_TOKEN = os.environ.get("HF_TOKEN")
7
+ REPO_ID = "google/gemma-2b-it-GGUF"
8
+ MODEL_FILENAME = "gemma-2b-it.gguf"
9
+ LOCAL_MODEL_PATH = f"/code/models/{MODEL_FILENAME}"
10
+ CACHE_DIR = "/code/cache"
11
+
12
+ os.makedirs(os.path.dirname(LOCAL_MODEL_PATH), exist_ok=True)
13
+ os.makedirs(CACHE_DIR, exist_ok=True)
14
+
15
+ def download_model():
16
+ try:
17
+ print("🔄 Attempting HF Hub download...")
18
+ model_path = hf_hub_download(
19
+ repo_id=REPO_ID,
20
+ filename=MODEL_FILENAME,
21
+ token=HF_TOKEN,
22
+ cache_dir=CACHE_DIR,
23
+ )
24
+ print("✅ Downloaded via hf_hub_download:", model_path)
25
+ return model_path
26
+ except Exception as e:
27
+ print("⚠️ hf_hub_download failed:", e)
28
+ print("🔁 Falling back to manual download...")
29
+
30
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
31
+ url = f"https://huggingface.co/{REPO_ID}/resolve/main/{MODEL_FILENAME}"
32
+ response = requests.get(url, headers=headers, stream=True)
33
+ response.raise_for_status()
34
+
35
+ with open(LOCAL_MODEL_PATH, "wb") as f:
36
+ for chunk in response.iter_content(chunk_size=8192):
37
+ if chunk:
38
+ f.write(chunk)
39
+ print("✅ Manual download completed:", LOCAL_MODEL_PATH)
40
+ return LOCAL_MODEL_PATH
41
+
42
+
43
+ print("📦 Loading GGUF model...")
44
+ model_path = download_model()
45
+ llm = Llama(model_path=model_path)
46
+
47
+ def generate_structure(prompt: str) -> str:
48
+ output = llm(prompt, max_tokens=512)
49
+ return output["choices"][0]["text"].strip()
prompt.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def get_strict_prompt() -> str:
2
+ return """
3
+ You are a Minecraft-style structure planner.
4
+
5
+ Only output a JSON object describing a 3D structure using this format:
6
+
7
+ {
8
+ "width": <int>,
9
+ "height": <int>,
10
+ "depth": <int>,
11
+ "layers": [
12
+ [
13
+ ["stone", "stone", "stone"],
14
+ ["stone", "air", "stone"],
15
+ ["stone", "stone", "stone"]
16
+ ],
17
+ ...
18
+ ]
19
+ }
20
+
21
+ Only use lowercase Minecraft block IDs (e.g. "stone", "air", "glass", "planks").
22
+ Max size: 7×7×7. Do not include any natural language or explanation.
23
+ Output strictly valid JSON only.
24
+ """
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ llama-cpp-python==0.2.72 # prebuilt versions now available from PyPI
4
+ python-dotenv
5
+ huggingface_hub
structures.json ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "castle_tower",
4
+ "description": "A medieval tower with battlements and defensive height.",
5
+ "required_blocks": ["stone_bricks", "cobblestone", "mossy_stone_bricks", "oak_planks", "torch"],
6
+ "tags": ["medieval", "defense"]
7
+ },
8
+ {
9
+ "name": "underground_bunker",
10
+ "description": "A secure underground base with reinforced walls and redstone lighting.",
11
+ "required_blocks": ["obsidian", "iron_block", "redstone_lamp", "lever", "smooth_stone"],
12
+ "tags": ["underground", "modern"]
13
+ },
14
+ {
15
+ "name": "treehouse",
16
+ "description": "A cozy elevated structure built into a tree canopy.",
17
+ "required_blocks": ["oak_logs", "oak_planks", "leaves", "ladder", "glass_pane"],
18
+ "tags": ["nature", "elevated"]
19
+ },
20
+ {
21
+ "name": "desert_hut",
22
+ "description": "A simple shelter for desert biomes.",
23
+ "required_blocks": ["sandstone", "smooth_sandstone", "cut_sandstone", "oak_door", "torch"],
24
+ "tags": ["desert", "village"]
25
+ },
26
+ {
27
+ "name": "ice_temple",
28
+ "description": "A mystical temple made from packed ice and glowing blocks.",
29
+ "required_blocks": ["packed_ice", "blue_ice", "snow_block", "sea_lantern", "light_blue_stained_glass"],
30
+ "tags": ["frozen", "temple"]
31
+ },
32
+ {
33
+ "name": "sky_platform",
34
+ "description": "A suspended platform in the sky, usable as base foundation.",
35
+ "required_blocks": ["stone_slab", "glass", "iron_block", "torch", "scaffolding"],
36
+ "tags": ["sky", "platform"]
37
+ },
38
+ {
39
+ "name": "nether_watchtower",
40
+ "description": "A watchtower adapted for survival in the Nether.",
41
+ "required_blocks": ["nether_bricks", "red_nether_bricks", "soul_torch", "basalt", "iron_bars"],
42
+ "tags": ["nether", "fortification"]
43
+ },
44
+ {
45
+ "name": "floating_island",
46
+ "description": "A small magical floating island with vegetation.",
47
+ "required_blocks": ["grass_block", "dirt", "leaves", "oak_logs", "glowstone"],
48
+ "tags": ["floating", "fantasy"]
49
+ },
50
+ {
51
+ "name": "library_room",
52
+ "description": "An interior room filled with books and study space.",
53
+ "required_blocks": ["bookshelf", "oak_planks", "lantern", "glass_pane", "carpet"],
54
+ "tags": ["indoor", "library"]
55
+ },
56
+ {
57
+ "name": "farm_stable",
58
+ "description": "A small stable and feeding zone for animals.",
59
+ "required_blocks": ["hay_block", "fence", "oak_planks", "coarse_dirt", "torch"],
60
+ "tags": ["farm", "animals"]
61
+ },
62
+ {
63
+ "name": "swamp_shack",
64
+ "description": "A mossy shack on stilts above swampy water.",
65
+ "required_blocks": ["mossy_cobblestone", "spruce_planks", "vines", "lily_pad", "oak_trapdoor"],
66
+ "tags": ["swamp", "shack"]
67
+ },
68
+ {
69
+ "name": "mine_entrance",
70
+ "description": "A small cave entrance with support beams and torches.",
71
+ "required_blocks": ["stone", "oak_logs", "rails", "torch", "gravel"],
72
+ "tags": ["mining", "cave"]
73
+ }
74
+ ]