Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .skills/tika-eval-encoding-regression.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ To see what one chain change actually did, Compare the new run against the
(IBM850 / x-MacRoman → windows-1252) vs the prior run and nothing else. A
bigger-than-expected diff means the change fired more broadly than intended.

## Per-file detector attribution (`X-TIKA:encodingDetectionTrace`)
## Per-file detector attribution (`tk:encoding-detection-trace`)

Every JSON extract from a chain with multiple detectors carries
`X-TIKA:encodingDetectionTrace` in metadata. It's a per-detector emission
`tk:encoding-detection-trace` in metadata. It's a per-detector emission
log with the META detector's arbitration tag at the end:

```
Expand All @@ -174,8 +174,8 @@ meta detector chose. If the trace shows ONLY Mojibuster firing with a CJK
pick, the bug is in Mojibuster's emission (pool too narrow), not in
JunkFilter's arbitration.

`X-TIKA:encodingDetector` is the simple-name credit string;
`X-TIKA:detectedEncoding` is the final answer (also in `Content-Encoding`).
`tk:encoding-detector` is the simple-name credit string;
`tk:detected-encoding` is the final answer (also in `Content-Encoding`).

## Reproducing a single-file detection without a full chain

Expand Down
2 changes: 1 addition & 1 deletion .skills/tika-eval-h2-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ WHERE DETECTED_ENCODING REGEXP 'big5|gb|euc|shift|jis|2022|949'
```

(`DETECTED_ENCODING` is on `ENCODINGS_A`/`ENCODINGS_B` — join to `PROFILES`/`CONTENTS`
on `ID` — populated from `X-TIKA:detectedEncoding`.)
on `ID` — populated from `tk:detected-encoding`.)

## Tip

Expand Down
32 changes: 16 additions & 16 deletions docs/modules/ROOT/pages/advanced/embedded-documents.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ documents. They answer: "Which document contained this one?" All fields are defi

=== Nesting Identifiers

`TikaCoreProperties.EMBEDDED_ID` (`X-TIKA:embedded_id`)::
`TikaCoreProperties.EMBEDDED_ID` (`tk:embedded-id`)::
A 1-indexed integer assigned by Tika to each embedded document during parsing. IDs are
assigned in the order documents are encountered by the `RecursiveParserWrapper`. This ID
uniquely identifies each embedded document within a single parse operation.

`TikaCoreProperties.EMBEDDED_ID_PATH` (`X-TIKA:embedded_id_path`)::
`TikaCoreProperties.EMBEDDED_ID_PATH` (`tk:embedded-id-path`)::
A path showing the containment hierarchy using `EMBEDDED_ID` values. For example, `/1/3`
indicates that the file with `EMBEDDED_ID=3` was contained within the file with
`EMBEDDED_ID=1`. This is the most reliable field for tracking containment relationships.
Expand All @@ -64,22 +64,22 @@ folder structures or original paths within the containers themselves.

=== Synthetic Paths

`TikaCoreProperties.EMBEDDED_RESOURCE_PATH` (`X-TIKA:embedded_resource_path`)::
`TikaCoreProperties.EMBEDDED_RESOURCE_PATH` (`tk:embedded-resource-path`)::
A synthetic path built by concatenating file names (from `RESOURCE_NAME_KEY`) at each
nesting level. This provides a human-readable path through the containment hierarchy.
+
WARNING: Do not use this field for creating directory structures to write out attachments.
There may be path collisions, illegal characters, or zip slip vulnerabilities. Use
`EMBEDDED_ID_PATH` for reliable containment tracking.

`TikaCoreProperties.FINAL_EMBEDDED_RESOURCE_PATH` (`X-TIKA:final_embedded_resource_path`)::
`TikaCoreProperties.FINAL_EMBEDDED_RESOURCE_PATH` (`tk:final-embedded-resource-path`)::
Similar to `EMBEDDED_RESOURCE_PATH`, but calculated at the end of the full parse. For some
parsers, an embedded file's name isn't known until after its child files have been parsed.
This field may have fewer "unknown" file names than `EMBEDDED_RESOURCE_PATH`.

=== Resource Naming

`TikaCoreProperties.RESOURCE_NAME_KEY` (`X-TIKA:resourceName`)::
`TikaCoreProperties.RESOURCE_NAME_KEY` (`tk:resource-name`)::
The file name (not path) of the resource. Tika makes a best effort to determine a meaningful
name from the container's metadata. When unavailable, Tika falls back to synthetic names
such as `embedded-1.jpeg`.
Expand All @@ -95,7 +95,7 @@ the nesting structure. All fields below are defined in `TikaCoreProperties`.

=== Internal Paths

