Upgrade to Pro — share decks privately, control downloads, hide ads and more …

dev2next 2026 - Garbage In, Insight Out

dev2next 2026 - Garbage In, Insight Out

We blame the model when AI hallucinates. But the most common cause isn't a flawed model — it's flawed data. Or worse, no meaningful data at all.

A document might look perfect on screen, but underneath it's often a flat stream of characters without structure and headings that are just big bold text, tables reduced to a jumble of disconnected cells, figures with captions that bear no relationship to the image they describe, and footnotes scattered wherever the layout engine decided to put them. The relationships between sections, the hierarchy of content, the intent behind a table, etc is lost. What looks like rich, structured content to a human is, to an AI, little more than an undifferentiated wall of tokens.

Enter Docling, an open-source toolkit that tackles this problem head-on: it converts messy, real-world documents into clean, structured, AI-ready data. It understands page layout, table structure, reading order, formulas, and code blocks, producing a rich unified document representation that downstream AI systems can actually reason over.

The catch? Everything we've described lives in the Python ecosystem. And last time I checked, I'm a Java Champion! Even though it gets cold in Colorado, Java developers shouldn't have to be left out in it. That's exactly the gap Docling Java was built to close.

In this session, I'll introduce Docling Java and dive into how it brings first-class document intelligence to the JVM. I'll walk through the library's architecture and show how it plugs naturally into the frameworks and AI stacks you're likely already using.

Along the way, I'll build up from simple to more sophisticated patterns, with a particular focus on building RAG pipelines that produce the kind of meaningful, structured data that gives your model a fighting chance to stop taking the blame. By the end, you'll leave with concrete, runnable patterns you can take back to your own Java codebase.

Avatar for Eric Deandrea

Eric Deandrea PRO

October 13, 2026

Video

More Decks by Eric Deandrea

Other Decks in Technology

