Skip to content

Resolve Issue #113: Agentic decision trace + Root node channel fix - #114

Merged
EricNGOntos merged 4 commits into
stagingfrom
feat/wuchengke/dev
May 29, 2026
Merged

EricNGOntos merged 4 commits into
stagingfrom
feat/wuchengke/dev

Conversation

@EricNGOntos

Copy link
Copy Markdown
Contributor

Closes #113

Summary

This PR implements two improvements to the agentic retrieval pipeline:

1. Navigation Decision Trace (decision_trace)

Adds a structured decision_trace field to the retrieval API response and MCP tool output, giving downstream agents full visibility into every significant LLM decision in the pipeline.

New response field:

{
  "decision_trace": [
    {"phase": "kg_select", "action": "select", "selected_documents": [{"name": "doc.docx", "confidence": 1.0, "source": "kg_llm_select"}]},
    {"phase": "navigate", "document": "doc.docx", "action": "NAVIGATE", "reason": "...", "selected_paths": ["四、 市场分析"]},
    {"phase": "navigate", "document": "doc.docx", "action": "STOP", "reason": "...", "stop_type": "no_relevant_child"},
    {"phase": "discovery_select", "document": "doc.docx", "action": "skip"}
  ]
}

Files changed:

  • core/types.py — Added NavigateStepResult dataclass, decision_trace field on AgenticResult
  • navigation/tools.py — Returns NavigateStepResult with reason/stop_type
  • navigation/document.py — Collects _decision_steps per document
  • orchestrator.py — Assembles kg_select + navigation steps into decision_trace (fixed overwrite bug: assignment replaced with .extend())
  • workflow/types.py, step_runner.py, execution/routes.py, response_projection.py — Propagates trace through the stack
  • apps/api/app/api/v1/routes/retrieval.py — Exposes decision_trace in API response schema
  • apps/api/app/mcp/retrieval_server.py — Exposes decision_trace + stop_reason in MCP output

2. Root Node Channel Fix

Previously, the Root section (document cover page) was routed through the wrong channel:

  • It was excluded from the navigation tree due to split_section_path("Root") → []depth=0 → filtered by depth < 1
  • It appeared in bottom discovery candidates as a bare path="Root" label with no context, giving the LLM no actionable information

Fix:

  • navigation/section_tree.py — Treats Root as a virtual L1 node so it appears in the navigation tree with its top-level summary (document outline)
  • orchestrator.py — Filters section_path == "Root" rows from discovery_by_doc; Root content is now accessible exclusively through hierarchical navigation

Result in navigation prompt:

▸ [SELECT] [L1] path="Root"  [text=1 image=15 table=1] [Leaf]
    This document includes: 法律声明, 前言, 一、 概述, 二、 人工智能用于解决网络安全的历史, ...

Backward Compatibility

All changes are 100% backward-compatible. No request parameters changed. The decision_trace field is null in non-agentic mode (legacy BM25 route).

Testing

E2E verified with debug_agentic_e2e.py against real DB data and live LLM calls:

  • Full pipeline completes in 6051ms (5 LLM calls)
  • decision_trace contains 5 entries: kg_select → navigate → navigate → discovery_select × 2
  • Root appears correctly in navigation tree with top_summary
  • Discovery candidates contain no Root path entries
  • make lint passes (ruff, all checks passed)

…d pre-pass LLM grouping for hierarchical merging.
…er generation

- Updated retrieval architecture to prioritize evidence_text as the primary output, with answer_text now deprecated and always empty.
- Revised documentation and code comments to reflect the new evidence-centric approach.
- Removed legacy components related to answer synthesis and streamlined retrieval processes.
- Added tests for new evidence rendering and discovery selection functionalities.
…teps to return structured NavigateStepResult
@EricNGOntos EricNGOntos added the agentic-rag-core Core agentic RAG retrieval pipeline label May 29, 2026
@EricNGOntos EricNGOntos self-assigned this May 29, 2026
@EricNGOntos
EricNGOntos merged commit 7ca5035 into staging May 29, 2026
5 of 7 checks passed
@EricNGOntos
EricNGOntos deleted the feat/wuchengke/dev branch May 29, 2026 03:11
try:
if int(level_val) > 0:
last_valid_idx = pos
except (TypeError, ValueError):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentic-rag-core Core agentic RAG retrieval pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants