oracle-ai-developer-hub

Part 5: Oracle MLE Compute Sandbox

LLMs are unreliable at math. Percentiles, weighted means, post-fetch reshaping — anything quantitative — should run in a deterministic engine, not in the model’s head. We route those snippets through Oracle’s Multilingual Engine (MLE) — JavaScript that runs inside the Oracle process, called via DBMS_MLE.

Why JavaScript and not Python?

Oracle AI Database 26ai Free ships MLE with JavaScript. Python MLE is a separate package not enabled in this build, which surfaces as ORA-04101: Multilingual Engine does not support the language PYTHON. The agent doesn’t care which language we expose — it’ll happily emit JS for the kinds of computation we need (arithmetic, string formatting, JSON reshaping).

Why MLE rather than a subprocess sandbox?

What’s pre-built

Nothing in Oracle itself — MLE is available out of the box on Oracle AI Database 26ai with the grants app/scripts/bootstrap.py already gave to AGENT:

This Part just defines the Python helper that calls DBMS_MLE.EVAL for us.

The exec_js helper

exec_js(code) wraps your JS in a try/catch + console.log capture, evaluates it inside a fresh MLE context, and returns:

{"stdout": "<captured console.log>", "stderr": "<error if thrown>", "ok": True/False}

The wrapper uses mle-js-bindings to export a result value, which the Python side imports via DBMS_MLE.IMPORT_FROM_MLE and parses as JSON.

Why the agent will actually reach for it

The Part 7 system prompt has an explicit rule:

“For numeric work over fetched rows … you MUST fetch with run_sql and then call exec_js to compute.”

This pushes percentile / mean / max / unit-conversion / reshaping work through MLE rather than letting the model do arithmetic in its head or rely solely on SQL aggregation. Without that rule GPT-class models often skip the JS hop and answer from a single run_sql aggregate — convenient but harder to audit when the math gets non-trivial.

A concrete example

const totals = [199, 4999, 12999, 599, 8999, 24999, 1499, 89999, 3499, 599, 19999, 11999]
                 .slice().sort((a, b) => a - b);
const n = totals.length;
function pct(p) {
    const k = (n - 1) * p;
    const f = Math.floor(k);
    return f === Math.min(f + 1, n - 1)
         ? totals[f]
         : totals[f] + (totals[Math.min(f + 1, n - 1)] - totals[f]) * (k - f);
}
const sum = totals.reduce((a, b) => a + b, 0);
console.log("n=" + n + " mean=" + Math.floor(sum/n) +
            " p50=" + Math.round(pct(0.50)) + " p95=" + Math.round(pct(0.95)));

The model emits this JS in response to “compute percentiles over these order totals”, exec_js runs it inside Oracle, and the result lands back in the agent’s context as deterministic, audit-traceable output.

Key Takeaways — Part 5

Troubleshooting

ORA-04101: Multilingual Engine does not support the language PYTHON — Use JavaScript. Python MLE isn’t enabled on Free.

No stdout but ok: true — The snippet didn’t call console.log. Wrap your final value in console.log(...) to capture it.

stderr: "ReferenceError: require is not defined" — The wrapper imports require("mle-js-bindings"). If you’re running a snippet directly via DBMS_MLE.EVAL outside exec_js, you need to handle bindings yourself.

ORA-04036: PGA memory ... exceeds PGA_AGGREGATE_LIMIT — Raise pga_aggregate_limit. The pre-built setup raises it to 4 GiB; if you’re running outside the Codespace, do this once as SYSDBA against CDB$ROOT.