Answers
Answers a question from one or more collections, with citations.#
/lmkit/v1/search/answerThe grounded-answer endpoint: retrieves the best-matching content from the selected collections (every retrieval control of the search endpoint applies: search_type, filters, rerank, query_mode, context expansion), generates an answer on a local chat model bound to those sources, and returns the answer with citations. Citations cover EVERY retrieved source: 'cited' marks the ones the answer references inline as [n], and semantic matches carry the exact character span of the supporting chunk within the document's stored page Markdown. 'grounding' controls strictness: 'Strict' (default) answers from the sources only and refuses a question that retrieves nothing without calling the model; 'Relaxed' lets clearly-flagged general knowledge fill gaps. Set 'stream' for Server-Sent Events (delta frames, a terminal frame with the full result, then 'data: [DONE]'). Search type degrades automatically: 'Hybrid' falls back to whichever mode the tenant has enabled.
Request body
application/json ·
| Property | Type | Description |
|---|---|---|
cluster_id | string | The search cluster that holds the tenant and collections. If not provided, the default cluster is used. |
tenant_idrequired | string (uuid) | The tenant that owns the collections. |
collection_id | string (uuid) | A single collection to answer from. Ignored when 'collection_ids' is provided. |
collection_ids | string (uuid)[] | The set of collections to answer from in one call. Takes precedence over 'collection_id'. |
questionrequired | string | The question to answer. |
search_type | How supporting sources are retrieved: 'Hybrid' (default) combines word and meaning matching and degrades automatically to whichever mode the tenant has enabled; 'Semantic' and 'FullText' force one mode. | |
fusion | Hybrid retrieval only: how the full-text and semantic arms are combined. 'Convex' (default) blends normalized scores, preserving each arm's confidence; 'Rrf' fuses by rank. | |
groundedness | Verifies the generated answer against the sources it was given, which catches the case a score floor cannot: retrieval returned plausible same-topic passages that do not answer the question. 'Off' (default) skips the check; 'Report' returns the answer unchanged with its supported-claim fraction and the unsupported claims; 'Refuse' replaces an answer below 'groundedness_threshold' with the grounded refusal. The check costs additional model passes. | |
groundedness_threshold | object (double) | Supported-claim fraction at or above which an answer is kept under 'Refuse'. Defaults to 1. |
top_k | object (int32) | How many sources to retrieve and ground the answer on (1..20). Defaults to 5. |
filters | object | Optional metadata filter (equality map), as on the search endpoint. Mutually exclusive with 'filter'. |
filter | one of object · | |
min_score | object (double) | Optional relevance floor for retrieved sources, as on the search endpoint. Defaults to 0. |
rerank | boolean | When true, a cross-encoder reranking pass re-scores the retrieved sources before grounding, as on the search endpoint. |
rerank_top_n | object (int32) | The reranking over-fetch depth, as on the search endpoint. Defaults to 50. |
rerank_alpha | object (double) | The rerank blend, as on the search endpoint. Defaults to 1. |
query_mode | Query understanding, as on the search endpoint: 'Contextual' (with 'chat_history'), 'MultiQuery', or 'Hyde' (semantic/hybrid retrieval only). Defaults to 'Original'. | |
chat_history | [] | Prior conversation turns for contextual query rewriting, as on the search endpoint. |
query_variants | object (int32) | MultiQuery variant count (1..5), as on the search endpoint. Defaults to 3. |
context_expansion | How much surrounding content each source contributes: 'Chunk' (default: the matched chunk with its neighbors; full pages for full-text matches) or 'Page' (the whole matched page). | |
max_chunks_per_document | object (int32) | Maximum sources drawn from one document (1..10), so one strong document does not crowd out the rest. Defaults to 3. |
model | string | The chat model that generates the answer. Empty uses the server's default chat model. |
grounding | How strictly the answer is bound to the sources. 'Strict' (default): answer from the sources only; a question the sources cannot answer is declined, and one that retrieves nothing is refused without an inference pass ('answer' is empty and 'context_found' false). 'Relaxed': general knowledge may fill gaps, flagged as such. | |
prompt_template | string | Optional custom prompt template. Must contain '@context' (replaced by the numbered source blocks) and '@question'. Empty uses the built-in grounded template. |
max_completion_tokens | object (int32) | Maximum tokens the answer may generate. Defaults to 1024. |
temperature | object (double) | Sampling temperature. 0 (default) decodes greedily, which suits grounded answering; above 0 samples. |
max_context_characters | object (int32) | Character budget for the source blocks in the prompt (sources past the budget are returned as retrieved-but-unused). Defaults to 24000. |
stream | boolean | When true, the answer streams as Server-Sent Events: data frames carrying 'delta' (and 'thinking' for reasoning models), a terminal frame carrying the full answer with 'citations' and 'done': true, then the literal 'data: [DONE]'. |
Responses
| Status | Type | Description |
|---|---|---|
| 200 | OK | |
| 400 | Bad Request | |
| 404 | Not Found | |
| 503 | application/json | Service Unavailable |
curl -X POST "$LMKIT_ONE_URL/lmkit/v1/search/answer" \
-H "Authorization: Bearer $LMKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cluster_id": "string",
"tenant_id": "string",
"collection_id": "string",
"collection_ids": [
"string"
],
"question": "",
"search_type": "Hybrid"
}'