Skip to content

feat(doc-intel): expose models, features, query fields, and structured output - #1913

Merged
Adam Fourney (afourney) merged 12 commits into
microsoft:mainfrom
chienyuanchang:chienyuanchang/di_convertor_update
Oct 22, 2026
Merged

Adam Fourney (afourney) merged 12 commits into
microsoft:mainfrom
chienyuanchang:chienyuanchang/di_convertor_update

Conversation

@chienyuanchang

@chienyuanchang Chien Yuan Chang (chienyuanchang) commented May 26, 2026 •

Copy link
Copy Markdown
Member

Summary

  • expose Document Intelligence model selection with docintel_model_id
  • expose analysis add-ons with docintel_features; None preserves the existing defaults and [] disables all default add-ons
  • expose queryFields with docintel_query_fields and automatically enable the required queryFields feature
  • serialize structured fields from prebuilt and custom models as YAML front matter
  • add matching CLI flags for model, features, and query fields
  • retain the SDK-default API version behavior from fix(doc-intel): default api_version to None in DocumentIntelligenceConverter #2267 while adding MarkItDown user-agent telemetry
  • document API-key, AZURE_API_KEY, and DefaultAzureCredential authentication

Consolidated work

Usage

from azure.ai.documentintelligence.models import DocumentAnalysisFeature
from markitdown import MarkItDown

md = MarkItDown(
    docintel_endpoint="<document_intelligence_endpoint>",
    docintel_model_id="prebuilt-layout",
    docintel_features=[
        DocumentAnalysisFeature.OCR_HIGH_RESOLUTION,
        DocumentAnalysisFeature.STYLE_FONT,
    ],
    docintel_query_fields=["Title", "Author"],
)
result = md.convert("document.pdf")
print(result.markdown)

Use docintel_features=[] to disable the default formulas, ocrHighResolution, and styleFont add-ons. Office inputs continue to omit OCR-only add-ons. Query fields automatically add the required queryFields feature without mutating the caller's feature list.

Validation

  • GITHUB_ACTIONS=1 python -m pytest packages/markitdown/tests -q — 1080 passed, 57 skipped
  • focused Document Intelligence and CLI tests — 54 passed
  • Black 23.7.0 — 5 changed Python files unchanged
  • git diff --check
  • live Entra-authenticated Document Intelligence calls:
    • prebuilt-layout succeeded with default add-ons, no add-ons, and only ocrHighResolution
    • prebuilt-read succeeded with no add-ons and returned its expected flatter text-oriented Markdown
    • prebuilt-receipt succeeded with no add-ons and produced structured YAML front matter
    • the queryFields request path was accepted with valid identifiers, but the selected repository samples returned no query-field documents; positive field serialization remains covered by unit tests

Credits

@chienyuanchang
Chien Yuan Chang (chienyuanchang) marked this pull request as ready for review May 26, 2026 17:01
Preserve the SDK-default API version behavior from microsoft#2267 while retaining Document Intelligence user-agent telemetry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add configurable analysis features, CLI and README coverage, and API-key authentication guidance while integrating queryFields and structured model output.

Co-authored-by: Tai An <antai12232931@outlook.com>

Co-authored-by: hshgogogo <2081920847@qq.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@chienyuanchang Chien Yuan Chang (chienyuanchang) changed the title feat: Expand Document Intelligence converter — custom models, queryFields, structured field front matter feat(doc-intel): expose models, features, query fields, and structured output Oct 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Structured output can produce invalid or incorrectly typed YAML and lose or misattribute fields from multiple documents.

2 open issues
What changed in this PR

This PR expands MarkItDown’s Azure Document Intelligence integration with configurable analysis options and structured output while preserving existing defaults.

Changes:

  • Exposes model selection, analysis features, and query fields through Python and CLI options.
  • Adds YAML front matter for extracted fields and MarkItDown user-agent telemetry.
  • Documents authentication options and adds converter and CLI tests.
File Description
README.md Documents authentication, configuration, and structured output.
packages/​markitdown/​tests/​test_docintel_converter.py Tests configuration, request forwarding, telemetry, and front matter.
packages/​markitdown/​tests/​test_cli_misc.py Tests forwarding Document Intelligence CLI options.
packages/​markitdown/​src/​markitdown/​converters/​_doc_intel_converter.py Implements configurable analysis and structured-field serialization.
packages/​markitdown/​src/​markitdown/​_markitdown.py Forwards public configuration to the converter.
packages/​markitdown/​src/​markitdown/​__main__.py Adds and parses Document Intelligence CLI flags.

Review effort: Balanced

Comment thread packages/markitdown/src/markitdown/converters/_doc_intel_converter.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@afourney

Copy link
Copy Markdown
Member

This comment was auto-generated by GPT-6 Astra and posted at the repository maintainer’s request.

Rechecked commit fd3b526c641b11d9e24dd5040ad21fd58a67ebca. The YAML quoting change resolves the examples from the earlier review: all 18 string key/value round-trip checks and 50 focused Document Intelligence and CLI tests passed.

Two P2 findings remain:

  1. Preserve document boundaries when serializing structured fields. _fields_to_front_matter() merges every document into one mapping. Later documents overwrite matching fields but retain unmatched fields from earlier documents. With two SDK AnalyzedDocument objects, I reproduced Vendor B’s name and invoice ID paired with Vendor A’s invoice total. This produces a record that never existed and discards earlier documents’ fields. Serialize each document’s fields separately and add coverage for overlapping and missing fields across documents. Code

  2. Handle selection-group values before falling back to raw content. _field_value() does not handle value_selection_group. An SDK DocumentField(type="selectionGroup", value_selection_group=["Email"]) returns None and disappears from the front matter when content is absent. When raw content is present, the selected values are still lost in favor of that text. Preserve the selected-value list and add regression coverage. Code

I recommend addressing these before merging. Validation used local SDK objects and mocked service calls; the full suite and live Azure calls were not run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Structured fields containing control characters can produce invalid YAML front matter that downstream parsers reject.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Escape control characters in quoted YAML strings

packages/​markitdown/​src/​markitdown/​converters/​_doc_intel_converter.py:223

The quoted-string escaping leaves control characters such as form feed (U+000C) and backspace (U+0008) unchanged. For example, a structured field containing page one\fpage two produces a literal form feed inside the quoted scalar. YAML forbids that character even inside quotes, so downstream consumers cannot parse the front matter. Escape the remaining control characters and add a regression case for a field containing a form feed.

2 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Scientific-notation floats can lose their numeric type when the generated front matter is parsed by YAML 1.1 readers.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve numeric type for scientific-notation floats

packages/​markitdown/​src/​markitdown/​converters/​_doc_intel_converter.py:206

Scientific-notation floats lose their numeric type with YAML 1.1 readers such as yaml.safe_load, which the new round-trip tests use. For example, value_number=1e-7 is emitted as 1e-07 and loads as a string rather than a float; 1e20 has the same problem. Include a decimal point in exponential float mantissas (for example, 1.0e-07) and add numeric round-trip regressions for small and large values.

Review effort: Balanced

Comment thread packages/markitdown/src/markitdown/__main__.py
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@afourney
Adam Fourney (afourney) merged commit 7482c09 into microsoft:main Oct 22, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants