Browse the docs · Apsi 2.0.0
Using Apsi with other languages
Apsi keeps a clear border between its own world and the outside: values that cross it are converted by fixed
rules (quantities with units always travel as {"value": ..., "unit": "..."}), and every cross-language
call needs a permission first.
Python
# apsi run app.apsi --allow-python
let np = pyimport("numpy")
let scipy_special = pyimport("scipy.special")
print(scipy_special.gamma(5.5))
- Python objects behave like normal values: call methods and read attributes — except attributes that start
with
_, which are blocked for safety to_py(x)converts an Apsi value into a Python/JSON value;from_py(v)converts back
Calling Apsi from Python
import apsi
it = apsi.Interpreter(permissions={"fs"})
env = it.run(open("physics.apsi", encoding="utf-8").read(), "physics.apsi")
kinetic = env.vars["kinetic"] # Apsi functions can be called from Python directly
PyTorch
# apsi run train.apsi --allow-python
let t = to_torch(randn(4, 4), device="cuda") # Apsi tensor -> torch.Tensor
let back = from_torch(t @ t) # torch.Tensor -> Apsi tensor
# whole models: `use layers` then torch_module(model, params) -> torch.nn.Module (see BACKENDS.md)
C / C++ / Rust (FFI)
// vecmath.c -> gcc -O3 -shared -fPIC vecmath.c -o libvecmath.so
double dot(const double *a, const double *b, int64_t n);
# apsi run app.apsi --allow-ffi
let lib = cload("libvecmath.so")
let c_dot = lib.fn("dot", [ptr_f64, ptr_f64, i64], f64)
print(c_dot(a, b, len(a)))
- Types:
f64 f32 i32 i64 void cstr ptr_f64 ptr_f32 ptr_i32 ptr_i64 - Tensors passed as
ptr_*are not copied, so C code can write its results straight into an Apsi tensor - C++: wrap the functions in
extern "C" { ... } - Rust:
#[no_mangle] pub extern "C" fn ..., built as acdylib - Quantities must be passed as
x.magnitude, so you choose the unit on purpose library_path("vecmath")shows the filecloadwould open (vecmath.dllon Windows,libvecmath.soon Linux);--allow-ffi=vecmath.so@<sha256>pins a library to its hash
JavaScript / Next.js / Java / Go / C# (HTTP)
apsi serve model.apsi --port 8787 --only predict kinetic
GET /functionslists the functions with their parameter typesPOST /call/<name>with the body{"args": [...], "kwargs": {...}}- arguments are checked for type, unit and shape on every call; a mismatch returns HTTP 400 with
{"error", "kind"} - CORS is enabled and the body size is limited to 10 MB
Next.js (App Router, server action or route handler):
export async function kinetic(massKg: number, speed: number) {
const r = await fetch("http://127.0.0.1:8787/call/kinetic", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ args: [{ value: massKg, unit: "kg" }, { value: speed, unit: "m/s" }] }),
});
const { result, error } = await r.json();
if (error) throw new Error(error);
return result; // { value: 9, unit: "J" }
}
Java 11+:
var client = java.net.http.HttpClient.newHttpClient();
var req = java.net.http.HttpRequest.newBuilder(java.net.URI.create("http://127.0.0.1:8787/call/predict"))
.header("Content-Type", "application/json")
.POST(java.net.http.HttpRequest.BodyPublishers.ofString("{\"args\": [[1, 2, 3]]}"))
.build();
System.out.println(client.send(req, java.net.http.HttpResponse.BodyHandlers.ofString()).body());
For a full server with routes, middleware and authentication use use web — see SERVER.md.
Files and network
load_csv,save_csv,load_json,save_json,read_text,write_textneed thefspermission; relative paths are resolved against the.apsifile that is runninghttp_get(url)andhttp_post_json(url, data)need thenetpermission
Found a mistake? Report it · Markdown source