post/bytesandbrains-0-3-0-first-public-release
bytesandbrains 0.3.0 - First public release
First public release: framework + sans-IO Engine + Wire + role traits + CpuBackend reference.
First public release of the BytesAndBrains framework.
Quick start
cargo add bytesandbrains
[dependencies]
bytesandbrains = "0.3"
The shipped examples/federated_learning.rs is the canonical end-to-end pattern. The condensed shape is the three-phase pipeline every program follows: author, compile, install.
// pattern condensed from examples/federated_learning.rs
use bytesandbrains::placeholders::ModelSlot;
use bytesandbrains::{install, Address, Compiler, Config, Graph, Module, PeerId};
struct ClientLogic;
impl Module for ClientLogic {
fn name(&self) -> &str { "ClientLogic" }
fn body(&self, g: &mut Graph) {
// Record an op that consumes the server's params, applies them
// to the bound Model, then ships the updated params back.
let server_params = g.input("server_params");
let _ = ModelSlot.load_parameters(g, server_params);
let updated = ModelSlot.params(g);
let server_peer = g.input("server_peer");
g.net_out("updated_params", server_peer, updated);
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// AUTHOR. Module body records into a ModelProto.
let client_proto = ClientLogic.build()?;
// COMPILE. Bind concretes, partition, get back the installed ModelProto.
let client_artifact = Compiler::new()
.bind_model::<MyModel>("model")
.compile(client_proto)?;
// INSTALL. Produce a Node bound to this peer's partition.
let target = client_artifact.functions[0].name.clone();
let peer = PeerId::from(101);
let mut client = install(
peer,
Address::empty().p2p(peer),
client_artifact,
&target,
Config::new(),
)?;
// The host drives client.poll(&mut cx) and ships outbound envelopes.
Ok(())
}
Added
Moduletrait. Authors record their workload as a Rust struct whosebody(&self, g: &mut Graph)method records computation against an ONNXModelProto.- Graph DSL records NodeProtos through method calls. Inputs declared with
g.input("name"); local sinks withg.output("name", value); network sinks withg.net_out("name", peers, value). - Compiler:
Compiler::new().bind_<role>::<T>("slot").compile(module) -> ModelProtobinds concretes and partitions the graph across Nodes, inserting cross-node edges as wire ops. - Sans-IO Engine: single-threaded state machine driven by the host’s
poll(), eight-phase poll cycle. - Wire: one
WireEnvelopeproto carries both data-plane values and control-plane protocol traffic. Framed protobuf on the byte side, address-suffix routing on the wire side. - Eight role traits:
BackendRuntime,ModelRuntime,IndexRuntime,AggregatorRuntime,CodecRuntime,DataSourceRuntime,PeerSelectorRuntime,ProtocolRuntime. Library makers implement the matchingbb::<Role>Contract traits inbb-runtime/src/contracts/; the#[derive(bb::<Role>)]bridges generate the engine-side<Role>Runtimeimpl. ConcreteComponenttrait. Every plug-in derives this through#[derive(bb::Concrete)]and submits itself throughinventory::submit!. DCE strips unreferenced entries.- Snapshot and restore on the Node.
- Cross-Component event bus and lock-free MPMC ingress queue.
- Companion crate
bb-derive: proc-macros for#[derive(bb::Concrete)]and#[derive(bb::<Role>)], plus the declarativebb::register_op!{}andbb::register_protocol!{}macros. - Reference
CpuBackendunderbytesandbrains::backends::cpu, implementing theai.onnx v1op subset the framework needs.
Details: whitepaper | docs.rs | GitHub.