ZyVOP Logo
Content That Connects
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZyVOP Logo
Content That Connects

The Developer Publishing Hub. Write once, cross-post to Dev.to, Medium, Hashnode, WordPress & Bluesky with automated canonical source tags and zero paywalls.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • Developer API & CLI
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Developer Publishing Hub.

Zero paywalls · Full content ownership
All systems operational
HomeEmbedding Docling-NLP in Ad-Hoc UI Applications: A Lightweight Blueprint

Embedding Docling-NLP in Ad-Hoc UI Applications: A Lightweight Blueprint

Alain Airom (Ayrom)
Alain Airom (Ayrom)
Build Engineer
August 31, 2026
3 min read
Embedding Docling-NLP in Ad-Hoc UI Applications: A Lightweight Blueprint
#nlp#doclingnlp#bob#docling
👍1

Implementing a “Graph Language Model” with Docling-NLP

Image from Docling-AI

Image from Docling-AI

Building a local, privacy-focused Document AI pipeline often feels like balancing heavy models with sluggish performance. IBM’s open-source ecosystem solves this by splitting document parsing and entity extraction into two specialized tools: docling (Python-based document conversion) and docling-nlp (a C++ compiled core with Python bindings via pybind11).

This guide outlines a complete, practical framework for embedding docling-nlp into an ad-hoc Streamlit interface, based on the reference architecture designed by IBM Bob.


What is Docling NLP: Graph Language Model

Excerpt from Github;

Finding entities and relations via NLP on text and documents and creating Graphs from NLP entities and relations in document collections
To get easily started, simply install the docling-nlp package from PyPi. This can be done using the traditional pip install docling-nlp or via uv uv add docling-nlp.


High-Level Architecture Overview of the sample implementation

The system divides responsibilities across distinct runtime layers:

  • Streamlit GUI Layer (app.py): Provides interactive controls for raw text, file uploads, URLs, and real-time visualization.

  • Python Processing Layer (src/docling_processor.py): Interfaces with docling to extract reading-order Markdown, DataFrames, and plain text chunks.

  • C++ NLP Layer (src/nlp_processor.py): Uses pybind11 bindings to run native C++ entity and relation extraction at ~1.2M tokens/sec.

Dynamic Workflow & Sequence Dataflow

When a document or raw string is provided, execution moves synchronously across the document parsing pipeline into the pybind11-wrapped C++ core:


Core Implementation

Pre-processing Markdown Input

docling-nlp achieves high performance when operating on clean text spans. Passing raw Markdown syntax (headings, code blocks, links) introduces noise into tokenization boundaries. The utility layer strips markup before passing text down to C++:

def clean_markdown_for_nlp(text: str) -> str:
    """Strip Markdown syntax so C++ NLP receives clean prose."""
    if not text:
        return text
    cleaned = text
    for pattern, replacement in _MD_CLEAN_PATTERNS:
        cleaned = pattern.sub(replacement, cleaned)
    return re.sub(r"\n{3,}", "\n\n", cleaned).strip()

Enter fullscreen mode Exit fullscreen mode

Interfacing with the C++ NLP Core

The NLPProcessor wraps initializations, runs inference on text chunks, and parses zero-indexed array representations back into rich dataclass objects:

# src/nlp_processor.py
from docling_nlp.utils.load_pretrained_models import load_pretrained_nlp_modelsfrom docling_nlp.nlp_utils import init_nlp_model​class NLPProcessor:
    def __init__(self):
        self._model = None​
    def _get_model(self):
        if self._model is None:
            # Load pre-compiled weights and init pybind11 bindings
            load_pretrained_nlp_models(force=False, verbose=False)
            self._model = init_nlp_model()
        return self._model​
    def process_text(self, text: str) -> NLPResult:
        result = NLPResult(source_text=text)
        nlp_input = clean_markdown_for_nlp(text) if is_markdown_text(text) else text

        # Invoke native C++ inference engine
        raw = self._get_model().apply_on_text(nlp_input)
        self._parse_raw_result(raw, result)
        return result

Enter fullscreen mode Exit fullscreen mode

Streamlit Caching & Singletons

Re-loading ONNX parsing models or C++ NLP weights on every UI interaction slows response times. Wrapping processor instantiations with @st.cache_resource ensures singletons persist across application re-runs:

# app.py
@st.cache_resource(show_spinner="Loading Docling processor…")def get_docling_processor() -> DoclingProcessor:
    return DoclingProcessor()​@st.cache_resource(show_spinner="Loading C++ NLP model via pybind11…")def get_nlp_processor() -> NLPProcessor:
    return NLPProcessor()

Enter fullscreen mode Exit fullscreen mode


Conclusion: What This Application Demonstrates

Beyond the underlying code, this ad-hoc application serves as a concrete proof-of-concept for lightweight local document intelligence:

  • Local-First Privacy & Zero Cloud Dependency: Documents, tables, and raw text are parsed entirely on the host machine without sending sensitive data to external API endpoints.

  • High-Speed Hybrid Execution: It shows how Python and native C++ can be bridged via pybind11 to deliver near-instantaneous token processing (~1.2M tokens/sec) directly inside a web interface.

  • Unified Document Extraction: Complex file formats (PDFs, DOCX, HTML, Images) are seamlessly transformed into reading-order Markdown, structured DataFrames, and entity-rich JSON outputs through a single workflow.

  • Zero-Friction Interface: By wrapping sophisticated machine learning pipelines into an intuitive Streamlit UI, non-technical users can interact with complex NLP pipelines without running shell scripts or managing code.

Thanks for reading 🎩

Links

  • Docling.ai: https://docling.ai/

  • Docling Docs: https://docling-project.github.io/docling/

  • Docling Github: https://github.com/docling-project/docling

  • Docling NLP: https://github.com/docling-project/docling-nlp

  • Code repo for this post: https://github.com/aairom/docling-nlp-implementation

Comments (0)

Login to post a comment.

Alain Airom (Ayrom)
Alain Airom (Ayrom)

Build Engineer

IT guy, IBMer... sharing my hands-on experiences and technical subjects of my interest (IBM or not). A bit "touche à tout"!

Subscribe to Alain Airom (Ayrom)'s Newsletter

More from Alain Airom (Ayrom)

View profile

Automating AI Context: How I Built a Custom Extension for IBM Bob IDE to Inject Project Rules

Building my own “vsix” extension to automate my own projects Introduction Setting up consistent workspace instructions across projects can quickly become a tedi...

10 minAug 31

Deep Dive: Testing Radar UI for Kubernetes using MCP, a Go GUI, and an Autonomous Agent

Hand-on test of radarhq.io K8S UI and dashboard on a macOS with Minikube and Podman Introduction Kubernetes dashboards are often either overloaded with unnecess...

5 minAug 31

Loop Engineering 101

From Curiosity to Creation: Building a Loop Engineering Application with IBM’s Bob Introduction For some time now, “Loop Engineering” has been generating signif...

9 minAug 31

Building an OpenTelemetry Instrumentation Wizard

Accelerating observability adoption by automating OpenTelemetry instrumentation across heterogeneous codebases Introduction Years ago, I was tasked with buildin...

14 minAug 31

Benchmarking Local AI: Building a llama.cpp vs. Ollama Comparison & Benchmarking App

Pros and cons of both tools provided by Bob! Introduction I’ve been reading and seeing blog posts regarding the virtues of llama.cpp versus Ollama. Myself, I'm ...

5 minAug 31