Transcript

  1. Who wrote this paper? “...the paper titled “Segmentation for document

    layout analysis: not dead yet” was written by Logan Markewich, Hao Zhang, Yubin Xing, Navid Lambert-Shirzad, Jiang Zhexin, Roy Lee, Zhi Li, and Seok-Bum Ko.” @edeandrea
  2. Who am I? • Java Champion • 27+ years software

    development experience • Works on Open Source projects Quarkus LangChain4j, Quarkus LangChain4j Docling Java, Quarkus Docling Langfuse Java, Quarkus Langfuse Spring Boot, Spring Framework, Spring Security Testcontainers Wiremock Microcks • Boston Java Users ACM Chapter Vice Chair & Board Member • Published Author • Cat lover @edeandrea
  3. Retrieval Augmented Generation (RAG) Enhance LLM knowledge by providing relevant

    information in real-time from other sources – Dynamic data that changes frequently ᠆ Fine-tuning is expensive! 2 stages ᠆ ᠆ Indexing / Ingestion Retrieval / Augmentation @edeandrea
  4. Retrieval Augmented Generation (RAG) Enhance LLM knowledge by providing relevant

    information in real-time from other sources – Dynamic data that changes frequently ᠆ Fine-tuning is expensive! 2 stages ᠆ ᠆ Indexing / Ingestion Retrieval / Augmentation @edeandrea
  5. DocLayNet Pfitzmann, Auer, Dolfi, Nassar, Staar (IBM Research, KDD 2022)

    A real, peer-reviewed paper. Five-author header, dense twocolumn body, complex tables, figures, footnotes: everything our abstract complains about. It's a paper about document-layout analysis. It's about to have its own layout analyzed. arxiv.org/abs/2206.01062 @edeandrea
  6. Mode A: The obvious way Extract Apache Tika: plain text,

    no layout awareness Chunk Sentence splitter: fixed rules, no table sense This is the same code most people reach for first. This is what it actually does to our document. @edeandrea
  7. 🔴 LIVE Mode A: “Who wrote the paper?” “...the paper

    titled “Segmentation for document layout analysis: not dead yet” was written by Logan Markewich, Hao Zhang, Yubin Xing, Navid Lambert-Shirzad, Jiang Zhexin, Roy Lee, Zhi Li, and Seok-Bum Ko.” “This is the most clearly identified paper in the context with its author list provided.” @edeandrea
  8. 🔴 LIVE Mode A: “Who wrote the paper?” “...the paper

    titled “Segmentation for document layout analysis: not dead yet” was written by Logan Markewich, Hao Zhang, Yubin Xing, Navid Lambert-Shirzad, Jiang Zhexin, Roy Lee, Zhi Li, and Seok-Bum Ko.” No . ] 5 on [ er . p a p s t thi “This is the most clearly identified paper in the context with its author list provided.” Tha at t i c t's i @edeandrea
  9. 🔴 LIVE Mode A: “Who wrote the paper?” “...the paper

    titled “Segmentation for document layout analysis: not dead yet” was written by Logan Markewich, Hao Zhang, Yubin Xing, Navid Lambert-Shirzad, Jiang Zhexin, Roy Lee, Zhi Li, and Seok-Bum Ko.” No . ] 5 on [ er . p a p s t thi “This is the most clearly identified paper in the context with its author list provided.” Tha at t i c t's i What actually got retrieved (top 4, by score): 0.80 “In 2017 14th IAPR International Conference on Document Analysis and Recognition …” 0.79 “In Proceedings of the 28th International Conference on Computational Linguistics…” 0.79 “In Proceedings of the International Conference on Document Analysis and Recognit…” 0.78 “In Proceedings of the International Conference on Document Analysis and Recognit…” @edeandrea
  10. Mode A: The Extractor package dev.ericdeandrea.docling.ai.ingestion.extraction; public class TikaExtractor {

    private final ApacheTikaDocumentParser parser = new ApacheTikaDocumentParser(); public ExtractionResult extract(Path documentPath) { return new ExtractionResult(FileSystemDocumentLoader.loadDocument(documentPath, parser)); } } The extraction logic, imports omitted. No configuration, no tuning, no reason to suspect it's wrong. @edeandrea
  11. Mode A: The Chunker package dev.ericdeandrea.docling.ai.ingestion.chunking; public class NaiveChunker {

    public List<TextSegment> chunk(ExtractionResult result, Mode mode) { var splitter = new DocumentBySentenceSplitter(maxTokens, overlap); var segments = splitter.split(result.document()); // 2 sentences before + after, joined as "extended_content" metadata enrichWithSurroundingContext(segments, 2, 2); return segments.stream() // attachMetadata() tries to attach provenance, but there isn't any here. .map(segment -> attachMetadata(segment, result, mode)) .toList(); } } @edeandrea
  12. Retrieval: the boring part, on purpose package dev.ericdeandrea.docling.ai.rag; final class

    ExtendedContentRetrievalAugmentorBuilder { static RetrievalAugmentor build(EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel, DemoConfig config) { var retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(config.rag().topK()) .build(); // This is the line that surfaces the chunker's "extended_content" // enrichment to the LLM. Everything else here is default wiring. var contentInjector = DefaultContentInjector.builder() .metadataKeysToInclude(List.of("extended_content")) .build(); } return DefaultRetrievalAugmentor.builder() .contentRetriever(retriever) .contentInjector(contentInjector) .build(); } Same for all three modes. Mostly LangChain4j's own builder vocabulary, barely any of it is ours. @edeandrea
  13. “vegetative electron microscopy” A phrase that means nothing. It's appeared

    in dozens of papers anyway. It's now used as a fingerprint by paper-mill screening tools. One theory, not confirmed: a column-misread spliced two phrases together. Reading order isn't just a demo inconvenience. It's already real. retractionwatch.com/2025/02/10/vegetative-electron-microscopy-fingerprint-paper-mill
  14. Why not just a bigger model? Cost Running a vision-language

    model over every page doesn't scale the way a purpose-built extraction step does. @edeandrea
  15. Why not just a bigger model? Cost Running a vision-language

    model over every page doesn't scale the way a purpose-built extraction step does. Latency Big vision models are slow. Fine for a demo, not fine for a pipeline processing real volume. @edeandrea
  16. Why not just a bigger model? Cost Running a vision-language

    model over every page doesn't scale the way a purpose-built extraction step does. Latency Big vision models are slow. Fine for a demo, not fine for a pipeline processing real volume. Capacity Throwing the whole document at a bigger model just moves the chunking problem earlier. It doesn't remove it. @edeandrea
  17. Why not just a bigger model? Cost Running a vision-language

    model over every page doesn't scale the way a purpose-built extraction step does. Capacity Throwing the whole document at a bigger model just moves the chunking problem earlier. It doesn't remove it. Latency Big vision models are slow. Fine for a demo, not fine for a pipeline processing real volume. Privacy A lot of enterprises can't send proprietary documents to a third-party API. On-prem isn't optional for them. @edeandrea
  18. Meet Docling Open source Document intelligence Multi-format MIT license, Linux

    Foundation project Advanced, cost-efficient PDF, Word, PowerPoint, HTML, and more Unified representation Privacy & security Plug-and-play Rich, LLM-friendly Self-host it, or use the managed service For building apps & agents docling.ai @edeandrea
  19. Mode B: One thing changes Extract Docling instead of Tika:

    structured extraction, layout & table awareness. Chunk The exact same sentence splitter as Mode A. Unchanged. On purpose. Everything downstream of extraction (embedding model, vector store, retrieval, prompt, LLM) stays identical to Mode A. @edeandrea
  20. Mode B: One thing changes Extract Docling instead of Tika:

    structured extraction, layout & table aware. Chunk The exact same sentence splitter as Mode A. Unchanged. On purpose. Everything downstream of extraction (embedding model, vector store, retrieval, prompt, LLM) stays identical to Mode A. If the answer changes, extraction is the only thing that could have caused it. @edeandrea
  21. 🔴 LIVE “Who wrote the paper?” again Mode A (Tika)

    Mode B (Docling) “...the paper titled “Segmentation for document layout analysis: not dead yet” was written by Logan Markewich, Hao Zhang, Yubin Xing, Navid Lambert-Shirzad, Jiang Zhexin, Roy Lee, Zhi Li, and Seok-Bum Ko.” “...the paper “DocLayNet: A Large HumanAnnotated Dataset for Document-Layout Analysis” was written by: Birgit Pfitzmann, Christoph Auer, Ahmed S. Nassar, Michele Dolfi, and Peter Staar” Wrong. Still. ...then confirms it by walking through every author's IBM Research Rueschlikon address and email from the extended-content block, plus the arXiv:2206.01062v1 metadata. Correct. Verbose. @edeandrea
  22. Mode B: The Extractor Swap package dev.ericdeandrea.docling.ai.ingestion.extraction; public class DoclingNaiveExtractor

    { public Uni<ExtractionResult> extract(Path documentPath) { var parser = DoclingDocumentParser.builder() .doclingClient(this.doclingServeApi) .documentRequest(request) .documentExtractor(response -> { // Flattens the structured DoclingDocument into the full-text Document // The naive chunker sentence-splits var doclingDoc = response.getDocument().getJsonContent(); doclingDocumentHolder.set(doclingDoc); return Document.from(buildFullText(doclingDoc)); }) .build(); } return Uni.createFrom() .completionStage(Unchecked.supplier(() -> { var in = Files.newInputStream(documentPath); return parser.parseAsync(in) .whenComplete((_, _) -> closeQuietly(in)); })) .map(document -> new ExtractionResult( document, buildProvenance(doclingDocumentHolder.get(), document.text()))); } buildFullText() and buildProvenance() do the real work here. @edeandrea
  23. Mode C: One more thing changes Extract + chunk Docling's

    hybrid chunker, in one server-side round trip. No local NaiveChunker at all this time. Table rows become facts Each cell keeps its row and column label attached, e.g. “All, FRCNN.R101 = 73.4”, so one chunk carries a complete fact instead of needing to correlate headers across chunks. Orphaned figure text gets rescued Chart labels that would otherwise be silently dropped get collected into their own retrievable chunk. @edeandrea
  24. 🔴 LIVE Full circle: “Who wrote the paper?” Mode A

    Mode B Mode C “...Segmentation for document layout analysis: not dead yet… Logan Markewich, Hao Zhang, et al.” “...the paper … was written by: Birgit Pfitzmann, Christoph Auer, Ahmed S. Nassar, Michele Dolfi, and Peter Staar” “...the authors of the paper are: Birgit Pfitzmann, Christoph Auer, Michele Dolfi, Ahmed S. Nassar, and Peter Staar” ...then walks through every author's IBM Research address and email from the extended-content block, plus the arXiv metadata, to confirm it. “...clearly stated in the ACM Reference Format section at the beginning of the document.” Wrong. Correct. Verbose. Correct. Direct. @edeandrea
  25. 🔴 LIVE The easy questions tie too “How many annotators

    were used in the production annotation phase, and how long did it take?” A, B, and C: 32 annotators, approximately three months. All three, correct. “What percentage of DocLayNet pages are Patents?” A, B, and C: 8%. All three, correct. (Mode C only gets there because of the orphanedpicture rescue from the last slide.) @edeandrea
  26. 🔴 LIVE Same answer, wildly different evidence “What does Table

    2 show, and what network architecture won overall?” Mode A Mode B Mode C “YOLOv5x won overall.” “YOLOv5x6 won overall in Table 2.” YOLOv5x6: 77.7, R101: 71.5, FRCNN: 70.1, R50: 68.4 Correct, with the actual scores. Correct. Bare assertion, no scores, no metadata. Correct. Same assertion, now with page/type metadata in the chunks. @edeandrea
  27. 🔴 LIVE Only Mode C can answer “By how many

    mAP points does YOLOv5x outperform Faster R-CNN overall?” Mode A Mode B Mode C “I don't have enough information.” “The actual table with numerical values is not included in the provided context.” “FRCNN.R101: 70.1, YOLOv5x6: 77.7. The difference is 77.7 - 70.1 = 7.6 mAP points.” @edeandrea
  28. Mode C: extract and chunk, one call package dev.ericdeandrea.docling.ai.ingestion.extraction; public

    class DoclingHybridExtractor { public Uni<List<TextSegment>> extractAndChunk(Path documentPath) { // One request: extraction AND structure-aware chunking, server-side. var request = HybridChunkDocumentRequest.builder() .includeConvertedDoc(true).build(); doclingServeApi.chunkFilesWithHybridChunkerAsync(request, documentPath) .map(response -> { // Server already returns fully-formed chunks. No local chunker. var segments = response.getChunks().stream() .map(chunk -> TextSegment.from(chunk.getText(), metadataFor(chunk))) .collect(toCollection(ArrayList::new)); // Rescue chart labels the chunker would otherwise drop. rescueOrphanedPictureText(response, segments); return segments; }); } } Simplified for the slide: the real method inlines this logic rather than calling named helpers. Same behavior. @edeandrea
  29. Not just a Quarkus thing LangChain4j What this whole demo

    runs on Quarkus quarkus-docling, co-maintained with Alex Soto Spring Boot Arconia by Thomas Vitale, plugs into Spring AI's RAG pipeline Thomas Vitale and I built the same idea independently, then joined forces: docling-java, one foundation under all three. @edeandrea
  30. Five questions, three modes, all real Mode A Mode B

    Mode C Annotators & timeline ✓ ✓ ✓ Patents percentage ✓ ✓ ✓ Who wrote the paper? ✗ ✓ ✓ Table 2 winner (bare → metadata → scores) ✓ ✓ ✓✓ mAP difference (only C answers) ✗ ✗ ✓✓ Question ✗ couldn't ✓ answered ✓✓ answered with grounded evidence (page / table / scores) @edeandrea