Vectorless reasoning retrieval
Retrieval.Strategy.REASONING descends a document tree with a model choosing the branch. It does not score fragments, so there is no embedding and no similarity on the path. The strategy and the TreeNavigator SPI are @since 0.14.0 in TnsAI 0.14.0 (TnsAI@c2bb5306). They are in Maven Central 0.14.1.
TnsAI does not bundle a navigator. A blank navigatorModel, or an identifier
no installed provider uniquely serves, is a configuration error. It fails
before @Retrieval.onFailure applies.
When to use it
| Strategy | Walk | Selector | Cost shape |
|---|---|---|---|
SEMANTIC / HYBRID | Flat corpus | Vector / BM25 / RRF score | Index + one search |
HIERARCHICAL | Child → parent | Semantic hit, then deterministic parents | Index + one search + cheap expansion |
REASONING | Root → leaf | Installed TreeNavigator | One model call per opened level |
Use REASONING on long structured corpora — regulation, specification,
contract — where the answering passage often shares no vocabulary with the
question. Use HIERARCHICAL when a similarity hit is already close and you
only need surrounding parents. Use vector or hybrid when lexical or embedding
overlap is a good proxy for relevance.
A traversal that shipped full content to the model would cost what reading the corpus costs. The navigator therefore sees only titles and summaries.
Declarative
navigatorModel is required. "provider:model-id" below is a placeholder,
not a working identifier.
@KnowledgeSource(
name = "handbook",
type = KnowledgeSource.KnowledgeType.FILE,
path = "knowledge/handbook")
@Retrieval(
strategy = Retrieval.Strategy.REASONING,
sources = "handbook",
navigatorModel = "provider:model-id",
queryParam = "question")
public final class HandbookRole extends Role {
@ActionSpec(
type = ActionType.LLM,
description = "Answer from the handbook tree")
public String answer(String question) {
return question;
}
}RetrievalConfig.builder().strategy(Retrieval.Strategy.REASONING) .navigatorModel("provider:model-id") is the builder counterpart.
The runtime path is RoleRagBinding.strategyFor →
TreeNavigatorRegistry.resolve → ReasoningRAGStrategy. The binding
validates HierarchyIndex and resolves the provider at strategy-selection
time, so a missing tree or a missing navigator surfaces above
@Retrieval.onFailure. Only failures the provider raises while choosing a
branch follow the failure policy. Cancellation is not a retrieval failure.
Install a TreeNavigator
Implement com.tnsai.intelligence.rag.TreeNavigator with a public no-argument
constructor. Register exactly this UTF-8 service file:
META-INF/services/com.tnsai.intelligence.rag.TreeNavigatorThe file contains the provider's fully qualified class name. The package-private
TreeNavigatorRegistry loads providers with ServiceLoader. Resolution is
deterministic:
- a blank model fails with
IllegalArgumentException - no provider that
supports(model)fails withTreeNavigatorException - two or more matching providers fail with
TreeNavigatorException - classpath order never picks a winner
TnsAI owns the walk. The provider only judges the current node. The runtime
bounds visits (maxNodesVisited default 15 across all roots, maxDepth
default 6 on any single path), checks every returned id against the
children just offered, and records why a path stopped.
Request carries query, model, current, candidates,
remainingVisits, and a CancellationToken. Implementations should observe
the token before and after blocking work. The current
ReasoningRAGStrategy constructs that request with
CancellationToken.none() and also fails the retrieve if the calling thread
is interrupted.
Programmatic
Construct the strategy over an existing HierarchyIndex. Titles and summaries
are metadata, not content:
Map<String, String> metadata = new LinkedHashMap<>();
metadata.put(HierarchyMetadata.ID, "refunds");
metadata.put(HierarchyMetadata.PARENT_ID, "billing");
metadata.put(HierarchyMetadata.SOURCE, "handbook");
metadata.put(ReasoningRAGStrategy.NODE_TITLE_METADATA, "Refunds");
metadata.put(ReasoningRAGStrategy.NODE_SUMMARY_METADATA,
"Refunds are issued within 14 days");
RetrievedDocument node = new RetrievedDocument(
"Refunds are issued within 14 days.",
"refunds",
0.0,
metadata);
HierarchyIndex index = new HierarchyIndex(List.of(node /* , … */));
RAGStrategy strategy = new ReasoningRAGStrategy(
index,
new ApplicationTreeNavigator(),
"docs:title-match");
List<RetrievedDocument> landed =
strategy.retrieve("how do refunds work", new RAGContext());ApplicationTreeNavigator is application code. Absent
reasoningTitle / reasoningSummary keys, the navigator sees the hierarchy
id and an empty summary. Producing those summaries is indexing work; it is
not part of this retrieval strategy.
What comes back
There is no score model. Every landed node carries
ReasoningRAGStrategy.SELECTED_SCORE (1.0), so RAGContext.minScore()
admits every result. metadataFilters() and maxResults() still apply.
Stop reasons are written to HierarchyMetadata.STOP_REASON. None of them
fail the request:
| Reason | Meaning |
|---|---|
LEAF | The current node has no children. |
NAVIGATOR_STOP | The provider returned Decision.stop(). |
UNKNOWN_NODE | The provider named an id that was not offered. |
BUDGET_EXHAUSTED | maxNodesVisited was spent. |
MAX_DEPTH | The single-path depth cap was hit. |
The path taken is in HierarchyMetadata.PATH; depth is
HierarchyMetadata.DEPTH. A hallucinated branch therefore returns a partial
answer from the last valid node instead of throwing.
Not this page
- The eight-strategy inventory on Strategies
- Tree ingestion, persistence, or a second document-tree model
- Optional PDF / Office extractors
- PageIndex competitor positioning
Qdrant vector index
TnsAI 0.14.0 (TnsAI@01fba8ef, TAN-3101 / PR #131) ships an optional Qdrant backend for VectorMemoryStore. The types are @since 0.14.0. They ship in Maven Central 0.14.1.
Smart document segmentation
com.tnsai.intelligence.rag.segment.SmartDocumentSegmenter splits a long paper on headings and returns com.tnsai.intelligence.rag.segment.DocumentSegment records. Both are @since 0.14.0 in TnsAI 0.14.0 (TnsAI@609a661d, TAN-3651). They ship in Maven Central 0.14.1.