From c8a791f7069725539514d065580a406da8688438 Mon Sep 17 00:00:00 2001 From: Abhinavexist Date: Sat, 18 Jul 2026 23:54:52 +0530 Subject: [PATCH] chore: align SDK with server #218 (max_completion_tokens, models) Server PR interfaze#218 (OpenAI 1:1 spec-compat) is deploying: - max_completion_tokens is now honored as an alias for max_tokens (max_tokens still wins), so drop the README guidance that said to avoid it. - GET /v1/models is OpenAI-enveloped and GET /v1/models/{id} now exists; add mocked tests locking in models.list()/retrieve() including the spec-shaped model_not_found 404. --- README.md | 4 ++-- tests/test_models.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/test_models.py diff --git a/README.md b/README.md index 16c09f4..0f639d5 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,8 @@ URLs and base64 work; raw `bytes` do **not** (must be base64-encoded — this SD ## Good to know - Interfaze implements `chat.completions` and `models`; other OpenAI endpoints are not exposed. -- `temperature` ≤ 1, `max_tokens` ≤ 32000, `top_p` ≤ 1 (above → 400). Use `max_tokens` (not - `max_completion_tokens`) to bound output. +- `temperature` ≤ 1, `max_tokens` ≤ 32000, `top_p` ≤ 1 (above → 400). Both `max_tokens` and + `max_completion_tokens` bound output (`max_tokens` wins if both are set). - `n`, `seed`, `stop`, penalties, `logprobs`, `tool_choice`, `top_k` are ignored by Interfaze. - The underlying OpenAI client is available at `interfaze.openai`. diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..cb840ba --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import httpx +import pytest +import respx +from openai import NotFoundError + +from interfaze import Interfaze + +MODELS_URL = "https://api.interfaze.ai/v1/models" +MODEL = {"id": "interfaze-beta", "object": "model", "owned_by": "interfaze", "name": "Interfaze Beta"} +MODELS_LIST = {"object": "list", "data": [MODEL]} +NOT_FOUND = { + "error": { + "message": "The model 'nope' does not exist", + "type": "invalid_request_error", + "code": "model_not_found", + } +} + + +@respx.mock +def test_models_list(): + respx.get(MODELS_URL).mock(return_value=httpx.Response(200, json=MODELS_LIST)) + page = Interfaze(api_key="t").models.list() + assert [m.id for m in page] == ["interfaze-beta"] + assert page.data[0].owned_by == "interfaze" + + +@respx.mock +def test_models_retrieve(): + respx.get(f"{MODELS_URL}/interfaze-beta").mock(return_value=httpx.Response(200, json=MODEL)) + m = Interfaze(api_key="t").models.retrieve("interfaze-beta") + assert m.id == "interfaze-beta" and m.owned_by == "interfaze" + + +@respx.mock +def test_models_retrieve_not_found(): + respx.get(f"{MODELS_URL}/nope").mock(return_value=httpx.Response(404, json=NOT_FOUND)) + with pytest.raises(NotFoundError): + Interfaze(api_key="t").models.retrieve("nope")