# 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"]