Skip to main content

llama-index-postprocessor-needlepath

Needlepath context selection as a LlamaIndex BaseNodePostprocessor: given the retrieved nodes and the query, keep the nodes that carry the answer and replace each one's text with the part of it that does.

pip install llama-index-postprocessor-needlepath
from llama_index.postprocessor.needlepath import NeedlepathPostprocessor

query_engine = index.as_query_engine(
    node_postprocessors=[NeedlepathPostprocessor(operating_point="np-2026-07-r2")],
)

The key comes from NEEDLEPATH_API_KEY. If the service is slow, down, or stands down, the query engine gets the nodes it was given, unchanged.

Scope, stated honestly

This is a RAG-retrieval seam. It never sees tool outputs, so it exercises the weakest of Needlepath's use cases — retrieved chunks are already short and already ranked. It exists because LlamaIndex is where a large number of developers already have a postprocessor slot, and an integration that does not exist cannot be evaluated. If you are choosing where to try Needlepath first and you have an agent with tool calls, start there instead.

Configuration

Parameter Default What it does
operating_point Required. Immutable label. Also NEEDLEPATH_OPERATING_POINT.
max_context_tokens 4000 Budget for the selected context, and the default trigger.
trigger_tokens 0 Skip the call below this. 0 means "use the budget".
excerpt True Replace kept nodes' text with their excerpt. False filters only.
update_scores False Replace NodeWithScore.score with the selection score.
preserve_input_order False Return kept nodes in retrieval order rather than ranked order.
shadow False Measure and report; change nothing.
enabled True Kill switch. Needs no credentials when False.

Any other keyword is forwarded to the core client (base_url, api_key, timeout, …).

Two LlamaIndex-specific decisions

Scores are not overwritten by default. A reranker replaces NodeWithScore.score with its own. Ours is not calibrated against your retriever's similarity, and silently substituting one for the other corrupts any downstream threshold or similarity_cutoff. The selection score is available as node metadata; set update_scores=True if you want reranker-like behaviour and know what your thresholds mean.

Provenance metadata is hidden from the model. Node metadata is interpolated into the prompt under MetadataMode.LLM and into embeddings under MetadataMode.EMBED. Every needlepath_* key this package writes is added to excluded_llm_metadata_keys and excluded_embed_metadata_keys on the copy, so debug data never reaches the model or an index.

Node identity survives

A rewritten node is a model_copy(deep=True) with set_content() applied, so id_, metadata, relationships and therefore ref_doc_id are carried over verbatim. Building a fresh TextNode would mint a new random id_ and drop relationships, severing ref_doc_id, dedup and PrevNextNodePostprocessor.

The nodes you pass in are never mutated.

Fail open

What happens What the query engine gets
Timeout, 5xx, throttling, contract violation the original nodes, unchanged
The gate stands down, or selects nothing the original nodes, unchanged
No QueryBundle the original nodes, unchanged
Every returned id is unrecognized the original nodes, unchanged

The no-query case is worth calling out: every shipped reranker raises ValueError("Missing query bundle in extra info.") there. This does not. A postprocessor that raises turns a missing query into a failed query for the whole engine, and the fail-open rule is binding at a framework boundary.

postprocessor.stats.as_dict() aggregates the counters.

Async

_apostprocess_nodes is overridden rather than inherited. The base class's default is asyncio.to_thread(self._postprocess_nodes, …), which is correct but burns a thread per query on what is a network call — and nine call sites in llama-index-core reach the async path, including RetrieverQueryEngine and every chat engine.

Packaging

Named llama-index-postprocessor-needlepath rather than needlepath-llamaindex. That is the one naming exception to Needlepath's vendor-first convention: a package outside the host convention is not discoverable on LlamaHub at all.

PEP 420 namespace layout — llama_index/ and llama_index/postprocessor/ carry no __init__.py, so this distribution coexists with llama-index-core and every other integration under the same directories.

Tested against

llama-index-core==0.14.23. Range >=0.13.0,<0.15, matching every shipped llama-index-postprocessor-* package. CI runs against the newest minor.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llama_index_postprocessor_needlepath-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file llama_index_postprocessor_needlepath-0.1.0.tar.gz.

File metadata

File hashes

Hashes for llama_index_postprocessor_needlepath-0.1.0.tar.gz
Algorithm Hash digest
SHA256 90ceaa5e0e4458db7c0657b87cd5d48ad85a239d364b4080528a62e0289ff97d
MD5 dbd3253acac765581de855613053de37
BLAKE2b-256 9b6c987e68ca041e9ce5ec839c607ce0d74da3014b5f77d3117cf5d1b82a484e

See more details on using hashes here.

File details

Details for the file llama_index_postprocessor_needlepath-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for llama_index_postprocessor_needlepath-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 81e952b259c56671f01417c574a7f79d93e2dbccdba06ec25f5679601f17d817
MD5 811906ec76430fc800c9b78c0d3bad64
BLAKE2b-256 bbed318ec37274251c3870c9509f7e326e433ff5a74dbedff4dd3db857acaf2d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page