`TikaCoreProperties.INTERNAL_PATH` (`X-TIKA:internalPath`)::
`TikaCoreProperties.INTERNAL_PATH` (`tk:internal-path`)::
The path (including file name) as literally stored within the container. This is what the
container knows about where the file lives in its internal structure:
+
Expand All @@ -108,7 +108,7 @@ This differs fundamentally from `EMBEDDED_RESOURCE_PATH`:
* `INTERNAL_PATH` is what the _container stores_ about the file's location within itself
* `EMBEDDED_RESOURCE_PATH` is what _Tika synthesizes_ from the nesting structure

`TikaCoreProperties.ORIGINAL_RESOURCE_NAME` (`X-TIKA:origResourceName`)::
`TikaCoreProperties.ORIGINAL_RESOURCE_NAME` (`tk:orig-resource-name`)::
For some file formats, the file path where the document was last saved on the creator's
system. For example, an `.xlsx` file named `budget.xlsx` may include a metadata property
storing where it was last saved: `C:\Users\Alice\budget.xlsx`. This is not specific to
Expand All @@ -118,7 +118,7 @@ embedded files - it's a property that certain file formats preserve about themse

Microsoft Office formats use additional identifiers for embedded objects.

`TikaCoreProperties.EMBEDDED_RELATIONSHIP_ID` (`X-TIKA:embeddedRelationshipId`)::
`TikaCoreProperties.EMBEDDED_RELATIONSHIP_ID` (`tk:embedded-relationship-id`)::
A Microsoft-specific identifier used internally to reference embedded objects within
Office documents. This is the relationship ID from the Office Open XML or OLE structure.

Expand All @@ -134,35 +134,35 @@ embedded. Defined in the `Office` metadata class.
|Property |Metadata Key |Source

|`EMBEDDED_ID`
|`X-TIKA:embedded_id`
|`tk:embedded-id`
|Containment

|`EMBEDDED_ID_PATH`
|`X-TIKA:embedded_id_path`
|`tk:embedded-id-path`
|Containment

|`EMBEDDED_RESOURCE_PATH`
|`X-TIKA:embedded_resource_path`
|`tk:embedded-resource-path`
|Containment

|`FINAL_EMBEDDED_RESOURCE_PATH`
|`X-TIKA:final_embedded_resource_path`
|`tk:final-embedded-resource-path`
|Containment

|`RESOURCE_NAME_KEY`
|`X-TIKA:resourceName`
|`tk:resource-name`
|Containment

|`INTERNAL_PATH`
|`X-TIKA:internalPath`
|`tk:internal-path`
|Container

|`ORIGINAL_RESOURCE_NAME`
|`X-TIKA:origResourceName`
|`tk:orig-resource-name`
|Container

|`EMBEDDED_RELATIONSHIP_ID`
|`X-TIKA:embeddedRelationshipId`
|`tk:embedded-relationship-id`
|Container (MS)

|`Office.EMBEDDED_STORAGE_CLASS_ID`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ java -jar tika-app.jar -J -t /tmp/tika-app-test/batch-input /tmp/tika-app-test/b
ls /tmp/tika-app-test/batch-output2
----

*Expected:* Creates .json files with text content (X-TIKA:content_handler should be ToTextContentHandler).
*Expected:* Creates .json files with text content (tk:content-handler should be ToTextContentHandler).

=== Test 11: Version Check

Expand Down Expand Up @@ -183,7 +183,7 @@ java -jar tika-app.jar --language testPDF.pdf
java -jar tika-app.jar --digest=md5 --json testPDF.pdf
----

*Expected:* JSON output includes `X-TIKA:digest:MD5` field.
*Expected:* JSON output includes `tk:digest:MD5` field.

=== Test 15: URL Input

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ match.
----

The `parse-context > commons-digester-factory` block makes every
extracted record carry an `X-TIKA:digest:SHA256` metadata field —
extracted record carry an `tk:digest:SHA256` metadata field —
required by `tika-eval` for embedded-document alignment across runs.

=== Config B (variant under test)
Expand Down Expand Up @@ -233,7 +233,7 @@ Open the `.xlsx` files directly, or use the `regression` skill
== Tips

* *Keep the digester identical between A and B.* tika-eval uses the
`X-TIKA:digest:SHA256` field on embedded documents to align records
`tk:digest:SHA256` field on embedded documents to align records
across the two extracts. If A digests and B doesn't (or different
algorithms), the embedded-doc alignment falls back to filename and
produces false-positive diffs.
Expand Down Expand Up @@ -310,7 +310,7 @@ Compare step finishes in 2-5 minutes depending on extract size.
. Open `reports/mimes/mime_diffs_A_to_B.xlsx` to see the headline
MIME-detection differences; the encoding-detector chain change
surfaces as charset diffs in `mimes/mime_diffs_A_to_B_details.xlsx`
(`X-TIKA:detected_encoding`).
(`tk:detected-encoding`).

A regression analysis writeup goes in
`~/Desktop/claude-todo/<reports-dir-name>-analysis.md` per the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/xml
curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/json
----

*Expected:* JSON object with metadata and X-TIKA:content field.
*Expected:* JSON object with metadata and tk:content field.

=== Test 7: PUT /meta

Expand Down
16 changes: 8 additions & 8 deletions docs/modules/ROOT/pages/advanced/setting-limits.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ siblings at the current level continue to be processed.
|`throwOnMaxDepth`
|false
|Whether to throw an `EmbeddedLimitReachedException` when maxDepth is reached.
If false, processing continues and `X-TIKA:maxDepthReached=true` is set in metadata.
If false, processing continues and `tk:exception:embedded-depth-limit-reached=true` is set in metadata.

|`maxCount`
|-1 (unlimited)
Expand All @@ -113,7 +113,7 @@ stops immediately.
|`throwOnMaxCount`
|false
|Whether to throw an `EmbeddedLimitReachedException` when maxCount is reached.
If false, processing continues and `X-TIKA:maxEmbeddedCountReached=true` is set.
If false, processing continues and `tk:exception:embedded-resource-limit-reached=true` is set.
|===

=== maxDepth Behavior
Expand Down Expand Up @@ -380,7 +380,7 @@ Metadata metadata = Metadata.newInstance(context);
|`maxTotalBytes`
|10 MB
|Maximum total estimated size of all metadata in UTF-16 bytes. When exceeded,
additional metadata is silently dropped and `X-TIKA:WARN:truncated_metadata` is set.
additional metadata is silently dropped and `tk:warn:truncated-metadata` is set.

|`maxFieldSize`
|100 KB
Expand Down Expand Up @@ -436,15 +436,15 @@ of `includeFields` or size limits:

* `Content-Type` - Required for parser selection
* `Content-Length`, `Content-Encoding`, `Content-Disposition`
* `X-TIKA:content` - The extracted text content
* `X-TIKA:Parsed-By` - Parser chain information
* `X-TIKA:WARN:*` - Warning metadata
* `tk:content` - The extracted text content
* `tk:parsed-by` - Parser chain information
* `tk:warn:*` - Warning metadata
* Access permission fields

=== Detecting Truncation

When metadata is truncated due to limits, Tika sets the metadata field
`X-TIKA:WARN:truncated_metadata` to `true`. You can check for this in your code:
`tk:warn:truncated-metadata` to `true`. You can check for this in your code:

[source,java]
----
Expand All @@ -458,7 +458,7 @@ if ("true".equals(metadata.get(TikaCoreProperties.TRUNCATED_METADATA))) {

1. **Always set limits** when processing untrusted content
2. **Use `includeFields`** to capture only the metadata you need
3. **Monitor for truncation** by checking `X-TIKA:WARN:truncated_metadata`
3. **Monitor for truncation** by checking `tk:warn:truncated-metadata`
4. **Combine with process isolation** - limits protect against memory issues,
but xref:advanced/robustness.adoc[process isolation] protects against crashes
5. **Test with adversarial files** - use Tika's `MockParser` to simulate extreme cases
Expand Down
4 changes: 2 additions & 2 deletions docs/modules/ROOT/pages/configuration/digesters.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ document deduplication, integrity verification, and forensic analysis.
== Overview

Digesters compute hash values of document content and store them in metadata. The digest value
is stored with a key like `X-TIKA:digest:SHA256` (for HEX encoding) or `X-TIKA:digest:SHA256:BASE32`
is stored with a key like `tk:digest:SHA256` (for HEX encoding) or `tk:digest:SHA256:BASE32`
(for non-default encodings).

Tika provides two digester implementations:
Expand Down Expand Up @@ -95,7 +95,7 @@ By default, digest values are encoded as lowercase hexadecimal. You can specify
}
----

Non-default encodings include the encoding in the metadata key: `X-TIKA:digest:SHA256:BASE32`.
Non-default encodings include the encoding in the metadata key: `tk:digest:SHA256:BASE32`.

=== Skip Container Document Digest

Expand Down
24 changes: 12 additions & 12 deletions docs/modules/ROOT/pages/migration-to-4x/chunk-strategies.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
= Chunk Strategies for Search Engines

Tika 4.x introduces a unified chunking and embedding pipeline (`tika-inference`) that produces
a `tika:chunks` array on each document's metadata. This page describes the strategies for
a `tk:chunks` array on each document's metadata. This page describes the strategies for
emitting those chunks to Elasticsearch and OpenSearch.

== Background
Expand All @@ -33,7 +33,7 @@ The `tika-inference` module produces chunks from two sources:
image embedding endpoint (e.g., Jina CLIP v2). Each chunk carries a `PaginatedLocator`
(page number) and a vector, but no text.

Both types are stored in the same `tika:chunks` metadata field as a JSON array. When multiple
Both types are stored in the same `tk:chunks` metadata field as a JSON array. When multiple
components produce chunks (e.g., image embedder runs during parsing, text embedder runs as a
metadata filter), they merge into the same array via `ChunkSerializer.mergeInto()`.

Expand All @@ -57,13 +57,13 @@ Image-only chunks omit `text`; text-only chunks omit `paginated`.

=== Option A: Chunks as Nested Objects

Each file (container or embedded) is **one ES/OpenSearch document**. The `tika:chunks` field
Each file (container or embedded) is **one ES/OpenSearch document**. The `tk:chunks` field
is mapped as a https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html[`nested`] type.

[source,json]
----
{"index":{"_id":"report.pdf"}}
{"title":"Q4 Report","mime":"application/pdf","tika:chunks":[
{"title":"Q4 Report","mime":"application/pdf","tk:chunks":[
{"text":"Revenue grew...","vector":"...","locators":{"text":[{"start_offset":0,"end_offset":120}]}},
{"text":"Operating costs...","vector":"...","locators":{"text":[{"start_offset":121,"end_offset":300}]}},
{"vector":"...","locators":{"paginated":[{"page":1}]}},
Expand Down Expand Up @@ -143,11 +143,11 @@ within each document (not exploded into separate docs, not a stringified blob).
[source,json]
----
{"index":{"_id":"email.msg"}}
{"title":"Re: Q4 report","mime":"message/rfc822","tika:chunks":[
{"title":"Re: Q4 report","mime":"message/rfc822","tk:chunks":[
{"text":"Hi team, see attached...","vector":"...","locators":{"text":[{"start_offset":0,"end_offset":35}]}}
]}
{"index":{"_id":"email.msg-<uuid>"}}
{"title":"Q4-report.pdf","mime":"application/pdf","parent":"email.msg","tika:chunks":[
{"title":"Q4-report.pdf","mime":"application/pdf","parent":"email.msg","tk:chunks":[
{"vector":"...","locators":{"paginated":[{"page":1}]}},
{"vector":"...","locators":{"paginated":[{"page":2}]}},
{"text":"Revenue grew...","vector":"...","locators":{"text":[{"start_offset":0,"end_offset":120}]}},
Expand All @@ -174,15 +174,15 @@ Tika 4.x currently implements **Option D**:

* The `AttachmentStrategy` (`SEPARATE_DOCUMENTS` or `PARENT_CHILD`) controls how
**embedded files** are emitted — each embedded file becomes its own document.
* The `tika:chunks` field on each document holds all chunks (text + image) as a
* The `tk:chunks` field on each document holds all chunks (text + image) as a
structured JSON array.
* The emitter clients (`ElasticsearchClient`, `OpenSearchClient`) detect the `tika:chunks`
* The emitter clients (`ElasticsearchClient`, `OpenSearchClient`) detect the `tk:chunks`
field and write it as **raw JSON** rather than an escaped string, so the nested objects
are indexable.

== The `tika:chunks` Field
== The `tk:chunks` Field

All chunk data — regardless of source — is unified in a single metadata field: `tika:chunks`.
All chunk data — regardless of source — is unified in a single metadata field: `tk:chunks`.

There is no separate field for image embeddings vs. text embeddings. A chunk is a chunk:

Expand All @@ -207,7 +207,7 @@ For Option D with `nested` kNN support, a mapping like this works:
"mime": {"type": "keyword"},
"content": {"type": "text"},
"parent": {"type": "keyword"},
"tika:chunks": {
"tk:chunks": {
"type": "nested",
"properties": {
"text": {"type": "text"},
Expand Down Expand Up @@ -241,7 +241,7 @@ For Option D with `nested` kNN support, a mapping like this works:
}
----

NOTE: The `vector` field in `tika:chunks` stores base64-encoded float32 arrays during Tika
NOTE: The `vector` field in `tk:chunks` stores base64-encoded float32 arrays during Tika
processing, but the emitter writes them as-is. If your mapping uses `dense_vector`, you may
need a pipeline or custom serialization to convert the base64 vectors to float arrays at
index time. Alternatively, map `vector` as `keyword` and decode at query time.
Expand Down
Loading
Loading