Router Retriever
In this guide, we define a custom router retriever that selects one or more candidate retrievers in order to execute a given query.
The router (BaseSelector
) module uses the LLM to dynamically make decisions on which underlying retrieval tools to use. This can be helpful to select one out of a diverse range of data sources. This can also be helpful to aggregate retrieval results across a variety of data sources (if a multi-selector module is used).
This notebook is very similar to the RouterQueryEngine notebook.
If you’re opening this Notebook on colab, you will probably need to install LlamaIndex 🦙.
%pip install llama-index-llms-openai
!pip install llama-index
# NOTE: This is ONLY necessary in jupyter notebook.# Details: Jupyter runs an event-loop behind the scenes.# This results in nested event-loops when we start an event-loop to make async queries.# This is normally not allowed, we use nest_asyncio to allow it for convenience.import nest_asyncio
nest_asyncio.apply()
import loggingimport sys
logging.basicConfig(stream=sys.stdout, level=logging.INFO)logging.getLogger().handlers = []logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
from llama_index.core import ( VectorStoreIndex, SimpleDirectoryReader, StorageContext, SimpleKeywordTableIndex,)from llama_index.core import SummaryIndexfrom llama_index.core.node_parser import SentenceSplitterfrom llama_index.llms.openai import OpenAI
Note: NumExpr detected 12 cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 8.NumExpr defaulting to 8 threads.
Download Data
Section titled “Download Data”!mkdir -p 'data/paul_graham/'!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
Load Data
Section titled “Load Data”We first show how to convert a Document into a set of Nodes, and insert into a DocumentStore.
# load documentsdocuments = SimpleDirectoryReader("./data/paul_graham/").load_data()
# initialize LLM + splitterllm = OpenAI(model="gpt-4")splitter = SentenceSplitter(chunk_size=1024)nodes = splitter.get_nodes_from_documents(documents)
# initialize storage context (by default it's in-memory)storage_context = StorageContext.from_defaults()storage_context.docstore.add_documents(nodes)
# definesummary_index = SummaryIndex(nodes, storage_context=storage_context)vector_index = VectorStoreIndex(nodes, storage_context=storage_context)keyword_index = SimpleKeywordTableIndex(nodes, storage_context=storage_context)
list_retriever = summary_index.as_retriever()vector_retriever = vector_index.as_retriever()keyword_retriever = keyword_index.as_retriever()
from llama_index.core.tools import RetrieverTool
list_tool = RetrieverTool.from_defaults( retriever=list_retriever, description=( "Will retrieve all context from Paul Graham's essay on What I Worked" " On. Don't use if the question only requires more specific context." ),)vector_tool = RetrieverTool.from_defaults( retriever=vector_retriever, description=( "Useful for retrieving specific context from Paul Graham essay on What" " I Worked On." ),)keyword_tool = RetrieverTool.from_defaults( retriever=keyword_retriever, description=( "Useful for retrieving specific context from Paul Graham essay on What" " I Worked On (using entities mentioned in query)" ),)
Define Selector Module for Routing
Section titled “Define Selector Module for Routing”There are several selectors available, each with some distinct attributes.
The LLM selectors use the LLM to output a JSON that is parsed, and the corresponding indexes are queried.
The Pydantic selectors (currently only supported by gpt-4-0613
and gpt-3.5-turbo-0613
(the default)) use the OpenAI Function Call API to produce pydantic selection objects, rather than parsing raw JSON.
Here we use PydanticSingleSelector/PydanticMultiSelector but you can use the LLM-equivalents as well.
from llama_index.core.selectors import LLMSingleSelector, LLMMultiSelectorfrom llama_index.core.selectors import ( PydanticMultiSelector, PydanticSingleSelector,)from llama_index.core.retrievers import RouterRetrieverfrom llama_index.core.response.notebook_utils import display_source_node
PydanticSingleSelector
Section titled “PydanticSingleSelector”retriever = RouterRetriever( selector=PydanticSingleSelector.from_defaults(llm=llm), retriever_tools=[ list_tool, vector_tool, ],)
# will retrieve all context from the author's lifenodes = retriever.retrieve( "Can you give me all the context regarding the author's life?")for node in nodes: display_source_node(node)
Selecting retriever 0: This choice is most relevant as it mentions retrieving all context from the essay, which could include information about the author's life..
Node ID: 7d07d325-489e-4157-a745-270e2066a643
Similarity: None
Text: What I Worked On
February 2021
Before college the two main things I worked on, outside of schoo…
Node ID: 01f0900b-db83-450b-a088-0473f16882d7
Similarity: None
Text: showed Terry Winograd using SHRDLU. I haven’t tried rereading The Moon is a Harsh Mistress, so I …
Node ID: b2549a68-5fef-4179-b027-620ebfa6e346
Similarity: None
Text: Science is an uneasy alliance between two halves, theory and systems. The theory people prove thi…
Node ID: 4f1e9f0d-9bc6-4169-b3b6-4f169bbfa391
Similarity: None
Text: been explored. But all I wanted was to get out of grad school, and my rapidly written dissertatio…
Node ID: e20c99f9-5e80-4c92-8cc0-03d2a527131e
Similarity: None
Text: stop there, of course, or you get merely photographic accuracy, and what makes a still life inter…
Node ID: dbdf341a-f340-49f9-961f-16b9a51eea2d
Similarity: None
Text: that big, bureaucratic customers are a dangerous source of money, and that there’s not much overl…
Node ID: ed341d3a-9dda-49c1-8611-0ab40d04f08a
Similarity: None
Text: about money, because I could sense that Interleaf was on the way down. Freelance Lisp hacking wor…
Node ID: d69e02d3-2732-4567-a360-893c14ae157b
Similarity: None
Text: a web app, is common now, but at the time it wasn’t clear that it was even possible. To find out,…
Node ID: df9e00a5-e795-40a1-9a6b-8184d1b1e7c0
Similarity: None
Text: have to integrate with any other software except Robert’s and Trevor’s, so it was quite fun to wo…
Node ID: 38f2699b-0878-499b-90ee-821cb77e387b
Similarity: None
Text: all too keenly aware of the near-death experiences we seemed to have every few months. Nor had I …
Node ID: be04d6a9-1fc7-4209-9df2-9c17a453699a
Similarity: None
Text: for a second still life, painted from the same objects (which hopefully hadn’t rotted yet).
Mean…
Node ID: 42344911-8a7c-4e9b-81a8-0fcf40ab7690
Similarity: None
Text: which I’d created years before using Viaweb but had never used for anything. In one day it got 30…
Node ID: 9ec3df49-abf9-47f4-b0c2-16687882742a
Similarity: None
Text: I didn’t know but would turn out to like a lot: a woman called Jessica Livingston. A couple days …
Node ID: d0cf6975-5261-4fb2-aae3-f3230090fb64
Similarity: None
Text: of readers, but professional investors are thinking “Wow, that means they got all the returns.” B…
Node ID: 607d0480-7eee-4fb4-965d-3cb585fda62c
Similarity: None
Text: to the “YC GDP,” but as YC grows this becomes less and less of a joke. Now lots of startups get t…
Node ID: 730a49c9-55f7-4416-ab91-1d0c96e704c8
Similarity: None
Text: So this set me thinking. It was true that on my current trajectory, YC would be the last thing I …
Node ID: edbe8c67-e373-42bf-af98-276b559cc08b
Similarity: None
Text: operators you need? The Lisp that John McCarthy invented, or more accurately discovered, is an an…
Node ID: 175a4375-35ec-45a0-a90c-15611505096b
Similarity: None
Text: Like McCarthy’s original Lisp, it’s a spec rather than an implementation, although like McCarthy’…
Node ID: 0cb367f9-0aac-422b-9243-0eaa7be15090
Similarity: None
Text: must tell readers things they don’t already know, and some people dislike being told such things…
Node ID: 67afd4f1-9fa1-4e76-87ac-23b115823e6c
Similarity: None
Text: 1960 paper.
But if so there’s no reason to suppose that this is the limit of the language that m…
nodes = retriever.retrieve("What did Paul Graham do after RISD?")for node in nodes: display_source_node(node)
Selecting retriever 1: The question asks for a specific detail from Paul Graham's essay on 'What I Worked On'. Therefore, the second choice, which is useful for retrieving specific context, is the most relevant..
Node ID: 22d20835-7de6-4cf7-92de-2bee339f3157
Similarity: 0.8017176790752668
Text: that big, bureaucratic customers are a dangerous source of money, and that there’s not much overl…
Node ID: bf818c58-5d5b-4458-acbc-d87cc67a36ca
Similarity: 0.7935885352785799
Text: So this set me thinking. It was true that on my current trajectory, YC would be the last thing I …
PydanticMultiSelector
Section titled “PydanticMultiSelector”retriever = RouterRetriever( selector=PydanticMultiSelector.from_defaults(llm=llm), retriever_tools=[list_tool, vector_tool, keyword_tool],)
nodes = retriever.retrieve( "What were noteable events from the authors time at Interleaf and YC?")for node in nodes: display_source_node(node)
Selecting retriever 1: This choice is relevant as it allows for retrieving specific context from the essay, which is needed to answer the question about notable events at Interleaf and YC..Selecting retriever 2: This choice is also relevant as it allows for retrieving specific context using entities mentioned in the query, which in this case are 'Interleaf' and 'YC'..> Starting query: What were noteable events from the authors time at Interleaf and YC?query keywords: ['interleaf', 'events', 'noteable', 'yc']> Extracted keywords: ['interleaf', 'yc']
Node ID: fbdd25ed-1ecb-4528-88da-34f581c30782
Similarity: None
Text: So this set me thinking. It was true that on my current trajectory, YC would be the last thing I …
Node ID: 4ce91b17-131f-4155-b7b5-8917cdc612b1
Similarity: None
Text: to the “YC GDP,” but as YC grows this becomes less and less of a joke. Now lots of startups get t…
Node ID: 9fe6c152-28d4-4006-8a1a-43bb72655438
Similarity: None
Text: stop there, of course, or you get merely photographic accuracy, and what makes a still life inter…
Node ID: d11cd2e2-1dd2-4c3b-863f-246fe3856f49
Similarity: None
Text: of readers, but professional investors are thinking “Wow, that means they got all the returns.” B…
Node ID: 2bfbab04-cb71-4641-9bd9-52c75b3a9250
Similarity: None
Text: must tell readers things they don’t already know, and some people dislike being told such things…
nodes = retriever.retrieve( "What were noteable events from the authors time at Interleaf and YC?")for node in nodes: display_source_node(node)
Selecting retriever 1: This choice is relevant as it allows for retrieving specific context from the essay, which is needed to answer the question about notable events at Interleaf and YC..Selecting retriever 2: This choice is also relevant as it allows for retrieving specific context using entities mentioned in the query, which in this case are 'Interleaf' and 'YC'..> Starting query: What were noteable events from the authors time at Interleaf and YC?query keywords: ['interleaf', 'yc', 'events', 'noteable']> Extracted keywords: ['interleaf', 'yc']
Node ID: 49882a2c-bb95-4ff3-9df1-2a40ddaea408
Similarity: None
Text: So this set me thinking. It was true that on my current trajectory, YC would be the last thing I …
Node ID: d11aced1-e630-4109-8ec8-194e975b9851
Similarity: None
Text: to the “YC GDP,” but as YC grows this becomes less and less of a joke. Now lots of startups get t…
Node ID: 8aa6cc91-8e9c-4470-b6d5-4360ed13fefd
Similarity: None
Text: stop there, of course, or you get merely photographic accuracy, and what makes a still life inter…
Node ID: e37465de-c79a-4714-a402-fbd5f52800a2
Similarity: None
Text: must tell readers things they don’t already know, and some people dislike being told such things…
Node ID: e0ac7fb6-84fc-4763-bca6-b68f300ec7b7
Similarity: None
Text: of readers, but professional investors are thinking “Wow, that means they got all the returns.” B…
nodes = await retriever.aretrieve( "What were noteable events from the authors time at Interleaf and YC?")for node in nodes: display_source_node(node)
Selecting retriever 1: This choice is relevant as it allows for retrieving specific context from the essay, which is needed to answer the question about notable events at Interleaf and YC..Selecting retriever 2: This choice is also relevant as it allows for retrieving specific context using entities mentioned in the query, which in this case are 'Interleaf' and 'YC'..> Starting query: What were noteable events from the authors time at Interleaf and YC?query keywords: ['events', 'interleaf', 'yc', 'noteable']> Extracted keywords: ['interleaf', 'yc']message='OpenAI API response' path=https://api.openai.com/v1/embeddings processing_ms=25 request_id=95c73e9360e6473daab85cde93ca4c42 response_code=200
Node ID: 76d76348-52fb-49e6-95b8-2f7a3900fa1a
Similarity: None
Text: So this set me thinking. It was true that on my current trajectory, YC would be the last thing I …
Node ID: 61e1908a-79d2-426b-840e-926df469ac49
Similarity: None
Text: to the “YC GDP,” but as YC grows this becomes less and less of a joke. Now lots of startups get t…
Node ID: cac03004-5c02-4145-8e92-c320b1803847
Similarity: None
Text: stop there, of course, or you get merely photographic accuracy, and what makes a still life inter…
Node ID: f0d55e5e-5349-4243-ab01-d9dd7b12cd0a
Similarity: None
Text: of readers, but professional investors are thinking “Wow, that means they got all the returns.” B…
Node ID: 1516923c-0dee-4af2-b042-3e1f38de7e86
Similarity: None
Text: must tell readers things they don’t already know, and some people dislike being told such things…