Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions python/freetoken/server/openai_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ async def handle_completion(
unsupported = _completion_unsupported_reason(req)
if unsupported is not None:
return create_error_response(unsupported)
if req.n != 1:
return create_error_response("Only n=1 is supported", param="n")
try: # surfaces an out-of-range max_tokens as a 400 rather than a 500 from the worker
default_max_tokens = (
getattr(state.config, "max_output_tokens", None) or DEFAULT_MAX_OUTPUT_TOKENS
Expand Down
19 changes: 19 additions & 0 deletions tests/server/test_openai_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
from types import SimpleNamespace

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from freetoken.message import TokenizeMsg, UserReply
Expand Down Expand Up @@ -356,6 +357,24 @@ def test_completion_rejects_token_id_prompts():
assert "token-id prompt" in body["error"]["message"]


@pytest.mark.parametrize("stream", [False, True])
@pytest.mark.parametrize("n", [0, 2])
def test_completion_refuses_n_other_than_one(n, stream):
state = FakeState([UserReply(uid=42, incremental_output="hello", finished=True)])
response = run(
handle_completion(
CompletionRequest(model="client-model", prompt="say hi", n=n, stream=stream),
request=None,
state=state,
model_sampling={},
)
)

assert response.status_code == 400
assert json.loads(response.body)["error"]["param"] == "n"
assert state.sent is None


def test_completion_accepts_text_prompt():
state = FakeState(
[UserReply(uid=42, incremental_output="hello", finished=True, prompt_tokens_delta=2, completion_tokens_delta=1)]
Expand Down
Loading