File formats and ingestion
KnowledgeType.FILE says where documents come from (a path). DocumentFormat says how their bytes are interpreted. They are not the same field.
@KnowledgeSource.format() defaults to DocumentFormat.AUTO. AUTO is
resolved independently for every regular, non-symlink file under the
root. An explicit format is strict: every remaining candidate must use
one of that format's registered extensions (except TEXT, which
accepts any file name and decodes UTF-8).
include / exclude run before the format check. An excluded file
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.
Nested .gitignore / .tnsignore and FileIngestionService.Limits
are the same contract on declarative FILE sources and Server
FileIndexer. Details: Pipeline — ignore and admission.
Only KnowledgeType.FILE has a bundled loader. URL, DATABASE, and
MEMORY are SPI keys with no framework loader — those sources are
skipped with a warning unless an application module registers one.
@KnowledgeSource(name = "mixed", path = "knowledge", format = DocumentFormat.AUTO)@KnowledgeSource(
name = "xml-corpus",
path = "data",
format = DocumentFormat.XML,
include = {"**/*.xml"})@KnowledgeSource(
name = "code",
path = "src",
format = DocumentFormat.SOURCE_CODE,
include = {"**/*.java", "**/*.kt"})A single file path is ingested as one document. A directory is walked;
* / ? do not cross directories, ** matches zero or more segments.
Include is evaluated first; any matching exclude drops the path.
Format matrix
Aliases come from DocumentFormat. Media types are what
DefaultContentDetector reports. PDF / Office backends stay
optional on tnsai-intelligence — they are not bundled just
because you depend on tnsai-intelligence. EPUB is claimed without
those libraries (JDK zip + jsoup). A missing extractor for a claimed
binary format fails when that format is requested.
| Format | Extensions | Media type | Bundled decode | Extractor | Chunk unit |
|---|---|---|---|---|---|
AUTO | (per file) | (detected) | n/a | detector + format extractor | (detected) |
TEXT | txt (any name accepted) | text/plain | yes | StructuredTextContentExtractor | small file kept whole; else line/char groups |
MARKDOWN | md, markdown | text/markdown | yes | same | heading/block path when present |
HTML | html, htm | text/html | yes | same | element path |
CSV | csv | text/csv | yes | same | row groups (max 4096 columns) |
TSV | tsv | text/tab-separated-values | yes | same | row groups |
JSON | json | application/json | yes | same | structural path |
JSONL | jsonl, ndjson | application/x-ndjson | yes | same | line records |
YAML | yaml, yml | application/yaml | yes | same | structural path |
XML | xml | application/xml | yes | same | element path |
SOURCE_CODE | java, kt, kts, scala, groovy, js, jsx, ts, tsx, py, rb, php, go, rs, c, h, cc, cpp, cxx, hpp, cs, swift, sh, bash, zsh, sql, css | text/plain | yes | SourceCodeContentExtractor | symbol blocks (class/function/method); fallback file/residual spans |
PDF | pdf | application/pdf | optional PDFBox | OfficeDocumentContentExtractor | page |
DOCX | docx | OOXML word | optional POI | same | paragraph/table |
XLSX | xlsx | OOXML sheet | optional POI | same | sheet/row |
PPTX | pptx | OOXML slides | optional POI | same | slide |
EPUB | epub | application/epub+zip | yes (zip+jsoup) | same | spine chapter |
SOURCE_CODE is a family. Language is not a DocumentFormat
value. TnsAI 0.14.0 (TnsAI@a652e847, TAN-5618 / PR #140) detects
it after the format is selected and emits stable symbol blocks
through SourceCodeContentExtractor + NormalizedDocumentChunker.
The type ships on the v0.14.0 tag and remains in Maven Central 0.14.1.
Detection order: languageHint metadata, then extension, then
shebang / content hints. Known keys include java, kotlin,
javascript, typescript, python, go, rust, plus the other
family extensions (ruby, php, scala, c, cpp, csharp,
swift, shell, sql, css). Unrecognized content becomes
source.
| Language / path | parser metadata | Notes |
|---|---|---|
| Java on a full JDK | jdk.compiler | Nested types, methods, signatures, package, imports, extends / implements, method calls. A parse failure moves to structural-fallback. |
| TypeScript, JavaScript, Kotlin, Python, Go, Rust on a full JDK | structural-fallback | Declarations, braces, strings, comments; Python uses indentation. |
| Other family languages on a full JDK | structural-fallback | Language metadata is still recorded; a file with no recognized symbol uses a generic-fallback block. |
Provider discovery and TEXT, MARKDOWN, and JSONL extraction work on a
Java 21 JRE without jdk.compiler. SOURCE_CODE remains available there and
uses the bounded JRE structural adapter. That adapter records
parser=structural, fallback=true, and
fallbackReason=jdk-compiler-unavailable. This is distinct from the full-JDK
non-Java structural-fallback path and from a generic-fallback block emitted
when no structural symbol is recognized.
Fallback use and reason are always visible. Document-level keys include
language, parser, fallback, and fallbackReason. Symbol blocks
add:
| Key | Meaning |
|---|---|
symbol | Simple name (<init> constructors become the type name) |
symbolKind | e.g. class / method / file / residual |
parentSymbol | Enclosing type when present |
signature | Bounded declaration text |
parser | jdk.compiler, structural-fallback, structural, or generic-fallback, depending on the path above |
lineStart / line provenance | Survives indexing |
NormalizedDocumentChunker keeps those blocks as retrieval units
instead of whole-file / line groups. The 100-line / 16 KiB limits apply
to every emitted block, including oversized symbol blocks.
Declarative @KnowledgeSource(format = SOURCE_CODE) and Server
CodeChunker share extraction, symbol boundaries, content, language,
and line provenance, but not the exact ID namespace. Declarative FILE
ingest prefixes the path with source.name; CodeChunker uses the path
directly. FileIndexer does not call CodeChunker; it uses
FileIngestionService, which loads the same extractor. See
Pipeline — CodeChunker.
Limits and failures
Default extract bounds (ExtractionContext): 16 MiB raw input, 16 MiB
normalized text, 65 536 blocks. Shared walk caps
(FileIngestionService.Limits.defaults(), TnsAI 0.14.0): 64 MiB
decoded aggregate, 4 096 files, 8 192 walk entries, depth 64. Shared
chunker (NormalizedDocumentChunker): 100 lines / 16 KiB per generic
chunk, 1024 chunks / 16 MiB per document.
- Explicit format + wrong extension → binding/config error before ingest.
- AUTO + unknown type → skip that file; empty usable set → error.
- Ingest/extract failures throw
com.tnsai.rag.DocumentProcessingException(@since 0.13.0). Catch this type — notIllegalArgumentException— for a missing backend or a corrupt file. The public message has source name, URI, format, and a framework detail. Document bytes are never in it.
| Stage | When |
|---|---|
UNSUPPORTED_FORMAT | No ContentExtractor is installed for the requested format |
VALIDATION | Size / identity / returned-format checks fail |
EXTRACTION | Provider throw, timeout, interrupt, null result, or unreadable explicit office (PDF/DOCX/XLSX/PPTX/EPUB) after the office extractor is on the SPI (TnsAI 0.14.0, TAN-5812) |
DETECTION / CHUNKING | Detection or chunker failures on the same type |
- Binary format declared, extractor/backend absent →
UNSUPPORTED_FORMAT. Never treat those bytes as UTF-8. - Extract timeout default: 30 s (
ContentExtractorRegistry) →EXTRACTION. ContentExtractorRegistry.discover()andFileIngestionServiceshare oneMETA-INF/servicessnapshot (TAN-5812). The office extractor is not hand-appended beside ServiceLoader, so the advertised format set is the ingest set.
Fingerprints and reindex
Each indexed file gets ingestionFingerprint (SHA-256 of source
identity + content hash + declared/detected format + extractor id/
version + include/exclude + chunker id/version). Content bytes alone
do not decide reuse. After a parser, chunker, selector, or extractor
version change, rebuild the index — stale chunks stay until you
re-ingest.
Related
- Knowledge Base
- Pipeline
- Strategies
- Smart segmentation — analysis splitter, not FILE ingest
Embedding prefixes
EmbeddingFunctions.matryoshka derives a shorter, L2-normalized prefix from any EmbeddingFunction. The helper and EmbeddingDimensionMismatchException are @since 0.14.0 in TnsAI 0.14.0 (TnsAI@c2bb5306). They ship in Maven Central 0.14.1.
KnowledgeTools as GraphRAG
KnowledgeToolsGraphStoreProvider is the bundled GraphStoreProvider that serves live KnowledgeTools triples to @Retrieval(strategy = GRAPH). The provider is @since 0.14.0 in TnsAI 0.14.0 (TnsAI@c2bb5306). It ships in Maven Central 0.14.1.