Find answers from the community

Updated 2 months ago

i'm getting this error on a ReACT agent:```Observation: Error: 'function' object has no

i'm getting this error on a ReACT agent:

Plain Text
Observation: Error: 'function' object has no attribute 'metadata'
k
t
15 comments
Please stand by @tomi as I search the knowledge base. I normally take about 20 seconds or so. :wave:
----------------------
The error message you're seeing suggests that the function you're trying to use with your ReAct agent doesn't have the necessary metadata attribute. In LlamaIndex, when you're setting up a ReAct agent, you need to turn your functions into tools by supplying the appropriate metadata.

Here's an example of how to do this, using the QueryEngineTool class:

Plain Text
from llama_index.core.tools import QueryEngineTool

budget_tool = QueryEngineTool.from_defaults(
    query_engine,
    name="canadian_budget_2023",
    description="A RAG engine with some basic facts about the 2023 Canadian federal budget.",
)


In this example, query_engine is the function you're trying to use, and name and description are the metadata attributes you're supplying.

Then, you can add this tool to your ReAct agent like this:

Plain Text
agent = ReActAgent.from_tools(
    [multiply_tool, add_tool, budget_tool], verbose=True
)


In this example, multiply_tool and add_tool are other tools that you've already set up.

Please check your code to ensure that you're correctly setting up your tools with the necessary metadata before adding them to your ReAct agent.

For more information, you can refer to the LlamaIndex documentation ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai what i have is of type AgentRunner. how do i get a query engine from it
Let me check the knowledge base for you. One moment! :books:
----------------------
The AgentRunner class in LlamaIndex is used to run an agent, which can be any worker that implements the BaseAgentWorker interface. It doesn't directly provide a method to extract a query engine.

However, if you have access to the agent worker that was used to create the AgentRunner, you can potentially access the query engine from there, depending on the specific type of agent worker. For example, if you used a QueryUnderstandingAgentWorker or LLMCompilerAgentWorker, you could access the query engine tools that were passed to it during initialization.

Here's an example of how you might have created an AgentRunner:

Plain Text
from llama_index.core.agent import AgentRunner
from llama_index.packs.query_understanding_agent.step import QueryUnderstandingAgentWorker
from llama_index.core.tools import QueryEngineTool

llm = OpenAI(model="gpt-4")

tools = [
    QueryEngineTool.from_defaults(
        query_engine=index.as_query_engine(),
        description="A tool that is useful for retrieving specific snippets from the Paul Graham's life",
    ),
    QueryEngineTool.from_defaults(
        query_engine=steve_index.as_query_engine(),
        description="A tool that is useful for retrieving specific snippets from the Steve Jobs's life",
    ),
]

agent_worker = QueryUnderstandingAgentWorker.from_tools(tools, llm=llm, verbose=True)
agent = AgentRunner(agent_worker)


In this case, tools is a list of QueryEngineTool instances, each of which wraps a query engine. If you have access to this list, you can access the query engines from there.

If you don't have access to the original list of tools or the agent worker, and you only have an AgentRunner instance, you might not be able to extract the query engines. The AgentRunner class doesn't provide a public API for accessing the underlying agent worker or its properties.
For more information, you can refer to the LlamaIndex documentation ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai what i'm trying to do is pass multiple agents as tools to another agent
Let me check the knowledge base for you. One moment! :books:
----------------------
In LlamaIndex, you can indeed pass multiple agents as tools to another agent. This is done by wrapping each agent in a QueryEngineTool and then passing the list of these tools to the from_tools method of the agent you're creating.

Here's an example of how you might do this:

Plain Text
from llama_index.core.tools import QueryEngineTool

# Assume sql_agent and gmail_agent are your existing agents
query_engine_tools = [
    QueryEngineTool(
        query_engine=sql_agent,
        metadata=ToolMetadata(
            name="sql_agent", description="Agent that can execute SQL queries."
        ),
    ),
    QueryEngineTool(
        query_engine=gmail_agent,
        metadata=ToolMetadata(
            name="gmail_agent",
            description="Tool that can send emails on Gmail.",
        ),
    ),
]

outer_agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)


In this example, sql_agent and gmail_agent are existing agents that you want to use as tools. You wrap each of them in a QueryEngineTool, providing a name and description for each. Then, you pass the list of these tools to the from_tools method of the ReActAgent class to create your new agent.

For more information, you can refer to the LlamaIndex documentation ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai in your example, what's the type of sql_agent and gmail_agent?
Let me check the knowledge base for you. One moment! :books:
----------------------
In the example provided, sql_agent and gmail_agent are assumed to be instances of classes that inherit from BaseQueryEngine. This is a base class in LlamaIndex for creating query engines, which are components that can process queries and return results.

The sql_agent could be an instance of a class that executes SQL queries against a database, and gmail_agent could be an instance of a class that interacts with the Gmail API to send emails.

Here's a simplified example of what these classes might look like:

Plain Text
from llama_index.core.query_engine import BaseQueryEngine

class SQLAgent(BaseQueryEngine):
    def query(self, input):
        # Code to execute SQL query and return results
        pass

class GmailAgent(BaseQueryEngine):
    def query(self, input):
        # Code to send email via Gmail API and return results
        pass

sql_agent = SQLAgent()
gmail_agent = GmailAgent()


In this example, SQLAgent and GmailAgent are subclasses of BaseQueryEngine that implement the query method. You create instances of these classes and then use them as tools in your ReActAgent.

Please note that this is a simplified example. The actual implementation of these classes would depend on the specifics of how you want to interact with your SQL database and the Gmail API.

For more information, you can refer to the LlamaIndex documentation ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@kapa.ai is metadata required when creating a query engine tool
Let me check the knowledge base for you. One moment! :books:
----------------------
Yes, the metadata parameter is required when creating a QueryEngineTool in LlamaIndex. The metadata parameter is an instance of the ToolMetadata class, which includes the name and description of the tool, among other things.

Here's an example of how you might create a QueryEngineTool:

Plain Text
from llama_index.core.tools import QueryEngineTool, ToolMetadata

query_engine_tool = QueryEngineTool(
    query_engine=my_query_engine,
    metadata=ToolMetadata(
        name="my_tool",
        description="A tool that does something useful.",
    ),
)


In this example, my_query_engine is your query engine, and you're creating a ToolMetadata instance with the name "my_tool" and a description.

For more information, you can refer to the LlamaIndex documentation ().
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Add a reply
Sign up and join the conversation on Discord