Implementation:Run llama Llama index AutoMergingRetriever
Overview
The AutoMergingRetriever is a specialized retriever that automatically merges child nodes into their parent nodes when a sufficient proportion of a parent's children have been retrieved. This implements a hierarchical retrieval strategy where initial fine-grained vector search results are progressively consolidated into broader context windows by walking up a document hierarchy tree.
Source File: llama-index-core/llama_index/core/retrievers/auto_merging_retriever.py (194 lines)
Module: llama_index.core.retrievers.auto_merging_retriever
Class Definition
class AutoMergingRetriever(BaseRetriever):
"""
This retriever will try to merge context into parent context.
The retriever first retrieves chunks from a vector store.
Then, it will try to merge the chunks into a single context.
"""
Dependencies
| Module | Import |
|---|---|
llama_index.core.base.base_retriever |
BaseRetriever
|
llama_index.core.callbacks.base |
CallbackManager
|
llama_index.core.indices.query.schema |
QueryBundle
|
llama_index.core.indices.utils |
truncate_text
|
llama_index.core.indices.vector_store.retrievers.retriever |
VectorIndexRetriever
|
llama_index.core.schema |
BaseNode, IndexNode, NodeWithScore, MetadataMode, QueryBundle
|
llama_index.core.storage.storage_context |
StorageContext
|
Constructor
def __init__(
self,
vector_retriever: VectorIndexRetriever,
storage_context: StorageContext,
simple_ratio_thresh: float = 0.5,
verbose: bool = False,
callback_manager: Optional[CallbackManager] = None,
object_map: Optional[dict] = None,
objects: Optional[List[IndexNode]] = None,
) -> None
| Parameter | Type | Default | Description |
|---|---|---|---|
vector_retriever |
VectorIndexRetriever |
required | The underlying vector index retriever used for initial chunk retrieval |
storage_context |
StorageContext |
required | Storage context providing access to the docstore for fetching parent nodes |
simple_ratio_thresh |
float |
0.5 |
Threshold ratio of retrieved children to total children above which a parent merge occurs |
verbose |
bool |
False |
Whether to print verbose merge information |
callback_manager |
Optional[CallbackManager] |
None |
Optional callback manager for event tracking |
object_map |
Optional[dict] |
None |
Optional object map passed to the base retriever |
objects |
Optional[List[IndexNode]] |
None |
Optional list of index nodes passed to the base retriever |
Core Methods
_retrieve
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]
The main retrieval entry point. Performs the following steps:
- Calls the underlying
_vector_retriever.retrieve()to get initial nodes. - Calls
_try_merging()in a loop until no further changes occur. - Sorts the final nodes by similarity score in descending order.
- Returns the merged and sorted node list.
_try_merging
def _try_merging(
self, nodes: List[NodeWithScore]
) -> Tuple[List[NodeWithScore], bool]
Orchestrates two merging strategies in sequence:
- Fill-in nodes via
_fill_in_nodes()-- inserts gap nodes between consecutive siblings. - Parent merging via
_get_parents_and_merge()-- replaces child clusters with parent nodes.
Returns the updated node list and a boolean indicating whether any changes were made. The loop in _retrieve continues calling this method until convergence (no more changes).
_get_parents_and_merge
def _get_parents_and_merge(
self, nodes: List[NodeWithScore]
) -> Tuple[List[NodeWithScore], bool]
The primary merging logic:
- Collect parents: Iterates through all retrieved nodes, fetching parent nodes from the docstore. Builds a mapping of parent IDs to their currently retrieved children.
- Compute ratios: For each parent, calculates the ratio of retrieved children to total children.
- Merge decision: If the ratio exceeds
_simple_ratio_thresh(default 0.5), all the individual child nodes are removed and replaced with the parent node. - Score averaging: The merged parent node's score is set to the average of its children's scores.
_fill_in_nodes
def _fill_in_nodes(
self, nodes: List[NodeWithScore]
) -> Tuple[List[NodeWithScore], bool]
Fills in gaps between consecutive sibling nodes. If node i has a next_node reference that matches node i+1's prev_node reference, the intermediate node is fetched from the docstore and inserted between them. The gap node's score is set to the average of the two surrounding nodes.
Algorithm Flow
1. Vector retrieval -> initial nodes 2. Loop: a. Fill in sibling gap nodes b. Check parent merge ratios c. Replace child clusters with parents when ratio > threshold d. Repeat until no changes 3. Sort by score (descending) 4. Return final nodes
Design Notes
- The merging is iterative -- after merging children into parents, those parents may themselves be eligible for merging into grandparents, enabling multi-level hierarchical consolidation.
- The
simple_ratio_threshof 0.5 means that if more than half of a parent's children were retrieved, the entire parent context replaces the individual children. - Parent nodes are cached in a local dictionary (
parent_nodes) within a single merge pass to avoid redundant docstore lookups. - The fill-in step ensures that when two sibling chunks are retrieved with a gap between them, the missing context is included before attempting a parent merge.
See Also
- RecursiveRetriever -- Another hierarchical retriever that follows index node links recursively
- RouterRetriever -- A retriever that routes queries to appropriate sub-retrievers
- TransformRetriever -- A retriever that transforms queries before retrieval