Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Run llama Llama index QueryPlanTool

From Leeroopedia

Overview

The QueryPlanTool module implements a query planning and execution system that orchestrates multiple tools as a directed acyclic graph (DAG). It enables an LLM to decompose a complex question into a tree of sub-questions, each assigned to a specific tool, and then executes them in dependency order. Results from child nodes are synthesized using a response synthesizer to produce a final answer.

Source File: llama-index-core/llama_index/core/tools/query_plan.py

Module: llama_index.core.tools.query_plan

Lines of Code: 233

Dependencies

Dependency Type Purpose
llama_index.core.bridge.pydantic.BaseModel Internal Base model for data classes
llama_index.core.bridge.pydantic.Field Internal Field definitions with descriptions
llama_index.core.response_synthesizers.BaseSynthesizer Internal Abstract base for response synthesizers
llama_index.core.response_synthesizers.get_response_synthesizer Internal Factory function for default synthesizer
llama_index.core.schema.NodeWithScore Internal Node with relevance score for synthesis
llama_index.core.schema.TextNode Internal Text node for child response storage
llama_index.core.tools.types.BaseTool Internal Base tool interface
llama_index.core.tools.types.ToolMetadata Internal Tool metadata
llama_index.core.tools.types.ToolOutput Internal Standard tool output wrapper
llama_index.core.utils.print_text Internal Colored text output utility

Data Models

Class: QueryNode

class QueryNode(BaseModel)

Represents a single node in the query plan DAG. Each node is either a leaf node (answered by a tool) or a branch node (answered by synthesizing child node results).

Field Type Description
id int Unique identifier for the query node
query_str str The question to be answered at this node
tool_name Optional[str] Name of the tool to execute (for leaf nodes); None for branch nodes
dependencies List[int] List of node IDs that must be resolved before this node

The tool_name and dependencies fields are mutually exclusive in practice:

  • Leaf nodes have a tool_name and empty dependencies.
  • Branch nodes have dependencies referencing child nodes.

Class: QueryPlan

class QueryPlan(BaseModel)

The top-level plan containing all query nodes.

Field Type Description
nodes List[QueryNode] All nodes in the query plan DAG

The QueryPlan model is used as the fn_schema for the QueryPlanTool, meaning the LLM is expected to generate a QueryPlan JSON when calling this tool.

Module Constants

Constant Description
DEFAULT_NAME "query_plan_tool"
QUERYNODE_QUERY_STR_DESC Description for the query string field
QUERYNODE_TOOL_NAME_DESC Description for the tool name field (mutually exclusive with dependencies)
QUERYNODE_DEPENDENCIES_DESC Description for the dependencies field (mutually exclusive with tool name)
DEFAULT_DESCRIPTION_PREFIX Default prefix for the tool description, explaining the DAG-based query plan concept

Class: QueryPlanTool

class QueryPlanTool(BaseTool)

Constructor

def __init__(
    self,
    query_engine_tools: List[BaseTool],
    response_synthesizer: BaseSynthesizer,
    name: str,
    description_prefix: str,
) -> None
Parameter Type Description
query_engine_tools List[BaseTool] Available tools that can be assigned to leaf nodes
response_synthesizer BaseSynthesizer Synthesizer for combining child node results
name str Tool name
description_prefix str Prefix text for the dynamically generated description

Instance Attributes

Attribute Type Description
_query_tools_dict Dict[str, BaseTool] Dictionary mapping tool names to tool instances
_response_synthesizer BaseSynthesizer Response synthesizer for combining results
_name str Tool name
_description_prefix str Description prefix
_custom_metadata Optional[ToolMetadata] Optional custom metadata override

Factory Method: from_defaults

@classmethod
def from_defaults(
    cls,
    query_engine_tools: List[BaseTool],
    response_synthesizer: Optional[BaseSynthesizer] = None,
    name: Optional[str] = None,
    description_prefix: Optional[str] = None,
) -> "QueryPlanTool"

Creates a QueryPlanTool with sensible defaults:

  • Defaults to DEFAULT_NAME if no name is provided.
  • Defaults to DEFAULT_DESCRIPTION_PREFIX if no description prefix is provided.
  • Creates a default response synthesizer via get_response_synthesizer().

Property: metadata

The metadata property dynamically generates a ToolMetadata that includes:

  • The description prefix.
  • A listing of all available tool names and descriptions.
  • The QueryPlan model as the fn_schema.

If _custom_metadata is set (via the setter), it is returned instead of the dynamically generated metadata.

Method: _execute_node

def _execute_node(
    self, node: QueryNode, nodes_dict: Dict[int, QueryNode]
) -> ToolOutput

Recursively executes a single query node:

  1. If the node has dependencies:
    1. Retrieves child QueryNode objects from nodes_dict.
    2. Recursively executes each child node.
    3. Wraps child responses as TextNode objects with query/response text.
    4. Creates NodeWithScore wrappers (score=1.0).
    5. Uses the response synthesizer to combine child results into a response.
    6. If the node also has a tool_name, additionally executes that tool (overriding the synthesized response).
  2. If the node has no dependencies (leaf node):
    1. Looks up the tool by node.tool_name in _query_tools_dict.
    2. Calls the tool with node.query_str.
  3. Prints execution details using colored output.
  4. Returns the ToolOutput.

Method: _find_root_nodes

def _find_root_nodes(self, nodes_dict: Dict[int, QueryNode]) -> List[QueryNode]

Identifies root nodes in the DAG by finding nodes that are not listed as a dependency of any other node. Uses a counting approach:

  1. Initializes a count of zero for each node ID.
  2. Iterates through all nodes, incrementing the count for each dependency reference.
  3. Nodes with a count of zero are root nodes (no other node depends on them).

Method: __call__

def __call__(self, *args: Any, **kwargs: Any) -> ToolOutput

Entry point for tool execution:

  1. Constructs a QueryPlan from the provided keyword arguments.
  2. Builds a dictionary mapping node IDs to QueryNode objects.
  3. Finds root nodes via _find_root_nodes.
  4. Validates that exactly one root node exists (raises ValueError otherwise).
  5. Recursively executes the root node via _execute_node.

Execution Flow

LLM generates QueryPlan JSON
    |
    v
QueryPlanTool.__call__(**plan_kwargs)
    |
    v
QueryPlan(nodes=[...]) -- parse into data model
    |
    v
_find_root_nodes() -- identify the root of the DAG
    |
    v
_execute_node(root_node)
    |
    +---> Has dependencies?
    |       |
    |       +---> Yes: recursively execute child nodes
    |       |         |
    |       |         v
    |       |     Synthesize child results with response_synthesizer
    |       |         |
    |       |         v
    |       |     (Optionally call tool_name if present)
    |       |
    |       +---> No (leaf node): call tool(node.query_str)
    |
    v
Return ToolOutput

Design Patterns

DAG-Based Query Decomposition

The module models complex queries as a DAG where each node is either answered by a specific tool (leaf) or by synthesizing the results of its child nodes (branch). This enables multi-hop reasoning over multiple data sources.

Recursive Execution

Node execution is implemented recursively. The _execute_node method processes dependencies depth-first before synthesizing results at the current level.

Dynamic Metadata Generation

The metadata property dynamically constructs the tool description by enumerating all registered tools. This ensures the LLM always has an up-to-date list of available tools when generating query plans.

See Also

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment