run-llama / LlamaIndexTS

LlamaIndex in TypeScript

Home Page:https://ts.llamaindex.ai

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ReAct agent crashes when no tool needed

alexander-fischer opened this issue · comments

I use the ReActAgent together with Llama3 via Ollama. If I ask a normal question like "Hello. How are you?" the agent crashes, since it's searching for a tool to use. I guess it should not throw an error if no tool needs to be used. Here is the stack trace:

Starting step(id, 0cf7f648-3c0c-4651-90a2-e3713085e94d).
Enqueueing output for step(id, 0cf7f648-3c0c-4651-90a2-e3713085e94d).
/Users/alex/dev/research/llamaindex-ts/node_modules/llamaindex/dist/cjs/agent/react.js:63
        throw new Error(`Could not extract tool use from input text: "${inputText}"`);
              ^
Error: Could not extract tool use from input text: "I need to use a tool to help me answer the question.

Action: None
Action Input: None

Please let me know how I can assist you with your task or question."
    at extractToolUse (/Users/alex/dev/research/llamaindex-ts/node_modules/llamaindex/dist/cjs/agent/react.js:63:15)
    at reACTOutputParser (/Users/alex/dev/research/llamaindex-ts/node_modules/llamaindex/dist/cjs/agent/react.js:176:54)
    at taskHandler (/Users/alex/dev/research/llamaindex-ts/node_modules/llamaindex/dist/cjs/agent/react.js:283:30)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.pull (/Users/alex/dev/research/llamaindex-ts/node_modules/llamaindex/dist/cjs/agent/base.js:432:13)

Here is the code for reproducing:

import { FunctionTool, Ollama, ReActAgent } from "llamaindex"

function add({ a, b }: { a: number; b: number }) {
  return `${a + b}`
}

const sumJSON = {
  type: "object",
  properties: {
    a: {
      type: "number",
      description: "The first number",
    },
    b: {
      type: "number",
      description: "The second number",
    },
  },
  required: ["a", "b"],
} as const

const sumTool = new FunctionTool(add, {
  name: "sumTool",
  description: "Add two integers and returns the result integer",
  parameters: sumJSON,
})

function multiply({ a, b }: { a: number; b: number }) {
  return `${a * b}`
}

const multiplyJSON = {
  type: "object",
  properties: {
    a: {
      type: "number",
      description: "The first number",
    },
    b: {
      type: "number",
      description: "The second number",
    },
  },
  required: ["a", "b"],
} as const

const multiplyTool = new FunctionTool(multiply, {
  name: "multiplyTool",
  description: "Multiply two integers and returns the result integer",
  parameters: multiplyJSON,
})

async function main() {
  const context = `You're an agent that function as a calculator. 
  Use the tools only if you're asked to calculate something.
  Don't provide more information than it was asked for.
  Do not rely on prior knowledge.`

  const ollama = new Ollama({
    model: "llama3",
  })

  const agent = new ReActAgent({
    llm: ollama,
    tools: [sumTool, multiplyTool],
    systemPrompt: context,
    verbose: true,
  })

  const prompt = "Hello. How are you?"

  const { response } = await agent.chat({
    message: prompt,
    verbose: true,
  })
  console.log("ANSWER:", response.message.content)
}

void main().then(() => {
  console.log("Done")
})

it would be nice to handle actions processing problems in getReACTAgentSystemHeader like this (see additional rules):

const getReACTAgentSystemHeader = (tools)=>{
    const description = tools.map((tool)=>`- ${tool.metadata.name}: ${tool.metadata.description} with schema: ${JSON.stringify(tool.metadata.parameters)}`).join("\n");
    const names = tools.map((tool)=>tool.metadata.name).join(", ");
    return `You are designed to help with a variety of tasks, from answering questions to providing summaries to other types of analyses.

## Tools
You have access to a wide variety of tools. You are responsible for using
the tools in any sequence you deem appropriate to complete the task at hand.
This may require breaking the task into subtasks and using different tools
to complete each subtask.

You have access to the following tools:
${description}

## Output Format
To answer the question, please use the following format.

"""
Thought: I need to use a tool to help me answer the question.
Action: tool name (one of ${names}) if using a tool.
Action Input: the input to the tool, in a JSON format representing the kwargs (e.g. {{"input": "hello world", "num_beams": 5}})
"""

Please ALWAYS start with a Thought.

Please use a valid JSON format for the Action Input. Do NOT do this {{'input': 'hello world', 'num_beams': 5}}.

If this format is used, the user will respond in the following format:

""""
Observation: tool response
""""

You should keep repeating the above format until you have enough information
to answer the question without using any more tools. At that point, you MUST respond
in the one of the following two formats:

""""
Thought: I can answer without using any more tools.
Answer: [your answer here]
""""

""""
Thought: I cannot answer the question with the provided tools.
Answer: Sorry, I cannot answer your query.
""""

## Additional Rules

If you are not sure about the action to make or the action inputs, use the following format:

""""
Thought: I need more informations from the user before using tools.
Answer: [ask the user for the needed informations]
""""

## Current Conversation
Below is the current conversation consisting of interleaving human and assistant messages.`;
};

but this works until after the user reply, after that the llm response will always be like:

ANSWER: You are designed to help with a variety of tasks, from answering questions to providing summaries to other types of analyses.

## Tools
You have access to a wide variety of tools. You are responsible for using
the tools in any sequence you deem appropriate to complete the task at hand. This may require breaking the task into subtasks and using different tools
to complete each subtask.

some other changes are needed to process that correctly