DecomposerNode
Overview
- Decomposes the user query into datasource‑scoped sub‑queries and combination operations.
- Produces deterministic IDs for sub‑queries and post‑combine ops.
- Sits after
DatasourceResolverNode and before GlobalPlannerNode.
- Class:
DecomposerNode
- Source:
packages/nl2sql/src/nl2sql/pipeline/nodes/decomposer/node.py
Responsibilities
- Invoke the LLM to produce
DecomposerResponse.
- Filter sub‑queries by resolved/allowed/unsupported datasources.
- Stabilize IDs using a hash of sub‑query content.
- Normalize and sort combine groups and post‑combine operations.
Position in Execution Graph
Upstream:
Downstream:
Trigger conditions:
- Executed only when
resolver_route returns continue.
flowchart LR
Resolver[DatasourceResolverNode] --> Decomposer[DecomposerNode] --> Planner[GlobalPlannerNode]
From GraphState:
user_query (str, required)
datasource_resolver_response (DatasourceResolverResponse, required)
Validation performed:
- Raises if no resolved datasources are available.
- Filters out sub‑queries that reference missing, restricted, or unsupported datasources.
Outputs
Mutations to GraphState:
decomposer_response (DecomposerResponse)
reasoning (completion status)
errors on failure
Side effects:
- None beyond LLM invocation.
Internal Flow (Step-by-Step)
- Validate resolver response; raise if no resolved datasources.
- Build
resolved_payload and schema_version_map.
- Invoke LLM chain with
user_query and resolved datasources.
- For each LLM sub‑query:
- Validate datasource existence and RBAC allowance.
- Assign deterministic ID via
_stable_id().
- Attach schema version.
- Remap combine groups to stable sub‑query IDs.
- Assign deterministic IDs to post‑combine ops.
- Sort sub‑queries, combine groups, and post‑combine ops.
- Return
DecomposerResponse.
- On exception, emit
ORCHESTRATOR_CRASH error.
Contracts & Interfaces
Implements a LangGraph node callable:
def __call__(self, state: GraphState) -> Dict[str, Any]
Key contracts:
DecomposerResponse
SubQuery
UnmappedSubQuery
PostCombineOp
Determinism Guarantees
- Stable IDs are generated via SHA‑256 hash of sub‑query content.
- Ordering of outputs is explicitly sorted.
- LLM output is non‑deterministic unless configured deterministically.
Error Handling
Emits PipelineError with:
ORCHESTRATOR_CRASH on exceptions.
Logs failures via logger.error.
Retry + Idempotency
- No internal retry logic.
- Idempotent for fixed LLM output; otherwise LLM variability can change output.
- One LLM call per pipeline execution.
- Hashing and sorting are in‑memory and low cost.
Observability
- Logger:
decomposer
- Adds a reasoning entry on completion or failure.
Configuration
- LLM configuration for agent name
decomposer via llm.yaml.
Extension Points
- Modify
DECOMPOSER_PROMPT for different decomposition strategies.
- Replace or wrap node in
build_graph() for custom behavior.
Known Limitations
- No fallback when LLM fails.
- Output quality depends on LLM configuration and prompt.
packages/nl2sql/src/nl2sql/pipeline/nodes/decomposer/node.py
packages/nl2sql/src/nl2sql/pipeline/nodes/decomposer/schemas.py