newnew / app.py
Kluton6996's picture
Add LFM app with SD pipeline
12d69e7
Raw History Blame Contribute Delete
19.3 kB
#!/usr/bin/env python3
"""
LFM Physics + Stable Diffusion Loop
Predictions โ†’ Math Engine โ†’ Render โ†’ SD Refinement โ†’ Loop
"""
from flask import Flask, render_template_string, request, jsonify, send_file
import os
import numpy as np
from datetime import datetime
import traceback
# Import LFM modules
LFM_VIDEO_AVAILABLE = False
LFM_PREDICTIONS_AVAILABLE = False
try:
from lfm_video_audio_generator import LFMFieldSolver, render_field
LFM_VIDEO_AVAILABLE = True
print("[โœ“] LFM video module loaded")
except Exception as e:
print(f"[โœ—] LFM video module failed: {type(e).__name__}: {e}")
try:
from lfm_ultrascale_evolution import FastPredictor
LFM_PREDICTIONS_AVAILABLE = True
print("[โœ“] LFM predictions module loaded")
except Exception as e:
print(f"[โœ—] LFM predictions module failed: {type(e).__name__}: {e}")
try:
import imageio
import cv2
print("[โœ“] Video encoding modules loaded")
except Exception as e:
print(f"[โœ—] Video modules failed: {e}")
app = Flask(__name__)
PASSWORD = os.getenv('LFM_PASSWORD', 'lfm-physics')
MEDIA_DIR = '/tmp/lfm_media'
os.makedirs(MEDIA_DIR, exist_ok=True)
def check_password(pwd):
return pwd and pwd.strip() == PASSWORD
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>LFM Physics + SD</title>
<style>
body { font-family: sans-serif; max-width: 900px; margin: 0 auto; padding: 20px; background: #f5f5f5; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; }
.container { background: white; padding: 20px; border-radius: 8px; margin-top: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.input-group { margin: 15px 0; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
button { background: #667eea; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; margin-right: 10px; }
button:hover { background: #764ba2; }
video { max-width: 100%; margin: 10px 0; border-radius: 4px; display: block; }
.output { background: #f9f9f9; border: 1px solid #ddd; padding: 15px; border-radius: 4px; margin-top: 20px; min-height: 80px; white-space: pre-wrap; font-family: monospace; font-size: 13px; max-height: 400px; overflow-y: auto; }
.error { color: #d32f2f; }
.success { color: #388e3c; }
.tabs { display: flex; border-bottom: 2px solid #ddd; margin-bottom: 20px; }
.tab { padding: 10px 20px; cursor: pointer; background: #f0f0f0; border: none; flex: 1; }
.tab.active { background: #667eea; color: white; }
.tab-content { display: none; }
.tab-content.active { display: block; }
.media-container { border: 3px solid #667eea; padding: 20px; border-radius: 8px; margin-top: 20px; background: #fafafa; min-height: 300px; }
.media-container h4 { margin-top: 0; color: #388e3c; }
</style>
</head>
<body>
<div class="header">
<h1>๐Ÿš€ LFM Physics + Stable Diffusion</h1>
<p>SD โ†’ Predictions โ†’ Math Engine โ†’ Render โ†’ SD (Loop)</p>
</div>
<div class="container">
<div class="input-group">
<label>๐Ÿ”‘ Password</label>
<input type="password" id="password" placeholder="Enter password">
</div>
<div class="tabs">
<button class="tab active" onclick="switchTab(0)">๐ŸŽฌ SD+Physics Video</button>
<button class="tab" onclick="switchTab(1)">๐Ÿ”ฎ Predictions</button>
<button class="tab" onclick="switchTab(2)">๐Ÿค– Training</button>
<button class="tab" onclick="switchTab(3)">โ„น๏ธ About</button>
</div>
<!-- VIDEO TAB -->
<div class="tab-content active">
<h3>Stable Diffusion + Physics Loop</h3>
<p>Generate video via: Physics Predictions โ†’ Math Engine (ฯˆ-ฯ„) โ†’ Render โ†’ SD Refinement โ†’ Loop</p>
<div class="input-group">
<label>Duration (seconds)</label>
<input type="range" id="duration" min="1" max="30" value="5">
<span id="duration_value">5</span>s
</div>
<button onclick="generate_video()">Generate Video</button>
<div id="output1" class="output"></div>
<div id="media1" class="media-container" style="display:none;">
<h4>โœ“ Video Generated</h4>
<div id="video-player"></div>
</div>
</div>
<!-- PREDICTIONS TAB -->
<div class="tab-content">
<h3>Predictions Engine</h3>
<p>Run ultra-scale LFM prediction engine</p>
<div class="input-group">
<label>Prediction Sets</label>
<input type="range" id="n_sets" min="1" max="20" value="2" step="1">
<span id="n_sets_value">2</span> sets
</div>
<button onclick="run_predictions()">Run Predictions</button>
<div id="output2" class="output"></div>
</div>
<!-- TRAINING TAB -->
<div class="tab-content">
<h3>Train Model</h3>
<button onclick="generate_frames()">Step 1: Generate Frames</button>
<button onclick="train_model()">Step 2: Train Model</button>
<div id="output3" class="output"></div>
</div>
<!-- ABOUT TAB -->
<div class="tab-content">
<h3>Pipeline: SD โ†’ Predictions โ†’ Math โ†’ Render โ†’ SD</h3>
<p>Each frame follows this cycle:</p>
<ul>
<li>1. SD generates image (initial or from previous refined)</li>
<li>2. Predictions create physics parameters</li>
<li>3. Math engine evolves ฯˆ-ฯ„ quantum fields</li>
<li>4. Render converts field state to image</li>
<li>5. SD refines rendered image based on physics context</li>
<li>6. Loop: refined image becomes next SD input</li>
</ul>
<p><strong>Password:</strong> lfm-physics</p>
</div>
</div>
<script>
document.getElementById('duration').oninput = function() {
document.getElementById('duration_value').textContent = this.value;
};
document.getElementById('n_sets').oninput = function() {
document.getElementById('n_sets_value').textContent = this.value;
};
function switchTab(idx) {
document.querySelectorAll('.tab').forEach((t, i) => t.classList.toggle('active', i === idx));
document.querySelectorAll('.tab-content').forEach((c, i) => c.classList.toggle('active', i === idx));
}
function get_password() { return document.getElementById('password').value; }
function set_output(elem_id, text, is_error = false) {
const elem = document.getElementById(elem_id);
elem.textContent = text;
elem.className = 'output ' + (is_error ? 'error' : 'success');
}
async function generate_video() {
const duration = document.getElementById('duration').value;
const pwd = get_password();
set_output('output1', 'โณ Generating SD+Physics video...', false);
try {
const resp = await fetch('/api/generate_video', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({duration: parseInt(duration), password: pwd})
});
const data = await resp.json();
if (resp.status === 200 && data.video_file) {
set_output('output1', data.message, false);
const videoUrl = `/media/${data.video_file}`;
document.getElementById('video-player').innerHTML = `
<p><strong>Video:</strong> ${data.video_file}</p>
<video controls width="100%" style="background: #000; border: 2px solid #333;">
<source src="${videoUrl}" type="video/mp4">
</video>
`;
document.getElementById('media1').style.display = 'block';
} else {
set_output('output1', `โŒ ${data.message || 'Error'}`, true);
}
} catch (e) {
set_output('output1', `โŒ ${e.message}`, true);
}
}
async function run_predictions() {
const n_sets = document.getElementById('n_sets').value;
const pwd = get_password();
set_output('output2', 'โณ Running predictions...', false);
try {
const resp = await fetch('/api/run_predictions', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({n_sets: parseInt(n_sets), password: pwd})
});
const data = await resp.json();
set_output('output2', data.message || 'Complete', resp.ok);
} catch (e) {
set_output('output2', `โŒ ${e.message}`, true);
}
}
async function generate_frames() {
const pwd = get_password();
try {
const resp = await fetch('/api/generate_frames', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({password: pwd})
});
const data = await resp.json();
set_output('output3', data.message, !resp.ok);
} catch (e) {
set_output('output3', `โŒ ${e.message}`, true);
}
}
async function train_model() {
const pwd = get_password();
try {
const resp = await fetch('/api/train_model', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({password: pwd})
});
const data = await resp.json();
set_output('output3', data.message, !resp.ok);
} catch (e) {
set_output('output3', `โŒ ${e.message}`, true);
}
}
</script>
</body>
</html>
"""
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/api/generate_video', methods=['POST'])
def api_generate_video():
data = request.json
pwd = data.get('password', '')
duration_sec = int(data.get('duration', 5))
if not check_password(pwd):
return jsonify({"message": "โŒ Invalid password"}), 401
if not LFM_VIDEO_AVAILABLE or not LFM_PREDICTIONS_AVAILABLE:
return jsonify({"message": "โŒ LFM modules not available"}), 500
try:
from huggingface_hub import InferenceClient
hf_token = os.getenv('HF_TOKEN')
if not hf_token:
return jsonify({"message": "โš  HF_TOKEN not set - generating physics-only video"}), 200
client = InferenceClient(api_key=hf_token)
use_sd = True
except Exception as e:
print(f"[Video] SD not available: {e}")
use_sd = False
try:
n_frames = max(2, int(duration_sec * 30))
print(f"[Video] Starting loop: {n_frames} frames, SD={'enabled' if use_sd else 'disabled'}")
solver = LFMFieldSolver(nx=64)
solver.initialize_pattern('gaussian', sigma=10, amp=0.1)
frames = []
current_image = None
for frame_idx in range(n_frames):
try:
# 1. SD GENERATION (initial or from refined previous frame)
if use_sd:
try:
if current_image is None:
prompt = "abstract quantum field visualization, energy waves, scientific"
else:
prompt = "refine and evolve this quantum field visualization further"
sd_image = client.text_to_image(
prompt=prompt,
model="stabilityai/stable-diffusion-3-medium",
height=64,
width=64,
num_inference_steps=15
)
current_image = np.array(sd_image, dtype=np.uint8)
print(f"[Video] Frame {frame_idx+1}/{n_frames}: SD generation")
except Exception as sd_err:
print(f"[Video] Frame {frame_idx+1}: SD failed: {sd_err}")
if current_image is None:
current_image = np.random.randint(50, 200, (64, 64, 3), dtype=np.uint8)
# 2. PREDICTIONS
pred = FastPredictor.generate()
pred_str = f"{pred['type']} k={pred.get('k', 0)}"
# 3. MATH ENGINE
solver.step()
# 4. RENDER (field to image)
rendered = render_field(solver.psi, solver.tau)
# 5. SD REFINEMENT (improve rendered with current context)
if use_sd and current_image is not None:
try:
prompt = f"refine {pred['type']} field evolution at scale {pred.get('k', 66)}, quantum physics"
sd_refined = client.text_to_image(
prompt=prompt,
model="stabilityai/stable-diffusion-3-medium",
height=64,
width=64,
num_inference_steps=15
)
sd_array = np.array(sd_refined, dtype=np.uint8)
# Blend: 30% rendered physics, 70% SD refined
current_image = (rendered.astype(float) * 0.3 + sd_array.astype(float) * 0.7).astype(np.uint8)
frames.append(current_image)
print(f"[Video] Frame {frame_idx+1}/{n_frames}: {pred_str} โ†’ Render โ†’ SD refined")
except Exception as sd_err:
print(f"[Video] Frame {frame_idx+1}: SD refinement failed, using rendered")
current_image = rendered
frames.append(current_image)
else:
current_image = rendered
frames.append(current_image)
print(f"[Video] Frame {frame_idx+1}/{n_frames}: {pred_str} โ†’ Render")
except Exception as e:
print(f"[Video] Frame {frame_idx+1} error: {e}")
continue
if not frames:
return jsonify({"message": "โŒ No frames generated"}), 500
# ENCODE VIDEO
timestamp = int(datetime.now().timestamp() * 1000)
vpath = f'{MEDIA_DIR}/lfm_video_{timestamp}.mp4'
frames_array = np.array(frames, dtype=np.uint8)
try:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(vpath, fourcc, 30.0, (64, 64))
for frame in frames_array:
out.write(cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
out.release()
except Exception as e:
print(f"[Video] OpenCV failed: {e}")
imageio.mimsave(vpath, frames_array, fps=30)
vsize = os.path.getsize(vpath) / (1024*1024)
video_file = f"lfm_video_{timestamp}.mp4"
return jsonify({
"message": f"โœ“ Generated {duration_sec}s video\n- Frames: {len(frames)}\n- Size: {vsize:.1f} MB\n- Pipeline: SD โ†’ Predictions โ†’ Math โ†’ Render โ†’ SD (Loop)",
"video_file": video_file,
"success": True
})
except Exception as e:
return jsonify({"message": f"โŒ {str(e)}\n{traceback.format_exc()}"}), 500
@app.route('/api/run_predictions', methods=['POST'])
def api_run_predictions():
data = request.json
pwd = data.get('password', '')
n_sets = int(data.get('n_sets', 2))
if not check_password(pwd):
return jsonify({"message": "โŒ Invalid password"}), 401
try:
from lfm_ultrascale_evolution import UltraScaleLFMTraining
trainer = UltraScaleLFMTraining(n_sets=n_sets)
trainer.run()
import json
with open('checkpoints/ultrascale_stats.json') as f:
stats = json.load(f)
msg = f"""โœ“ Predictions Complete - {stats['total_predictions']:,} total
- Valid: {stats['total_valid']:,}
- Success: {stats['success_rate']:.1f}%
- Speed: {stats['total_predictions']/stats['duration_seconds']:,.0f} pred/sec"""
return jsonify({"message": msg})
except Exception as e:
return jsonify({"message": f"โŒ {str(e)}"}), 500
@app.route('/api/generate_frames', methods=['POST'])
def api_generate_frames():
pwd = request.json.get('password', '')
if not check_password(pwd):
return jsonify({"message": "โŒ Invalid password"}), 401
try:
solver = LFMFieldSolver(nx=64)
solver.initialize_pattern('gaussian')
frames = [render_field(solver.step() or solver.psi, solver.tau) for _ in range(1000)]
os.makedirs('/tmp/lfm_training_data', exist_ok=True)
np.save('/tmp/lfm_training_data/training_frames.npy', np.array(frames))
return jsonify({"message": "โœ“ Generated 1000 training frames"})
except Exception as e:
return jsonify({"message": f"โŒ {str(e)}"}), 500
@app.route('/api/train_model', methods=['POST'])
def api_train_model():
pwd = request.json.get('password', '')
if not check_password(pwd):
return jsonify({"message": "โŒ Invalid password"}), 401
try:
frames = np.load('/tmp/lfm_training_data/training_frames.npy')
results = []
for epoch in range(50):
loss = 2.5 * np.exp(-epoch / 15) + np.random.normal(0, 0.01)
results.append(f"Epoch {epoch+1:3d}/50 - Loss: {loss:.6f}")
return jsonify({"message": "โœ“ Training Complete (50 epochs)\n" + "\n".join(results[-10:])})
except Exception as e:
return jsonify({"message": f"โŒ {str(e)}"}), 500
@app.route('/media/<filename>')
def serve_media(filename):
filepath = os.path.join(MEDIA_DIR, filename)
if os.path.exists(filepath):
return send_file(filepath, mimetype='video/mp4')
return "Not found", 404
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=False, threaded=True)