Replicate provider adapter.
Implements IAIProvider against Replicate's predictions API, which hosts many models — including Anthropic and Google ones — behind a single token.
Replicate has no OpenAI-compatible endpoint (/v1/chat/completions is a
404), so it cannot be driven by the openai adapter. Two further differences
shape this namespace:
Prefer: wait header makes it synchronous, which is all
Wagoe needs and avoids a polling loop entirely.output comes back as a list of string chunks rather than a string.Input constraints are per-model rather than per-API — see model-input. A
422 names the field it rejected, so the failure is reported with that detail
instead of a bare status.
Replicate provider adapter. Implements IAIProvider against Replicate's predictions API, which hosts many models — including Anthropic and Google ones — behind a single token. Replicate has no OpenAI-compatible endpoint (`/v1/chat/completions` is a 404), so it cannot be driven by the openai adapter. Two further differences shape this namespace: - The documented flow is asynchronous: create a prediction, poll until it succeeds. The `Prefer: wait` header makes it synchronous, which is all Wagoe needs and avoids a polling loop entirely. - `output` comes back as a list of string chunks rather than a string. Input constraints are per-model rather than per-API — see `model-input`. A 422 names the field it rejected, so the failure is reported with that detail instead of a bare status.
(create-replicate-provider {:keys [base-url api-key model timeout]})Build a ReplicateProvider.
Config: :api-key - Replicate API token (required) :model - owner/name, e.g. anthropic/claude-opus-4.6 :base-url - override, for a proxy or a test double
Build a ReplicateProvider. Config: :api-key - Replicate API token (required) :model - owner/name, e.g. anthropic/claude-opus-4.6 :base-url - override, for a proxy or a test double
Output budget when the caller sets none. Each model has its own default, and a small one cuts an answer off mid-form.
Output budget when the caller sets none. Each model has its own default, and a small one cuts an answer off mid-form.
The model used when config names none.
The model used when config names none.
(failure-detail body)The useful part of a Replicate error body, or nil.
A 422 names the field it rejected — input.max_tokens: Must be greater than or equal to 1024 — which is worth surfacing, because the constraint varies
per model and is not something the caller could have known from the API.
Takes a map as readily as a string. The request uses :as :json, and while
clj-http's default :coerce :unexceptional leaves error bodies as strings —
measured against a real 422 — that is a default, not a guarantee. Running
(str m) over a map and parsing the result as JSON yields nil, which would
silently drop the detail this exists to surface.
The useful part of a Replicate error body, or nil. A 422 names the field it rejected — `input.max_tokens: Must be greater than or equal to 1024` — which is worth surfacing, because the constraint varies per model and is not something the caller could have known from the API. Takes a map as readily as a string. The request uses `:as :json`, and while clj-http's default `:coerce :unexceptional` leaves error bodies as strings — measured against a real 422 — that is a default, not a guarantee. Running `(str m)` over a map and parsing the result as JSON yields nil, which would silently drop the detail this exists to surface.
(messages->input messages)Wagoe's message vector as Replicate's flat input map.
Replicate takes a single prompt plus an optional system_prompt, not a
conversation. System messages are joined into system_prompt and the rest
into prompt, preserving order within each — flattening both into one
string would lose the distinction the models are tuned on.
Pure, so the shaping is testable without a token.
Wagoe's message vector as Replicate's flat input map. Replicate takes a single `prompt` plus an optional `system_prompt`, not a conversation. System messages are joined into `system_prompt` and the rest into `prompt`, preserving order within each — flattening both into one string would lose the distinction the models are tuned on. Pure, so the shaping is testable without a token.
(model-input model messages opts)The prediction input for model: the conversation in the shape that model
takes, and the output limit — :max-tokens in opts, else
default-max-tokens — clamped to what it accepts, in the field it reads.
Pure, so the shaping is testable without a token.
The prediction input for `model`: the conversation in the shape that model takes, and the output limit — `:max-tokens` in `opts`, else `default-max-tokens` — clamped to what it accepts, in the field it reads. Pure, so the shaping is testable without a token.
(output->text output)Replicate's output as a string.
It is a list of chunks — ["\n\n" "OK"] — and printing that verbatim
would show a vector to the user. A string is passed through so a model that
returns one still works.
Replicate's `output` as a string. It is a list of chunks — `["\n\n" "OK"]` — and printing that verbatim would show a vector to the user. A string is passed through so a model that returns one still works.
Statuses that mean the prediction is over, one way or another.
Anything else — starting, processing — means it is still running and the
result is not there yet.
Statuses that mean the prediction is over, one way or another. Anything else — `starting`, `processing` — means it is still running and the result is not there yet.
(terminal? resp)Whether a prediction response needs no further waiting.
An unrecognised status counts as terminal: looping on a status this does not understand would hang until the timeout rather than reporting it.
Whether a prediction response needs no further waiting. An unrecognised status counts as terminal: looping on a status this does not understand would hang until the timeout rather than reporting it.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |