Merge pull request #232 from ggozad/feat/page-generation-option

Control page image generation
This commit is contained in:
Yiorgis Gozadinos 2026-01-14 13:50:44 +02:00 committed by GitHub
commit d602ad48bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 86803 additions and 5 deletions

View file

@ -1,6 +1,14 @@
# Changelog
## [Unreleased]
### Added
- **Page Image Generation Control**: New `generate_page_images` option in `ConversionOptions` to control PDF page image extraction
- `generate_page_images: bool = True` - Enable/disable rendered page images (used by `visualize_chunk()`)
- Works with both `docling-local` and `docling-serve` converters
- For `docling-serve`, maps to `image_export_mode` API parameter (`embedded`/`placeholder`)
- Note: `generate_picture_images` (embedded figures/diagrams) works with local converter but has limited support in docling-serve
## [0.26.2] - 2026-01-13
### Changed

View file

@ -35,7 +35,8 @@ processing:
# Image settings
images_scale: 2.0 # Image scale factor
generate_picture_images: false # Include embedded images in output
generate_page_images: true # Include rendered page images (for visualize_chunk)
generate_picture_images: false # Include embedded figure/diagram images
# VLM picture description (optional)
picture_description:
@ -82,12 +83,16 @@ conversion_options:
```yaml
conversion_options:
images_scale: 2.0 # Image resolution scale factor
generate_picture_images: false # Include embedded images in output
generate_page_images: true # Include rendered page images
generate_picture_images: false # Include embedded figure/diagram images
```
- **images_scale**: Scale factor for extracted images. Higher values = better quality but larger size. Typical range: 1.0-3.0.
- **generate_page_images**: When `true` (default), rendered images of each PDF page are included in the document. Required for `visualize_chunk()` to show visual grounding. When `false`, page images are excluded to reduce document size.
- **generate_picture_images**: When `true`, embedded images (figures, diagrams) are included as base64-encoded data in the document. When `false` (default), images are excluded to reduce chunk size and avoid context bloat.
**Note:** With `docling-serve`, `generate_picture_images` has limited support - picture image data may not be returned in the JSON response. Page images work correctly with both local and remote converters.
#### Picture Description (VLM)
Use a Vision Language Model (VLM) to automatically describe images in documents. Descriptions become searchable text, improving RAG retrieval for visual content.

View file

@ -125,6 +125,7 @@ class ConversionOptions(BaseModel):
# Image options
images_scale: float = 2.0
generate_page_images: bool = True
generate_picture_images: bool = False
# VLM picture description

View file

@ -97,7 +97,7 @@ class DoclingLocalConverter(DocumentConverter):
do_ocr=opts.do_ocr,
do_table_structure=opts.do_table_structure,
images_scale=opts.images_scale,
generate_page_images=True,
generate_page_images=opts.generate_page_images,
generate_picture_images=opts.generate_picture_images or pic_desc.enabled,
table_structure_options=TableStructureOptions(
do_cell_matching=opts.table_cell_matching,

View file

@ -93,7 +93,10 @@ class DoclingServeConverter(DocumentConverter):
"table_mode": opts.table_mode,
"table_cell_matching": str(opts.table_cell_matching).lower(),
"images_scale": str(opts.images_scale),
"generate_picture_images": str(
"image_export_mode": "embedded"
if opts.generate_page_images
else "placeholder",
"include_images": str(
opts.generate_picture_images or pic_desc.enabled
).lower(),
"do_picture_description": str(pic_desc.enabled).lower(),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -304,11 +304,15 @@ class TestDoclingLocalConverter:
config.processing.conversion_options.do_ocr = False
config.processing.conversion_options.table_mode = "fast"
config.processing.conversion_options.images_scale = 3.0
config.processing.conversion_options.generate_page_images = False
converter = DoclingLocalConverter(config)
assert converter.config.processing.conversion_options.do_ocr is False
assert converter.config.processing.conversion_options.table_mode == "fast"
assert converter.config.processing.conversion_options.images_scale == 3.0
assert (
converter.config.processing.conversion_options.generate_page_images is False
)
@pytest.mark.asyncio
async def test_convert_pdf_without_picture_images(self, config):
@ -349,6 +353,44 @@ class TestDoclingLocalConverter:
"Pictures should have image data when generate_picture_images=True"
)
@pytest.mark.asyncio
async def test_convert_pdf_without_page_images(self, config):
"""Test PDF conversion excludes page images when disabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_page_images = False
converter = DoclingLocalConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that pages don't have image data
for page in doc.pages.values():
assert page.image is None, (
"Pages should not have image data when generate_page_images=False"
)
@pytest.mark.asyncio
async def test_convert_pdf_with_page_images(self, config):
"""Test PDF conversion includes page images when enabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_page_images = True
converter = DoclingLocalConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that pages have image data
pages_with_images = [p for p in doc.pages.values() if p.image is not None]
assert len(pages_with_images) > 0, (
"Pages should have image data when generate_page_images=True"
)
def test_get_vlm_api_url_with_ollama(self, config):
"""Test VLM API URL construction for Ollama provider."""
converter = DoclingLocalConverter(config)
@ -542,6 +584,7 @@ class TestDoclingServeConverter:
config.processing.conversion_options.table_cell_matching = False
config.processing.conversion_options.do_table_structure = False
config.processing.conversion_options.images_scale = 3.0
config.processing.conversion_options.generate_picture_images = False
converter = DoclingServeConverter(config)
doc_json = create_mock_docling_document("test")
@ -567,6 +610,8 @@ class TestDoclingServeConverter:
assert data["table_cell_matching"] == "false"
assert data["do_table_structure"] == "false"
assert data["images_scale"] == "3.0"
assert data["include_images"] == "false"
assert data["image_export_mode"] == "embedded"
@pytest.mark.asyncio
async def test_convert_text_connection_error(self, converter):
@ -769,7 +814,7 @@ class TestDoclingServeConverterPictureDescription:
data = call_kwargs["data"]
assert data["do_picture_description"] == "true"
assert data["generate_picture_images"] == "true"
assert data["include_images"] == "true"
assert "picture_description_api" in data
api_config = json.loads(data["picture_description_api"])
@ -884,3 +929,89 @@ class TestDoclingServeConverterIntegration:
assert pictures_with_descriptions, (
"At least one picture should have a VLM description"
)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_pdf_without_page_images(self, config):
"""Test PDF conversion excludes page images when disabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_page_images = False
converter = DoclingServeConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that pages don't have image data
for page in doc.pages.values():
assert page.image is None, (
"Pages should not have image data when generate_page_images=False"
)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_pdf_with_page_images(self, config):
"""Test PDF conversion includes page images when enabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_page_images = True
converter = DoclingServeConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that pages have image data
pages_with_images = [p for p in doc.pages.values() if p.image is not None]
assert len(pages_with_images) > 0, (
"Pages should have image data when generate_page_images=True"
)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_pdf_without_picture_images(self, config):
"""Test PDF conversion excludes picture images when disabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_picture_images = False
converter = DoclingServeConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that pictures don't have image data
for picture in doc.pictures:
assert picture.image is None, (
"Pictures should not have image data when generate_picture_images=False"
)
@pytest.mark.xfail(
reason="docling-serve does not return picture image data in JSON response "
"even with include_images=true. Page images work, but extracted picture/figure "
"images are not included. This is a docling-serve limitation."
)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_pdf_with_picture_images(self, config):
"""Test PDF conversion includes picture images when enabled."""
pdf_path = Path("tests/data/doclaynet.pdf")
if not pdf_path.exists():
pytest.skip("doclaynet.pdf not found")
config.processing.conversion_options.generate_picture_images = True
converter = DoclingServeConverter(config)
doc = await converter.convert_file(pdf_path)
assert isinstance(doc, DoclingDocument)
# Check that at least some pictures have image data
pictures_with_images = [p for p in doc.pictures if p.image is not None]
if doc.pictures:
assert len(pictures_with_images) > 0, (
"Pictures should have image data when generate_picture_images=True"
)