Skip to main content
Version: 3.1

Using Document Intelligence

Document Intelligence converts PDF, Word, and Excel documents and web pages into Markdown so that your Reaktors can process their content with AI models. Under the hood it uses Azure Document Intelligence (formerly Form Recognizer) for PDF conversion, mammoth for Word, SheetJS for Excel, and a built-in HTML-to-Markdown transformer for web pages. Everything is available through the @operaide/document package.


Overview

The package provides five groups of Aktors:

GroupPurpose
PDF ConversionConvert PDFs (URL or base64) to Markdown
Word ConversionConvert DOCX files (base64) to Markdown
Excel ConversionConvert XLSX workbooks (base64) to one CSV block per sheet
Page & Chapter ManipulationSplit, filter, and number pages and chapters within converted Markdown
URL to MarkdownFetch web pages and convert their HTML to Markdown

PDF conversion requires a configured Connection of type document-intelligence. See the administrator guide for connection setup, caching, and proxy configuration.


PDF Conversion

aktorConvertPDFToMarkdown

Converts a single PDF to Markdown. The PDF can be passed as a URL or a base64 data string.

import { aktorConvertPDFToMarkdown } from '@operaide/document';

const markdown = aktorConvertPDFToMarkdown({
pdf: pdfUrlOrBase64, // URL string or base64 data
connectionName: 'default', // optional — name of the document-intelligence connection
});
ParameterTypeDescription
pdfstringThe PDF to convert — either a URL or a data:application/pdf;base64,… string
connectionNamestring (optional)Name of the Document Intelligence connection. Falls back to system default when omitted. Use 'default' for the default connection.

Returns a string containing the Markdown representation of the PDF.

aktorConvertMultiplePDFsToMarkdown

Batch-converts an array of PDFs. Each PDF is converted sequentially through the same connection.

import { aktorConvertMultiplePDFsToMarkdown } from '@operaide/document';

const markdowns = aktorConvertMultiplePDFsToMarkdown({
pdfs: [pdfUrl1, pdfUrl2],
connectionName: 'default',
});
ParameterTypeDescription
pdfsstring[]Array of PDF URLs or base64 strings
connectionNamestring (optional)Connection name (same as above)

Returns string[] — one Markdown string per input PDF.

Full Example: PDF to AI Extraction

A typical workflow converts a PDF attachment to Markdown and then passes the text to an LLM for structured extraction:

import { aktorSetting, createAktorComposition, registerReaktorDefinition } from '@operaide/aktor';
import { aktorAICall, aktorAISettingProviderModel, aktorMessagesFromSystemAndUser } from '@operaide/ai';
import { aktorConvertPDFToMarkdown } from '@operaide/document';
import { z } from 'zod';

const aktorInvoiceExtractor = createAktorComposition('aktorInvoiceExtractor', ({ pdf }) => {
const connectionName = aktorSetting(
z.string(),
'default',
'Document Intelligence Connection'
);

const markdown = aktorConvertPDFToMarkdown({ pdf, connectionName });

return aktorAICall({
messages: aktorMessagesFromSystemAndUser({
system: aktorSetting(
z.string().describe('[textarea] System Prompt'),
'Extract invoice number, date, total, and line items from the document.',
'System Prompt'
),
user: markdown,
}),
providerModel: aktorAISettingProviderModel(),
});
});

registerReaktorDefinition({
reaktorDefinitionId: 'invoice-extractor',
label: 'Invoice Extractor',
description: 'Extract structured data from a PDF invoice',
inputSchema: z.object({
pdf: z.string().describe('[file-upload] PDF invoice'),
}),
outputSchema: z.string(),
aktor: aktorInvoiceExtractor,
});
tip

Wrap connectionName in aktorSetting so that operators can switch the connection at deployment time without code changes.


Word Conversion

Word conversion runs locally with mammoth and turndown. No connection required.

aktorConvertDocxToMarkdown

Converts a single DOCX file to Markdown.

import { aktorConvertDocxToMarkdown } from '@operaide/document';

const markdown = aktorConvertDocxToMarkdown({
docx: docxBase64, // data:...;base64,... or raw base64
});
ParameterTypeDescription
docxstringDOCX file as base64 data, optionally with a data: URI prefix

