Skip to content
PtahPtah

Configure an embedding provider

Four lines of a specification decide where your corpus goes. This page is what each of them means, and how to find out whether they are right before anything is sent.

model:
provider: openai-compatible
endpoint_class: local # local | hosted | gateway
endpoint: http://localhost:11434/v1
identifier: bge-small-en
revision: "sha256:..." # where the provider exposes one
credential: env:PTAH_EMBED_TOKEN
reported_dimension: 384
normalization: none

provider names the adapter, and there is one: openai-compatible, meaning a POST /v1/embeddings that answers in the OpenAI shape. An endpoint that speaks something else needs a gateway in front of it.

endpoint_class is your statement, not a measurement. Ptah cannot tell from an address who operates it. The class is carried into the plan and into the generation identity, so moving a corpus from a local endpoint to a hosted one is a different generation rather than a quiet change of who has your text.

identifier and revision are the model. Where the provider exposes an immutable revision, name it: without one the generation is reported as partially reproducible, with the reason, because asking the same provider again may answer with different vectors and Ptah cannot see that it did.

Nothing here needs a hosted provider, a Ptah account, or an outbound connection. An endpoint on localhost with no credential is a complete configuration, and it is the one to reach for when the text must not leave the machine.

Leave credential out entirely in that case. An empty reference means no Authorization header rather than an empty one.

credential: env:PTAH_EMBED_TOKEN # an environment variable
credential: file:/run/secrets/token # a file, read at the moment of use

Two schemes: env and file. Either names where the value is, and the value is read at the moment of each request and not kept. What Ptah records — in the plan, in the run’s own tables, in published evidence, in what an agent can see — is the reference.

That is what makes a specification a file you can commit.

A file: reference is refused when the filesystem lets anyone but the owner read it, where the platform can answer that question. A token in a world-readable file is a token every process on the host has.

Terminal window
ptah inference probe --spec spec.yaml
bge-small-en at localhost:11434, declared local
- ok reachable: the endpoint at localhost:11434 answered
- ok authorized: no credential was sent, and the endpoint asked for none
- ok embeds: model bge-small-en answered an embedding request
- ok shape: one vector of 384 finite values for one input
- ok dimension: 384 dimensions, as declared
- ok batch: 2 inputs answered with 2 vectors
- ok cancellation: a canceled request stopped rather than answering
- ok error shape: a refused request arrived as a classified error the engine can act on

Two fixed strings go out and nothing from your database does, so this is runnable — and its output shareable — before anybody has decided to send a corpus anywhere. It opens no database either, which is what lets a CI job run it against a specification somebody is still writing.

It returns 1 when a check fails.

A check the probe could not make is reported as unmeasured rather than as a pass. That distinction is the whole value of the verb: a credential that does not resolve — an unset variable, a missing file, one the filesystem lets other users read — is refused before a single byte leaves the process, so the probe says the credential could not be used and that reachability was not measured:

bge-small-en at api.example.com, declared hosted
- fail authorized: the credential from env:PTAH_EMBED_TOKEN could not be used:
credential reference resolves to nothing: environment variable
PTAH_EMBED_TOKEN is unset or empty
- not measured: whether the endpoint at api.example.com is reachable, and
everything after it, because no request was sent

Nothing was asked of the endpoint, so nothing is claimed about it.

dimension is the one that used to be found late. Every fact a plan states about a provider is configured rather than measured, so before this verb the first thing that compared reported_dimension with what the endpoint answers was the backfill — which had already sent rows by then.

cancellation decides what an interrupted backfill costs. A provider that answers a canceled request turns your Ctrl-C into a wait, and the bill keeps running.

error shape is what the engine acts on. Retry, stop, fail the batch: every one of those decisions reads a classified error, and a refusal that arrives as whatever the endpoint wrote is one the engine cannot act on correctly.

A check that could not run is named rather than reported as passing. An unreachable endpoint reports the reachability check and says everything after it was not measured.

If the endpoint you named fails, Ptah does not try another one. It could not do so safely: a different provider is a different generation identity and a different privacy boundary, and choosing one for you would send your text somewhere you did not authorize while producing vectors that are not comparable with the ones already stored.

A failed backfill stops and resumes from its checkpoint when the endpoint is back.

Whether the provider retains what you send it. That is a contract question with them, and nothing here claims an answer.

See Security and data boundaries for what leaves the database, and Plan provider capacity for sizing the run against rate limits and cost.