Text to Cypher Tool

In the previous challenge, you created a tool that used the Neo4jVector Store and Retriever to identify movies with similar plots to the user’s input. This approach may be relatively easy to set up, but as you learned in Vectors & Semantic Search module of the Neo4j & LLM Fundamentals course, this approach can have its drawbacks.

Semantic Search using Vector Similarity relies on relative proximity in vector space, which may not provide a precise match.

Graph-enhanced semantic search combines the nuanced understanding of data from vector search with the contextual insights provided by graph features, leading to search results with greater depth and relevance by considering the relationships and hierarchies between entities within a broader knowledge network.

In this challenge, you will create a tool that uses the structure of the graph to generate a Cypher statement to answer a question.

To complete this challenge, you must:

  1. Create a Graph Cypher QA Chain

  2. Register the Chain as a Tool

Creating a Graph Cypher QA Chain

To create a QA Chain that generates Cypher, you must import the GraphCypherQAChain.

In the tools/ folder, create a new file called cypher.py. Copy the following code to import the GraphCypherQAChain and the Neo4jGraph store object created in Connecting to Neo4j lesson.

python
Importing Dependencies
Unresolved directive in lesson.adoc - include::https://raw.githubusercontent.com/neo4j-graphacademy/app-python/main/solutions/tools/cypher.py[tag=import]

The GraphCypherQAChain provides a static .from_llm() method for creating a new instance. The method requires one positional parameter, the llm and the GraphStore as the named graph parameter.

python
Creating a GraphCypherQAChain
Unresolved directive in lesson.adoc - include::https://raw.githubusercontent.com/neo4j-graphacademy/app-python/main/solutions/tools/cypher.py[tag=cypher-qa]

The chain will use the schema generated by the Neo4jGraph class to write a Cypher statement and execute it against the database.

Registering the Graph Cypher QA Chain as a Tool

Follow the instructions in the previous step to create a new Tool and append it to the tools list in agent.py.

Start by importing the tool.

python
Importing the GraphCypherQAChain
Unresolved directive in lesson.adoc - include::https://raw.githubusercontent.com/neo4j-graphacademy/app-python/main/solutions/tools/cypher.py[tag=importcypherqa]

Append a new Tool to the tools array. Give the tool a name, and a description.

The description should describe the information that can be retrieved from the database. The recommendations dataset holds information on movies, actors, and user reviews that the LLM may find useful in generating a response.

Finally, define the cypher_qa as the function to call using the func named parameter.

python
Registering the Tool
Unresolved directive in lesson.adoc - include::https://raw.githubusercontent.com/neo4j-graphacademy/app-python/main/solutions/tools/cypher.py[tag=tool]

Testing the Tool

You can test the new Cypher generation tool by asking the bot a question about a Movie. For example, you could ask "Who directed Toy Story?".

You can check that the new tool has been called in the console.

Console Output
> Entering new AgentExecutor chain...
{
    "action": "Cypher QA",
    "action_input": "Who directed Toy Story?"
}
> Entering new GraphCypherQAChain chain...
Generated Cypher:
MATCH (d:Director)-[:DIRECTED]->(m:Movie)
WHERE m.title = "Toy Story"
RETURN d.name AS director
Full Context:
[{'director': 'John Lasseter'}]
> Finished chain.
Observation: {'query': 'Who directed Toy Story?', 'result': 'John Lasseter directed Toy Story.'}
Thought:{
    "action": "Final Answer",
    "action_input": "John Lasseter directed Toy Story."
}
> Finished chain.

With minimal configuration, the LLM can generate more complex questions. For example, Did the same director direct Toy Story and Toy Story 2?

Console Output
> Entering new AgentExecutor chain...
{
    "action": "Cypher QA",
    "action_input": "Did the same director direct Toy Story and Toy Story 2?"
}
> Entering new GraphCypherQAChain chain...
Generated Cypher:
MATCH (d:Director)-[:DIRECTED]->(m:Movie)
WHERE m.title IN ['Toy Story', 'Toy Story 2']
WITH d, collect(m.title) AS movies
WHERE size(movies) = 2
RETURN d.name AS director, movies
Full Context:
[{'director': 'John Lasseter', 'movies': ['Toy Story', 'Toy Story 2']}]
> Finished chain.
Observation: {'query': 'Did the same director direct Toy Story and Toy Story 2?', 'result': 'Yes, the same director, John Lasseter, directed both Toy Story and Toy Story 2.'}
Thought:{
    "action": "Final Answer",
    "action_input": "Yes, the same director, John Lasseter, directed both Toy Story and Toy Story 2."
}
> Finished chain.

Did it work for you? Once you have completed the steps, click the button below to mark the lesson as completed.

Summary

In this lesson, you created a tool capable of generating a Cypher statement to answer a specific question and execute it against the database. But the Cypher it generates isn’t perfect.

In the next lesson, you will learn how to handle edge cases by fine-tuning the prompt used to generate the Cypher statement.

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?