Skip to content

Commit 432524c

Browse files
committed
docs(openapi,config): document /v1/answer/pageindex + pageindex block
OpenAPI 3.1 spec for the new endpoint: - POST /v1/answer/pageindex documented with the PageIndexAnswerRequest body shape (document_id, query, optional model, max_hops, max_pages_per_fetch, stream, reasoning) and PageIndexAnswerResponse (answer, citations, hops_taken, usage, trace_token, pages_read, reasoning_trace). - PageIndexCitation, PageReadEntry, and PageIndexTraceEntry component schemas describe the page-grounded citation shape, the per-call navigation footprint, and per-hop reasoning trace entries. - The 200 response carries content for BOTH application/json (non-streaming) and text/event-stream (when stream:true) with documentation of the SSE event types: `started`, one event per tool call (get_document_structure / get_pages / done), and a terminal `answer` event carrying the full payload. - 501 covers both "no LLM client" and "retrieval.pageindex.enabled=false" so operators looking at the spec see the toggle that disables the endpoint. - QueryResponse's strategy enum gains "pageindex" so /v1/query responses returned by a pageindex-default deployment validate against the schema. - ?reasoning=true query parameter is documented as an alternative to the body's reasoning field. config.example.yaml: - retrieval.strategy comment lists every available strategy with a one-line description of each, so an operator picking a strategy can see what they're choosing between without reading code. - New retrieval.pageindex block with enabled / max_hops / page_content_limit / model knobs, default values matching the engine defaults, and a comment block explaining the three-tool loop, the trace_token / reasoning_trace / streaming differentiators, and the graceful-degradation behaviour when no TOC tree is persisted yet (the synthesised view fallback).
1 parent ae4a23a commit 432524c

2 files changed

Lines changed: 393 additions & 2 deletions

File tree

config.example.yaml

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,20 @@ llm:
9595
reasoning_model: "gemini-2.5-pro"
9696

9797
retrieval:
98-
# strategy: single-pass | chunked-tree
98+
# strategy: single-pass | chunked-tree | agentic | pageindex
99+
#
100+
# single-pass: whole tree in one LLM call; fastest, smallest docs.
101+
# chunked-tree: split the tree, reason over slices in parallel, merge.
102+
# The default. Scales to any tree size by trading
103+
# context for parallelism.
104+
# agentic: iterative outline → expand → read → done loop.
105+
# Picks per-section IDs via a tool-using model.
106+
# pageindex: PageIndex-style page-based agentic loop. Three
107+
# tools (get_document_structure / get_pages / done);
108+
# the model navigates by INCLUSIVE PAGE RANGE
109+
# rather than by section ID. Best for paginated
110+
# documents (SEC filings, academic PDFs) where the
111+
# per-section interface is too noisy.
99112
strategy: "chunked-tree"
100113

101114
chunked_tree:
@@ -232,6 +245,54 @@ retrieval:
232245
# audit flows may bump this; tight memory budgets shrink it.
233246
ttl_seconds: 86400
234247

248+
# pageindex: PageIndex-style page-based agentic strategy and its
249+
# dedicated POST /v1/answer/pageindex endpoint.
250+
#
251+
# The strategy runs a three-tool loop:
252+
# 1. get_document_structure() — returns the TOC tree (titles +
253+
# page ranges, no body text).
254+
# 2. get_pages(start_page, end_page) — returns the concatenated
255+
# content of every section whose page range overlaps.
256+
# 3. done(answer, cited_pages, reasoning) — terminates with the
257+
# natural-language answer plus the cited inclusive ranges.
258+
#
259+
# Unlike /v1/answer there's no separate synthesis call — the
260+
# model emits the final answer inside the done tool call. The
261+
# response carries per-page-range citations with answer-span
262+
# quotes, a deterministic trace_token (replayable via
263+
# /v1/replay), and an optional reasoning_trace describing every
264+
# tool call. Streaming via SSE is available with `stream:true`
265+
# on the request body — one event per tool call so callers
266+
# watch the navigation in real time.
267+
#
268+
# OPT-OUT. Default enabled. Disable to unwire the endpoint
269+
# (returns 501); the strategy itself can still be selected by
270+
# setting `retrieval.strategy: pageindex` even when this block
271+
# is disabled.
272+
#
273+
# Works WITHOUT a persisted TOC tree (pre-PR-A state) — the
274+
# strategy synthesises a TOC view from the section list when
275+
# documents.toc_tree is NULL. No request fails because of a
276+
# missing TOC.
277+
pageindex:
278+
enabled: true
279+
# Cap on LLM turns per request, including the terminal done
280+
# turn. The reference PageIndex demo converges in 3-5 hops on
281+
# typical questions; 8 leaves buffer for retries on parse
282+
# failures and the occasional extra get_pages call.
283+
max_hops: 8
284+
# Cap on chars one get_pages tool call returns. 16,000 ≈ 4K
285+
# tokens — enough for a 5-7 page excerpt, well under any
286+
# flagship model's context window. Higher values risk burning
287+
# context budget on stray full-document fetches.
288+
page_content_limit: 16000
289+
# Override the navigation-loop model; empty inherits the
290+
# request's model (which itself falls back to the engine
291+
# default). Most deployments leave this blank — navigation
292+
# and answer happen in the same loop, so a "small model for
293+
# navigation, large for answer" split doesn't apply.
294+
model: ""
295+
235296
ingest:
236297
# The summarize and HyDE stages run concurrently. This caps the total
237298
# number of LLM calls in flight across both stages combined, so the

0 commit comments

Comments
 (0)