Technology · Framework

PyO3

An earlier in-process Python binding for embeddings, replaced by a separate inference server.

FAFO Core · FAFOHiveRust to Python bridgeAn embedding model in process
An async Rust service · one Python island

I use a language bridge where it saves time and remove it when it costs more than it saves, without disturbing the code that depends on it. These are thin wrappers around a third-party Python model; the judgment is in where the boundary sat and when it moved.

An embedding model inside a Rust function

In FAFO Core and Function Forge the research and memory functions are Rust, and the embedding model they needed was easiest to reach through a Python library. I used PyO3 to bring the model into the Rust function and keep everything else native. The rest of the function stays ordinary Rust on the substrate, queue-driven and controllable like any other.

The research steps that consumed these embeddings, a validator for candidate question-and-answer pairs and a near-neighbour rebalancing step, were ported from an earlier Python pipeline into typed Rust functions, with this wrapper as the only Python left in them.

Earlier pipeline
Rust functions
Python
typed Rust
Proportions illustrative. The model loads once and is shared behind a mutex; a model swap that changes the vector dimension fails at once.

Moving the model behind a service boundary

In FAFOHive I used the same pattern first and later moved off it. The memory service ran the embedding model in process through PyO3, then through a GPU subprocess. Every search feature depended on that path.

PyO3 bought speed of delivery; once its cost showed, I moved the model behind a network boundary.

In process
memory service

GPU memory and process stability both suffered.

Behind a boundary
memory service, same interface
mutual TLS

No caller changed.

The graph tools that sit beside the embeddings are in A code explainer that is not allowed to invent.