Annotation Interface Knowledge


@Documented @Retention(RUNTIME) @Target({}) public @interface Knowledge
Declares a body of knowledge and how it reaches the model.

Knowledge is declared in one place — the knowledge member of AgentSpec or RoleSpec — and used by name:


 @RoleSpec(knowledge = {
     @Knowledge(name = "product-docs", path = "knowledge/products"),
     @Knowledge(name = "handbook", path = "knowledge/handbook.md",
                use = Knowledge.Use.DIRECT),
     @Knowledge(name = "questions", path = "knowledge/questions.md",
                unit = KnowledgeUnit.HEADING, use = Knowledge.Use.SEQUENTIAL)
 })
 public class SupportRole extends Role {

     @ActionSpec(type = ActionType.LLM, description = "Answer a question",
                 knowledge = {@Knowledge(name = "product-docs"), @Knowledge(name = "handbook")})
     public String answer(String question) { ... }
 }
 

Who sees what

An action's entry names a declared source and may set only use(), maxTokens() and search(), each replacing the declared value as a whole, so a search set there drops every member of the declared Search; setting a source member such as path() there fails at startup. In one scope every source behaves by its own use: DIRECT sources enter whole, SEARCH sources run through one engine, a SEQUENTIAL source contributes its next unit, and the blocks join in declaration order.

Unset members

use(), maxTokens() and search() are arrays whose empty default means "not given"; write one value as usual (use = Knowledge.Use.DIRECT). More than one value fails at startup.

Which types are served

TnsAI bundles loaders for Knowledge.Type.FILE and HTTP/HTTPS Knowledge.Type.URL. DATABASE is an extension point: the framework resolves it through the SourceLoader SPI, and an application supplies the loader as an optional module. Knowledge.Type.MEMORY and Knowledge.Type.GRAPH load nothing, so no loader serves them.

What a missing loader costs depends on what searches the source. A Role's action knowledge skips a source whose type has no installed loader with a warning and binds from whichever sources did load; that binding fails only when every enabled source is unloadable, so there a missing loader costs part of the corpus and the warning is the only signal. An engine a com.tnsai.rag.RetrievalEngineProvider creates fails at creation on any enabled source whose type has no installed loader, MEMORY and GRAPH apart since no loader serves them; an agent's chat knowledge creates its engine at startup, so it fails there.

Retrieval against a remote index — a vector database, a search API — is deliberately not a knowledge source. Those are queried per request, whereas a loader runs once and materialises documents, so they cannot be expressed against this seam at all. They are served by com.tnsai.rag.RetrievalEngineProvider instead.