Returns a string containing GFM Markdown. Headings, lists, and tables are preserved.

aktorConvertMultipleDocxsToMarkdown

Batch-converts an array of DOCX files.

import { aktorConvertMultipleDocxsToMarkdown } from '@operaide/document';

const markdowns = aktorConvertMultipleDocxsToMarkdown({
docxs: [docx1, docx2],
});
ParameterTypeDescription
docxsstring[]Array of DOCX base64 strings

Returns string[] — one Markdown string per input file.


Excel Conversion

Excel conversion runs locally with SheetJS. No connection required. Each sheet becomes a fenced csv block under a ## Sheet: <name> heading, so an LLM can read both the structure and the data.

aktorConvertXlsxToCsv

Converts a single XLSX workbook to Markdown.

import { aktorConvertXlsxToCsv } from '@operaide/document';

const markdown = aktorConvertXlsxToCsv({
xlsx: xlsxBase64,
});
ParameterTypeDescription
xlsxstringXLSX file as base64 data, optionally with a data: URI prefix

Returns a string. Empty sheets are skipped.

Example output:

## Sheet: Customers

```csv
id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com
```

## Sheet: Orders

```csv
id,customer_id,total
101,1,49.99
```

aktorConvertMultipleXlsxsToCsv

Batch-converts an array of XLSX workbooks.

import { aktorConvertMultipleXlsxsToCsv } from '@operaide/document';

const markdowns = aktorConvertMultipleXlsxsToCsv({
xlsxs: [xlsx1, xlsx2],
});
ParameterTypeDescription
xlsxsstring[]Array of XLSX base64 strings

Returns string[] — one Markdown document per workbook.


Working with Converted Markdown

Azure Document Intelligence embeds page markers into the Markdown output. The package provides Aktors that operate on these markers to split, filter, and serialize page content.

Page Markers

The converted Markdown contains two types of HTML comments:

  • <!-- PageBreak --> — separates pages
  • <!-- PageNumber="5" --> — indicates the detected page number (numeric or Roman numeral)

Key Types

interface PageData {
content: string; // Page content including markers
pageNumbers: string[]; // All detected page numbers on this page
pageNumber: string; // Assigned page number (numeric or Roman)
}

interface PageListEntry {
documentId: string;
pages: PageData[];
}

interface VectorDbDocumentMarkdown {
documentId: string;
markdown: string;
}

aktorSplitMarkdownToPages

Splits an array of VectorDbDocumentMarkdown objects into PageListEntry objects. Each document's Markdown is split at <!-- PageBreak --> markers and page numbers are extracted.

import { aktorSplitMarkdownToPages } from '@operaide/document';

const pageList = aktorSplitMarkdownToPages({
markdown: [
{ documentId: 'doc-1', markdown: convertedMarkdown },
],
});
// pageList: PageListEntry[]

aktorGetFirstPages

Returns the first N pages of each document as a JSON string. Defaults to 3 pages when pageCount is omitted.

import { aktorGetFirstPages } from '@operaide/document';

const firstPagesJson = aktorGetFirstPages({
documents: pageList,
pageCount: 2,
});

aktorGetContentFromPages

Filters documents to only include specific pages. Pass a DocumentPages[] array where each entry maps a document ID to a comma-separated list of page numbers. If pages is 'null', all pages of that document are returned.

import { aktorGetContentFromPages } from '@operaide/document';

const filtered = aktorGetContentFromPages({
relevantPages: [
{ documentId: 'doc-1', pages: '1, 3, 5' },
],
documents: pageList,
});

aktorGetJSONFromDocuments

Serializes a PageListEntry[] array to a JSON string.

import { aktorGetJSONFromDocuments } from '@operaide/document';

const json = aktorGetJSONFromDocuments({ documents: pageList });

Chapter Extraction

These Aktors add chapter numbering to Markdown headings and extract a table of contents. They are useful when you need an LLM to work with specific sections of a long document.

aktorGetChaptersFromMarkdown

Takes an array of Markdown strings, adds chapter numbers to headings (e.g. 1, 1.1, 2), and returns the table of contents as a string.

