weftgraph-remote-embedding-plugin 0.1.0

Remote embedding provider for the graph-storage gear: the alternative plugin of ADR-0004, over the OpenAI-compatible /embeddings protocol
Documentation

weftgraph-remote-embedding-plugin

weftgraph is a code name, not a product name. This crate is a preview release of a graph-storage gear built for CF/Gears and consumed by Constructor Studio, published from the fork vasylcf/gears-rust so that cargo add is all a consumer needs. It is deliberately not published under the cf-gears-* namespace: the name a first-party graph-storage gear eventually takes is Constructor Fabric's to choose, and this crate must not stand in its way. In-tree the crate is cf-gears-graph-storage-remote-embedding-plugin, and the library it builds keeps its remote_embedding_plugin name, so moving to an official crate later is a one-line change in a consumer's manifest.

The remote embedding provider of the graph-storage gear: the alternative plugin ADR-0004 names beside the in-process ONNX default. It implements graph_storage_sdk::plugin_api::EmbeddingProviderV1 over the OpenAI-compatible POST /embeddings protocol, which OpenAI, Azure OpenAI, Groq, Together, Ollama, vLLM and most self-hosted inference servers expose.

Use it where the gear's process cannot host a model — a memory ceiling, no CPU budget for inference, or a platform that already runs an inference service.

Enabling it

The gear links the plugin behind its remote feature and selects it by configuration:

graph-storage:
  config:
    embedding_provider: remote
    embedding_dimension: 384
    embedding_remote_base_url: "https://api.openai.com/v1"
    embedding_remote_model: "text-embedding-3-small"
    # Name of the environment variable holding the bearer credential.
    embedding_remote_api_key_env: "GRAPH_STORAGE_EMBEDDING_API_KEY"
    # Send the `dimensions` request field (Matryoshka models). Turn off for a
    # fixed-width model and set embedding_dimension to its native width.
    embedding_remote_request_dimensions: true

One deployment runs one provider. Switching providers over a populated graph changes the embedding-space identity; the gear then blocks the vector arm until the graph is re-embedded, and every other path keeps working.

What the identity promises

The space is named by model at endpoint at width, and by how the vectors are asked for and kept: whether the request carries an explicit dimensions field (embedding_remote_request_dimensions) and whether the answer is L2-normalized both fold into the identity hash alongside the model, the transport and the width.

So two deployments pointing one model name at one host share a space only if those settings match too — flipping either gives a different identity, and stored vectors under the old one stop ranking. That is the intended behaviour and the README used not to say it: a reader taking "model at endpoint at width" literally would expect a normalization change to be invisible, and would be surprised by a deployment that suddenly declares its space mismatched.

The shape of what goes into the hash is frozen once the plugin is released: adding or renaming a field in the identity blobs changes the identity of every deployment that upgrades, exactly as a normalization change does (see EmbeddingSpaceId::new in the SDK).

A vendor silently changing the weights behind a stable model name is still not detectable from this side — ADR-0004 places that under model governance and treats remote embedding as governed data egress.

Vectors are L2-normalized before storage by default, because the gear's index serves cosine similarity and not every compatible endpoint returns unit vectors.

Testing

cargo test -p cf-gears-graph-storage-remote-embedding-plugin

The suite runs the SDK's executable provider contract against a mock endpoint (wiremock), plus batching, alignment, width, credential and deadline cases. No network and no credential are needed.