File size: 7,856 Bytes
95c0719 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | import os
import uvicorn
import re
import numpy as np
import matplotlib
matplotlib.use('Agg') # Prevents extra GUI windows from opening on your Ubuntu desktop
import matplotlib.pyplot as plt
import mpld3
import plotly.graph_objects as go
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from llama_cpp import Llama
app = FastAPI()
# 1. GPU INITIALIZATION (RTX 4060 Ti)
llm = Llama(
model_path="/mnt/ai_data/math_APP/qwen_math_q4_k_m.gguf",
n_gpu_layers=-1,
n_ctx=2048,
verbose=False
)
def fix_plotly_colorscales(code):
"""Intercepts Matplotlib colormap names and swaps them for Plotly equivalents."""
# Maps common Matplotlib names to their closest Plotly counterparts
color_map = {
"spring": "Viridis",
"summer": "Plasma",
"autumn": "Inferno",
"winter": "Cividis",
"magma": "Magma"
}
for mpl_name, plotly_name in color_map.items():
# Handles both single and double quotes, and case sensitivity
code = re.sub(f"['\"]{mpl_name}['\"]", f"'{plotly_name}'", code, flags=re.IGNORECASE)
return code
@app.get("/", response_class=HTMLResponse)
async def index():
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Math Core</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Fira+Code&display=swap');
.code-box { font-family: 'Fira Code', monospace; }
iframe { border: none; width: 100%; height: 100%; border-radius: 1rem; background: white; }
</style>
</head>
<body class="bg-gray-950 text-gray-100 min-h-screen p-6">
<div class="max-w-7xl mx-auto">
<header class="mb-8 flex justify-between items-center">
<h1 class="text-3xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-cyan-400">Math Visualizer Core</h1>
<div class="text-xs font-mono text-gray-500 bg-gray-900 px-3 py-1 rounded-full border border-gray-800">Resilient Engine v2.0</div>
</header>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<div class="lg:col-span-4 space-y-4">
<div class="bg-gray-900 p-5 rounded-2xl border border-gray-800 shadow-xl">
<label class="block text-xs font-bold text-gray-500 uppercase mb-2">Research Prompt</label>
<textarea id="promptInput" rows="5"
class="w-full bg-gray-800 border border-gray-700 rounded-xl p-4 text-sm focus:ring-2 focus:ring-blue-500 outline-none transition-all"
placeholder="e.g., Create a rotating 3D torus..."></textarea>
<button onclick="generateVisual()" id="genBtn"
class="w-full mt-4 bg-blue-600 hover:bg-blue-500 py-3 rounded-xl font-bold transition-all shadow-lg shadow-blue-900/40">
Execute on GPU
</button>
</div>
<div class="bg-gray-900 p-5 rounded-2xl border border-gray-800">
<pre id="codeDisplay" class="code-box bg-black p-4 rounded-lg overflow-x-auto text-[11px] text-green-400 border border-gray-800 min-h-[200px]"></pre>
</div>
</div>
<div class="lg:col-span-8">
<div class="bg-gray-900 rounded-2xl border border-gray-800 h-[650px] relative overflow-hidden flex items-center justify-center">
<div id="loader" class="hidden z-20 flex flex-col items-center">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mb-4"></div>
<p class="text-blue-400">Solving Geometry...</p>
</div>
<div id="vizContainer" class="w-full h-full p-2">
<div id="placeholder" class="h-full flex items-center justify-center text-gray-600 italic">
Ready for computation.
</div>
</div>
</div>
</div>
</div>
</div>
<script>
async function generateVisual() {
const prompt = document.getElementById('promptInput').value;
const btn = document.getElementById('genBtn');
const loader = document.getElementById('loader');
const vizContainer = document.getElementById('vizContainer');
const placeholder = document.getElementById('placeholder');
const codeBox = document.getElementById('codeDisplay');
if (!prompt) return;
btn.disabled = true;
loader.classList.remove('hidden');
placeholder.classList.add('hidden');
codeBox.innerText = "# Synthesizing logic...";
try {
const response = await fetch('/process', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ prompt: prompt })
});
const data = await response.json();
codeBox.innerText = data.code;
if (data.html) {
vizContainer.innerHTML = `<iframe srcdoc='${data.html.replace(/'/g, "'")}'></iframe>`;
} else if (data.error) {
vizContainer.innerHTML = `<div class='p-10 text-red-500 font-mono text-xs overflow-auto h-full whitespace-pre-wrap'>${data.error}</div>`;
}
} catch (err) {
codeBox.innerText = "# Execution failed.";
} finally {
loader.classList.add('hidden');
btn.disabled = false;
}
}
</script>
</body>
</html>
"""
@app.post("/process")
async def process_request(request: Request):
data = await request.json()
user_prompt = data.get("prompt")
instruction = (
"Output ONLY raw Python code. Use plotly.graph_objects (go) for 3D/animations "
"and name the figure 'fig'. Use matplotlib.pyplot (plt) for 2D. "
"CRITICAL: Never use plt.show() or fig.show(). Use Plotly-safe colorscales."
)
formatted = f"<|im_start|>system\n{instruction}<|im_end|>\n<|im_start|>user\n{user_prompt}<|im_end|>\n<|im_start|>assistant\n"
output = llm(formatted, max_tokens=1536, stop=["<|im_end|>"])
code = re.sub(r"```python|```", "", output['choices'][0]['text']).strip()
# Apply the colorscale fix
code = fix_plotly_colorscales(code)
try:
plt.clf()
plt.close('all')
# Scope with "Dummy Show" to prevent Ubuntu window popups
def dummy_show(*args, **kwargs): pass
exec_scope = {
"plt": plt, "np": np, "go": go, "mpld3": mpld3,
"__builtins__": __builtins__
}
plt.show = dummy_show
exec(code, exec_scope)
if "fig" in exec_scope:
# Captures Plotly (3D/Animated)
html_output = exec_scope["fig"].to_html(full_html=False, include_plotlyjs='cdn')
else:
# Captures Matplotlib (2D)
html_output = mpld3.fig_to_html(plt.gcf())
return {"code": code, "html": html_output}
except Exception as e:
return {"code": code, "error": str(e)}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000) |