|
|
@@ -79,6 +79,40 @@ Every list must name at least one modality except a model's own, where an empty
|
|
|
|
|
|
Both fields state a claim about your endpoint rather than checking it. A model that declares images its endpoint does not serve is not caught here; the provider rejects the request instead.
|
|
|
|
|
|
+### Request compatibility
|
|
|
+
|
|
|
+A gateway can hold a working key at a reachable address and still refuse every request. pi-ai decides the shape of a request — which role carries the system prompt, which field caps the output, how a thinking level travels — from the endpoint's URL, and an address it does not recognize is addressed as though it were OpenAI itself. Most OpenAI-compatible gateways refuse at least one thing OpenAI accepts.
|
|
|
+
|
|
|
+Two account for most of it. A model that declares reasoning has its system prompt sent as `role: "developer"`, which many gateways reject outright, and the output cap is sent as `max_completion_tokens`, which a server that only knows `max_tokens` refuses. The form has no field for either; correct them on the route in `$DSH_HOME/settings.yaml`:
|
|
|
+
|
|
|
+```yaml
|
|
|
+llm-pi-ai:
|
|
|
+ providers:
|
|
|
+ my-gateway:
|
|
|
+ apiKeyEnv: GATEWAY_API_KEY
|
|
|
+ api: openai-completions
|
|
|
+ baseURL: https://gateway.example/v1
|
|
|
+ compat:
|
|
|
+ supportsDeveloperRole: false
|
|
|
+ maxTokensField: max_tokens
|
|
|
+ models:
|
|
|
+ - id: my-model
|
|
|
+```
|
|
|
+
|
|
|
+A route's `compat` is the default for its models, and a model's own wins field by field, so one model can be corrected without restating the route:
|
|
|
+
|
|
|
+```yaml
|
|
|
+ models:
|
|
|
+ - id: my-model
|
|
|
+ - id: my-reasoner
|
|
|
+ compat:
|
|
|
+ thinkingFormat: deepseek
|
|
|
+```
|
|
|
+
|
|
|
+What neither sets keeps the installed catalog's value for that model, and what the catalog does not describe falls to pi-ai's detection. Give every switch you name a value: a key left empty (`supportsDeveloperRole:`) is refused rather than ignored, because an empty value would erase what the catalog knows while saying nothing in its place. A name no protocol accepts is refused too, and the message lists the ones that are available.
|
|
|
+
|
|
|
+Each switch belongs to the protocols that declare it, so a switch valid on one `api` may be refused on another — the message names what that protocol does offer. Like `input` above, a switch states a claim about your endpoint rather than checking it: setting one your gateway does not actually need simply sends a different request.
|
|
|
+
|
|
|
## Select a model
|
|
|
|
|
|
Configured providers appear in the model picker. Selecting a model also makes it the default for new sessions. A session that has already sent a request retains the model recorded in its own log.
|
|
|
@@ -90,6 +124,9 @@ If a saved default names a provider that was deleted, the composer displays **Se
|
|
|
- **`MISSING_CREDENTIAL`** — Store the provider key through the Models page or supply the referenced environment variable.
|
|
|
- **`UNKNOWN_MODEL`** — Select a configured model or add the missing model to the custom provider.
|
|
|
- **Fetching available models returns 401** — Check the key. Model discovery calls the OpenAI-compatible `GET /models` endpoint; enter models manually for endpoints that do not provide it.
|
|
|
+- **The gateway refuses every request although the key and URL are right** — Its request shape differs from OpenAI's. Start with `compat.supportsDeveloperRole: false` and `compat.maxTokensField: max_tokens` on the route.
|
|
|
+- **Only reasoning models fail** — pi-ai sends their system prompt as the `developer` role, which the gateway rejects. Set `compat.supportsDeveloperRole: false`.
|
|
|
+- **A compat switch is refused as having no value** — A key written with nothing after the colon. Give it a value, or remove the key to keep the installed catalog's.
|
|
|
- **An image is refused before sending** — The model declares no image modality. Give a custom provider's model `input: [text, image]`; DeepSeek's own chat-completions route is text-only and cannot be configured otherwise.
|
|
|
- **The provider rejects a request carrying an image** — The model declares images its endpoint does not actually serve. Remove `image` from whichever list granted it — the model's `input`, or the route's `defaultInput` — then start a new session: the attached image stays in the session log, so the same request repeats until the session moves off it.
|
|
|
|