import { aktorGetChaptersFromMarkdown } from '@operaide/document';

const toc = aktorGetChaptersFromMarkdown({
documents: [markdownString1, markdownString2],
});
// "# 1 Introduction\n## 1.1 Background\n# 2 Methods\n…"

aktorMarkdownChapterNumbers

Adds chapter numbers to headings in an array of Markdown strings and returns the combined result.

import { aktorMarkdownChapterNumbers } from '@operaide/document';

const numbered = aktorMarkdownChapterNumbers({
markdown: [markdownString],
});

aktorMarkdownChaptersTransform

Filters Markdown content to include only the specified chapters. Chapters are identified by their number (e.g. '1', '2.3'), separated by newlines.

import { aktorMarkdownChaptersTransform } from '@operaide/document';

const selected = aktorMarkdownChaptersTransform({
markdown: numberedMarkdown,
chapters: '1\n2.3\n4',
});

URL to Markdown

These Aktors fetch web pages and convert their HTML to Markdown using Turndown. No Document Intelligence connection is required.

aktorMarkdownFromURLs

Fetches an array of URLs and returns their content as Markdown strings. Empty results are filtered out.

import { aktorMarkdownFromURLs } from '@operaide/document';

const markdowns = aktorMarkdownFromURLs({
urls: ['https://example.com/page1', 'https://example.com/page2'],
optionsName: 'my-options', // optional — name of registered transformation options
});

aktorCreateSearchURLs

Builds an array of URLs from search terms and a URL template. The template must contain {{search}} as a placeholder.

import { aktorCreateSearchURLs } from '@operaide/document';

const urls = aktorCreateSearchURLs({
searchTerms: 'term one\nterm two', // newline-separated
site: 'https://example.com/search?q={{search}}',
});
// ["https://example.com/search?q=term%20one", "https://example.com/search?q=term%20two"]

Custom Transformation Hooks

You can register custom HTML and Markdown transformation functions that are applied during URL-to-Markdown conversion:

import { registerUrlToMarkdownOptions } from '@operaide/document';
import type { TransformHtmlFn, TransformMarkdownFn } from '@operaide/document';

const transformHtml: TransformHtmlFn = (root, url) => {
root('nav').remove(); // strip navigation
root('.sidebar').remove(); // strip sidebar
return root;
};

const transformMarkdown: TransformMarkdownFn = (markdown, metadata) => {
return markdown.replace(/\[edit\]/gi, ''); // remove edit links
};

registerUrlToMarkdownOptions({
name: 'my-options',
description: 'Custom cleanup for example.com',
options: {
transformHtmlFn: transformHtml,
transformMarkdownFn: transformMarkdown,
},
});

Then reference 'my-options' as optionsName when calling aktorMarkdownFromURLs.


Common Patterns

PDF Attachment → AI Data Extraction

Convert an email attachment to Markdown, then extract structured data:

const base64Doc = aktorEmailFilesToBase64({ files: attachments });
const markdown = aktorConvertPDFToMarkdown({ pdf: base64Doc });

const result = aktorAICall({
messages: aktorMessagesFromSystemAndUser({
system: aktorConst('Extract the order number, date, and total.'),
user: markdown,
}),
providerModel: aktorAISettingProviderModel(),
});

Combining with Vectorization

Document Intelligence is the default document loader in the vectorization pipeline. When you call aktorVektorEmbeddingPipeline, the pipeline automatically uses Document Intelligence to convert uploaded PDFs to Markdown before chunking and embedding. You do not need to call aktorConvertPDFToMarkdown separately in that case.


Best Practices

  1. Use aktorSetting for the connection name so operators can change it without editing code.

  2. Use 'default' as the connection name for standard single-connection setups.

  3. Prefer aktorConvertPDFToMarkdown over assembling lower-level conversion calls — it handles connection lookup, error wrapping, and result extraction.

  4. Lean on the vectorization pipeline when building RAG applications. It calls Document Intelligence internally, so you get conversion, chunking, and embedding in one step.

  5. Link to the admin guide in your Reaktor's documentation or settings description so operators know which connection to configure. See Document Intelligence Configuration.