# NEURAL ATARI GEN-CORE v1.0
FROM python:3.10-slim
WORKDIR /app
# 1. System Dependencies
# Fixed: libgl1-mesa-glx -> libgl1 (Debian Bookworm compatibility)
RUN apt-get update && apt-get install -y \
curl \
git \
libgomp1 \
libgl1 \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# 2. Python Environment
RUN pip install --upgrade pip
RUN pip install --no-cache-dir \
torch \
torchvision \
numpy \
flask \
flask-sock \
diffusers \
transformers \
accelerate \
peft \
pillow \
safetensors \
scipy \
sentencepiece \
diskcache
# 3. User Setup (Required for HF Spaces)
RUN useradd -m -u 1000 user
USER user
ENV HOME=/home/user \
PATH=/home/user/.local/bin:$PATH
# 4. The Monolithic Application (Embedded via HEREDOC)
COPY --chown=user <<'HYPER_EOF' app.py
import sys, os, io, base64, json, warnings, time, threading, random, re
import torch
import numpy as np
from flask import Flask
from flask_sock import Sock
from PIL import Image
from transformers import AutoModelForCausalLM, AutoTokenizer
from diffusers import StableDiffusionPipeline, LCMScheduler
import diskcache
warnings.filterwarnings("ignore")
# --- FRONTEND (React + Tailwind + Retro CSS) ---
HTML = r"""
Neural Atari 2600
"""
# --- BACKEND LOGIC ---
class NeuralSystem:
def __init__(self):
self.device = "cuda" if torch.cuda.is_available() else "cpu"
self.dtype = torch.float16 if self.device == "cuda" else torch.float32
print(f"⚡ Device: {self.device} | Type: {self.dtype}")
# 1. Load Coder LLM
print("🧠 Loading Logic Engine (Qwen)...")
self.model_id = "Qwen/Qwen2.5-Coder-1.5B-Instruct"
self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
self.llm = AutoModelForCausalLM.from_pretrained(self.model_id, torch_dtype=self.dtype).to(self.device)
# 2. Load Vision
print("🎨 Loading Vision Engine (SD-LCM)...")
self.pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=self.dtype,
safety_checker=None
)
if self.device == "cuda":
self.pipe = self.pipe.to("cuda")
self.pipe.load_lora_weights("latent-consistency/lcm-lora-sdv1-5")
self.pipe.scheduler = LCMScheduler.from_config(self.pipe.scheduler.config)
self.pipe.set_progress_bar_config(disable=True)
print("✓ SYSTEMS ONLINE")
def generate_code(self, prompt):
"""Generates JS Game Class"""
system_prompt = """You are an Atari 2600 developer. Write a Javascript Class named 'Game'.
The class MUST have:
1. constructor(ctx, width, height, spriteSheet)
2. init() - setup state
3. update(keys) - logic (keys.ArrowUp, etc)
4. draw() - rendering
Constraints:
- Canvas size is 160x192.
- Use ctx.fillStyle, ctx.fillRect, ctx.drawImage.
- The spriteSheet is an Image object. Assume it is a 2x2 grid (128x128 pixels total).
- Source sprites from the sheet: ctx.drawImage(this.spriteSheet, sx, sy, sw, sh, dx, dy, dw, dh).
- Keep logic simple (Pong, Space Invaders, Breakout style).
- Return ONLY the javascript code for the class, no markdown."""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Create a game about: {prompt}"}
]
text = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = self.tokenizer([text], return_tensors="pt").to(self.device)
with torch.no_grad():
outputs = self.llm.generate(
inputs.input_ids,
max_new_tokens=1024,
temperature=0.2,
do_sample=True
)
code = self.tokenizer.decode(outputs[0][len(inputs.input_ids[0]):], skip_special_tokens=True)
# Cleanup markdown if present
code = re.sub(r'```javascript|```', '', code).strip()
return code
def generate_sprites(self, prompt):
"""Generates Sprite Sheet"""
# Enhance prompt for Atari style
style = "pixel art sprite sheet, atari 2600 style, 8-bit, black background, minimal colors, distinct shapes, white sprites, retro"
full_prompt = f"{style}, {prompt}"
with torch.no_grad():
image = self.pipe(
full_prompt,
num_inference_steps=4, # Fast LCM
guidance_scale=1.5,
width=256,
height=256
).images[0]
# Convert to Base64
buf = io.BytesIO()
image.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode()
# Init Global System
engine = NeuralSystem()
app = Flask(__name__)
sock = Sock(app)
@sock.route('/atari')
def atari_socket(ws):
ws.send(json.dumps({"type": "log", "data": "SYSTEM READY."}))
while True:
data = ws.receive()
if not data: break
msg = json.loads(data)
if msg['type'] == 'generate':
prompt = msg['prompt']
# 1. Generate Logic
ws.send(json.dumps({"type": "log", "data": "WRITING CODE..."}))
try:
code = engine.generate_code(prompt)
ws.send(json.dumps({"type": "log", "data": "CODE COMPILED."}))
# 2. Generate Assets
ws.send(json.dumps({"type": "log", "data": "DREAMING SPRITES..."}))
sprites = engine.generate_sprites(prompt)
ws.send(json.dumps({"type": "log", "data": "ASSETS LOADED."}))
# 3. Send Bundle
ws.send(json.dumps({
"type": "game_ready",
"data": {
"code": code,
"sprites": sprites,
"bgColor": "#000000"
}
}))
except Exception as e:
ws.send(json.dumps({"type": "log", "data": f"ERROR: {str(e)}"}))
@app.route('/')
def index():
return HTML
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860)
HYPER_EOF
# 5. Runtime Configuration
EXPOSE 7860
CMD ["python", "app.py"]