Wire providers.docling_serve.timeout through to the client
The setting was documented but did not exist on DoclingServeConfig, so it was silently dropped, and DoclingServeClient.from_config never forwarded the timeout parameter it already accepted. The per-request timeout was therefore pinned at the constructor default of 300s with no way to change it. Add the field, forward it, and reject a non-positive value. Also parametrize over the checked-in *.yaml.example files and validate each through AppConfig, so an example that no longer loads fails a test rather than a user's first run.
This commit is contained in:
parent
73944f91ea
commit
15868762b0
6 changed files with 30 additions and 0 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- `providers.docling_serve.timeout` (default 300 seconds), forwarded to the docling-serve client's per-request timeout.
|
||||||
- `evaluations run --filter/-f CLAUSE`: SQL `WHERE` clause over document columns, applied to the retrieval benchmark's searches and to every capability search during QA. Recorded as `document_filter` in experiment metadata.
|
- `evaluations run --filter/-f CLAUSE`: SQL `WHERE` clause over document columns, applied to the retrieval benchmark's searches and to every capability search during QA. Recorded as `document_filter` in experiment metadata.
|
||||||
- `mtrag_clapnq` / `mtrag_clapnq_rewrite` / `mtrag_clapnq_live` / `mtrag_clapnq_live_uncompacted` evaluation datasets: multi-turn QA with gold-prefix and live-session conversation replay, live arms with and without `EvidenceCompactionCapability`, Recall@k/nDCG@k retrieval metrics, eligibility-aware citation scoring, refusal precision/recall, per-turn tool-traffic attributes, and `citation_status` / `turn_citation_status` eval attributes.
|
- `mtrag_clapnq` / `mtrag_clapnq_rewrite` / `mtrag_clapnq_live` / `mtrag_clapnq_live_uncompacted` evaluation datasets: multi-turn QA with gold-prefix and live-session conversation replay, live arms with and without `EvidenceCompactionCapability`, Recall@k/nDCG@k retrieval metrics, eligibility-aware citation scoring, refusal precision/recall, per-turn tool-traffic attributes, and `citation_status` / `turn_citation_status` eval attributes.
|
||||||
- Raw chunk metadata is now exposed to search and citation results, through `SearchResult.chunk_meta` and `Citation.chunk_meta`. For context-expanded results, the metadata is that of the anchor chunk.
|
- Raw chunk metadata is now exposed to search and citation results, through `SearchResult.chunk_meta` and `Citation.chunk_meta`. For context-expanded results, the metadata is that of the anchor chunk.
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ providers:
|
||||||
docling_serve:
|
docling_serve:
|
||||||
base_url: http://localhost:5001
|
base_url: http://localhost:5001
|
||||||
api_key: "" # Optional API key for authentication
|
api_key: "" # Optional API key for authentication
|
||||||
|
timeout: 300 # Per-request timeout in seconds
|
||||||
```
|
```
|
||||||
|
|
||||||
For converter / chunker config options (chunking strategy, tokenizer,
|
For converter / chunker config options (chunking strategy, tokenizer,
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,11 @@ class DoclingServeConfig(BaseModel):
|
||||||
description="Max attempts per request across the fleet before giving up; "
|
description="Max attempts per request across the fleet before giving up; "
|
||||||
"each retry fails over to another instance.",
|
"each retry fails over to another instance.",
|
||||||
)
|
)
|
||||||
|
timeout: float = Field(
|
||||||
|
default=300,
|
||||||
|
gt=0,
|
||||||
|
description="Per-request timeout in seconds for submit, poll and result calls.",
|
||||||
|
)
|
||||||
circuit_breaker: CircuitBreakerConfig = Field(
|
circuit_breaker: CircuitBreakerConfig = Field(
|
||||||
default_factory=lambda: CircuitBreakerConfig(
|
default_factory=lambda: CircuitBreakerConfig(
|
||||||
failure_threshold=3, cooldown_s=30.0
|
failure_threshold=3, cooldown_s=30.0
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ class DoclingServeClient:
|
||||||
return cls(
|
return cls(
|
||||||
base_urls=config.base_urls,
|
base_urls=config.base_urls,
|
||||||
api_key=config.api_key,
|
api_key=config.api_key,
|
||||||
|
timeout=config.timeout,
|
||||||
circuit_breaker=config.circuit_breaker,
|
circuit_breaker=config.circuit_breaker,
|
||||||
max_attempts=config.max_attempts,
|
max_attempts=config.max_attempts,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
@ -557,3 +559,21 @@ def test_get_config_initialises_lazily_then_reuses(monkeypatch):
|
||||||
first = config_module.get_config()
|
first = config_module.get_config()
|
||||||
assert isinstance(first, AppConfig)
|
assert isinstance(first, AppConfig)
|
||||||
assert config_module.get_config() is first
|
assert config_module.get_config() is first
|
||||||
|
|
||||||
|
|
||||||
|
# Every YAML config shipped in the repo has to load. These are what users copy.
|
||||||
|
_EXAMPLE_CONFIGS = sorted(
|
||||||
|
(Path(__file__).resolve().parent.parent).glob("**/*.yaml.example")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_example_configs_are_present():
|
||||||
|
"""Guard against the glob silently matching nothing."""
|
||||||
|
assert _EXAMPLE_CONFIGS
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"path", _EXAMPLE_CONFIGS, ids=lambda p: p.parent.name + "/" + p.name
|
||||||
|
)
|
||||||
|
def test_example_config_validates(path: Path):
|
||||||
|
AppConfig.model_validate(yaml.safe_load(path.read_text()) or {})
|
||||||
|
|
|
||||||
|
|
@ -474,11 +474,13 @@ def test_from_config_wires_retry_and_breaker():
|
||||||
ds = config.providers.docling_serve
|
ds = config.providers.docling_serve
|
||||||
ds.base_url = "http://cfg-n:5001"
|
ds.base_url = "http://cfg-n:5001"
|
||||||
ds.max_attempts = 7
|
ds.max_attempts = 7
|
||||||
|
ds.timeout = 42.0
|
||||||
ds.circuit_breaker = CircuitBreakerConfig(failure_threshold=9, cooldown_s=90.0)
|
ds.circuit_breaker = CircuitBreakerConfig(failure_threshold=9, cooldown_s=90.0)
|
||||||
|
|
||||||
for component in (DoclingServeConverter(config), DoclingServeChunker(config)):
|
for component in (DoclingServeConverter(config), DoclingServeChunker(config)):
|
||||||
client = component.client
|
client = component.client
|
||||||
assert client._max_attempts == 7
|
assert client._max_attempts == 7
|
||||||
|
assert client.timeout == 42.0
|
||||||
assert client._breaker_config.failure_threshold == 9
|
assert client._breaker_config.failure_threshold == 9
|
||||||
assert client._breaker_config.cooldown_s == 90.0
|
assert client._breaker_config.cooldown_s == 90.0
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue