BaseRetriever
. This is demonstrated in the Property Graph Custom Retriever example.from llama_index.core.retrievers import BaseRetriever from llama_index.core.schema import NodeWithScore, QueryBundle from llama_index.postprocessor.cohere_rerank import CohereRerank class CustomMultiVectorRetriever(BaseRetriever): def __init__( self, vector_retrievers, reranker, top_n=5 ): self.vector_retrievers = vector_retrievers self.reranker = reranker self.top_n = top_n super().__init__() def _retrieve(self, query_bundle: QueryBundle): all_nodes = [] for retriever in self.vector_retrievers: nodes = retriever.retrieve(query_bundle) all_nodes.extend(nodes) reranked_nodes = self.reranker.postprocess_nodes( all_nodes, query_bundle=query_bundle ) return reranked_nodes[:self.top_n]
from llama_index.core.retrievers import VectorIndexRetriever from llama_index.core import VectorStoreIndex # Assume you have multiple vector store indexes index1 = VectorStoreIndex.from_documents(documents1) index2 = VectorStoreIndex.from_documents(documents2) retriever1 = VectorIndexRetriever(index=index1, similarity_top_k=10) retriever2 = VectorIndexRetriever(index=index2, similarity_top_k=10) reranker = CohereRerank(api_key=cohere_api_key, top_n=5) custom_retriever = CustomMultiVectorRetriever( vector_retrievers=[retriever1, retriever2], reranker=reranker, top_n=5 )
retrieve
method with a QueryBundle
object:from llama_index.core import QueryBundle query_str = "Your query here" query_bundle = QueryBundle(query_str=query_str) retrieved_nodes = custom_retriever.retrieve(query_bundle)
from llama_index.agent.openai import OpenAIAgent top_agent = OpenAIAgent.from_tools( tool_retriever=custom_retriever, system_prompt="""\ You are an agent designed to answer queries about the documentation. Please always use the tools provided to answer a question. Do not rely on prior knowledge. """, llm=llm, verbose=True, )
tool_retriever=custom_retriever
specifies that your custom retriever should be used to fetch tools (or in this case, relevant document chunks) for the agent.system_prompt
instructs the agent on its role and how to use the provided tools.llm
is the language model you're using (you'll need to define this separately).verbose=True
enables detailed logging of the agent's actions.response = top_agent.chat("Your question here") print(str(response))
CustomSimpleAgentWorker
and QueryPipelineAgentWorker
. Both of these classes have run_step
and arun_step
(asynchronous) methods. Here's how you can integrate your custom retriever with these:CustomSimpleAgentWorker
:from llama_index.core.agent import CustomSimpleAgentWorker class MyCustomAgentWorker(CustomSimpleAgentWorker): def __init__(self, custom_retriever, *args, **kwargs): super().__init__(*args, **kwargs) self.custom_retriever = custom_retriever def run_step(self, step, task, **kwargs): # Use your custom retriever here retrieved_data = self.custom_retriever.retrieve(step.input) # Process the retrieved data and incorporate it into your step execution # ... # Then call the parent method to execute the step return super().run_step(step, task, **kwargs)
QueryPipelineAgentWorker
:In both cases, you're overriding the `run_step` method to incorporate your custom retriever. You can do something similar for the `arun_step` method if you need asynchronous execution. To use these custom workers:
``
Remember that the exact implementation details may vary depending on your specific use case and the version of LlamaIndex you're using.
For more detailed information on the
run_step method and its usage in agent workflows, you can refer to the following documentation:
1. [CustomSimpleAgentWorker.run_step](<https://docs.llamaindex.ai/en/latest/api_reference/agent/#llama_index.core.agent.CustomSimpleAgentWorker.run_step>)
2. [QueryPipelineAgentWorker.run_step](<https://docs.llamaindex.ai/en/latest/api_reference/agent/#llama_index.core.agent.QueryPipelineAgentWorker.run_step>)
These resources provide more context on how the
run_step` method is implemented and can be customized in LlamaIndex agent workflows.from llama_index.core.indices.query.query_transform.base import ( StepDecomposeQueryTransform, ) from llama_index.core.query_engine import MultiStepQueryEngine step_decompose_transform = StepDecomposeQueryTransform(llm=gpt4, verbose=True) query_engine = index.as_query_engine() query_engine = MultiStepQueryEngine( query_engine=query_engine, query_transform=step_decompose_transform, index_summary="Used to answer questions about the author" )
flush=True
parameter in the print()
function is used in this example to ensure that the output is immediately written to the console or output stream without buffering. This is particularly important in the context of asynchronous programming and streaming responses. Let me explain why:async for
) to iterate over chunks of the response. This means the response is being streamed in parts rather than all at once.flush=True
, each chunk of the response is immediately displayed as soon as it's received, rather than waiting for the buffer to fill or for the entire response to complete.flush=True
overrides this behavior.flush=True
is a common practice when dealing with streaming or real-time data in Python, especially in asynchronous contexts like the one shown in this LlamaIndex example.MetadataFilters
class that allows you to specify filters based on metadata fields. You can use this to filter on specific collections or other metadata attributes.from llama_index.core.vector_stores import MetadataFilters, ExactMatchFilter # Create a filter for a specific collection filters = MetadataFilters( filters=[ExactMatchFilter(key="collection_name", value="your_collection_name")] ) # Use the filter with your retriever results = retriever.retrieve("your query", filters=filters)
retriever = index.as_retriever( vector_store_kwargs={"filter": {"collection_name": "your_collection_name"}} ) results = retriever.retrieve("your query")
2. [DuckDB metadata filter example](<https://docs.llamaindex.ai/en/latest/examples/vector_stores/DuckDBDemo/#metadata-filter-example>) demonstrates how to use metadata filters with DuckDB:
acomplete
with a structured Pydantic output in LlamaIndex, you can leverage the as_structured_llm
method along with a Pydantic model. Here's how you can do it:from pydantic import BaseModel class YourStructuredOutput(BaseModel): field1: str field2: int # Add more fields as needed
as_structured_llm
:from llama_index.llms.openai import OpenAI llm = OpenAI(model="gpt-3.5-turbo") structured_llm = llm.as_structured_llm(YourStructuredOutput)
acomplete
with your structured LLM:import asyncio async def get_structured_output(): response = await structured_llm.acomplete("Your prompt here") return response.raw # This will be an instance of YourStructuredOutput # Run the async function result = asyncio.run(get_structured_output()) print(result)
acomplete
method while ensuring that the output is structured according to your Pydantic model.acomplete
with a structured Pydantic output in LlamaIndex, you can leverage the as_structured_llm
method along with a Pydantic model. Here's how you can do it:from pydantic import BaseModel class YourStructuredOutput(BaseModel): field1: str field2: int # Add more fields as needed
as_structured_llm
:from llama_index.llms.openai import OpenAI llm = OpenAI(model="gpt-3.5-turbo") structured_llm = llm.as_structured_llm(YourStructuredOutput)
acomplete
with your structured LLM:import asyncio async def get_structured_output(): response = await structured_llm.acomplete("Your prompt here") return response.raw # This will be an instance of YourStructuredOutput # Run the async function result = asyncio.run(get_structured_output()) print(result)
acomplete
method while ensuring that the output is structured according to your Pydantic model.