Datagrunt 5.3.8: Rationalization Hot-Path Performance and Include Schema Cache Collision Fix
Datagrunt 5.3.8 is now available! This release focuses on deep performance optimizations across the rationalization structured extraction subsystem (src/datagrunt/rationalization/), introduces a new fault-isolated batch envelope builder (build_envelopes_isolated), and resolves a subtle cache collision bug involving include_schema=False (#490).
Key Highlights in Datagrunt 5.3.8
include_schemaCache Collision Fix (envelope.py) — Resolves a cache key material generation issue inEnvelope.key_material()whereinclude_schema=Falseandinclude_schema=Trueproduced identical JSON key material wheninclude_schemawas omitted whenTrue.- Fault-Isolated Batch Envelope Building (
build_envelopes_isolated) — Introducesbuild_envelopes_isolated()to process extraction units while isolating per-unit non-fatal PDF rendering errors intoSkippedUnit(reason="image_only")objects without aborting batch envelope assembly. - Iterative Zero-Parse Deep JSON Cloning (
_clone_jsoninwire.py) — Replaces costlyjson.dumps()/json.loads()canonical serialization cycles with an iterative, non-recursivedict/listdeep copy routine bounded at 1,000,000 nodes. - Pre-Validated Pipeline Fast Paths (
_trusted_*constructors) — Bypasses redundant UTF-8 encodability and string validation loops during internal batch extraction pipelines via_trusted_model_request,_trusted_provider_response, and_trusted_envelope. - Schema & Reference Hot-Path Acceleration (
_refs.py,_canonical.py) — Adds $O(1)$ ASCII fast-paths incanonical_json, fast string pointer formatting injson_pointer, fast token checks indef_name, and stack-allocated subschema traversal (_push_subschemas).
1. Resolving the include_schema Cache Key Collision Bug (#490)
Understanding the Cache Collision Risk
In Datagrunt’s schema-driven PDF extraction pipeline, the Envelope object represents the formatted system and user prompt pair supplied to LLM providers. To avoid redundant LLM requests, Envelope.key_material() generates canonical JSON representing the cache key inputs.
Prior to version 5.3.8, Envelope.key_material() omitted the include_schema flag when include_schema=True and only set material["include_schema"] = False when disabled. Under specific prompt configurations, this could lead to identical cache key material across requests where include_schema differed, causing potential cache collisions across provider execution modes.
Hardened Component Reference Tracking & Caching
Datagrunt 5.3.8 fixes this collision and optimizes key material generation:
- Explicit False Mapping:
include_schemais explicitly specified whenFalse. - Exact Reference State (
_key_state): Internal memoization captures exact object identity tuples across all 13 envelope components (system_rules,schema_json,context_json,payload,images, etc.). - Instantaneous Key Material Reuse: If component references remain untouched,
_key_material_json()returns pre-rendered canonical JSON without re-traversing the material dictionary.
from datagrunt.rationalization.envelope import Envelope
# Create envelopes with identical payloads but different schema inclusion settings
env_with_schema = Envelope(
unit_id="doc1:p0001",
prompt="Extract invoice items",
context_json="{}",
payload="<el id=\"p0001_e001\">...</el>",
schema_json='{"type": "object"}',
header_element_ids=(),
include_schema=True,
)
env_no_schema = Envelope(
unit_id="doc1:p0001",
prompt="Extract invoice items",
context_json="{}",
payload="<el id=\"p0001_e001\">...</el>",
schema_json='{"type": "object"}',
header_element_ids=(),
include_schema=False,
)
# Guaranteed unique cache key materials
assert env_with_schema.key_material() != env_no_schema.key_material()
assert "include_schema" in env_no_schema.key_material()2. Fault-Isolated Batch Envelope Building (build_envelopes_isolated) (#490)
Graceful Error Handling for Large-Scale PDF Batches
When processing thousands of PDF pages in multi-tenant ingestion pipelines, individual page image renders can occasionally fail due to corrupted stream data or isolated renderer faults. Previously, an exception during page rendering within build_envelopes() would interrupt the entire document envelope creation process.
Isolating Soft Render Faults
Datagrunt 5.3.8 introduces build_envelopes_isolated() in src/datagrunt/rationalization/envelope.py:
from datagrunt import PDFReader
from datagrunt.rationalization.envelope import build_envelopes_isolated
from datagrunt.rationalization.units import build_units
document = PDFReader("complex_multipage_report.pdf").document
units = build_units(document, multimodal=True)
# Build envelopes with per-unit fault isolation
kept_units, envelopes, skipped_units = build_envelopes_isolated(
units,
document,
prompt="Extract financial tables",
context=None,
schema_json='{"type": "object"}',
multimodal=True,
)
print(f"Successfully generated {len(envelopes)} envelopes across {len(kept_units)} units.")
if skipped_units:
print(f"Skipped {len(skipped_units)} problematic page units:")
for skipped in skipped_units:
print(f" Unit: {skipped.unit_id}, Reason: {skipped.reason}")Fatal vs. Soft Exception Isolation
build_envelopes_isolated() catches non-fatal DatagruntPDFError instances during page rendering and converts the unit into a SkippedUnit(reason="image_only"). Fatal errors (PDFEncryptedError, PDFCorruptError, PDFSourceChangedError, BundleCorruptError) continue to be re-raised immediately to prevent downstream processing of invalid or tampered documents.
3. High-Throughput Wire & Framing Hot-Path Performance (#490)
Iterative Zero-Parse Deep JSON Cloning (_clone_json)
In batch pipeline operations, transferring schemas and model requests between provider interfaces required creating deep copies of JSON structures. Standard copy.deepcopy() or json.loads(json.dumps()) roundtrips incur heavy CPU and memory allocation overhead.
Datagrunt 5.3.8 implements _clone_json() in src/datagrunt/rationalization/wire.py:
- Iterative Stack Processing: Copies
dictandliststructures using explicit queues, avoiding Python recursion limit issues on deep schemas. - ASCII & Scalar Fast Paths: Bypasses UTF-8 re-encoding for ASCII string keys and primitive scalars (
int,bool, finitefloat). - Node Cap Safety (
_CLONE_MAX_NODES = 1_000_000): Enforces a maximum node limit during cloning to prevent resource exhaustion attacks on untrusted schemas.
Pre-Computed Header & Opener Escaping
Within envelope.py, rendering unit section openers and header context blocks previously re-escaped header texts repeatedly for every unit in a document.
- Single-Pass Opener Escaping (
_opener_lines): Precomputes and caches single-line escaped strings (_one_line) once per unique visible opener heading across all document group scopes. - Pre-Padded Document Line (
doc_line): Pre-escapes the document ID header string (<document>...</document>) on_Framecreation, removing string formatting overhead inside hot loops.
Summary of Changes in 5.3.8
| File | Changes | Description |
|---|---|---|
src/datagrunt/rationalization/envelope.py |
+435 / -95 | Implemented build_envelopes_isolated, fixed include_schema cache collision bug, added _trusted_envelope, precomputed opener lines, and memoized image digests. |
src/datagrunt/rationalization/result.py |
+445 / -139 | Optimized result extraction hot paths, fast-path verification, and provider response handling. |
src/datagrunt/rationalization/schema.py |
+250 / -10 | Optimized schema transformation and validation hot paths. |
src/datagrunt/rationalization/wire.py |
+172 / -0 | Implemented _clone_json, _trusted_model_request, _trusted_provider_response, and _to_trusted_json. |
src/datagrunt/rationalization/units.py |
+162 / -23 | Optimized unit element ownership checks and block validation. |
src/datagrunt/rationalization/_refs.py |
+37 / -14 | Optimized reference pointer formatting, unescaped token detection, and subschema iteration. |
src/datagrunt/rationalization/_canonical.py |
+3 / -2 | Added ASCII fast path to canonical_json. |
src/datagrunt/rationalization/markers.py |
+25 / -2 | Optimized marker resolution and validation. |
tests/rationalization_tests/* |
+817 / -0 | Added comprehensive unit tests for isolated envelope creation, _clone_json, cache collision prevention, and ref parsing. |
pyproject.toml & __init__.py |
+3 / -3 | Bumped package version from 5.3.7 to 5.3.8. |
Getting Started
To upgrade to Datagrunt 5.3.8 using uv:
uv pip install --upgrade datagruntFor schema-driven PDF extraction support:
uv pip install --upgrade "datagrunt[pdf,rationalize]"