Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/api/app/api/v1/routes/retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class RetrievalQueryRequest(BaseModel):
)
use_agentic: bool | None = Field(
None,
description="Deprecated mode hint retained for cache/request compatibility; retrieval always uses the agentic workflow.",
description="Set to true to enable agentic retrieval (LLM doc-select + navigation). Default (None/false) uses classic 3-channel top-K.",
)

@field_validator("channels")
Expand Down
1 change: 0 additions & 1 deletion apps/api/tests/contract/test_demo_documents_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ async def test_should_materialize_demo_source_without_parse_or_credit_charge(
monkeypatch: MonkeyPatch,
) -> None:
fake_result_storage = FakeResultStorage()
monkeypatch.setenv("RETRIEVAL_AGENTIC_ENABLED", "false")

async with developer_api_client_factory() as api_client:
import app.services.demo.source_materializer as source_materializer_module
Expand Down
28 changes: 2 additions & 26 deletions apps/api/tests/contract/test_retrieval_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,34 +358,11 @@ async def test_should_return_empty_results_for_an_empty_query(


@pytest.mark.asyncio
async def test_retrieval_should_ignore_false_agentic_hint_and_use_workflow(
async def test_retrieval_should_use_classic_topk_when_agentic_is_false(
developer_api_client_factory: Callable[
[], AbstractAsyncContextManager[AsyncClient]
],
monkeypatch: MonkeyPatch,
) -> None:
async def fake_run_request(
self: object,
db: AsyncSession,
*,
request: WorkflowRunRequest,
llm_fn: object | None = None,
) -> WorkflowResult:
return WorkflowResult(
namespace=request.namespace,
query=request.query,
router_used="workflow_single_step",
answer_text="",
plan=QueryPlan.single_step(request.query),
referenced_chunks=[],
results=[],
)

monkeypatch.setattr(
"shared.services.retrieval.workflow.orchestrator.WorkflowOrchestrator.run_request",
fake_run_request,
)

async with developer_api_client_factory() as api_client:
await _seed_retrieval_document(
user_id="local-dev-user",
Expand Down Expand Up @@ -414,8 +391,7 @@ async def fake_run_request(
assert response.status_code == 200

response_json = cast(dict[str, object], response.json())
assert response_json["router_used"] == "workflow_single_step"
assert response_json["results"] == []
assert response_json["router_used"] == "classic_topk"


@pytest.mark.asyncio
Expand Down
7 changes: 0 additions & 7 deletions apps/worker/app/services/document_agent/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ def _run_structural(self) -> PageAnatomyMap:
profile, initial_decision, _planner_result = self._propose_profile(
actor="planner"
)
self._run_h1_boundary_pipeline()
executor_result = ReActExecutor(
self.ctx,
registry=REGISTRY,
Expand Down Expand Up @@ -209,7 +208,6 @@ def _run_lightweight_anatomy(
)
else:
self._ensure_disabled_toc_placeholder()
self._run_h1_boundary_pipeline()
if skip_shard_plan:
# Page-based track processes pages individually via VLM and never
# consumes the shard plan; only build_anatomy_map's invariant needs
Expand Down Expand Up @@ -385,8 +383,3 @@ def _run_toc_extraction_pipeline(self) -> None:
actor=f"toc:{tool_name}",
)

def _run_h1_boundary_pipeline(self) -> None:
self._dispatch_profile_tool(
tool_name="match.h1_pages",
actor="toc:match.h1_pages",
)
10 changes: 5 additions & 5 deletions apps/worker/app/services/document_agent/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,9 @@ class Shard:
page_start: int
page_end: int
page_offset: int
anchor_type: Literal["h1_boundary", "blank_separator", "forced_max_size"]
anchor_type: Literal["h1_boundary", "blank_separator", "forced_max_size", "toc_chapter_boundary"]
anchor_evidence: str
confidence: float
split_depth: int = 1 # 1=H1 cut, 2=H2 cut, etc.
is_continuation: bool = False # True for continuation shards that don't contain parent heading

def to_dict(self) -> dict[str, Any]:
return asdict(self)
Expand Down Expand Up @@ -218,10 +216,11 @@ class PageAnatomyMap:
page_features: list[PageFeature]
page_labels: list[PageLabel]
toc_result: TocResult
h1_result: H1BoundaryResult
shard_plan: ShardPlan
h1_result: H1BoundaryResult | None = None
document_profile: DocumentProfile | None = None
toc_hierarchies: list[dict[str, Any]] | None = None
toc_page_offset: int | None = None
global_signals: dict[str, Any] = field(default_factory=dict)
trace_summary: dict[str, Any] = field(default_factory=dict)
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
Expand All @@ -236,12 +235,13 @@ def to_dict(self) -> dict[str, Any]:
"page_features": [feature.to_dict() for feature in self.page_features],
"page_labels": [label.to_dict() for label in self.page_labels],
"toc_result": self.toc_result.to_dict(),
"h1_result": self.h1_result.to_dict(),
"h1_result": self.h1_result.to_dict() if self.h1_result else None,
"shard_plan": self.shard_plan.to_dict(),
"document_profile": self.document_profile.to_dict()
if self.document_profile
else None,
"toc_hierarchies": self.toc_hierarchies,
"toc_page_offset": self.toc_page_offset,
"global_signals": dict(self.global_signals),
"trace_summary": dict(self.trace_summary),
"created_at": self.created_at.isoformat(),
Expand Down
4 changes: 0 additions & 4 deletions apps/worker/app/services/document_agent/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,5 @@ def has_toc_hierarchies(blackboard: AgentBlackboard) -> tuple[bool, str]:
return bool(blackboard.toc_hierarchies), "toc_hierarchies missing; call extract_toc first"


def has_h1_result(blackboard: AgentBlackboard) -> tuple[bool, str]:
return blackboard.h1_result is not None, "h1_result missing; call match_h1 first"


def has_shard_plan(blackboard: AgentBlackboard) -> tuple[bool, str]:
return blackboard.shard_plan is not None, "shard_plan missing; call propose_shard first"
1 change: 1 addition & 0 deletions apps/worker/app/services/document_agent/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class AgentBlackboard:
toc_result: TocResult | None = None
toc_hierarchies: list[dict[str, Any]] | None = None
h1_result: H1BoundaryResult | None = None
toc_page_offset: int | None = None
shard_plan: ShardPlan | None = None
validation_report: dict[str, Any] | None = None
verdict: AgentVerdict | None = None
Expand Down
1 change: 0 additions & 1 deletion apps/worker/app/services/document_agent/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from . import find_toc_anchor_pages as find_toc_anchor_pages # noqa: F401
from . import grep_text as grep_text # noqa: F401
from . import inspect_pages as inspect_pages # noqa: F401
from . import match_h1_pages as match_h1_pages # noqa: F401
from . import page_locate as page_locate # noqa: F401
from . import propose_shard_plan as propose_shard_plan # noqa: F401
from . import validate_anatomy_map as validate_anatomy_map # noqa: F401
Expand Down
Loading
Loading