Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6773fe3
feat: implement node assembler for page memory hierarchy to support s…
EricNGOntos Jun 22, 2026
0035b4a
feat: implement page asset integration into node assembly and chunk c…
EricNGOntos Jun 23, 2026
6d7042c
feat: enhance document profiling and page memory integration with ski…
EricNGOntos Jun 23, 2026
a0ab8ca
feat: enhance retrieval and document ingestion with new chunk types a…
EricNGOntos Jun 24, 2026
c8f88ce
refactor: decouple page memory from image URIs and simplify node meta…
EricNGOntos Jun 25, 2026
3bf5d69
feat: integrate summary engine for enhanced document parsing and asse…
EricNGOntos Jun 25, 2026
eea74df
feat: implement concurrent page tagging and enrich image and table as…
EricNGOntos Jun 25, 2026
dfc10f1
feat: standardize page_memory track for PDF/PPTX, implement page-coun…
EricNGOntos Jun 25, 2026
5dbd084
chore: align parser env defaults
EricNGOntos Jun 26, 2026
3531581
refactor: replace legacy data_type integer with flexible chunk_types …
EricNGOntos Jun 26, 2026
10e6ba8
feat: implement intermediate node chain collapse and add utilities fo…
EricNGOntos Jun 29, 2026
e11a41f
Add thread-safe trace logging, remove unused heading dataframes, and …
EricNGOntos Jun 29, 2026
ab73cc7
refactor: remove budget tracking dependency from page memory services
EricNGOntos Jun 29, 2026
48ce6ea
chore: fix lint and type errors caught by ruff and pyright
EricNGOntos Jun 29, 2026
dd0a25a
fix: resolve alembic revision ID conflict causing cycle detection fai…
EricNGOntos Jun 29, 2026
81fe498
test: fix failing tests from page-memory native hierarchy branch
EricNGOntos Jun 29, 2026
24b50ad
refactor: remove page_memory_work_summary_20260624.md file and stream…
EricNGOntos Jul 1, 2026
fd12be7
Merge remote-tracking branch 'origin/feat/wuchengke/page-memory-nativ…
EricNGOntos Jul 1, 2026
c340924
feat: enhance skeleton extractor with native hierarchy support and ag…
EricNGOntos Jul 2, 2026
dcf0fec
Merge remote-tracking branch 'origin/main' into feat/wuchengke/page-m…
EricNGOntos Jul 2, 2026
ac82c1a
fix: remove dead commented code and propagate PageLocateConfig to pen…
EricNGOntos Jul 2, 2026
e28f57c
refactor: remove PageLocateResidualAgent fallback from skeleton extra…
EricNGOntos Jul 2, 2026
a42b189
fix: resolve PR #200 lint and typecheck failures
EricNGOntos Jul 3, 2026
411c115
feat: add toc_page_offset to PageAnatomyMap and AgentBlackboard
EricNGOntos Jul 3, 2026
625bd9a
feat: prune out-of-scope TOC nodes before offset-guided anchoring
EricNGOntos Jul 3, 2026
f870572
feat: add chapter boundary detection and toc_chapter_boundary anchor …
EricNGOntos Jul 3, 2026
8a72bb7
Merge remote-tracking branch 'origin/main' into feat/wuchengke/remove…
EricNGOntos Jul 3, 2026
f583eaf
fix: use private _calibrate_offset_via_vlm import after merge rename
EricNGOntos Jul 3, 2026
00d944f
feat: restore use_agentic switch with classic top-K retrieval route
EricNGOntos Jul 7, 2026
5af9c63
fix: update contract test to expect classic_topk when use_agentic=False
EricNGOntos Jul 7, 2026
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