Serve Mode¶
Added in version 2.2.
conda-forge availability
Included in the conda-forge package (v2.12+). No additional build flags required.
Serve mode wraps any eOn potential as an rgpot-compatible server, exposing it over Cap’n Proto RPC. This allows external tools, such as Julia-based optimization frameworks (e.g., ChemGP), to evaluate energies and forces without embedding C++ code directly.
Compilation¶
Serve mode requires the with_serve build option and a Cap’n Proto installation.
The serve pixi environment provides all necessary dependencies:
pixi run -e serve bash
meson setup builddir -Dwith_serve=true
meson compile -C builddir
To also enable Metatomic (ML) potentials:
meson setup builddir \
-Dwith_serve=true \
-Dwith_metatomic=true \
-Dpip_metatomic=true \
-Dtorch_version=2.9
meson compile -C builddir
Usage¶
Serve mode supports four modes of operation: single-potential, replicated, gateway, and multi-model. Each mode is selected by the combination of CLI flags provided.
Single-Potential¶
The simplest usage serves one potential on a single port:
eonclient -p lj --serve-port 12345
This starts a blocking RPC server on localhost:12345 serving the Lennard-Jones
potential. The server runs until interrupted with Ctrl+C.
To bind to all interfaces:
eonclient -p lj --serve-host 0.0.0.0 --serve-port 12345
Replicated¶
To start multiple copies of the same potential on sequential ports:
eonclient -p lj --serve-port 12345 --replicas 4
This starts 4 independent servers on ports 12345 through 12348, each with its own potential instance and event loop. Useful when clients can load-balance across known ports.
Gateway¶
Gateway mode exposes a single port backed by a pool of potential instances. Incoming requests are dispatched round-robin across the pool, so clients only need to know one address:
eonclient -p lj --serve-port 12345 --replicas 6 --gateway
This creates 6 LJ potential instances and serves them all behind port 12345. Each incoming RPC call is routed to the next available instance. This is the recommended mode for high-throughput use cases where clients should not need to track multiple ports.
Multi-Model¶
The --serve flag accepts a comma-separated specification of
potential:port or potential:host:port pairs, each served concurrently
in its own thread:
eonclient --serve "lj:12345,eam_al:12346"
With explicit hosts:
eonclient --serve "lj:0.0.0.0:12345,eam_al:0.0.0.0:12346"
Potential Configuration¶
Potentials that require parameters (Metatomic, XTB, etc.) can be configured
via the --config flag, which loads an INI-format config file:
eonclient --serve "metatomic:12345" --config model.ini
The config file uses the same INI format as eOn’s standard config.ini. For
example, a Metatomic model:
[Metatomic]
model_path = /path/to/model.pt
device = cuda
length_unit = angstrom
Or for XTB:
[XTBPot]
paramset = GFN2xTB
accuracy = 1.0
Config-Driven Serve¶
The [Serve] section allows fully config-driven serving without CLI flags
beyond --config:
[Potential]
potential = lj
[Serve]
host = localhost
port = 12345
replicas = 4
gateway_port = 0
eonclient --config serve.ini
The dispatch logic when serving from config:
If
endpointsis set, each endpoint is served in its own thread.If
gateway_port > 0, a single gateway port is opened backed by a pool ofreplicaspotential instances.Otherwise,
replicasindependent servers are started on sequential ports beginning atport.
Examples¶
Gateway with a Metatomic model:
[Potential]
potential = metatomic
[Metatomic]
model_path = /path/to/model.pt
device = cuda
[Serve]
host = 0.0.0.0
gateway_port = 12345
replicas = 6
Multi-model endpoints:
[Serve]
endpoints = lj:12345,eam_al:12346,metatomic:0.0.0.0:12347
[Metatomic]
model_path = /path/to/model.pt
Configuration¶
[Serve]
JSON configuration¶
Added in version 2.12.
Parameters can also be loaded from JSON strings programmatically, enabling serve mode clients to send configuration without INI files:
Parameters params;
params.load_json(R"({
"Potential": {"potential": "LJ"},
"Serve": {"host": "0.0.0.0", "port": 12345, "replicas": 4}
})");
The JSON format mirrors the INI section/key structure. See Parameters system for the full schema.
Protocol¶
The RPC protocol is defined by rgpot’s Potentials.capnp schema. Each request
sends:
positions: flat array
[x1, y1, z1, x2, y2, z2, ...](Angstroms)atmnrs: atomic numbers
[Z1, Z2, ...]box: 3x3 cell matrix (row-major flat array)
Each response returns:
energy: total potential energy (eV)
forces: flat array matching positions layout (eV/Angstrom)
Integration with ChemGP¶
ChemGP connects to serve mode via its RpcPotential oracle:
using ChemGP
# Connect to a running eonclient --serve instance
pot = RpcPotential("localhost", 12345, atmnrs, box)
E, F = ChemGP.calculate(pot, positions)
# Use as a GP optimization oracle (gradient = -forces)
oracle = make_rpc_oracle(pot)
See the ChemGP RPC tutorial for details.
Architecture Notes¶
The serve mode uses a ForceCallback (flat-array std::function) interface
internally, completely decoupling the eOn potential from the capnp server.
This avoids a type collision between eOn’s Eigen-based AtomMatrix and rgpot’s
custom AtomMatrix by never allowing both types to coexist in the same
translation unit. The capnp schema code is compiled in a separate TU
(ServeRpcServer.cpp) from the eOn potential wrapper (ServeMode.cpp). For
more on the integration pattern, see the
rgpot integration guide.
Command Reference¶
Flag |
Description |
|---|---|
|
Multi-model serve spec: |
|
Host for single-potential mode (default: |
|
Port for single-potential mode with |
|
Number of server instances or gateway pool size (default: |
|
Enable gateway mode (single port, round-robin pool) |
|
INI config file for potential and serve parameters |
|
Potential type (used with |