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.
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.
// 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.
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.
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.
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:
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.
npm run test tools.test.ts
View Unit Test
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.