This file documents the Ollama-compatible surface that exists today.
| Method | Path | Current behavior |
|---|---|---|
| POST | /api/generate |
Ollama-style generate; streaming returns NDJSON chunks |
| POST | /api/chat |
Ollama-style chat; streaming returns NDJSON chunks |
| POST | /api/embed |
Current Ollama embedding format |
| POST | /api/embeddings |
Legacy embedding format |
| GET | /api/tags |
Lists locally available models in Ollama format |
| GET | /api/ps |
Running models |
| POST | /api/show |
Real registry-backed model metadata |
| GET | /api/version |
Returns 0.2.0-npu-proxy |
| POST | /api/pull |
Download model files from Hugging Face |
| GET | /api/search |
NPU Proxy extension |
| GET | /api/models/known |
NPU Proxy extension |
Not implemented in this repository:
DELETE /api/deletePOST /api/copyPOST /api/create
- The successful live NPU certification run in this repository exercised
POST /api/generate. /api/chatremains implemented and now uses the shared chat-template rendering path, falling back to the legacy role-prefixed formatter only when tokenizer templates are unavailable or disabled.GET /api/tagsreturns locally available registry/scanned models withmodels[].name,model,modified_at,size,digest, anddetails.POST /api/shownow returns real model metadata:modelfile,parameters,template,details, andmodel_infofrom the registry/tokenizer path.- The Ollama embedding endpoints are implemented and
all-minilmvalidated on NPU here via a static-shape profile, butbge-smallon NPU still failed workstation validation when the Intel NPU plugin raisedcheck_sdpa_nodes(model).
/api/generate, /api/chat, and /api/pull stream newline-delimited JSON chunks.
Current implementation detail:
- media type:
application/x-ndjson - the final success frame for
/api/generateand/api/chatincludesdone: trueanddone_reason done_reasonis eitherstoporlength;lengthmeans generation reached the effective max output token limit- stream failures emit a terminal NDJSON error object and stop without a final
done: truesuccess frame
This is different from the OpenAI chat endpoint, which uses SSE.
/api/generate and /api/chat currently expose advisory routing semantics that are narrower than multi-engine execution.
- the router can classify a request toward a preferred or fallback device
- the current runtime still behaves as a single active engine for real execution
X-NPU-Proxy-Devicereports the actual configured/loaded singleton runtime deviceX-NPU-Proxy-Route-Reasonis currentlysingle_engine_runtime, whileX-NPU-Proxy-Token-Countstill exposes the advisory token-count classification input
The server merges incoming Ollama options with these current defaults:
| Parameter | Default |
|---|---|
temperature |
0.8 |
top_k |
40 |
top_p |
0.9 |
repeat_penalty |
1.1 |
num_predict |
128 |
num_ctx |
2048 |
num_batch |
512 |
seed |
0 |
stop |
[] |
mirostat |
0 |
mirostat_tau |
5.0 |
mirostat_eta |
0.1 |
min_p |
0.0 |
typical_p |
1.0 |
tfs_z |
1.0 |
| Incoming parameter | Current handling |
|---|---|
temperature |
passed through |
top_k |
passed through |
top_p |
passed through |
seed |
passed through |
repeat_penalty |
renamed to repetition_penalty |
num_predict |
renamed to max_new_tokens |
stop |
renamed to stop_strings |
presence_penalty and frequency_penalty are combined into:
repetition_penalty = 1.0 + (presence_penalty + frequency_penalty) / 2
If repeat_penalty is explicitly provided, it wins.
Logged at debug level and dropped:
mirostatmirostat_taumirostat_etamin_ptypical_ptfs_z
Silently ignored:
num_ctxnum_batch
Unknown parameters are warned about and ignored.
Non-streaming POST /api/generate returns a single object with done: true and done_reason:
{
"model": "tinyllama-1.1b-chat-int4-ov",
"created_at": "2025-01-01T00:00:00Z",
"response": "Hello!",
"done": true,
"total_duration": 1000000,
"eval_count": 1,
"done_reason": "stop"
}Non-streaming POST /api/chat has the same final fields, with generated content under message:
{
"model": "tinyllama-1.1b-chat-int4-ov",
"created_at": "2025-01-01T00:00:00Z",
"message": {"role": "assistant", "content": "Hello!"},
"done": true,
"total_duration": 1000000,
"eval_count": 1,
"done_reason": "stop"
}For streaming, done_reason appears on the final NDJSON success frame alongside done: true.
POST /api/embed and POST /api/embeddings validate input before loading the engine:
| Condition | HTTP status | code |
Message |
|---|---|---|---|
| Empty input list | 400 | empty_input |
Embedding input must contain at least one item |
| Batch larger than 128 | 413 | embedding_batch_too_large |
Embedding input batch is too large |
| Empty or whitespace-only text | 400 | empty_input |
Embedding input text must not be empty |
| Single text over 8192 characters | 413 | embedding_input_too_large |
Embedding input text is too large |
| Request total over 65536 characters | 413 | embedding_request_too_large |
Embedding request is too large |
Responses include X-Request-ID. Ollama error responses use the flat envelope returned by the implementation:
{
"error": "Embedding input text must not be empty (request id: req-abc123)",
"code": "empty_input"
}These paths work with built-in registry IDs and scanned local model IDs, such as:
tinyllama-1.1b-chat-int4-ovphi-2-int4-ovmistral-7b-int4-ov
/api/pull and /api/models/known understand short aliases such as:
tinyllamaphi-3llama3.2mistralbge-smallall-minilm
Alias resolution and download support do not imply that a model path is validated on Intel NPU hardware.
The currently validated NPU embedding alias on this workstation is all-minilm.
POST /api/pull now supports both public and private Hugging Face repos:
- public repos: no token required
- private repos: require an explicit Hugging Face token
The API does not silently inherit ambient server-side Hugging Face credentials for user-selected pulls. Private pulls must provide a token in exactly one of these places:
- request body field:
huggingface_token Authorization: Bearer <token>header
If a cached model was originally pulled with explicit private auth, anonymous callers do not get a cached success response for that repo.
$env:OLLAMA_HOST = "http://127.0.0.1:8080"
ollama pull tinyllama
ollama run tinyllama "Hello"
ollama psimport ollama
client = ollama.Client(host="http://127.0.0.1:8080")
response = client.chat(
model="tinyllama",
messages=[{"role": "user", "content": "Hello!"}],
)curl http://127.0.0.1:8080/api/chat -d '{
"model": "tinyllama-1.1b-chat-int4-ov",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": false
}'curl -X POST http://127.0.0.1:8080/api/pull \
-H "Content-Type: application/json" \
-H "Authorization: Bearer hf_xxx" \
-d '{"name": "your-org/private-model", "stream": false}'Use the CLI log-level flag for debugging:
npu-proxy --host 127.0.0.1 --port 8080 --log-level debugThese routes are repository-specific extensions, not standard Ollama API endpoints:
/api/search/api/models/known
/api/search supports:
qsort=popular|newest|downloads|likeslimitoffsettype=all|llm|embedding|visionquantizationmin_downloads
The vision filter is part of the search API surface only; this document does not claim vision serving support.