Completions
POST /v1/completions continues one prompt, or several prompts, with a Base model. It follows OpenAI's completions API, so the openai SDK calls it with client.completions.create(...). Sample continuations shows the tasks, and the API reference has the schema of every field.
Request fields
prompt is required. Apart from model and max_tokens, a field that you leave out, or sets to null, gets OpenAI's default, or the value that turns a vLLM field off. The model's own generation_config.json never sets a default.
A field marked vLLM comes from vLLM, the engine that runs the Base models in Inference, and is not in OpenAI's API. A field marked vllm-lens comes from vllm-lens, the vLLM plugin that reads and changes the residual stream. The openai SDK sends both kinds only in extra_body (Send vLLM's fields).
What to continue
| Field | Default | What it does |
|---|---|---|
model | the default model | The id of a model from GET /v1/models, such as llama-8b. Left out, the model that the list marks default. |
prompt | required | A text, a list of token ids, or a list of several texts or several token-id lists. |
max_tokens | the context left | The most tokens to write for each choice. The rules are under this table. |
n | 1 | The number of choices to write for each prompt. |
stop | none | A text, or a list of at most 4 texts. The model stops before it writes one of them. |
echo | false | Put the prompt in front of the generated text. |
add_special_tokens | true | vLLM. Add the model's special tokens, such as BOS, to a text prompt. Inference adds none to token ids. |
The rules of max_tokens:
- Left out or
null, it is the model'smax_model_lenless the prompt's tokens as the Hold counts them. It is at least 1 and at most 32,000, and at most 15,600 withoutstream. - A request with more than one prompt, or with
nabove 1, must set it. - A request writes at most 32,000 tokens in all: the prompts ×
n×max_tokens(Size caps). - Without
stream, a value above 15,600 gets 400deadline_infeasible. Inference cannot write more within the API's 14-minute wait (Requests without a stream). - The prompt and
max_tokenstogether must fit the model'smax_model_len(Prompt too long). - Near the end of your tokens, the API lowers it to what your Budget can hold. The header
X-Acs-Max-Tokens-Clampedthen says so (Near the end of your tokens). - In a Job's request and in a Loom Branch, it is 16 when you leave it out.
How to sample
| Field | Default | What it does |
|---|---|---|
temperature | 1 | Divide the scores of the tokens by this number before sampling, from 0 to 2. 0 takes the likeliest token each time. |
top_p | 1 | Sample only from the likeliest tokens whose probabilities add up to top_p. More than 0 and at most 1. |
top_k | 0 | vLLM. Sample only from the top_k likeliest tokens. 0 or -1 turns the filter off. |
min_p | 0 | vLLM. Leave out the tokens less likely than min_p times the likeliest token, from 0 to 1. 0 turns the filter off. |
presence_penalty | 0 | Make a token that is already in the generated text less likely, or more likely for a negative number, from -2 to 2. |
frequency_penalty | 0 | As presence_penalty, but more for each time that the token is already in the generated text, from -2 to 2. |
repetition_penalty | 1 | vLLM. Make the tokens of the prompt and the generated text less likely by this factor, more than 0. 1 turns the penalty off. |
seed | none | Sample with this seed, 0 or more. |
At temperature 0, or with the same seed, the same request on the same model gets the same tokens and log probabilities again, with one exception. vLLM batches your request with other requests. The batch can change a log probability by a little, and now and then a token where two tokens are almost equally likely.
What to return
| Field | Default | What it does |
|---|---|---|
logprobs | none | Return the log probability of each generated token, and of the logprobs likeliest tokens at its position. 0 to 100. |
prompt_logprobs | none | vLLM. Return the log probability of each prompt token, and of the likeliest tokens at its position. 0 to 100, or -1 for the whole vocabulary of one prompt. Not with stream. |
stream | false | Send the Completion as Server-Sent Events. |
stream_options | none | Only with stream. {"include_usage": true} adds a last chunk with the usage of the request. With "continuous_usage_stats": true (vLLM), each chunk has the usage of its choice so far, with or without include_usage. |
output_residual_stream | none | vllm-lens. Return the Activations at these Layers, or true for every Layer. false returns none. Only for one prompt and an n of 1. |
apply_steering_vectors | none | vllm-lens. Add these Steering vectors to the residual stream. Only for one prompt and an n of 1. |
Read token probabilities, Read Activations, and Steer a Completion show these fields in use.
Other fields
| Field | Default | What it does |
|---|---|---|
priority | 0 | vLLM. 0 or more. A request with a lower number runs first. Requests with the same number wait in the order that they arrived. null is 0. A text of digits, such as "5", and true or false count as their number. |
user | none | OpenAI's id for the person who asked. Inference gets it and does nothing with it. |
Strict validation
The API checks the type of every field before the request reaches Inference, and it refuses what it does not know. A wrong value never falls back to a default (Why the API is strict).
- A field that the API does not know gets 400 with the code
invalid_request(Unknown field). - A value of the wrong type gets 400, with
paramset to the field. A number in a string, such as"2", is not a number, except forpriority.1and"true"are not booleans. A whole number such as1is valid for a decimal field such astemperature. - The API checks the ranges of
logprobs,prompt_logprobs,seed,priority, and the sampling fields in How to sample. It also checks the shape of the Activations and Steering vector fields, and the size caps. - The API refuses
nabove 1 at atemperaturebelow 0.00001, where Inference picks the likeliest token each time. - The API refuses
stream_optionswithoutstream: true, andprompt_logprobswithstream: true. - Inference checks the other values, for example that each token id of a prompt is in the model's vocabulary. The API passes on Inference's 400, with Inference's message and
param.
This request sends max_tokens as a string, so the API refuses it:
curl "$ACS_API_BASE/completions" \
-H "Authorization: Bearer $ACS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "llama-8b", "prompt": "The sky is", "max_tokens": "2"}'{
"error": {
"message": "Invalid type for 'max_tokens': expected a number.",
"type": "invalid_request_error",
"param": "max_tokens",
"code": "invalid_request"
},
"request_id": "req_9f2c4e1a7b3d4c5e8f6a0b1c2d3e4f5a"
}Size caps
Each cap keeps one request from using too much memory in the API or in Inference. A request over a cap gets 400 invalid_request_error, with param set to the field, and does not reach Inference. The caps count a prompt's tokens as the Hold counts them, with the model's tokenizer.
| Cap | Field | Why |
|---|---|---|
The prompts × n is at most 128 | n | OpenAI's limit on n. |
The prompts × n × max_tokens is at most 32,000, and a max_tokens of 0 counts as 1 | max_tokens | The Hold of a request is then at most its prompt and 32,000 tokens. |
At most 4 stop texts | stop | OpenAI's limit. |
prompt_logprobs: -1 takes at most 256 prompt tokens in all × n, or 16 with output_residual_stream | prompt_logprobs | Each prompt token then has a log probability for each token of the vocabulary (128,256 for meta-llama/Llama-3.1-8B). Inference holds them all in memory. |
At most 33,554,432 (2^25) top log probabilities of the prompt. Each prompt token × n has k + 1 for prompt_logprobs k, and k + 1 more for logprobs k with echo. | prompt_logprobs or logprobs | Inference holds each one in memory, and the answer carries each one. |
Layers × tokens × the model's hidden size is at most 33,554,432 (2^25) for one capture. The tokens are the prompt's and max_tokens. | output_residual_stream | The API reads the Activations of a capture as one text. |
At most 8 Steering vectors, and 2,097,152 (2^21) numbers in all of them. A vector with position_spans counts once for each position of its spans. | apply_steering_vectors | The API sends the numbers to Inference as float32: at most 8 MiB. |
llama-8b has a hidden size of 4,096, so one capture is at most 8,192 Layers × tokens. That is all 32 Layers for 256 tokens, or 1 Layer for 8,192 tokens.
The whole request body is at most 8 MiB on every route, and a larger body gets 413 (Status codes). The body can cap the Steering vectors first: in JSON, 8 MiB holds about 699,000 numbers of 12 characters each. Encoded Steering vectors take about a tenth of those bytes, so eight vectors over all 32 Layers of meta-llama/Llama-3.1-8B fit.
This request asks for 2 choices of 16,001 tokens, which is 32,002 tokens in all:
curl "$ACS_API_BASE/completions" \
-H "Authorization: Bearer $ACS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "llama-8b", "prompt": "The sky is", "max_tokens": 16001, "n": 2}'{
"error": {
"message": "At most 32000 generated tokens in all: n = 2 times max_tokens = 16001 for each of 1 prompts is 32002.",
"type": "invalid_request_error",
"param": "max_tokens",
"code": "invalid_request"
},
"request_id": "req_9f2c4e1a7b3d4c5e8f6a0b1c2d3e4f5a"
}Response fields
The Quickstart shows a whole Completion.
| Field | What it is |
|---|---|
id | The id of the Completion, from Inference. |
object | Always "text_completion". |
created | When Inference made the Completion, in Unix seconds. |
model | The model that wrote it. |
choices | One choice for each prompt and each of its n samples, in the order of their index. |
usage | The prompt_tokens, completion_tokens, and total_tokens of the whole request. prompt_tokens counts each prompt once, whatever n is. |
activations | The Activations, only when the request has output_residual_stream. |
Each choice has these fields:
| Field | What it is |
|---|---|
index | p * n + i for choice i of prompt p. |
text | The generated text. With echo, the prompt comes first. |
logprobs | null, or the lists that logprobs asks for. |
finish_reason | "length" when the choice reached max_tokens or the model's context length. "stop" when the model wrote its end-of-text token or a stop text. Inference can add other reasons. |
stop_reason | The stop text that ended the choice, or null. With finish_reason "stop", null means that the model wrote its end-of-text token. |
prompt_logprobs | null, or the list that prompt_logprobs asks for, with null for the first prompt token. |
In a stream, each data: event is a chunk with the same id, object, created, and model. Its choices has the next text of one choice, with finish_reason and stop_reason null until the last chunk of that choice. With include_usage, a last chunk has "choices": [] and the usage of the whole request. The Activations come in a last chunk of their own, and data: [DONE] ends the stream. Every 5 seconds the stream also has a : keepalive comment line, which SSE clients skip (Requests with a stream).
Not in the API
The API does not take these fields and routes of OpenAI's API:
best_of. vLLM accepts it and ignores it, so the API refuses it as an unknown field.nreturns each choice instead.suffix. vLLM supports it only for models that fill in the middle of a text.logit_bias.- Chat. The API applies no chat template (No chat template).
POST /v1/chat/completionsgets 400invalid_request_errorwith the messageThis API serves Base models, which have no chat format: send POST /v1/completions with a prompt instead of POST /v1/chat/completions with messages.
Work in the background
How the API runs Jobs, harvests, Loom Nodes, and Playground Runs without a client, in what order, and what happens when it restarts.
Models
The Base models that the API serves, the fields and limits of each one, and the route that says whether a model is Warm or how far its start has got.