ThongCoding commited on
Commit
2fc68b4
·
1 Parent(s): 74d601a
Files changed (5) hide show
  1. .gitignore +1 -0
  2. Dockerfile +1 -1
  3. app.py +15 -42
  4. model.py +37 -0
  5. structure_prompt_config.json +3 -0
.gitignore CHANGED
@@ -1 +1,2 @@
1
  tester.py
 
 
1
  tester.py
2
+ __pycache__/
Dockerfile CHANGED
@@ -10,4 +10,4 @@ COPY . /code
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"]
 
10
  RUN pip install --no-cache-dir -r requirements.txt
11
  RUN chmod -R 777 /code
12
 
13
+ CMD ["python", "app.py"]
app.py CHANGED
@@ -1,50 +1,23 @@
1
- import os
2
- import requests
3
  from fastapi import FastAPI, Request
4
  from fastapi.responses import JSONResponse
5
- from llama_cpp import Llama
6
-
7
- REPO_ID = "TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF"
8
- MODEL_FILENAME = "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf"
9
- MODEL_PATH = f"./models/{MODEL_FILENAME}"
10
- HF_TOKEN = os.getenv("HF_TOKEN")
11
-
12
- # Ensure models folder exists
13
- os.makedirs("./models", exist_ok=True)
14
- os.chmod("./models", 0o777) # ensure write access
15
-
16
- # Download model if missing
17
- if not os.path.exists(MODEL_PATH):
18
- print("📦 Downloading TinyLlama Q4_K_M model...")
19
- url = f"https://huggingface.co/{REPO_ID}/resolve/main/{MODEL_FILENAME}"
20
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
21
- r = requests.get(url, headers=headers, stream=True)
22
- if r.status_code != 200:
23
- raise RuntimeError(f"❌ Download failed: {r.status_code} {r.text[:200]}")
24
- with open(MODEL_PATH, "wb") as f:
25
- for chunk in r.iter_content(8192):
26
- f.write(chunk)
27
- print("✅ Model downloaded")
28
-
29
- # Load into llama-cpp
30
- print("🔧 Loading TinyLlama model...")
31
- llm = Llama(
32
- model_path=MODEL_PATH,
33
- n_ctx=512,
34
- n_threads=os.cpu_count() or 1
35
- )
36
 
37
  app = FastAPI()
38
 
39
  @app.get("/")
40
- async def root():
41
- return {"status": "🟢 TinyLlama-1.1B Q4_K_M is ready"}
42
 
43
  @app.post("/prompt")
44
- async def prompt(req: Request):
45
- body = await req.json()
46
- prompt = body.get("prompt") or ""
47
- if not prompt:
48
- return JSONResponse(status_code=400, content={"error": "Missing 'prompt' field"})
49
- resp = llm(prompt, max_tokens=512, stop=["</s>"])
50
- return {"response": resp["choices"][0]["text"].strip()}
 
 
 
 
 
 
 
1
  from fastapi import FastAPI, Request
2
  from fastapi.responses import JSONResponse
3
+ from model import generate_structure
4
+ import uvicorn
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  app = FastAPI()
7
 
8
  @app.get("/")
9
+ def index():
10
+ return {"message": "Minecraft AI Builder Backend is running."}
11
 
12
  @app.post("/prompt")
13
+ async def prompt_handler(req: Request):
14
+ try:
15
+ data = await req.json()
16
+ prompt = data.get("prompt", "")
17
+ response = generate_structure(prompt)
18
+ return {"response": response}
19
+ except Exception as e:
20
+ return JSONResponse(status_code=500, content={"error": str(e)})
21
+
22
+ if __name__ == "__main__":
23
+ uvicorn.run(app, host="0.0.0.0", port=7860)
model.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from llama_cpp import Llama
3
+ from huggingface_hub import hf_hub_download
4
+
5
+ # Model parameters
6
+ REPO_ID = "TheBloke/phi-2-GGUF"
7
+ MODEL_FILENAME = "phi-2.Q4_K_M.gguf"
8
+ MODEL_PATH = f"./models/{MODEL_FILENAME}"
9
+
10
+ # Auto-download if model not present
11
+ if not os.path.exists(MODEL_PATH):
12
+ os.makedirs("./models", exist_ok=True)
13
+ print("📦 Downloading GGUF model manually from Hugging Face...")
14
+ MODEL_PATH = hf_hub_download(
15
+ repo_id=REPO_ID,
16
+ filename=MODEL_FILENAME,
17
+ local_dir="./models",
18
+ local_dir_use_symlinks=False
19
+ )
20
+ print(f"✅ Model downloaded to {MODEL_PATH}")
21
+
22
+ # Initialize Llama model
23
+ llm = Llama(
24
+ model_path=MODEL_PATH,
25
+ n_ctx=512,
26
+ n_threads=2,
27
+ verbose=True
28
+ )
29
+
30
+ def generate_structure(prompt: str) -> str:
31
+ response = llm.create_chat_completion(
32
+ messages=[{"role": "user", "content": prompt}],
33
+ temperature=0.4,
34
+ top_p=0.95,
35
+ max_tokens=1024,
36
+ )
37
+ return response["choices"][0]["message"]["content"]
structure_prompt_config.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "template": "You are a Minecraft-style structure planner. You have the curiosity to build almost anything you could think of. {structure_name}\n\nOnly output a JSON object describing a 3D structure using this format:\n\n{{\n \"width\": <int>,\n \"height\": <int>,\n \"depth\": <int>,\n \"layers\": [\n [\n [\"stone\", \"stone\", \"stone\"],\n [\"stone\", \"air\", \"stone\"],\n [\"stone\", \"stone\", \"stone\"]\n ],\n ...\n ]\n}}\n\nOnly use lowercase Minecraft block IDs (e.g. \"stone\", \"air\", \"glass\", \"planks\").\nYou could only build this structure using {blocks_allowed}\nDo not include any natural language or explanation.\nOutput strictly valid JSON only."
3
+ }