The transport: one POST to /v1/systemone per call.
This is the Jev.Backend for TypeSafe and every server that speaks its wire
format, and the default. Jev.Server calls it from a task; scripts and
evaluation harnesses call it directly.
Configuration
config :jev,
api_key: System.get_env("TYPESAFE_API_KEY"), # or the TYPESAFE_API_KEY env var
base_url: "https://api.typesafe.ai",
model: "jev-latest",
max_retries: 3,
receive_timeout: 30_000,
usd_per_million_input: 0.042,
req_options: [] # merged into Req.new/1, e.g. a test plugEvery option except usd_per_million_input and req_options can also be
passed per call. Requests that fail with 429 or 529 are retried with backoff,
honouring Retry-After, as the API documentation asks.
Endpoints
The wire format is spoken by more than TypeSafe: self-hosted decision models
such as Laya, kev, decider, and jeff serve the same /v1/systemone. Name
them under endpoints and pick one per call with endpoint::
config :jev,
endpoints: [
laya: [base_url: "http://localhost:8000"],
jeff: [base_url: "https://jeff.internal", api_key: "...", model: "gliformer-large"]
]
Jev.HTTP.post(state, questions, endpoint: :laya)The top-level configuration is the :typesafe endpoint, which is the
default; config :jev, endpoint: :laya changes the default. A named
endpoint takes base_url (required), api_key, model, and
usd_per_million_input, plus max_retries, receive_timeout, and
req_options. It never inherits the TypeSafe key or price: without an
api_key no Authorization header is sent, and the price defaults to zero.
Transport settings are inherited. See endpoint/1 for the resolved result.
Telemetry
Every call runs under Jev.Telemetry.span/4, with backend: Jev.HTTP,
the endpoint name, and the model in the metadata; the stop event adds
status and request_id. The state itself is never put in metadata, only
its hash.
Summary
Types
@type endpoint() :: %{ name: atom(), base_url: String.t(), api_key: String.t() | nil, model: String.t(), max_retries: non_neg_integer(), receive_timeout: timeout(), usd_per_million_input: number(), req_options: keyword() }
A resolved endpoint, as returned by endpoint/1.
Functions
Resolves the endpoint a call with opts would use.
opts[:endpoint], then config :jev, endpoint:, then :typesafe names the
endpoint. :typesafe is built from the top-level configuration; any other
name is looked up under config :jev, endpoints:. Per-call base_url,
api_key, model, max_retries, and receive_timeout override the result.
iex> Jev.HTTP.endpoint(endpoint: :local, model: "laya-421m").model
"laya-421m"Raises ArgumentError for an unknown name or a named endpoint without a
base_url.
@spec post( Jev.entry(), keyword(Jev.shorthand()) | %{required(atom()) => Jev.shorthand()}, [option()] ) :: {:ok, Jev.reply()} | {:error, Jev.Error.t() | JSONCodec.Error.t() | Exception.t()}
Evaluates questions against state.
Returns {:ok, reply} with the map described in Jev, or {:error, error}
where error is a Jev.Error for a non-2xx response, a JSONCodec.Error
for a 200 whose body does not fit Jev.Wire, or the transport exception.
Raises ArgumentError for malformed questions, an unknown endpoint, or a
missing TypeSafe API key.