Since:
0.18.0
Author:
TnsAI Team
See Also:
  • Element Details

    • name

      String name
      Knowledge name, unique within the declaring Agent or Role.

      An action names the knowledge it sees by this name, and the class config file and run-level overrides address the source by it.

      Returns:
      source name
    • type

      Knowledge source type, which selects the loader.

      Defaults to Knowledge.Type.FILE, the type TnsAI bundles a loader for. The default is deliberately a type that works: an unserviceable default fails every declaration that omits this element.

      Returns:
      source type
      Default:
      FILE
    • format

      Content format for a FILE or HTTP/HTTPS URL source.

      DocumentFormat.AUTO is resolved independently for every file in a directory. An explicit format is strict: every regular, non-symbolic-link candidate must use one of that format's registered extensions before ingestion starts. DocumentFormat.TEXT intentionally accepts any file name and performs raw UTF-8 decoding.

      include() and exclude() narrow candidates before this format check. An excluded file is not an AUTO candidate and cannot trigger an explicit-format mismatch. Unsupported AUTO candidates that survive the selectors are skipped; a directory that contains files but no usable candidate is a configuration error.

      Returns:
      declared document format
      Default:
      AUTO
    • path

      String path
      Directory or file the corpus is read from.

      Used by Knowledge.Type.FILE and Knowledge.Type.URL. A relative FILE path, written here or given by a Config file, resolves against the base directory ClassConfig.useBaseDirectory(java.nio.file.Path) set, when one is set, and against the working directory otherwise. It resolves when the source is read, so a base directory set after that applies from the next run. Absolute paths and URLs are kept as written.

      Returns:
      path or URL
      Default:
      ""
    • connection

      String connection
      Database connection string or reference.

      Used by Knowledge.Type.DATABASE, whose loader is supplied by an application module.

      Returns:
      connection string
      Default:
      ""
    • query

      String query
      Query template a database source ingests with.

      Used by Knowledge.Type.DATABASE. Use the ${query} placeholder for the search term.

      Returns:
      query template
      Default:
      ""
    • enabled

      boolean enabled
      Whether this source is ingested at all.

      A disabled source is skipped at binding time, so it contributes no documents and an action cannot name it.

      Returns:
      true if enabled
      Default:
      true
    • select

      String select
      Part of the source at path() to read, as a structural path prefix.

      Each loaded document keeps only the blocks at and below the selector, as in $.products for JSON or /catalog[1]/book[2] for XML; the StructuralPath class lists the root of every built-in format. Applies to Knowledge.Type.FILE and Knowledge.Type.URL sources.

      The selector is strict per document: every document of the source must hold the selected part. A document the selector selects nothing from, an empty one included, or a selector that does not start at its format's root, fails when it is loaded. For a directory whose files do not all hold the part, narrow the files with include() and exclude(). A SourceLoader that does not keep structural paths, as a third-party loader may not, refuses a source that sets a selector. Changing the selector re-ingests the source.

      Returns:
      selector, empty for the whole source
      See Also:
      Default:
      ""
    • include

      String[] include
      Include globs for a Knowledge.Type.FILE source.

      Empty — the default — admits every regular, non-symbolic-link file beneath the configured root. Each pattern matches the entire root-relative path with / separators. * and ? do not cross directories; ** matches zero or more path segments. A brace group matches any one of its comma-separated alternatives, so *.{md,pdf} picks both file types and {docs,guides}/*.md both folders. An alternative is literal text and the same tokens; braces do not nest, and an empty group or an empty alternative fails binding, as do [, ] and \. Matching ignores case: pattern and path are lower-cased one code point at a time, whatever the default locale, so *.pdf admits B.PDF and I, i and İ match one another, while the Turkish dotless ı stays distinct. Lines in a .gitignore or .tnsignore still match case-sensitively. Include is evaluated before exclude().

      Returns:
      include selectors
      Default:
      {}
    • exclude

      String[] exclude
      Exclude globs for a Knowledge.Type.FILE source.

      Empty — the default — excludes nothing. A path that matches any exclude pattern is dropped even if it also matched include(). Exclude globs use the same syntax as include(), brace groups included, and ignore case as it does, so drafts/** drops Drafts/x.md. Invalid syntax fails binding, naming this source and the selector.

      Returns:
      exclude selectors
      Default:
      {}
    • unit

      How each admitted FILE or HTTP/HTTPS URL source becomes retrieval documents.

      This is an ingest-time decision applied once when the source is loaded. It does not change per query, and it does not affect how search() ranks the resulting documents.

      KnowledgeUnit.AUTO — the default — is the existing hybrid: a file that fits one chunk stays one document, a larger file is split by the shared chunker. The other values are explicit opt-ins. RECORD is not a value: JSONL and CSV already yield one document per row under their extractors. Non-AUTO units are therefore rejected for CSV, TSV, and JSONL; LINE additionally requires a textual format, and HEADING requires Markdown.

      Returns:
      slicing unit
      Default:
      AUTO
    • chunkContext

      ChunkContext chunkContext
      Ingest-time chunk context prepended before embedding and BM25.

      ChunkContext.NONE — the default — omits the extra fingerprint fields. STRUCTURAL is free. LLM requires an installed ChunkContextGenerator and chunkContextModel(). FILE sources only. KnowledgeUnit.LINE rejects any non-NONE value.

      Returns:
      chunk-context mode
      Default:
      NONE
    • chunkContextModel

      String chunkContextModel
      Model identifier for ChunkContext.LLM. Ignored for NONE and STRUCTURAL.
      Returns:
      generating model
      Default:
      ""
    • refresh

      String refresh
      How often a loaded Knowledge.Type.FILE source is checked for changed files.

      Empty — the default — loads the source once. Otherwise a retrieval that searches this source, once the interval has passed since the last check, first compares the files under path() with the ones loaded: added and changed files are read again, removed files leave the index, and unchanged files are kept as they are. A file that cannot be read keeps its previous content and is tried again at the next check, and that content still counts toward the source's limits; a source that cannot be read at all, or would pass its limits, keeps its previous content too. The binding logs one WARN for such a source, then DEBUG while it fails the same way, and WARN again when it fails another way; the file loader still logs a WARN for each file it could not read, at every check.

      A Knowledge.Use.SEQUENTIAL source is checked when a reader is opened; when its files changed, every reader of it starts again at the first unit. A snapshot an explicit com.tnsai.intelligence.rag.binding.KnowledgeScope holds, a binding whose index a remote vector store owns, and an engine a RetrievalEngineProvider creates from a source list keep what they loaded: refresh does not apply to them.

      Write a whole number followed by s, m or h, as in 30s, 5m or 1h, in any case, or an ISO-8601 duration such as PT5M. Zero checks on every retrieval. A negative or unreadable value, or any value on a source that is not FILE, fails at startup. A @Config file or a run file sets it under the source's name, as "refresh": "5m", and a blank value there turns it off.

      Returns:
      refresh interval, empty for none
      Since:
      0.18.7
      Default:
      ""
    • use

      How this source reaches the model.

      Empty — the default — means Knowledge.Use.SEARCH. More than one value fails at startup.

      Returns:
      one usage mode, or empty for Knowledge.Use.SEARCH
      Default:
      {}
    • maxTokens

      int[] maxTokens
      Token budget for a Knowledge.Use.DIRECT source.

      The DIRECT sources of one scope share a budget: the sum of their estimated sizes must fit the budget given here, or a quarter of the model's input window when no source in the scope gives one. An unknown input window with no budget given fails. Only valid with use = DIRECT; a non-positive value fails at startup.

      Returns:
      one positive budget, or empty for the derived budget
      Default:
      {}
    • search

      Search[] search
      Ranking settings for a Knowledge.Use.SEARCH source.

      Only valid with use = SEARCH (or unset). See Search for how several SEARCH sources in one scope merge.

      Returns:
      one Search, or empty for the defaults
      Default:
      {}