Docling-serve cassettes

This commit is contained in:
Yiorgis Gozadinos 2025-12-26 18:59:46 +02:00
parent c3a3b4a5b4
commit 0da8ba97c4
No known key found for this signature in database
5 changed files with 22031 additions and 38 deletions

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,100 @@
interactions:
- request:
body: "--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data; name=\"to_formats\"\r\n\r\njson\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition:
form-data; name=\"do_ocr\"\r\n\r\ntrue\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data; name=\"force_ocr\"\r\n\r\nfalse\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition:
form-data; name=\"do_table_structure\"\r\n\r\ntrue\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data;
name=\"table_mode\"\r\n\r\naccurate\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data; name=\"table_cell_matching\"\r\n\r\ntrue\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition:
form-data; name=\"images_scale\"\r\n\r\n2.0\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data;
name=\"generate_picture_images\"\r\n\r\nfalse\r\n--4379b32700c5b8d95062406eb16d4651\r\nContent-Disposition: form-data;
name=\"files\"; filename=\"tmpeojgnbxt.md\"\r\nContent-Type: text/markdown\r\n\r\n```python\ndef test():\n return
42\n```\r\n--4379b32700c5b8d95062406eb16d4651--\r\n"
headers:
accept:
- '*/*'
accept-encoding:
- gzip, deflate, zstd
connection:
- keep-alive
content-length:
- '1011'
content-type:
- multipart/form-data; boundary=4379b32700c5b8d95062406eb16d4651
host:
- localhost:5001
method: POST
uri: http://localhost:5001/v1/convert/file
response:
headers:
content-length:
- '1114'
content-type:
- application/json
parsed_body:
document:
doctags_content: null
filename: tmpeojgnbxt.md
html_content: null
json_content:
body:
children:
- $ref: '#/texts/0'
content_layer: body
label: unspecified
meta: null
name: _root_
parent: null
self_ref: '#/body'
form_items: []
furniture:
children: []
content_layer: furniture
label: unspecified
meta: null
name: _root_
parent: null
self_ref: '#/furniture'
groups: []
key_value_items: []
name: tmpeojgnbxt
origin:
binary_hash: 9008975733065065710
filename: tmpeojgnbxt.md
mimetype: text/markdown
uri: null
pages: {}
pictures: []
schema_name: DoclingDocument
tables: []
texts:
- captions: []
children: []
code_language: unknown
content_layer: body
footnotes: []
formatting: null
hyperlink: null
image: null
label: code
meta: null
orig: |-
def test():
return 42
parent:
$ref: '#/body'
prov: []
references: []
self_ref: '#/texts/0'
text: |-
def test():
return 42
version: 1.8.0
md_content: null
text_content: null
errors: []
processing_time: 0.0017275830000471615
status: success
timings: {}
status:
code: 200
message: OK
version: 1

View file

@ -0,0 +1,103 @@
interactions:
- request:
body: "--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data; name=\"to_formats\"\r\n\r\njson\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition:
form-data; name=\"do_ocr\"\r\n\r\ntrue\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data; name=\"force_ocr\"\r\n\r\nfalse\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition:
form-data; name=\"do_table_structure\"\r\n\r\ntrue\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data;
name=\"table_mode\"\r\n\r\naccurate\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data; name=\"table_cell_matching\"\r\n\r\ntrue\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition:
form-data; name=\"images_scale\"\r\n\r\n2.0\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data;
name=\"generate_picture_images\"\r\n\r\nfalse\r\n--798e57b119ed24827326455c645311ae\r\nContent-Disposition: form-data;
name=\"files\"; filename=\"content.md\"\r\nContent-Type: text/markdown\r\n\r\n# Test Document\n\nThis is a test.\r\n--798e57b119ed24827326455c645311ae--\r\n"
headers:
accept:
- '*/*'
accept-encoding:
- gzip, deflate, zstd
connection:
- keep-alive
content-length:
- '1000'
content-type:
- multipart/form-data; boundary=798e57b119ed24827326455c645311ae
host:
- localhost:5001
method: POST
uri: http://localhost:5001/v1/convert/file
response:
headers:
content-length:
- '1225'
content-type:
- application/json
parsed_body:
document:
doctags_content: null
filename: content.md
html_content: null
json_content:
body:
children:
- $ref: '#/texts/0'
- $ref: '#/texts/1'
content_layer: body
label: unspecified
meta: null
name: _root_
parent: null
self_ref: '#/body'
form_items: []
furniture:
children: []
content_layer: furniture
label: unspecified
meta: null
name: _root_
parent: null
self_ref: '#/furniture'
groups: []
key_value_items: []
name: content
origin:
binary_hash: 18149311266811077188
filename: content.md
mimetype: text/markdown
uri: null
pages: {}
pictures: []
schema_name: DoclingDocument
tables: []
texts:
- children: []
content_layer: body
formatting: null
hyperlink: null
label: title
meta: null
orig: Test Document
parent:
$ref: '#/body'
prov: []
self_ref: '#/texts/0'
text: Test Document
- children: []
content_layer: body
formatting: null
hyperlink: null
label: text
meta: null
orig: This is a test.
parent:
$ref: '#/body'
prov: []
self_ref: '#/texts/1'
text: This is a test.
version: 1.8.0
md_content: null
text_content: null
errors: []
processing_time: 0.002875374999803171
status: success
timings: {}
status:
code: 200
message: OK
version: 1

View file

@ -1,3 +1,4 @@
from pathlib import Path
from unittest.mock import AsyncMock, Mock, patch
import pytest
@ -11,6 +12,11 @@ from haiku.rag.config import AppConfig, Config
from haiku.rag.converters import get_converter
@pytest.fixture(scope="module")
def vcr_cassette_dir():
return str(Path(__file__).parent / "cassettes" / "test_chunker")
@pytest.mark.asyncio
async def test_local_chunker(qa_corpus: Dataset):
"""Test DoclingLocalChunker with real document."""
@ -479,28 +485,11 @@ This is content.
assert meta1.page_numbers == [1, 2]
def is_docling_serve_available(base_url: str = "http://localhost:5001") -> bool:
"""Check if docling-serve is running and accessible."""
import requests
try:
response = requests.get(f"{base_url}/health", timeout=2)
return response.status_code == 200
except Exception:
return False
@pytest.mark.skipif(
not is_docling_serve_available(),
reason="docling-serve not available at http://localhost:5001",
)
@pytest.mark.integration
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_local_and_serve_chunkers_produce_same_output():
"""Test that local and serve chunkers produce identical output for the same document.
This integration test requires docling-serve to be running on localhost:5001.
Note: Labels are resolved from the DoclingDocument since docling-serve API
only returns ref strings, not labels. See:
https://github.com/docling-project/docling-serve/issues/448

View file

@ -6,7 +6,6 @@ from unittest.mock import AsyncMock, Mock, patch
import httpx
import pytest
import requests
from docling_core.types.doc.document import DoclingDocument
from haiku.rag.config import AppConfig
@ -16,13 +15,9 @@ from haiku.rag.converters.docling_serve import DoclingServeConverter
from haiku.rag.converters.text_utils import TextFileHandler
def is_docling_serve_available(base_url: str = "http://localhost:5001") -> bool:
"""Check if docling-serve is running and accessible."""
try:
response = requests.get(f"{base_url}/health", timeout=2)
return response.status_code == 200
except Exception:
return False
@pytest.fixture(scope="module")
def vcr_cassette_dir():
return str(Path(__file__).parent / "cassettes" / "test_converters")
def create_mock_docling_document_json(name: str = "test") -> dict:
@ -560,13 +555,8 @@ class TestDoclingServeConverter:
assert "files" in call_kwargs
@pytest.mark.integration
@pytest.mark.skipif(
not is_docling_serve_available(),
reason="docling-serve not available at http://localhost:5001",
)
class TestDoclingServeConverterIntegration:
"""Integration tests with real docling-serve (requires service running)."""
"""Integration tests with real docling-serve recorded via VCR."""
@pytest.fixture
def config(self):
@ -580,22 +570,23 @@ class TestDoclingServeConverterIntegration:
"""Create converter for integration tests."""
return DoclingServeConverter(config)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_text_real_service(self, converter):
"""Test text conversion with real docling-serve (integration)."""
"""Test text conversion with real docling-serve."""
doc = await converter.convert_text("# Test Document\n\nThis is a test.")
assert isinstance(doc, DoclingDocument)
assert doc.version == "1.8.0"
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_convert_code_file_real_service(self, converter):
"""Test code file conversion with real docling-serve (integration)."""
"""Test code file conversion with real docling-serve."""
code = "def test():\n return 42"
with tempfile.NamedTemporaryFile(mode="w", suffix=".py") as f:
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write(code)
f.flush()
temp_path = Path(f.name)
doc = await converter.convert_file(temp_path)
doc = await converter.convert_file(temp_path)
temp_path.unlink()
assert isinstance(doc, DoclingDocument)
result = doc.export_to_markdown()