Docling-serve cassettes
This commit is contained in:
parent
c3a3b4a5b4
commit
0da8ba97c4
5 changed files with 22031 additions and 38 deletions
File diff suppressed because one or more lines are too long
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from pathlib import Path
|
||||||
from unittest.mock import AsyncMock, Mock, patch
|
from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
@ -11,6 +12,11 @@ from haiku.rag.config import AppConfig, Config
|
||||||
from haiku.rag.converters import get_converter
|
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
|
@pytest.mark.asyncio
|
||||||
async def test_local_chunker(qa_corpus: Dataset):
|
async def test_local_chunker(qa_corpus: Dataset):
|
||||||
"""Test DoclingLocalChunker with real document."""
|
"""Test DoclingLocalChunker with real document."""
|
||||||
|
|
@ -479,28 +485,11 @@ This is content.
|
||||||
assert meta1.page_numbers == [1, 2]
|
assert meta1.page_numbers == [1, 2]
|
||||||
|
|
||||||
|
|
||||||
def is_docling_serve_available(base_url: str = "http://localhost:5001") -> bool:
|
@pytest.mark.vcr()
|
||||||
"""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.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_local_and_serve_chunkers_produce_same_output():
|
async def test_local_and_serve_chunkers_produce_same_output():
|
||||||
"""Test that local and serve chunkers produce identical output for the same document.
|
"""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
|
Note: Labels are resolved from the DoclingDocument since docling-serve API
|
||||||
only returns ref strings, not labels. See:
|
only returns ref strings, not labels. See:
|
||||||
https://github.com/docling-project/docling-serve/issues/448
|
https://github.com/docling-project/docling-serve/issues/448
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import pytest
|
import pytest
|
||||||
import requests
|
|
||||||
from docling_core.types.doc.document import DoclingDocument
|
from docling_core.types.doc.document import DoclingDocument
|
||||||
|
|
||||||
from haiku.rag.config import AppConfig
|
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
|
from haiku.rag.converters.text_utils import TextFileHandler
|
||||||
|
|
||||||
|
|
||||||
def is_docling_serve_available(base_url: str = "http://localhost:5001") -> bool:
|
@pytest.fixture(scope="module")
|
||||||
"""Check if docling-serve is running and accessible."""
|
def vcr_cassette_dir():
|
||||||
try:
|
return str(Path(__file__).parent / "cassettes" / "test_converters")
|
||||||
response = requests.get(f"{base_url}/health", timeout=2)
|
|
||||||
return response.status_code == 200
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def create_mock_docling_document_json(name: str = "test") -> dict:
|
def create_mock_docling_document_json(name: str = "test") -> dict:
|
||||||
|
|
@ -560,13 +555,8 @@ class TestDoclingServeConverter:
|
||||||
assert "files" in call_kwargs
|
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:
|
class TestDoclingServeConverterIntegration:
|
||||||
"""Integration tests with real docling-serve (requires service running)."""
|
"""Integration tests with real docling-serve recorded via VCR."""
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config(self):
|
def config(self):
|
||||||
|
|
@ -580,22 +570,23 @@ class TestDoclingServeConverterIntegration:
|
||||||
"""Create converter for integration tests."""
|
"""Create converter for integration tests."""
|
||||||
return DoclingServeConverter(config)
|
return DoclingServeConverter(config)
|
||||||
|
|
||||||
|
@pytest.mark.vcr()
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_convert_text_real_service(self, converter):
|
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.")
|
doc = await converter.convert_text("# Test Document\n\nThis is a test.")
|
||||||
assert isinstance(doc, DoclingDocument)
|
assert isinstance(doc, DoclingDocument)
|
||||||
assert doc.version == "1.8.0"
|
|
||||||
|
|
||||||
|
@pytest.mark.vcr()
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_convert_code_file_real_service(self, converter):
|
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"
|
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.write(code)
|
||||||
f.flush()
|
|
||||||
temp_path = Path(f.name)
|
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)
|
assert isinstance(doc, DoclingDocument)
|
||||||
result = doc.export_to_markdown()
|
result = doc.export_to_markdown()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue