Agent Tools

In the {lab-folder}/tools/index.ts file, you will find an initTools() function. This function provides an array of tools for the agent to use.

typescript
The initTools() function
export default async function initTools(
  llm: BaseChatModel,
  embeddings: Embeddings,
  graph: Neo4jGraph
): Promise<DynamicStructuredTool[]> {
  // TODO: Initiate chains
  // const cypherChain = await ...
  // const retrievalChain = await ...

  // TODO: Append chains to output
  return [];
}

Modify the function to return the Cypher Retrieval and Vector Retrieval tools along with appropriate descriptions for how the agent should use them.

Cypher Retrieval Chain

First, use the initCypherRetrievalChain() function to create an instance of the Cypher Retrieval Tool.

typescript
Cypher Retrieval Tool
// Initiate chains
const cypherChain = await initCypherRetrievalChain(llm, graph);

Append a new instance of the DynamicStructuredTool to the return array. Use the object passed to the constructor to give the tool the name graph-cypher-retrieval-chain and provide instructions for retrieving advanced movie information.

typescript
Dynamic Structured Tool
return [
    new DynamicStructuredTool({
      name: "graph-cypher-retrieval-chain",
      description:
        "For retrieving movie information from the database including movie recommendations, actors and user ratings",
      schema: AgentToolInputSchema,
      func: (input, _runManager, config) => cypherChain.invoke(input, config),
    }),
]

Vector Retrieval Chain

Next, use the initVectorRetrievalChain() function to create an instance of the Vector Retrieval Tool.

typescript
Vector Retrieval Tool
const retrievalChain = await initVectorRetrievalChain(llm, embeddings);

Append a new instance of the DynamicStructuredTool to the return array. Use the object passed to the constructor to give the tool the name graph-vector-retrieval-chain and provide instructions to use the tool when comparing movies by plot.

typescript
Dynamic Structured Tool
return [
    // ...
    new DynamicStructuredTool({
      name: "graph-vector-retrieval-chain",
      description:
        "For finding movies, comparing movies by their plot or recommending a movie based on a theme",
      schema: AgentToolInputSchema,
      func: (input, _runManager: any, config) =>
        retrievalChain.invoke(input, config),
    }),
]

Completed code

Your implemented function should resemble the following:

typescript
export default async function initTools(
  llm: BaseChatModel,
  embeddings: Embeddings,
  graph: Neo4jGraph
): Promise<DynamicStructuredTool[]> {
  // Initiate chains
  const cypherChain = await initCypherRetrievalChain(llm, graph);
  const retrievalChain = await initVectorRetrievalChain(llm, embeddings);

  return [
    new DynamicStructuredTool({
      name: "graph-cypher-retrieval-chain",
      description:
        "For retrieving movie information from the database including movie recommendations, actors and user ratings",
      schema: AgentToolInputSchema,
      func: (input, _runManager, config) => cypherChain.invoke(input, config),
    }),
    new DynamicStructuredTool({
      name: "graph-vector-retrieval-chain",
      description:
        "For finding movies, comparing movies by their plot or recommending a movie based on a theme",
      schema: AgentToolInputSchema,
      func: (input, _runManager: any, config) =>
        retrievalChain.invoke(input, config),
    }),
  ];
}

Testing your changes

If you have followed the instructions, you should be able to run the following unit test to verify the response using the npm run test command.

sh
Running the Test
npm run test tools.test.ts
View Unit Test
typescript
tools.test.ts
import { ChatOpenAI } from "@langchain/openai";
import initTools from ".";
import { Neo4jGraph } from "@langchain/community/graphs/neo4j_graph";
import { OpenAIEmbeddings } from "@langchain/openai";

describe("Tool Chain", () => {
  it("should return two tools", async () => {
    const graph = await Neo4jGraph.initialize({
      url: process.env.NEO4J_URI as string,
      username: process.env.NEO4J_USERNAME as string,
      password: process.env.NEO4J_PASSWORD as string,
      database: process.env.NEO4J_DATABASE as string | undefined,
    });

    const llm = new ChatOpenAI({
      openAIApiKey: process.env.OPENAI_API_KEY,
      modelName: "gpt-3.5-turbo",
      temperature: 0,
      configuration: {
        baseURL: process.env.OPENAI_API_BASE,
      },
    });

    const embeddings = new OpenAIEmbeddings({
      openAIApiKey: process.env.OPENAI_API_KEY as string,
      configuration: {
        baseURL: process.env.OPENAI_API_BASE,
      },
    });

    const tools = await initTools(llm, embeddings, graph);

    expect(tools).toBeDefined();
    expect(tools.length).toBeGreaterThanOrEqual(2);

    await graph.close();
  });
});

It works!

Once the tests have passed, hit the button below to mark the lesson as completed.

Summary

In this lesson, you implemented a function that creates a set of tools that the agent can use to perform specific tasks.

In the next lesson, you will create an agent and use this function to register these tools.

Chatbot

Hi, I am an Educational Learning Assistant for Intelligent Network Exploration. You can call me E.L.A.I.N.E.

How can I help you today?