A technical deep dive into architecting an end-to-end playground for DocLang — the AI-native markup language built for LLMs.
🚀 Introduction & Overview
As Large Language Model (LLM) applications mature, a fundamental friction point remains: legacy document formats were never designed for tokenizers.
- PDF was built for precise visual print layout.
- DOCX was built for human desktop editors.
- HTML is bloated with display tags, costing up to 5× more tokens for structured elements like tables.
DocLang is an open document standard governed by *Linux Foundation AI & Data *(backed by IBM, NVIDIA, Red Hat, ABBYY, and HumanSignal). DocLang maps structured documents cleanly to LLM tokens while preserving precise geometry, semantic hierarchies, code blocks, and formulas in an unambiguous XML markup representation.
What is Doclang?
Excerpt from Doclang’s site.
DocLang is the AI-native markup format for unstructured content — documents, images, audio, and video alike. It is engineered from the ground up around a single principle: mapping cleanly to LLM tokens. That makes DocLang the most efficient way to read, write, and reason about real-world content with modern AI.
The world’s knowledge lives in formats — PDF, HTML, Word, LaTeX, MP3, MP4 — that were designed for rendering or playback, not for understanding. The moment you hand them to an AI system, you lose structure, semantics, layout, timing, or all of them at once. And the formats AI does speak fluently fall short too: Markdown can’t describe complex content, HTML wastes tokens, LaTeX is ambiguous, and none of them speak audio or video at all.
DocLang fixes this:
- AI-native — a controlled vocabulary that aligns 1-to-1 with LLM tokenizers, keeping prompts and outputs short and predictable
- Lossless — preserves structure, semantics, layout, and geometry in a single representation
- Expressive — first-class support for tables, formulas, code, charts, nested lists, forms, and multimodal content with visual grounding
- Beyond documents — extends naturally to audio and video, with native primitives for transcripts, speakers, timestamps, scenes, and audio-visual grounding — so an interview, a lecture recording, or a film script lives in the same representation as a PDF
- Unambiguous — every tag has one job, so the same content always serializes the same way
- Open — an ISO standard, developed in the open, governed by industry leaders
If you build with LLMs and VLMs on real-world content, DocLang is the substrate you’ve been missing.
Implementation
To demonstrate the full lifecycle of ingesting, converting, validating, and querying DocLang, Bob authored and wired together the DocLang Demonstration Application.
┌─────────────────────────────────────────────────────────────────┐
│ Browser (UI) │
│ ┌───────────┐ ┌───────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ Markdown │ │ DocLang │ │ Upload │ │ Ask Ollama │ │
│ │ → DocLang │ │ Editor │ │ Document │ │ (Q&A on docs) │ │
│ └─────┬─────┘ └─────┬─────┘ └────┬─────┘ └────────┬────────┘ │
└────────│─────────────│────────────│───────────────────│─────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ Flask API (app.py) │
│ │
│ /api/convert/markdown → markdown_to_doclang() │
│ /api/convert/doclang → doclang_to_html() │
│ /api/validate → validate_doclang() │
│ /api/upload/submit → Docling job started (returns job_id) │
│ /api/upload/status/<id>→ poll job → doclang + preview │
│ /api/ask → Ollama /api/generate │
│ /api/save → output/{name}_{timestamp}.dclg.xml │
│ /api/samples → input/**/*.dclg.xml │
└──────────┬──────────────────────────┬───────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────────┐
│ Docling Engine │ │ Ollama (local LLM) │
│ (PDF/DOCX/HTML │ │ granite / any │
│ → DocLang XML) │ │ model installed │
└─────────────────┘ └──────────────────────┘
🏗️ System Architecture & Workflow Schemas
The application is structured as a lightweight, fast Flask API backing a multi-tab Single-Page Application (SPA) interface. It seamlessly bridges client-side interactions with heavy-duty document parsing engines and local LLMs.
High-Level System Architecture

The DocLang Demonstration Application is architected as a decoupled, multi-tier system engineered for low latency and smooth document processing. At its core, a lightweight Flask REST API coordinates requests between an interactive Single-Page Application (SPA) frontend, local file storage, and specialized downstream service workers. To keep the UI highly responsive during heavy document transformations, long-running extraction jobs are offloaded to an asynchronous thread pool worker powered by IBM’s Docling engine, while grounded natural language querying is driven directly by a local Ollama LLM instance.
Document Processing & Ingestion Pipeline
Under the hood, the application balances real-time user feedback with heavy computational tasks. The architecture is based on a fast Flask backend running on Python 3.10+, serving an intuitive multi-tab Single-Page Application. Rather than locking up the user interface when parsing massive PDFs, the application decouples frontend UI events from heavy background jobs — handing off document extraction to background threads and local AI inference to Ollama via local API calls.
🛠️ Key Implementation Highlights
Translating the DocLang specification from concept to a production-ready Web application required addressing critical real-world edge cases across multi-threading, schema conversion, and local LLM orchestration. The core backend implementation in app.py bridges low-level system hardware constraints with high-level parsing logic. Below, we break down three foundational components of the application's implementation, detailing how we tackled macOS hardware threading crashes, authored an efficient client-side Markdown converter, and connected DocLang directly to local Ollama inference.
Solving the macOS Metal / PyTorch MPS Threading Crash
When executing deep learning models (such as Docling’s layout and OCR models) inside a background worker thread on macOS, PyTorch attempts to dispatch ops through Apple Metal (MPS). In non-main threads, this throws an unrecoverable C-level abort: MTLCompiler: compileRequest ... Crashing instead.
Bob solved this cleanly in app.py by forcing PyTorch MPS fallback before any imports occur, and pinning Docling explicitly to CPU thread pools:
import os
# MUST be configured prior to importing torch or docling
os.environ.setdefault("PYTORCH_ENABLE_MPS_FALLBACK", "1")
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.pipeline_options import PdfPipelineOptions, AcceleratorOptions, AcceleratorDevice
def _make_converter():
"""Build a DocumentConverter pinned to CPU to ensure thread-safe execution on macOS."""
accel = AcceleratorOptions(num_threads=4, device=AcceleratorDevice.CPU)
opts = PdfPipelineOptions()
opts.accelerator_options = accel
return DocumentConverter(
format_options={
"pdf": PdfFormatOption(pipeline_options=opts),
}
)
Hand-Rolled Markdown to DocLang XML Parser
For fast client-side transformations without invoking heavy neural models, app.py features a custom Markdown-to-DocLang parser. It transforms standard Markdown elements into native DocLang tags:
def markdown_to_doclang(md_text: str) -> str:
"""Convert simplified Markdown into valid DocLang XML markup."""
lines = md_text.strip().splitlines()
elements: list[str] = []
i = 0
while i < len(lines):
line = lines[i]
stripped = line.strip()
if stripped.startswith("### "):
elements.append(f' <heading level="3">{stripped[4:]}</heading>')
elif stripped.startswith("## "):
elements.append(f' <heading level="2">{stripped[3:]}</heading>')
elif stripped.startswith("# "):
elements.append(f' <heading level="1">{stripped[2:]}</heading>')
elif stripped.startswith("```
"):
lang = stripped[3:].strip() or "text"
code_lines: list[str] = []
i += 1
while i < len(lines) and not lines[i].strip().startswith("
```"):
code_lines.append(lines[i])
i += 1
code_body = "\n".join(code_lines)
elements.append(
f' <code>\n <label value="{lang}"/>\n'
f' <content><![CDATA[\n{code_body}\n ]]></content>\n </code>'
)
elif stripped.startswith("- "):
list_items: list[str] = []
while i < len(lines) and lines[i].strip().startswith("- "):
list_items.append(f" <item><text>{lines[i].strip()[2:]}</text></item>")
i += 1
elements.append(" <list>\n" + "\n".join(list_items) + "\n </list>")
continue
elif stripped:
elements.append(f" <text>{stripped}</text>")
i += 1
return "<doclang>\n" + "\n".join(elements) + "\n</doclang>"
Local LLM Q&A Integration with Ollama
DocLang’s concise XML representation makes it optimal for direct inclusion in system prompts. The application routes user queries and DocLang markup directly to local Ollama models:
def ask_ollama(question: str, context_dclg: str) -> str:
"""Perform grounded Q&A over parsed DocLang XML using local Ollama instance."""
prompt = textwrap.dedent(f"""
You are a helpful assistant. The following is a document in DocLang format
(an AI-native XML document standard). Answer the user's question using only
the information present in the document.
<document>
{context_dclg}
</document>
Question: {question}
Answer:
""").strip()
resp = requests.post(
f"{OLLAMA_BASE_URL}/api/generate",
json={"model": OLLAMA_MODEL, "prompt": prompt, "stream": False},
timeout=60,
)
return resp.json().get("response", "").strip()
📊 Token Efficiency Benchmark
DocLang slashes context window consumption compared to legacy HTML representations — achieving ~64.2% token savings on standard documents containing complex tables, headings, and code samples.
🧪 Automated Testing Suite
To ensure reliability across background task queues, file IO, and API validation, Bob engineered a unit test suite using pytest in tests/test_app.py:
class TestAPIRoutes:
def test_api_convert_markdown(self, client):
resp = client.post("/api/convert/markdown", json={"markdown": "# Hello\n\nWorld."})
assert resp.status_code == 200
data = resp.get_json()
assert "doclang" in data
assert "html_preview" in data
assert "tokens" in data
def test_api_upload_submit_creates_job(self, client):
from io import BytesIO
data = {"file": (BytesIO(b"<html><body>Hello</body></html>"), "test.html")}
resp = client.post("/api/upload/submit", data=data, content_type="multipart/form-data")
assert resp.status_code == 200
body = resp.get_json()
assert "job_id" in body
# Poll async status
job_resp = client.get(f"/api/upload/status/{body['job_id']}")
assert job_resp.status_code == 200
💡 Conclusion
The DocLang Demo Application designed by Bob provides a complete blueprint for integrating next-generation AI-native document formats into enterprise software workflows.
By pairing IBM Docling’s multi-format extraction with DocLang’s token-optimized XML schema and Ollama’s local LLM reasoning, developers can build privacy-first, lightning-fast document intelligence pipelines.
Thanks for reading ⭐
Links
- Doclang site: https://doclang.ai/
- Doclang Project repository: https://github.com/doclang-project
- Code repository for this post: https://github.com/aairom/Doclang-Test










Top comments (0)