Annotation Interface Search
Knowledge.Use.SEARCH source is ranked and rendered.
@Search is never placed on its own; it is the
Knowledge.search() member of a knowledge declaration:
@RoleSpec(knowledge = {
@Knowledge(name = "product-docs", path = "knowledge/products",
search = @Search(strategy = Strategy.HYBRID, topK = 8)),
@Knowledge(name = "faq", path = "knowledge/faq")
})
public class SupportRole extends Role {
@ActionSpec(type = ActionType.LLM, description = "Answer a question",
knowledge = {@Knowledge(name = "product-docs"), @Knowledge(name = "faq")})
public String answer(String question) { ... }
}
Every member is an array whose empty default means "not given"; write a
single value as usual (topK = 8). More than one value fails at
startup. A member left unset takes the value stated on it.
Several SEARCH sources in one scope (an action's named set, or the chat
turn) run through one retrieval engine, so their @Search members
merge field by field: a member set by one source applies to the scope, and
two sources setting the same member to different values fail at startup.
An action's own @Knowledge(name = ..., search = @Search(...))
replaces the declared @Search as a whole: a member the action's
@Search leaves unset is not taken from the declaration, so it
takes the value another source in the scope sets, or the value stated on
it.
rerank = true requires a Reranker provider module on the
classpath that serves the declared rerankerModel(); TnsAI bundles
none. Without a matching provider the Role's retrieval configuration
fails at the start of the retrieval, before result-cache lookup or index
query/search work — onFailure cannot absorb a missing provider.
Unexpected failures from the provider's local capability check, and
failures raised while ranking, still follow onFailure().
Strategies
SEMANTIC- Vector similarity search onlyKEYWORD- BM25/TF-IDF keyword searchHYBRID- Combined semantic + keywordGRAPH- Knowledge graph traversalMULTI_QUERY- Generate multiple queries for broader coverageHIERARCHICAL- Child-hit selection with bounded parent expansionTEMPORAL- Content relevance with bounded time decayREASONING- Root-to-leaf tree descent with a model choosing the branch
- Since:
- 0.18.0
- Author:
- TnsAI Team
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumFallback actions on retrieval failure.static enumQuery expansion methods.static enumRetrieval strategies. -
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionboolean[]Whether to enable caching of retrieval results.int[]Cache TTL in seconds.String[]Context format template.int[]Maximum context window size in tokens.double[]Similarity threshold for deduplication.boolean[]Whether to deduplicate similar results.int[]Maximum number of generated query variations.boolean[]Whether to include source metadata in context.int[]How long past expiry a cached result may still serveSearch.FallbackAction.USE_CACHE, in seconds.double[]Minimum relevance score (0.0 - 1.0).String[]Exact, case-sensitive model identifier used by the tree-navigation provider whenstrategy()isSearch.Strategy.REASONING.Fallback behavior if retrieval fails at runtime.Query expansion/transformation method.String[]Exact, case-sensitive model identifier used by the query-expansion provider.String[]Name of the action parameter whose value is the retrieval query.boolean[]Whether to rerank results by relevance.String[]Exact, case-sensitive reranking model identifier.Retrieval strategy.int[]Number of results to retrieve per source during ordinary ranked retrieval.int[]Maximum number of results retained after ordinary retrieval reranking.
-
Element Details
-
strategy
Search.Strategy[] strategyRetrieval strategy.Unset (empty) means
Strategy.SEMANTIC.- Returns:
- strategy
- Default:
{}
-
queryParam
String[] queryParamName of the action parameter whose value is the retrieval query.Blank — the default — keeps the positional rule: the first
String-typed parameter in declaration order that carries a non-blank value. That is right for a single-parameter action and wrong as soon as an identifier precedes the question:search = @Search(topK = 5) // retrieves on tenantId public String answer(String tenantId, String question) { ... } search = @Search(topK = 5, queryParam = "question") // retrieves on question public String answer(String tenantId, String question) { ... }Naming the parameter also pins the binding: without it, reordering the parameters or inserting a
Stringin front of the question silently moves retrieval onto a different argument. Nothing fails — the corpus is searched for the wrong text, documents come back, and the model is handed confident grounding for a question nobody asked.Naming a parameter the action does not declare is a configuration error: the action fails at dispatch time and
onFailure()does not apply, on the same terms asrerankerModel(). A declared parameter that is absent, null, blank, or not aStringat call time is not an error — retrieval is skipped for that call, exactly as it is when the positional rule finds nothing.Parameter names come from the compiled bytecode, so the reactor's
-parameterscompiler flag is what makes this element work.Declared on a Role or Agent knowledge source this applies to every action that names the source, so each of them must declare a parameter of that name or fail. That is a strong requirement and deliberately so — the alternative, silently falling back to the positional rule on the actions that do not declare it, would reintroduce the very ambiguity naming the parameter was meant to remove. Set it on the action's own
@Knowledgeentry unless the actions genuinely share a signature.Unset (empty) means the positional rule.
- Returns:
- the query parameter's name, or blank for the positional rule
- Default:
{}
-
rerank
boolean[] rerankWhether to rerank results by relevance.When enabled, the intelligence module resolves a
com.tnsai.intelligence.rag.Rerankerprovider forrerankerModel(). TnsAI does not bundle or silently emulate a cross-encoder; applications install the provider that owns model inference and transport.A blank
rerankerModel()or identifier no installed provider serves is a configuration error. Role declarations fail while the Role is initialized, before any action dispatch; non-Role targets and programmatic overrides fail at dispatch before result-cache lookup or index query/search work. A non-positivetopN()also fails at dispatch before cache or index work.onFailure()does not apply. Unexpected failures from the provider's local capability check, and failures raised while ranking, follow the failure policy.Unset (empty) means
false.- Returns:
- true to rerank
- Default:
{}
-
rerankerModel
String[] rerankerModelExact, case-sensitive reranking model identifier.A non-blank value is required when
rerank()is enabled. The selected reranker provider defines the identifier format.Unset (empty) means
"".- Returns:
- reranker model
- Default:
{}
-
contextWindow
int[] contextWindowMaximum context window size in tokens.Must be positive. The intelligence runtime measures the complete rendered context, including
contextFormat()overhead, with the canonical content-awareTokenEstimator. Ranked document content is truncated only at Unicode code-point boundaries to fit.Unset (empty) means
4000.- Returns:
- max tokens
- Default:
{}
-
topK
int[] topKNumber of results to retrieve per source during ordinary ranked retrieval.Unset (empty) means
5.- Returns:
- top K
- Default:
{}
-
topN
int[] topNMaximum number of results retained after ordinary retrieval reranking.Must be positive when
rerank()is enabled. The runtime applies this limit after the provider returns for ordinary ranked retrieval. DIRECT does not apply result-count limits.With
rerank()disabled the value is neither validated nor applied: there is no reranking stage to cap, andtopK()alone bounds the ordinary retrieval result. The one place the limit outlives the reranker isSearch.FallbackAction.RETRY_SIMPLE, which caps its un-reranked retry at this value whenrerank()is enabled, so a degraded retrieval never injects more context than a healthy one.Unset (empty) means
3.- Returns:
- top N after rerank
- Default:
{}
-
minScore
double[] minScoreMinimum relevance score (0.0 - 1.0).The threshold is applied to the score emitted by the selected strategy, and increasing the value can only remove candidates. Semantic strategies use cosine similarity; keyword strategies use their native non-negative relevance score. Hybrid strategy RRF scores are normalized against the non-empty input streams, so
0.0preserves every HYBRID candidate and the default0.5remains meaningful when either one or both streams return candidates.Unset (empty) means
0.5.- Returns:
- min score
- Default:
{}
-
deduplicate
boolean[] deduplicateWhether to deduplicate similar results.Deduplication runs after query-result fusion and before optional reranking. The highest-ranked candidate remains the representative and retains its retrieval score.
Unset (empty) means
true.- Returns:
- true to dedupe
- Default:
{}
-
dedupeThreshold
double[] dedupeThresholdSimilarity threshold for deduplication.Must be finite and between
0.0and1.0, inclusive, whendeduplicate()is enabled. Candidates at or above the threshold are grouped.Unset (empty) means
0.9.- Returns:
- dedupe threshold
- Default:
{}
-
queryExpansion
Search.QueryExpansion[] queryExpansionQuery expansion/transformation method.Unset (empty) means
QueryExpansion.NONE.- Returns:
- query expansion type
- Default:
{}
-
queryExpansionModel
String[] queryExpansionModelExact, case-sensitive model identifier used by the query-expansion provider.A non-blank value is required when
queryExpansion()is notSearch.QueryExpansion.NONE, or whenstrategy()isSearch.Strategy.MULTI_QUERY. TnsAI resolves acom.tnsai.intelligence.rag.QueryExpanderprovider for the configured expansion mode and model; the provider owns inference, credentials, transport, and lifecycle management. An identifier no installed provider serves fails while a Role is initialized, before any action dispatch. Non-Role targets and programmatic overrides fail at dispatch before result-cache lookup or index query/search work.onFailure()does not apply. Unexpected failures from the provider's local capability check, and failures raised while expanding, follow the failure policy.Unset (empty) means
"".- Returns:
- query-expansion model
- Default:
{}
-
expandedQueries
int[] expandedQueriesMaximum number of generated query variations.The original query is always retained and does not count against this limit. Provider output is normalized, deduplicated, and truncated to this hard upper bound before retrieval.
Unset (empty) means
3.- Returns:
- query count
- Default:
{}
-
includeSpec
boolean[] includeSpecWhether to include source metadata in context.When false,
${source}and${score}placeholders render no document values. Document content is treated as data and cannot introduce placeholders through template substitution.Unset (empty) means
true.- Returns:
- true to include metadata
- Default:
{}
-
contextFormat
String[] contextFormatContext format template.The only supported placeholders are
${content},${source}, and${score}. Unsupported or unterminated placeholders fail configuration validation.Unset (empty) means
"[Source: ${source}]\n${content}\n".- Returns:
- format template
- Default:
{}
-
cache
boolean[] cacheWhether to enable caching of retrieval results.When enabled, the intelligence module caches the fully retrieved and reranked document list in a bounded, per-Role in-memory cache. Cache keys isolate the normalized query, Role, selected sources, strategy, and every option that changes the document result. Raw query text and retrieved content are not retained in cache keys or telemetry.
Unset (empty) means
true.- Returns:
- true to cache
- Default:
{}
-
cacheTTL
int[] cacheTTLCache TTL in seconds.Must be positive when
cache()is enabled. Binding eviction or corpus rebuild invalidates cached retrieval results regardless of the remaining TTL.Search.Strategy.TEMPORALranks by recency against the wall clock, which is not configuration and therefore cannot take part in the cache key. A cached temporal ranking is consequently pinned for the entry's TTL: within one TTL every hit is ordered as of the instant the entry was populated. Against the default 300 s and the built-in 30-day half-life the freshness multiplier moves by well under a hundredth of a percent, so it cannot reorder results; shorten this value if a deployment needs recency to turn over faster than that.Unset (empty) means
300.- Returns:
- cache duration
- Default:
{}
-
maxStaleness
int[] maxStalenessHow long past expiry a cached result may still serveSearch.FallbackAction.USE_CACHE, in seconds.cacheTTL()bounds how long a result is fresh; this bounds how long an expired one may still stand in for a failed retrieval. The two are measured in sequence, not from the same instant: an entry is fresh forcacheTTL, then eligible as a stale fallback for a furthermaxStaleness, then gone. This mirrors HTTPstale-if-error(RFC 5861), whose max-age argument likewise counts from the end of the freshness lifetime.Without a ceiling, a provider that stays down keeps the model answering from ever-older grounding: retention would be bounded only by a successful refresh, an explicit cache clear, or eviction. A finite default makes the bound the norm — past it, the original failure is rethrown and
Search.FallbackAction.USE_CACHEdegrades to nothing rather than to something arbitrarily old.Use
-1to opt out and allow an unbounded fallback. Any other non-positive value is rejected whenSearch.FallbackAction.USE_CACHEis selected, on the same terms ascacheTTL().Unset (empty) means
3600.- Returns:
- seconds past expiry a stale fallback stays eligible, or -1 for no ceiling
- Default:
{}
-
onFailure
Search.FallbackAction[] onFailureFallback behavior if retrieval fails at runtime.Applies to failures raised while serving a request — retrieval or reranker transport, provider exceptions, and incomplete FILE/URL source loading during binding construction. It does not apply to configuration this annotation cannot honour at all (an unknown knowledge name, blank
rerankerModel()or non-positivetopN()withrerank()enabled, no installed provider for the requested model,Search.FallbackAction.USE_CACHEwithcache()disabled); those fail the action regardless of this setting, becauseSearch.FallbackAction.CONTINUEwould otherwise run the LLM with no retrieved context while still reporting success.Cancellation is not a retrieval failure: an interrupted or cancelled dispatch propagates regardless of this setting, so no policy swallows it or spends a retry on it.
Unset (empty) means
FallbackAction.CONTINUE.- Returns:
- fallback action
- Default:
{}
-