pi-lemonade-link 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/llamacpp.md CHANGED
@@ -1,40 +1,37 @@
1
1
  # llama.cpp-Specific API
2
2
 
3
- This page documents Lemonade's llama.cpp-specific compatibility surface.
4
-
5
- ## Summary
3
+ This page documents Lemonade's llama.cpp-specific compatibility surface. Lemonade forwards each of these requests to a llama.cpp server: rerank to the model it names, and slots and tokenize, which name no model, to the most recently used loaded model.
6
4
 
5
+ <!-- BEGIN GENERATED: llamacpp.summary -->
7
6
  | Method | Endpoint | Description | Modality |
8
7
  |--------|----------|-------------|----------|
9
- | `POST` | [`/v1/rerank`](#post-v1rerank) | Reranking | query + documents -> relevance-scored documents |
10
- | `GET` | [`/v1/slots`](#get-v1slots) | Returns the current slots processing state | slots state |
11
- | `POST` | [`/v1/slots/{id}?action=save`](#post-v1slotsidactionsave) | Save the prompt cache of the specified slot to a file | prompt cache |
12
- | `POST` | [`/v1/slots/{id}?action=restore`](#post-v1slotsidactionrestore) | Restore the prompt cache of the specified slot from a file | prompt cache |
13
- | `POST` | [`/v1/slots/{id}?action=erase`](#post-v1slotsidactionerase) | Erase the prompt cache of the specified slot | prompt cache |
14
- | `POST` | [`/v1/tokenize`](#post-v1tokenize) | Tokenize a given text | tokenization |
15
-
8
+ | `POST` | [`/v1/rerank`](#post-v1rerank) | Score documents against a query | query + documents -> relevance-scored documents |
9
+ | `POST` | [`/v1/systemone`](#post-v1systemone) | Answer typed questions about content with a decision model | state + questions -> one answer per question |
10
+ | `GET` | [`/v1/slots`](#get-v1slots) | Read each slot's processing state | slots state |
11
+ | `POST` | [`/v1/slots/{id}?action=save`](#post-v1slotsid) | Save the prompt cache of the specified slot to a file | prompt cache |
12
+ | `POST` | [`/v1/slots/{id}?action=restore`](#post-v1slotsid) | Restore the prompt cache of the specified slot from a file | prompt cache |
13
+ | `POST` | [`/v1/slots/{id}?action=erase`](#post-v1slotsid) | Erase the prompt cache of the specified slot | prompt cache |
14
+ | `POST` | [`/v1/tokenize`](#post-v1tokenize) | Tokenize text | tokenization |
15
+ <!-- END GENERATED: llamacpp.summary -->
16
+
17
+ <!-- BEGIN GENERATED: llamacpp.rerank -->
16
18
  ## `POST /v1/rerank`
17
19
  <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
18
20
 
19
- Reranking API for llama.cpp-compatible reranker models. You provide a query and a list of documents, and receive relevance scores for each document. Lemonade will load the requested model automatically if it is not already loaded.
20
-
21
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/v1/rerank` endpoint.
22
-
23
- > **Note:** Lemonade also accepts `/reranking` and `/reranker` as aliases — all three route to the same handler and behave identically.
24
-
25
- > **Note:** The endpoint is available under all four path prefixes: `/api/v0/`, `/api/v1/`, `/v0/`, and `/v1/`.
21
+ Scores each document against a query. Only llama.cpp reranker models, such as `bge-reranker-v2-m3-GGUF`, serve this endpoint.
26
22
 
27
- > **Note:** This endpoint is only available for reranker-specific models using the `llamacpp` recipe, such as `bge-reranker-v2-m3-GGUF`.
23
+ Also served at `/v1/reranking` and `/v1/reranker`. Requires `LEMONADE_API_KEY` when it is set.
28
24
 
29
25
  ### Parameters
30
26
 
31
27
  | Parameter | Required | Description | Status |
32
28
  |-----------|----------|-------------|--------|
33
29
  | `query` | Yes | The search query text. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
34
- | `documents` | Yes | Array of document strings to score against the query. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
35
- | `model` | Yes | The reranking model to use. If not already loaded, Lemonade loads it before forwarding the request. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
30
+ | `documents` | Yes | Documents to score against the query. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
31
+ | `model` | Yes | The model to run; loaded on first use. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
32
+ | `ctx_size` | No | Lemonade extension: context size to load the model with, when this request loads it. Ignored when the model is already loaded. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
36
33
 
37
- ### Example request
34
+ ### Example
38
35
 
39
36
  === "PowerShell"
40
37
 
@@ -44,231 +41,399 @@ Reranking API for llama.cpp-compatible reranker models. You provide a query and
44
41
  -Method POST `
45
42
  -Headers @{ "Content-Type" = "application/json" } `
46
43
  -Body '{
47
- "model": "bge-reranker-v2-m3-GGUF",
48
- "query": "What is the capital of France?",
49
- "documents": [
50
- "Paris is the capital of France.",
51
- "Berlin is the capital of Germany.",
52
- "Madrid is the capital of Spain."
53
- ]
54
- }' -UseBasicParsing
44
+ "model": "bge-reranker-v2-m3-GGUF",
45
+ "query": "What is the capital of France?",
46
+ "documents": [
47
+ "Paris is the capital of France.",
48
+ "Berlin is the capital of Germany.",
49
+ "Madrid is the capital of Spain."
50
+ ]
51
+ }'
55
52
  ```
56
53
 
57
54
  === "Bash"
58
55
 
59
56
  ```bash
60
- curl -X POST http://localhost:13305/v1/rerank \
57
+ curl http://localhost:13305/v1/rerank \
61
58
  -H "Content-Type: application/json" \
62
59
  -d '{
63
- "model": "bge-reranker-v2-m3-GGUF",
64
- "query": "What is the capital of France?",
65
- "documents": [
66
- "Paris is the capital of France.",
67
- "Berlin is the capital of Germany.",
68
- "Madrid is the capital of Spain."
69
- ]
70
- }'
60
+ "model": "bge-reranker-v2-m3-GGUF",
61
+ "query": "What is the capital of France?",
62
+ "documents": [
63
+ "Paris is the capital of France.",
64
+ "Berlin is the capital of Germany.",
65
+ "Madrid is the capital of Spain."
66
+ ]
67
+ }'
71
68
  ```
72
69
 
73
- ### Response format
70
+ **Response:** `200 OK`
74
71
 
75
72
  ```json
76
73
  {
77
74
  "model": "bge-reranker-v2-m3-GGUF",
78
75
  "object": "list",
79
- "results": [
80
- {
81
- "index": 0,
82
- "relevance_score": 8.60673713684082
83
- },
84
- {
85
- "index": 1,
86
- "relevance_score": -5.3886260986328125
87
- },
88
- {
89
- "index": 2,
90
- "relevance_score": -3.555561065673828
91
- }
92
- ],
93
- "usage": {
94
- "prompt_tokens": 51,
95
- "total_tokens": 51
96
- }
76
+ "results": [{"index": 0, "relevance_score": 8.625761032104492}, ... 2 more],
77
+ "usage": {"prompt_tokens": 51, "total_tokens": 51}
97
78
  }
98
79
  ```
99
80
 
100
- **Field Descriptions:**
81
+ ### Response format
101
82
 
102
- - `model` - Model identifier used for reranking
103
- - `object` - Type of response object, always `"list"`
104
- - `results` - Array of all input documents with relevance scores
105
- - `index` - Original index of the document in the input array
106
- - `relevance_score` - Relevance score assigned by the model; higher means more relevant
107
- - `usage` - Token usage statistics
108
- - `prompt_tokens` - Number of tokens in the input
109
- - `total_tokens` - Total tokens processed
83
+ - `model` - The model that scored the documents.
84
+ - `object` - Always `"list"`.
85
+ - `results` - Every input document with its score, sorted by `relevance_score`, highest first.
86
+ - `index` - The document's position in `documents`.
87
+ - `relevance_score` - How relevant the model rates the document; higher is more relevant.
88
+ - `usage` - Tokens processed.
89
+ - `prompt_tokens` - Tokens in the query and documents.
90
+ - `total_tokens` - All tokens processed.
91
+
92
+ ### Errors
93
+
94
+ | Status | Code | When |
95
+ |--------|------|------|
96
+ | `400` | `invalid_json` | The body is not a JSON object |
97
+ | `400` | `missing_argument` | A required argument is missing |
98
+ | `400` | `invalid_argument` | An argument or a value nested in it has the wrong JSON type, or a value its schema does not list |
99
+ | `400` | | `model` is not a llama.cpp model |
100
+ | `400` | `model_load_refused` | The backend refuses the requested model as it is registered, before it starts anything, such as a decision model whose GGUF type the bundled llama.cpp does not support |
101
+ | `404` | `model_not_supported` | The requested model is filtered out on this system, such as an NPU model without an NPU |
102
+ | `404` | `model_not_found` | The requested model is not in the registry |
103
+ | `409` | `router_residency_conflict` | Loading the requested model would evict a model that a `collection.router` model needs resident on the same NPU |
104
+ | `409` | `slots_pinned_error` | Every loaded model of the requested model's type is pinned, so none can be unloaded to make room |
105
+ | `500` | | The backend reports an error; the backend's own status replaces this one when it sends one |
106
+ | `500` | | The request fails unexpectedly |
107
+ | `500` | `model_load_error` | Loading the requested model fails for another reason, such as a failed download or a backend that does not start |
108
+ <!-- END GENERATED: llamacpp.rerank -->
109
+
110
+ <!-- BEGIN GENERATED: llamacpp.systemone -->
111
+ ## `POST /v1/systemone`
112
+ <sub>![Status](https://img.shields.io/badge/status-experimental-orange)</sub>
113
+
114
+ Asks a decision model typed questions about one piece of content and returns one answer per question, without generating tokens. lemond forwards the request to the backend unchanged, including the order of each question's options: `llama-server` builds the prompt from the template in the GGUF, and FastFlowLM serves its d3 models on the NPU with `flm serve --decision`. Only `llamacpp` and `flm` models labelled `classification` and `systemone`, such as `Laya-GGUF` or `d3-lite-FLM`, serve this endpoint.
115
+
116
+ Requires `LEMONADE_API_KEY` when it is set.
110
117
 
111
- > **Note:** Results are returned in input order. To rank documents by relevance, sort `results` by `relevance_score` in descending order on the client side.
118
+ ### Parameters
112
119
 
113
- ## `GET /v1/slots`
114
- <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
120
+ | Parameter | Required | Description | Status |
121
+ |-----------|----------|-------------|--------|
122
+ | `model` | No | The classification model. Optional when exactly one classification model is loaded; that model is used. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
123
+ | `state` | Yes | The content to judge. A value that is not a string reaches the model as JSON text. `null` asks about the images only; the backend refuses it for decision types that need text. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
124
+ | `questions` | Yes | Maps each question id to a question, which the model answers independently of the others. A question has a `type` (`choice`, `score` or `noul`), `instructions`, and `criteria`: for `choice`, an object that maps each option to a description or `null`; for `score`, an array of 2 to 10 levels, lowest first; for `noul`, optional `true` and `false` descriptions. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
125
+ | `images` | No | Data URLs of images to judge with the state. A `llamacpp` model must load with an `mmproj` file, and `llama-server` decides which decision types read images. FLM's d3 models read images without one. | <sub>![Status](https://img.shields.io/badge/partial-yellow)</sub> |
126
+ | `ctx_size` | No | Lemonade extension: context size to load the model with, when this request loads it. Ignored when the model is already loaded. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
115
127
 
116
- Returns the current state of all processing slots in the llama.cpp server. Slots are parallel processing contexts that can handle multiple requests concurrently.
128
+ ### Cuts
117
129
 
118
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/slots` endpoint.
130
+ lemond adds `truncated` to each answer. A `laya` model (Laya, Julia-1) cuts a long option or a long question without saying so, so lemond refuses such a question with 400 instead.
119
131
 
120
- > **Note:** This endpoint is only available when a llama.cpp model is loaded.
132
+ ### Answer Quality
121
133
 
122
- > **Note:** This endpoint supports all four path prefixes: `/api/v0/slots`, `/api/v1/slots`, `/v0/slots`, and `/v1/slots`.
134
+ Answers depend on the model, on the wording of each question, and on the order of a `choice` question's options. Test a question with the model that serves it before a router policy relies on its scores.
123
135
 
124
- ### Parameters
136
+ ### Images
125
137
 
126
- This endpoint accepts no parameters.
138
+ Register the model with its projector file, for example on `/v1/pull`: `{"model_name": "user.my-decider", "checkpoint": "<repo>:<variant>", "mmproj": "<mmproj file>.gguf", "recipe": "llamacpp", "labels": ["classification", "systemone"]}`. Then send `images` as data URLs (`data:image/png;base64,...`), with or without a `state`.
127
139
 
128
- ### Example request
140
+ ### Example
129
141
 
130
142
  === "PowerShell"
131
143
 
132
144
  ```powershell
133
145
  Invoke-WebRequest `
134
- -Uri "http://localhost:13305/v1/slots" `
135
- -Method GET -UseBasicParsing
146
+ -Uri "http://localhost:13305/v1/systemone" `
147
+ -Method POST `
148
+ -Headers @{ "Content-Type" = "application/json" } `
149
+ -Body '{
150
+ "model": "Laya-GGUF",
151
+ "state": "Customer message: I was charged twice for my order last week and nobody has replied.",
152
+ "questions": {
153
+ "route": {
154
+ "type": "choice",
155
+ "instructions": "Which team should handle this?",
156
+ "criteria": {"billing": null, "shipping": null, "technical": null}
157
+ },
158
+ "angry": {"type": "noul", "instructions": "Is the customer angry?"},
159
+ "urgency": {
160
+ "type": "score",
161
+ "instructions": "How urgent is this?",
162
+ "criteria": ["can wait", "this week", "today", "right now"]
163
+ }
164
+ }
165
+ }'
136
166
  ```
137
167
 
138
168
  === "Bash"
139
169
 
140
170
  ```bash
141
- curl http://localhost:13305/v1/slots
171
+ curl http://localhost:13305/v1/systemone \
172
+ -H "Content-Type: application/json" \
173
+ -d '{
174
+ "model": "Laya-GGUF",
175
+ "state": "Customer message: I was charged twice for my order last week and nobody has replied.",
176
+ "questions": {
177
+ "route": {
178
+ "type": "choice",
179
+ "instructions": "Which team should handle this?",
180
+ "criteria": {"billing": null, "shipping": null, "technical": null}
181
+ },
182
+ "angry": {"type": "noul", "instructions": "Is the customer angry?"},
183
+ "urgency": {
184
+ "type": "score",
185
+ "instructions": "How urgent is this?",
186
+ "criteria": ["can wait", "this week", "today", "right now"]
187
+ }
188
+ }
189
+ }'
142
190
  ```
143
191
 
192
+ **Response:** `200 OK`
193
+
194
+ ```json
195
+ {
196
+ "model": "Laya-GGUF",
197
+ "answers": {
198
+ "route": {
199
+ "type": "choice",
200
+ "choice": "billing",
201
+ "probabilities": {"billing": 0.9912025457133901, ... 2 more},
202
+ "confidence": 0.9868038185700849,
203
+ "truncated": false
204
+ },
205
+ ... 2 more
206
+ },
207
+ "usage": {"input_tokens": 136, "output_tokens": 0}
208
+ }
209
+ ```
210
+
144
211
  ### Response format
145
212
 
213
+ - `model` - The model that answered.
214
+ - `answers` - One answer for each question, keyed by question id.
215
+ - One question's answer. Its fields depend on the question's `type`.
216
+ - `type` - The question's type.
217
+ - `choice` - `choice` questions: the most likely option.
218
+ - `score` - `score` questions: the expected level index, from `0` to the number of levels minus one.
219
+ - `legend` - `score` questions: each level's text, keyed by level index.
220
+ - The level's text.
221
+ - `probabilities` - `choice` and `score` questions: the probability of each option, keyed by option for `choice` and by level index for `score`. The probabilities sum to `1`.
222
+ - The probability, in `[0, 1]`.
223
+ - `confidence` - `choice` and `score` questions: how clearly the model prefers its answer; `0` when every option is equally likely.
224
+ - `noul` - `noul` questions: the probability that the answer is `true`.
225
+ - `truncated` - Added by Lemonade. `false` when the decision type refuses a `state` that does not fit instead of cutting it. Absent when it can cut the `state` without saying so (`lfm2-d1-omni`; `h2o-lightning` with a `state` over 32,000 bytes), so absence means unknown.
226
+ - `error` - FastFlowLM: `max_length_exceeded` when this question does not fit in the model's context, so the answer has no scores. The other questions are still answered; when every question is refused, the status is 400 `context_length_exceeded` instead.
227
+ - `message` - With `error`: why the question was refused, with its token count and the context size.
228
+ - `usage` - Tokens processed.
229
+ - `input_tokens` - Prompt tokens across all questions.
230
+ - `output_tokens` - Always `0`, because the model generates no tokens.
231
+
232
+ ### Errors
233
+
234
+ | Status | Code | When |
235
+ |--------|------|------|
236
+ | `400` | `invalid_json` | The body is not a JSON object |
237
+ | `400` | `missing_argument` | A required argument is missing |
238
+ | `400` | `invalid_argument` | An argument or a value nested in it has the wrong JSON type, or a value its schema does not list |
239
+ | `400` | | `model` is omitted and not exactly one classification model is loaded |
240
+ | `400` | | `model` lacks the `classification` or `systemone` label, or its backend does not answer SystemOne questions; checked before it loads |
241
+ | `400` | | The backend rejects a question, such as a `score` question with one level; the backend's status replaces this one |
242
+ | `400` | | A `laya` model (Laya, Julia-1) would cut an option or the question; `llama-server` cuts them without saying so |
243
+ | `400` | `context_length_exceeded` | `state` and a question do not fit in the model's context. FastFlowLM refuses only the questions that do not fit: while another question fits, the status is 200 and each refused answer carries `"error": "max_length_exceeded"` |
244
+ | `400` | `model_load_refused` | The backend refuses the requested model as it is registered, before it starts anything, such as a decision model whose GGUF type the bundled llama.cpp does not support |
245
+ | `404` | | The model is unloaded while the request waits for it |
246
+ | `404` | `model_not_supported` | The requested model is filtered out on this system, such as an NPU model without an NPU |
247
+ | `404` | `model_not_found` | The requested model is not in the registry |
248
+ | `409` | `router_residency_conflict` | Loading the requested model would evict a model that a `collection.router` model needs resident on the same NPU |
249
+ | `409` | `slots_pinned_error` | Every loaded model of the requested model's type is pinned, so none can be unloaded to make room |
250
+ | `500` | | The backend reports an error; the backend's own status replaces this one when it sends one |
251
+ | `500` | | The request fails unexpectedly |
252
+ | `500` | `model_load_error` | Loading the requested model fails for another reason, such as a failed download or a backend that does not start |
253
+ | `501` | | `images` is sent to a model that reads no images, or that loaded without `mmproj` |
254
+ <!-- END GENERATED: llamacpp.systemone -->
255
+
256
+ <!-- BEGIN GENERATED: llamacpp.slots -->
257
+ ## `GET /v1/slots`
258
+ <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
259
+
260
+ Returns the state of each processing slot in the llama.cpp server. Slots are the parallel contexts that serve concurrent requests.
261
+
262
+ Requires `LEMONADE_API_KEY` when it is set.
263
+
264
+ ### Parameters
265
+
266
+ This endpoint does not take any parameters.
267
+
268
+ ### Example
269
+
270
+ === "PowerShell"
271
+
272
+ ```powershell
273
+ Invoke-WebRequest -Uri "http://localhost:13305/v1/slots"
274
+ ```
275
+
276
+ === "Bash"
277
+
278
+ ```bash
279
+ curl http://localhost:13305/v1/slots
280
+ ```
281
+
282
+ **Response:** `200 OK`
283
+
146
284
  ```json
147
285
  [
148
286
  {
149
287
  "id": 0,
150
- "state": "idle",
151
- "next_token": {
152
- "has_next_token": false,
153
- "n_remain": 0,
154
- "n_decoded": 0
155
- },
156
- "task_id": -1,
157
- "cache_tokens": 1024
158
- },
159
- {
160
- "id": 1,
161
- "state": "processing",
162
- "next_token": {
163
- "has_next_token": true,
164
- "n_remain": 42,
165
- "n_decoded": 15
288
+ "next_token": [
289
+ {"has_next_token": false, "has_new_line": false, "n_remain": -1, "n_decoded": 0}
290
+ ],
291
+ "id_task": 355,
292
+ "n_ctx": 40960,
293
+ "is_processing": false,
294
+ "n_prompt_tokens": 267,
295
+ "n_prompt_tokens_cache": 0,
296
+ "n_prompt_tokens_processed": 0,
297
+ "params": {
298
+ "adaptive_decay": 0.8999999761581421,
299
+ "adaptive_target": -1.0,
300
+ "backend_sampling": false,
301
+ "chat_format": "peg-native",
302
+ "dry_allowed_length": 2,
303
+ "dry_base": 1.75,
304
+ "dry_multiplier": 0.0,
305
+ "dry_penalty_last_n": 64,
306
+ "dynatemp_exponent": 1.0,
307
+ "dynatemp_range": 0.0,
308
+ "frequency_penalty": 0.0,
309
+ "generation_prompt": "<|im_start|>assistant\n",
310
+ "ignore_eos": false,
311
+ "lora": [],
312
+ "max_tokens": -1,
313
+ "min_keep": 0,
314
+ "min_p": 0.0,
315
+ "mirostat": 0,
316
+ "mirostat_eta": 0.10000000149011612,
317
+ "mirostat_tau": 5.0,
318
+ "n_discard": 0,
319
+ "n_keep": 0,
320
+ "n_predict": -1,
321
+ "n_probs": 0,
322
+ "post_sampling_probs": false,
323
+ "presence_penalty": 0.0,
324
+ "reasoning_format": "deepseek",
325
+ "reasoning_in_content": false,
326
+ "repeat_last_n": 64,
327
+ "repeat_penalty": 1.0,
328
+ "samplers": [
329
+ "penalties",
330
+ "dry",
331
+ "top_n_sigma",
332
+ "top_k",
333
+ "typ_p",
334
+ "top_p",
335
+ "min_p",
336
+ "xtc",
337
+ "temperature"
338
+ ],
339
+ "seed": 4294967295,
340
+ "speculative.types": "none",
341
+ "stream": false,
342
+ "temperature": 0.6000000238418579,
343
+ "timings_per_token": false,
344
+ "top_k": 20,
345
+ "top_n_sigma": -1.0,
346
+ "top_p": 0.8500000238418579,
347
+ "typical_p": 1.0,
348
+ "xtc_probability": 0.0,
349
+ "xtc_threshold": 0.10000000149011612
166
350
  },
167
- "task_id": 123,
168
- "cache_tokens": 512
351
+ "speculative": false
169
352
  }
170
353
  ]
171
354
  ```
172
355
 
173
- **Field Descriptions:**
356
+ ### Response format
174
357
 
175
- - `id` - Unique identifier for the slot
176
- - `state` - Current processing state ("idle", "processing", etc.)
177
- - `next_token` - Information about token generation state
358
+ - `id` - The slot's ID.
359
+ - `next_token` - Generation state of the slot's current request.
178
360
  - `has_next_token` - Whether more tokens are expected
361
+ - `has_new_line` - Whether the request's generated text contains a newline.
179
362
  - `n_remain` - Number of tokens remaining to generate
180
363
  - `n_decoded` - Number of tokens already decoded
181
- - `task_id` - Identifier of the current task being processed (-1 if idle)
182
- - `cache_tokens` - Number of cached tokens in the slot's prompt cache
183
-
184
- ## `POST /v1/slots/{id}?action=save`
364
+ - `id_task` - The task the slot is processing, or processed last when idle.
365
+ - `n_ctx` - Context size of the slot.
366
+ - `is_processing` - Whether the slot is serving a request.
367
+ - `n_prompt_tokens` - Tokens in the slot's current prompt.
368
+ - `n_prompt_tokens_cache` - Prompt tokens reused from the slot's cache instead of processed again.
369
+ - `n_prompt_tokens_processed` - Prompt tokens processed for the current request.
370
+ - `params` - Sampling parameters of the slot's last request.
371
+ - `speculative` - Whether the slot uses speculative decoding.
372
+
373
+ ### Errors
374
+
375
+ | Status | When |
376
+ |--------|------|
377
+ | `400` | No model is loaded |
378
+ | `400` | The most recently used model is not a llama.cpp model |
379
+ | `404` | The model is unloaded while the request waits for it |
380
+ | `500` | The backend reports an error; the backend's own status replaces this one when it sends one |
381
+ | `500` | The request fails unexpectedly |
382
+ <!-- END GENERATED: llamacpp.slots -->
383
+
384
+ <!-- BEGIN GENERATED: llamacpp.slots_action -->
385
+ ## `POST /v1/slots/{id}`
185
386
  <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
186
387
 
187
- Save the prompt cache of a specific slot to a file. This allows you to persist the current context state for later restoration.
188
-
189
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/slots/{id}?action=save` endpoint.
190
-
191
- > **Note:** The llama.cpp server must be started with the `--slot-save-path` argument for save operations to work. See [Server Configuration](../guide/configuration/README.md) for details on configuring backend arguments.
192
- >
193
- > Example configuration:
194
- > ```bash
195
- > lemonade config set llamacpp.args="--slot-save-path /path/to/slot/saves"
196
- > ```
388
+ Saves a slot's prompt cache to a file, restores it from one, or erases it, so a conversation can resume where it left off.
197
389
 
198
- > **Note:** This endpoint supports all four path prefixes: `/api/v0/slots/{id}`, `/api/v1/slots/{id}`, `/v0/slots/{id}`, and `/v1/slots/{id}`.
390
+ Requires `LEMONADE_API_KEY` when it is set.
199
391
 
200
392
  ### Parameters
201
393
 
202
394
  | Parameter | Required | Description | Status |
203
395
  |-----------|----------|-------------|--------|
204
- | `id` | Yes | The slot ID to save (path parameter). | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
205
- | `filename` | Yes | The filename where the slot cache should be saved (JSON body). | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
396
+ | `id` (path) | Yes | The slot to act on. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
397
+ | `filename` | No | File to save to or restore from, relative to `--slot-save-path`. Required for `save` and `restore`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
398
+ | `action` (query) | Yes | `save` writes the slot's prompt cache to `filename`, `restore` reads it back from `filename`, and `erase` clears the slot. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
206
399
 
207
- ### Example request
400
+ Every action needs llama.cpp started with `--slot-save-path`. Set it for every load with `lemonade config set llamacpp.args="--slot-save-path /path/to/slot/saves"` (see [Server Configuration](../guide/configuration/README.md)), or for one load with `llamacpp_args` on [`POST /v1/load`](./lemonade.md#post-v1load).
208
401
 
209
- === "PowerShell"
402
+ ### Examples
210
403
 
211
- ```powershell
212
- Invoke-WebRequest `
213
- -Uri "http://localhost:13305/v1/slots/0?action=save" `
214
- -Method POST `
215
- -Headers @{ "Content-Type" = "application/json" } `
216
- -Body '{"filename": "my_conversation_cache.bin"}' -UseBasicParsing
217
- ```
404
+ #### Save
218
405
 
219
- === "PowerShell (/api/v1)"
406
+ === "PowerShell"
220
407
 
221
408
  ```powershell
222
409
  Invoke-WebRequest `
223
- -Uri "http://localhost:13305/api/v1/slots/0?action=save" `
410
+ -Uri "http://localhost:13305/v1/slots/0?action=save" `
224
411
  -Method POST `
225
412
  -Headers @{ "Content-Type" = "application/json" } `
226
- -Body '{"filename": "my_conversation_cache.bin"}' -UseBasicParsing
413
+ -Body '{"filename": "my_conversation_cache.bin"}'
227
414
  ```
228
415
 
229
416
  === "Bash"
230
417
 
231
418
  ```bash
232
- curl -X POST "http://localhost:13305/v1/slots/0?action=save" \
419
+ curl "http://localhost:13305/v1/slots/0?action=save" \
233
420
  -H "Content-Type: application/json" \
234
421
  -d '{"filename": "my_conversation_cache.bin"}'
235
422
  ```
236
423
 
237
- ### Response format
424
+ **Response:** `200 OK`
238
425
 
239
426
  ```json
240
427
  {
241
428
  "id_slot": 0,
242
429
  "filename": "my_conversation_cache.bin",
243
- "n_saved": 1024
430
+ "n_saved": 46,
431
+ "n_written": 5277108,
432
+ "timings": {"save_ms": 6.543}
244
433
  }
245
434
  ```
246
435
 
247
- **Field Descriptions:**
248
-
249
- - `id_slot` - The slot ID that was saved
250
- - `filename` - The filename where the cache was saved
251
- - `n_saved` - Number of tokens saved to the cache file
252
-
253
- ## `POST /v1/slots/{id}?action=restore`
254
- <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
255
-
256
- Restore the prompt cache of a specific slot from a previously saved file. This allows you to resume a conversation or context from where you left off.
257
-
258
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/slots/{id}?action=restore` endpoint.
259
-
260
- > **Note:** The llama.cpp server must be started with the `--slot-save-path` argument for restore operations to work.
261
-
262
- > **Note:** This endpoint supports all four path prefixes: `/api/v0/slots/{id}`, `/api/v1/slots/{id}`, `/v0/slots/{id}`, and `/v1/slots/{id}`.
263
-
264
- ### Parameters
265
-
266
- | Parameter | Required | Description | Status |
267
- |-----------|----------|-------------|--------|
268
- | `id` | Yes | The slot ID to restore to (path parameter). | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
269
- | `filename` | Yes | The filename from which to restore the slot cache (JSON body). | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
270
-
271
- ### Example request
436
+ #### Restore
272
437
 
273
438
  === "PowerShell"
274
439
 
@@ -277,74 +442,37 @@ Restore the prompt cache of a specific slot from a previously saved file. This a
277
442
  -Uri "http://localhost:13305/v1/slots/0?action=restore" `
278
443
  -Method POST `
279
444
  -Headers @{ "Content-Type" = "application/json" } `
280
- -Body '{"filename": "my_conversation_cache.bin"}' -UseBasicParsing
281
- ```
282
-
283
- === "PowerShell (/api/v1)"
284
-
285
- ```powershell
286
- Invoke-WebRequest `
287
- -Uri "http://localhost:13305/api/v1/slots/0?action=restore" `
288
- -Method POST `
289
- -Headers @{ "Content-Type" = "application/json" } `
290
- -Body '{"filename": "my_conversation_cache.bin"}' -UseBasicParsing
445
+ -Body '{"filename": "my_conversation_cache.bin"}'
291
446
  ```
292
447
 
293
448
  === "Bash"
294
449
 
295
450
  ```bash
296
- curl -X POST "http://localhost:13305/v1/slots/0?action=restore" \
451
+ curl "http://localhost:13305/v1/slots/0?action=restore" \
297
452
  -H "Content-Type: application/json" \
298
453
  -d '{"filename": "my_conversation_cache.bin"}'
299
454
  ```
300
455
 
301
- ### Response format
456
+ **Response:** `200 OK`
302
457
 
303
458
  ```json
304
459
  {
305
460
  "id_slot": 0,
306
461
  "filename": "my_conversation_cache.bin",
307
- "n_restored": 1024
462
+ "n_restored": 46,
463
+ "n_read": 5277108,
464
+ "timings": {"restore_ms": 1.595}
308
465
  }
309
466
  ```
310
467
 
311
- **Field Descriptions:**
312
-
313
- - `id_slot` - The slot ID that was restored
314
- - `filename` - The filename from which the cache was restored
315
- - `n_restored` - Number of tokens restored from the cache file
316
-
317
- ## `POST /v1/slots/{id}?action=erase`
318
- <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
319
-
320
- Erase (clear) the prompt cache of a specific slot. This removes all cached context from the slot, resetting it to an empty state.
321
-
322
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/slots/{id}?action=erase` endpoint.
323
-
324
- > **Note:** This endpoint supports all four path prefixes: `/api/v0/slots/{id}`, `/api/v1/slots/{id}`, `/v0/slots/{id}`, and `/v1/slots/{id}`.
325
-
326
- ### Parameters
327
-
328
- | Parameter | Required | Description | Status |
329
- |-----------|----------|-------------|--------|
330
- | `id` | Yes | The slot ID to erase (path parameter). | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
331
-
332
- ### Example request
468
+ #### Erase
333
469
 
334
470
  === "PowerShell"
335
471
 
336
472
  ```powershell
337
473
  Invoke-WebRequest `
338
474
  -Uri "http://localhost:13305/v1/slots/0?action=erase" `
339
- -Method POST -UseBasicParsing
340
- ```
341
-
342
- === "PowerShell (/api/v1)"
343
-
344
- ```powershell
345
- Invoke-WebRequest `
346
- -Uri "http://localhost:13305/api/v1/slots/0?action=erase" `
347
- -Method POST -UseBasicParsing
475
+ -Method POST
348
476
  ```
349
477
 
350
478
  === "Bash"
@@ -353,41 +481,56 @@ Erase (clear) the prompt cache of a specific slot. This removes all cached conte
353
481
  curl -X POST "http://localhost:13305/v1/slots/0?action=erase"
354
482
  ```
355
483
 
356
- ### Response format
484
+ **Response:** `200 OK`
357
485
 
358
486
  ```json
359
- {
360
- "id_slot": 0
361
- }
487
+ {"id_slot": 0, "n_erased": 46}
362
488
  ```
363
489
 
364
- **Field Descriptions:**
365
-
366
- - `id_slot` - The slot ID that was erased
367
-
368
- > **Note:** If the server returns an error, it may indicate that the slot was not found or that the operation failed.
490
+ ### Response format
369
491
 
492
+ - `id_slot` - The slot acted on.
493
+ - `filename` - `save` and `restore`: the file written or read.
494
+ - `n_saved` - `save`: tokens written.
495
+ - `n_restored` - `restore`: tokens read.
496
+ - `n_written` - `save`: bytes written.
497
+ - `n_read` - `restore`: bytes read.
498
+ - `n_erased` - `erase`: tokens cleared.
499
+ - `timings` - `save` and `restore`: how long the file operation took.
500
+
501
+ ### Errors
502
+
503
+ | Status | Code | When |
504
+ |--------|------|------|
505
+ | `400` | `invalid_json` | The body is not a JSON object |
506
+ | `400` | `missing_argument` | A required argument is missing |
507
+ | `400` | `invalid_argument` | An argument or a value nested in it has the wrong JSON type, or a value its schema does not list |
508
+ | `400` | | `id` is too large for a 32-bit integer |
509
+ | `400` | | No model is loaded |
510
+ | `400` | | The most recently used model is not a llama.cpp model |
511
+ | `404` | | The model is unloaded while the request waits for it |
512
+ | `500` | | The backend reports an error; the backend's own status replaces this one when it sends one |
513
+ | `500` | | The request fails unexpectedly |
514
+ <!-- END GENERATED: llamacpp.slots_action -->
515
+
516
+ <!-- BEGIN GENERATED: llamacpp.tokenize -->
370
517
  ## `POST /v1/tokenize`
371
518
  <sub>![Status](https://img.shields.io/badge/status-fully_available-green)</sub>
372
519
 
373
- Tokenize a given text. Does not count towards the current model's context window.
374
-
375
- > **Note:** This endpoint is part of Lemonade's llama.cpp compatibility layer. Internally, Lemonade forwards the request to llama.cpp's `/tokenize` endpoint.
520
+ Tokenizes text without using the model's context window. After a request to a reranker, for example, the reranker's tokenizer answers.
376
521
 
377
- > **Note:** This endpoint supports all four path prefixes: `/api/v0/tokenize`, `/api/v1/tokenize`, `/v0/tokenize`, and `/v1/tokenize`.
378
-
379
- > **Note:** Actual response values may vary for the same string across different models if the models do not share the same tokenizer.
522
+ Requires `LEMONADE_API_KEY` when it is set.
380
523
 
381
524
  ### Parameters
382
525
 
383
526
  | Parameter | Required | Description | Status |
384
527
  |-----------|----------|-------------|--------|
385
528
  | `content` | Yes | The text to tokenize. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
386
- | `add_special` | No | Boolean indicating if special tokens, i.e. `BOS`, should be inserted. Default: `false` | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
387
- | `parse_special` | No | Boolean indicating if special tokens should be tokenized. When `false` special tokens are treated as plaintext. Default: `true` | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
388
- | `with_pieces` | No | Boolean indicating whether to return token pieces along with IDs. Default: `false` | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
529
+ | `add_special` | No | Insert special tokens, such as `BOS`. Defaults to `false`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
530
+ | `parse_special` | No | Tokenize special tokens; `false` treats them as plain text. Defaults to `true`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
531
+ | `with_pieces` | No | Return each token's text piece with its ID. Defaults to `false`. | <sub>![Status](https://img.shields.io/badge/available-green)</sub> |
389
532
 
390
- ### Example request
533
+ ### Example
391
534
 
392
535
  === "PowerShell"
393
536
 
@@ -396,47 +539,37 @@ Tokenize a given text. Does not count towards the current model's context window
396
539
  -Uri "http://localhost:13305/v1/tokenize" `
397
540
  -Method POST `
398
541
  -Headers @{ "Content-Type" = "application/json" } `
399
- -Body '{"content": "This is a string to tokenize"}' -UseBasicParsing
400
- ```
401
-
402
- === "PowerShell (/api/v1)"
403
-
404
- ```powershell
405
- Invoke-WebRequest `
406
- -Uri "http://localhost:13305/api/v1/tokenize" `
407
- -Method POST `
408
- -Headers @{ "Content-Type" = "application/json" } `
409
- -Body '{"content": "This is a string to tokenize"}' -UseBasicParsing
542
+ -Body '{"content": "This is a string to tokenize"}'
410
543
  ```
411
544
 
412
545
  === "Bash"
413
546
 
414
547
  ```bash
415
- curl -X POST "http://localhost:13305/v1/tokenize" \
548
+ curl http://localhost:13305/v1/tokenize \
416
549
  -H "Content-Type: application/json" \
417
550
  -d '{"content": "This is a string to tokenize"}'
418
551
  ```
419
552
 
420
- ### Response format
421
-
422
- ```json
423
- {
424
- "tokens": [1919,369,264,886,310,74995]
425
- }
426
- ```
427
-
428
- If `with_pieces` is `true`:
553
+ **Response:** `200 OK`
429
554
 
430
555
  ```json
431
- {
432
- "tokens": [
433
- {"id": 123, "piece": "Hello"},
434
- {"id": 456, "piece": " world"},
435
- {"id": 789, "piece": "!"}
436
- ]
437
- }
556
+ {"tokens": [1986, 374, 264, 914, 311, 77651]}
438
557
  ```
439
558
 
440
- **Field Descriptions:**
559
+ ### Response format
441
560
 
442
- - `tokens` - Array of token IDs
561
+ - `tokens` - Token IDs, or `{"id", "piece"}` objects when `with_pieces` is `true`.
562
+
563
+ ### Errors
564
+
565
+ | Status | Code | When |
566
+ |--------|------|------|
567
+ | `400` | `invalid_json` | The body is not a JSON object |
568
+ | `400` | `missing_argument` | A required argument is missing |
569
+ | `400` | `invalid_argument` | An argument or a value nested in it has the wrong JSON type, or a value its schema does not list |
570
+ | `400` | | No model is loaded |
571
+ | `400` | | The most recently used model is not a llama.cpp model |
572
+ | `404` | | The model is unloaded while the request waits for it |
573
+ | `500` | | The backend reports an error; the backend's own status replaces this one when it sends one |
574
+ | `500` | | The request fails unexpectedly |
575
+ <!-- END GENERATED: llamacpp.tokenize -->