YugJ's picture
Upload app.py with huggingface_hub
7e6cd5a verified
Raw
History Blame Contribute Delete
22.6 kB
"""Python to Rust / C++ performance translator.
An LLM ports a Python program to a compiled language; both are then executed
under the same sandbox so the speedup and - just as importantly - the
correctness of the translation can be measured rather than assumed.
Run locally: python app.py
Deployed: see Dockerfile (Hugging Face Spaces, Docker SDK)
"""
from __future__ import annotations
import html
import os
import re
import uuid
# Gradio 6 defaults to server-side rendering, which fronts the Python app with
# a Node proxy. On Spaces that proxy shuts down immediately after startup and
# takes the app with it ("Stopping Node.js server..." then RUNTIME_ERROR).
# Nothing here needs SSR - it is a single interactive page, not a crawlable
# site - so turn it off before gradio is imported and reads the setting.
#
# Assigned, not setdefault: Spaces sets this variable itself, so setdefault
# silently kept the platform's value and the proxy stayed on.
os.environ["GRADIO_SSR_MODE"] = "false"
import gradio as gr # noqa: E402
from dotenv import load_dotenv # noqa: E402
# override=False so real environment variables win over a stray .env file.
# On a host, secrets arrive as env vars and must not be shadowed by a file.
load_dotenv(override=False)
# Hugging Face Spaces sets SPACE_ID on every Space. Detecting it beats relying
# on a manually-set variable: the Gradio SDK has no Dockerfile to carry ENV, so
# a forgotten setting would silently run the public demo in local mode -
# frontier models ungated against the owner's key, no rate limit, and the
# on-disk-secret check disabled. This must happen before providers/sandbox are
# imported, since both read the flag at import time.
ON_SPACES = bool(os.getenv("SPACE_ID"))
if ON_SPACES:
os.environ["PUBLIC_DEPLOYMENT"] = "1"
# ZeroGPU refuses to start a Space that declares no GPU function, failing
# with "No @spaces.GPU function detected during startup". This app is
# CPU-only by nature - it needs compilers, not a GPU - and the honest fix
# would be CPU Basic hardware, but downgrading an existing ZeroGPU Space
# requires a PRO subscription.
#
# Declaring a function that is never wired to any event satisfies the check
# at no cost: ZeroGPU allocates hardware on invocation, so one that is never
# called consumes no GPU time. Guarded by ImportError because the `spaces`
# package only exists on the platform, not in local development.
try:
import spaces
@spaces.GPU(duration=1)
def _zerogpu_startup_marker(): # never called; presence is the point
return None
except ImportError:
pass
import providers # noqa: E402 - imported after load_dotenv so it sees the keys
import sandbox # noqa: E402
from examples import DEFAULT_EXAMPLE, EXAMPLES # noqa: E402
from styles import CSS # noqa: E402
from system_info import retrieve_system_info # noqa: E402
sandbox.assert_safe_to_deploy()
REPO_URL = "https://github.com/Yugjohri/python-to-rust-cpp"
SYSTEM_INFO = retrieve_system_info()
TOOLCHAIN = sandbox.toolchain_status()
COMPILABLE = sandbox.available_languages()
# --------------------------------------------------------------------------
# prompting
# --------------------------------------------------------------------------
def build_system_prompt(language_key: str) -> str:
lang = sandbox.LANGUAGES[language_key]
integer_note = (
"Rust integers are fixed width and overflow panics in debug but wraps in "
"release - pick widths (i64/i128/u64) that cannot overflow for these inputs."
if language_key == "rust" else
"C++ integers are fixed width and signed overflow is undefined behaviour - "
"pick widths (long long / __int128) that cannot overflow for these inputs."
)
return f"""You convert Python programs into high-performance {lang.display}.
Rules:
- Respond with {lang.display} source only. No prose, no markdown fences.
- A single self-contained file using only the standard library.
- Output must be byte-for-byte identical to the Python program's, including
number formatting and wording. Format floats with the same precision.
- Preserve the algorithm. Do not substitute an asymptotically better one - the
point is to measure what the same work costs in a compiled language.
- {integer_note}
- Python integers are arbitrary precision; account for that where it matters.
- Time the computation the same way the Python does and print it identically.
"""
def build_user_prompt(python_code: str, language_key: str) -> str:
lang = sandbox.LANGUAGES[language_key]
cpu = SYSTEM_INFO.get("cpu", {})
compiler = lang.find_compiler() or lang.compilers[0]
flags = " ".join(
sandbox.build_compile_command(lang, "CC", f"main.{lang.extension}", "program")[1:]
)
# The exact toolchain version matters. Without it models reach for
# extensions like unsigned __int128, which GCC supports on 64-bit Linux
# but MinGW does not - a compile failure the model could have avoided.
version = TOOLCHAIN.get(language_key, "") or "version unknown"
os_name = SYSTEM_INFO.get("os", {}).get("system", "")
constraints = ""
if language_key == "cpp":
if sandbox.cpp_has_int128():
constraints = "- `__int128` IS available here if you need a wider accumulator.\n"
else:
constraints = (
"- `__int128` / `unsigned __int128` are NOT available with this "
"compiler. Using them will fail to compile. Use `long long` / "
"`unsigned long long`, or restructure to avoid needing 128 bits.\n"
)
return f"""Port this Python program to {lang.display}.
Target machine: {cpu.get('brand', 'unknown CPU')}, {cpu.get('cores_logical', '?')} logical cores, {os_name}.
Compiler present: {version}
It will be compiled with exactly:
{os.path.basename(compiler)} {flags}
Hard constraints for this toolchain:
{constraints}- Use only what that compiler version supports on this platform.
Respond with {lang.display} source only.
```python
{python_code}
```
"""
# --------------------------------------------------------------------------
# helpers
# --------------------------------------------------------------------------
FENCE = re.compile(r"^\s*```[a-zA-Z+]*\s*\n(.*?)\n?\s*```\s*$", re.DOTALL)
TIME_LINE = re.compile(r"^\s*execution time:.*$", re.IGNORECASE | re.MULTILINE)
def strip_fences(text: str) -> str:
"""Remove a surrounding markdown code fence if the model added one."""
match = FENCE.match(text.strip())
if match:
return match.group(1)
for token in ("```rust", "```rs", "```cpp", "```c++", "```"):
text = text.replace(token, "")
return text.strip()
def extract_seconds(output: str) -> float | None:
"""Pull the self-reported execution time out of a program's output."""
match = re.search(r"execution time:\s*([0-9.]+)", output or "", re.IGNORECASE)
if match:
try:
return float(match.group(1))
except ValueError:
return None
return None
def comparable(output: str) -> str:
"""Output with the timing line removed, for correctness comparison.
Timings legitimately differ between runs; everything else must not.
"""
return TIME_LINE.sub("", output or "").strip()
def format_duration(seconds: float) -> tuple[str, str]:
"""Split the magnitude from the unit.
Returned separately so the UI can right-align the digits in their own
column and left-align the unit in another. Formatting them as one string
and right-aligning that makes the decimal points jitter between rows,
because "s" and "ms" are different widths.
"""
if seconds >= 1:
return f"{seconds:.3f}", "s"
if seconds >= 1e-3:
return f"{seconds * 1e3:.2f}", "ms"
return f"{seconds * 1e6:.0f}", "us"
def idle_verdict(language_key: str = sandbox.DEFAULT_LANGUAGE) -> str:
lang = sandbox.LANGUAGES[language_key]
return (
f'<div class="verdict"><p class="idle">Run the Python, port it, then run '
f"the {lang.display} - the speedup and a correctness check appear here.</p></div>"
)
def render_verdict(py_out: str, target_out: str, language_key: str) -> str:
"""Build the hero panel: speedup, timing bars, correctness badge."""
lang = sandbox.LANGUAGES[language_key]
py_seconds = extract_seconds(py_out)
target_seconds = extract_seconds(target_out)
if py_seconds is None or target_seconds is None or target_seconds <= 0:
return idle_verdict(language_key)
ratio = py_seconds / target_seconds
speedup = f"{ratio:,.0f}x" if ratio >= 10 else f"{ratio:.1f}x"
widest = max(py_seconds, target_seconds)
py_width = max(2.0, py_seconds / widest * 100)
target_width = max(2.0, target_seconds / widest * 100)
py_body, target_body = comparable(py_out), comparable(target_out)
if not py_body or not target_body:
badge = '<span class="badge unknown">Run both to verify output</span>'
elif py_body == target_body:
badge = '<span class="badge match">Outputs identical</span>'
else:
badge = '<span class="badge mismatch">Outputs differ - translation is wrong</span>'
py_num, py_unit = format_duration(py_seconds)
tg_num, tg_unit = format_duration(target_seconds)
return f"""
<div class="verdict">
<div class="verdict-grid">
<div class="speedup-cell">
<div class="speedup">{speedup}</div>
<div class="speedup-label">faster in {html.escape(lang.display)}</div>
</div>
<div class="timings">
<div class="timing-row py">
<span class="name">Python</span>
<span class="bar-track"><span class="bar" style="width:{py_width:.1f}%"></span></span>
<span class="num">{py_num}</span><span class="unit">{py_unit}</span>
</div>
<div class="timing-row target">
<span class="name">{html.escape(lang.display)}</span>
<span class="bar-track"><span class="bar" style="width:{target_width:.1f}%"></span></span>
<span class="num">{tg_num}</span><span class="unit">{tg_unit}</span>
</div>
</div>
<div class="badge-cell">{badge}</div>
</div>
</div>
"""
# --------------------------------------------------------------------------
# event handlers
# --------------------------------------------------------------------------
def on_run_python(code: str, target_out: str, language_key: str):
result = sandbox.run_python(code)
text = result.display
return text, render_verdict(text, target_out, language_key)
def on_run_target(code: str, py_out: str, language_key: str):
result, _ = sandbox.run_compiled(language_key, code)
text = result.display
return text, render_verdict(py_out, text, language_key)
def on_port(model_id: str, python_code: str, language_key: str,
user_key: str, session_id: str):
"""Translate the Python using the selected model."""
lang = sandbox.LANGUAGES[language_key]
if not python_code.strip():
return "// Nothing to port - paste some Python on the left first.", ""
user_key = (user_key or "").strip()
# Only the host's own key is rate limited; a visitor's key costs us nothing.
if not user_key and providers.PUBLIC:
allowed, message = providers.limiter.check(session_id)
if not allowed:
return f"// {message}", _quota_html(session_id)
try:
client, used_host_key = providers.build_client(model_id, user_key)
except providers.NoKeyError as e:
return f"// {e}", _quota_html(session_id)
model = providers.BY_ID[model_id]
kwargs = {"reasoning_effort": "high"} if model.reasoning else {}
try:
response = client.chat.completions.create(
model=model.id,
messages=[
{"role": "system", "content": build_system_prompt(language_key)},
{"role": "user", "content": build_user_prompt(python_code, language_key)},
],
**kwargs,
)
except Exception as e:
# scrub() because provider SDKs sometimes echo the key back in errors
detail = providers.scrub(f"{type(e).__name__}: {e}")
return (f"// Request to {model.display} failed.\n// {detail}",
_quota_html(session_id))
if used_host_key and providers.PUBLIC:
providers.limiter.record(session_id)
reply = response.choices[0].message.content or ""
return strip_fences(reply), _quota_html(session_id)
def on_change_language(language_key: str):
"""Relabel everything that names the target language, and clear stale output."""
lang = sandbox.LANGUAGES[language_key]
ready = language_key in COMPILABLE
return (
gr.update(label=f"{lang.display} translation", language=lang.highlight, value=""),
gr.update(label=f"{lang.display} output", value=""),
gr.update(value=f"Port to {lang.display}"),
gr.update(
value=f"Run {lang.display}" if ready else f"Run {lang.display} (no compiler)",
interactive=ready,
),
idle_verdict(language_key),
)
def on_pick_example(name: str):
return EXAMPLES.get(name, "")
def _quota_html(session_id: str) -> str:
if not providers.PUBLIC or providers.limiter.limit <= 0:
return ""
left = providers.limiter.remaining(session_id)
return (
f'<p class="key-note">Free demo conversions left this hour: '
f"<strong>{left}</strong>. Use your own key below for unlimited access.</p>"
)
def new_session() -> str:
return uuid.uuid4().hex
# --------------------------------------------------------------------------
# static chrome
# --------------------------------------------------------------------------
START_LANG = sandbox.DEFAULT_LANGUAGE if sandbox.DEFAULT_LANGUAGE in COMPILABLE \
else (COMPILABLE[0] if COMPILABLE else sandbox.DEFAULT_LANGUAGE)
START = sandbox.LANGUAGES[START_LANG]
LANGUAGE_CHOICES = [
(f"{lang.display}" if key in COMPILABLE else f"{lang.display} (no compiler here)", key)
for key, lang in sandbox.LANGUAGES.items()
]
MASTHEAD = """
<div class="masthead">
<h1><span class="py">Python</span><span class="arrow">&#8594;</span><span class="rs">Rust &amp; C++</span></h1>
<p class="tagline">LLM translation, measured and verified</p>
<p>An LLM ports a Python program to Rust or C++. Both are compiled and executed
in a sandbox on this machine, so the speedup is measured rather than
estimated &mdash; and the outputs are compared, because a fast translation
that changes the answer is a broken one.</p>
<div class="links">
<a href="%s" target="_blank" rel="noopener">Source on GitHub</a>
<a href="#how">How it works</a>
</div>
</div>
""" % REPO_URL
def build_footer() -> str:
installed = [f"{sandbox.LANGUAGES[k].display}: {html.escape(TOOLCHAIN[k])}"
for k in COMPILABLE]
missing = [sandbox.LANGUAGES[k].display for k in sandbox.LANGUAGES
if k not in COMPILABLE]
missing_note = (
f"<br><strong>Note:</strong> no compiler found for {', '.join(missing)}, "
f"so translations to it can be generated but not executed here."
if missing else ""
)
return f"""
<div class="footer" id="how">
<p><strong>How it works.</strong> Your Python goes to the selected model with a
prompt that pins the exact compile flags and forbids algorithmic substitution.
The returned source is compiled with full optimisation and run. Both programs
self-report their execution time, and the non-timing output of each is compared
to verify the translation actually preserved the answer.</p>
<p><strong>Sandboxing.</strong> Submitted code never runs in the web server's
process. Each run gets a fresh subprocess with an allowlisted environment
containing no API keys, a scrubbed working directory, a wall-clock timeout, and
&mdash; on Linux &mdash; CPU, memory, and process-count limits.
Isolation here: {html.escape(TOOLCHAIN.get('isolation', 'unknown'))}.</p>
<p><strong>Keys.</strong> Frontier models never run on this instance's key. A key
you paste is used for that single request and is never logged, stored, or written
to disk.{missing_note}</p>
<p>{html.escape(TOOLCHAIN.get('python', ''))}{(' &middot; ' + ' &middot; '.join(installed)) if installed else ''}</p>
</div>
"""
# --------------------------------------------------------------------------
# interface
# --------------------------------------------------------------------------
def build_ui() -> gr.Blocks:
with gr.Blocks(title="Python → Rust & C++",
analytics_enabled=False) as ui:
session = gr.State(value=new_session)
# Inject the stylesheet into the page rather than passing css= to
# launch(). On Spaces the platform imports this module and calls
# launch() itself, so any styling passed there is silently dropped -
# the app would deploy looking completely unstyled.
gr.HTML(f"<style>{CSS}</style>")
gr.HTML(MASTHEAD)
verdict = gr.HTML(idle_verdict(START_LANG))
with gr.Row(equal_height=True, elem_classes=["picker"]):
example = gr.Dropdown(
choices=list(EXAMPLES.keys()), value=DEFAULT_EXAMPLE,
label="Example program", scale=5,
)
language = gr.Dropdown(
choices=LANGUAGE_CHOICES, value=START_LANG,
label="Translate to", scale=3,
)
model = gr.Dropdown(
choices=providers.dropdown_choices(), value=providers.default_model(),
label="Model", scale=5,
)
gr.Markdown(providers.availability_summary(), elem_classes=["status-line"])
with gr.Row(equal_height=True):
with gr.Column(scale=6):
python_box = gr.Code(
label="Python source", value=EXAMPLES[DEFAULT_EXAMPLE],
language="python", lines=24, elem_classes=["pane"],
)
with gr.Column(scale=6):
target_box = gr.Code(
label=f"{START.display} translation", value="",
language=START.highlight, lines=24, elem_classes=["pane"],
)
with gr.Row(elem_classes=["controls"]):
run_py = gr.Button("Run Python", elem_classes=["btn-run", "py"])
convert = gr.Button(f"Port to {START.display}", variant="primary",
elem_classes=["btn-convert"])
run_target = gr.Button(
f"Run {START.display}" if START_LANG in COMPILABLE
else f"Run {START.display} (no compiler)",
interactive=START_LANG in COMPILABLE,
elem_classes=["btn-run", "rust"],
)
with gr.Row(equal_height=True):
with gr.Column(scale=6):
py_out = gr.Textbox(label="Python output", lines=8,
elem_classes=["out-box", "py-out"],
buttons=["copy"])
with gr.Column(scale=6):
target_out = gr.Textbox(label=f"{START.display} output", lines=8,
elem_classes=["out-box", "rust-out"],
buttons=["copy"])
quota = gr.HTML(_quota_html(""))
with gr.Accordion("Use your own API key (optional)", open=False):
gr.Markdown(
"Needed for the frontier models marked **(need your own key)**, "
"which never run on this instance's account. Also removes the "
"rate limit.\n\n"
"**Worth knowing first:** on this benchmark GPT-5 Nano scored 62x "
"and GPT-5 scored 63x. The unmarked models need no key and give "
"you effectively the same answer.\n\n"
"A key you paste is sent over HTTPS, used for that single request, "
"then discarded - never logged, stored, or written to disk. It is "
"not saved in your browser either, so it clears on reload.\n\n"
"The code is open source if you would rather "
f"[read it]({REPO_URL}/blob/main/providers.py) or run this locally.",
elem_classes=["key-note"],
)
user_key = gr.Textbox(label="API key", placeholder="sk-...",
type="password", elem_classes=["keybox"])
gr.HTML(build_footer())
# ---- wiring ----
example.change(fn=on_pick_example, inputs=[example], outputs=[python_box])
language.change(
fn=on_change_language,
inputs=[language],
outputs=[target_box, target_out, convert, run_target, verdict],
)
run_py.click(
fn=on_run_python,
inputs=[python_box, target_out, language],
outputs=[py_out, verdict],
)
convert.click(
fn=on_port,
inputs=[model, python_box, language, user_key, session],
outputs=[target_box, quota],
)
run_target.click(
fn=on_run_target,
inputs=[target_box, py_out, language],
outputs=[target_out, verdict],
)
return ui
# Module-level so Hugging Face Spaces can find it. The Gradio SDK imports this
# file and serves the top-level Blocks object - it never runs the __main__
# block, so an app that only builds its UI in there deploys as a blank Space.
demo = build_ui()
if __name__ == "__main__":
demo.launch(
theme=gr.themes.Base(),
# Spaces route traffic to the container, so it must bind all interfaces.
# Locally, stay on loopback so the dev server is not exposed to the LAN.
server_name=os.getenv("SERVER_NAME", "0.0.0.0" if ON_SPACES else "127.0.0.1"),
server_port=int(os.getenv("PORT", "7860")),
)