diff --git a/docs/api_reference/guide_imports.json b/docs/api_reference/guide_imports.json index 832c03f996..176c686e52 100644 --- a/docs/api_reference/guide_imports.json +++ b/docs/api_reference/guide_imports.json @@ -341,7 +341,7 @@ "HugeGraph QA Chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_hugegraph_qa", "GraphSparqlQAChain": "https://python.langchain.com/docs/use_cases/more/graph/graph_sparql_qa", "ArangoDB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_arangodb_qa", - "Graph DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa", + "Neo4j DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa", "How to use a SmartLLMChain": "https://python.langchain.com/docs/use_cases/more/self_check/smart_llm", "Multi-Agent Simulated Environment: Petting Zoo": "https://python.langchain.com/docs/use_cases/agent_simulations/petting_zoo", "Multi-agent decentralized speaker selection": "https://python.langchain.com/docs/use_cases/agent_simulations/multiagent_bidding", @@ -3202,10 +3202,10 @@ "Graph QA": "https://python.langchain.com/docs/use_cases/more/graph/graph_qa" }, "GraphCypherQAChain": { - "Graph DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa" + "Neo4j DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa" }, "Neo4jGraph": { - "Graph DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa" + "Neo4j DB QA chain": "https://python.langchain.com/docs/use_cases/more/graph/graph_cypher_qa" }, "LLMBashChain": { "Bash chain": "https://python.langchain.com/docs/use_cases/more/code_writing/llm_bash" diff --git a/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb b/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb index f6f9ca8182..84adde72b1 100644 --- a/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb +++ b/docs/extras/use_cases/more/graph/graph_cypher_qa.ipynb @@ -5,7 +5,7 @@ "id": "c94240f5", "metadata": {}, "source": [ - "# Graph DB QA chain\n", + "# Neo4j DB QA chain\n", "\n", "This notebook shows how to use LLMs to provide a natural language interface to a graph database you can query with the Cypher query language." ] @@ -177,7 +177,7 @@ "\u001b[32;1m\u001b[1;3mMATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\n", "RETURN a.name\u001b[0m\n", "Full Context:\n", - "\u001b[32;1m\u001b[1;3m[{'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}, {'a.name': 'Tom Cruise'}]\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m[{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}]\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -185,7 +185,7 @@ { "data": { "text/plain": [ - "'Val Kilmer, Anthony Edwards, Meg Ryan, and Tom Cruise played in Top Gun.'" + "'Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.'" ] }, "execution_count": 7, @@ -236,7 +236,7 @@ "\u001b[32;1m\u001b[1;3mMATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\n", "RETURN a.name\u001b[0m\n", "Full Context:\n", - "\u001b[32;1m\u001b[1;3m[{'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}]\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m[{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}]\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -244,7 +244,7 @@ { "data": { "text/plain": [ - "'Val Kilmer and Anthony Edwards played in Top Gun.'" + "'Tom Cruise and Val Kilmer played in Top Gun.'" ] }, "execution_count": 9, @@ -294,11 +294,11 @@ "\u001b[32;1m\u001b[1;3mMATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\n", "RETURN a.name\u001b[0m\n", "Full Context:\n", - "\u001b[32;1m\u001b[1;3m[{'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}, {'a.name': 'Tom Cruise'}]\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m[{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}]\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n", - "Intermediate steps: [{'query': \"MATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\\nRETURN a.name\"}, {'context': [{'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}, {'a.name': 'Tom Cruise'}]}]\n", - "Final answer: Val Kilmer, Anthony Edwards, Meg Ryan, and Tom Cruise played in Top Gun.\n" + "Intermediate steps: [{'query': \"MATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\\nRETURN a.name\"}, {'context': [{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}]}]\n", + "Final answer: Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.\n" ] } ], @@ -352,10 +352,10 @@ { "data": { "text/plain": [ - "[{'a.name': 'Val Kilmer'},\n", + "[{'a.name': 'Tom Cruise'},\n", + " {'a.name': 'Val Kilmer'},\n", " {'a.name': 'Anthony Edwards'},\n", - " {'a.name': 'Meg Ryan'},\n", - " {'a.name': 'Tom Cruise'}]" + " {'a.name': 'Meg Ryan'}]" ] }, "execution_count": 13, @@ -367,10 +367,153 @@ "chain.run(\"Who played in Top Gun?\")" ] }, + { + "cell_type": "markdown", + "id": "f01dfb72-24ec-4ae7-883a-ee6646889b59", + "metadata": {}, + "source": [ + "## Add examples in the Cypher generation prompt\n", + "You can define the Cypher statement you want the LLM to generate for particular questions" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "59baeb88-adfa-4c26-8334-fcbff3a98efb", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.prompts.prompt import PromptTemplate\n", + "\n", + "\n", + "CYPHER_GENERATION_TEMPLATE = \"\"\"Task:Generate Cypher statement to query a graph database.\n", + "Instructions:\n", + "Use only the provided relationship types and properties in the schema.\n", + "Do not use any other relationship types or properties that are not provided.\n", + "Schema:\n", + "{schema}\n", + "Note: Do not include any explanations or apologies in your responses.\n", + "Do not respond to any questions that might ask anything else than for you to construct a Cypher statement.\n", + "Do not include any text except the generated Cypher statement.\n", + "Examples: Here are a few examples of generated Cypher statements for particular questions:\n", + "# How many people played in Top Gun?\n", + "MATCH (m:Movie {{title:\"Top Gun\"}})<-[:ACTED_IN]-()\n", + "RETURN count(*) AS numberOfActors\n", + "\n", + "The question is:\n", + "{question}\"\"\"\n", + "\n", + "CYPHER_GENERATION_PROMPT = PromptTemplate(\n", + " input_variables=[\"schema\", \"question\"], template=CYPHER_GENERATION_TEMPLATE\n", + ")\n", + "\n", + "chain = GraphCypherQAChain.from_llm(\n", + " ChatOpenAI(temperature=0), graph=graph, verbose=True, cypher_prompt=CYPHER_GENERATION_PROMPT\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "47c64027-cf42-493a-9c76-2d10ba753728", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (m:Movie {name:\"Top Gun\"})<-[:ACTED_IN]-(:Actor)\n", + "RETURN count(*) AS numberOfActors\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'numberOfActors': 4}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Four people played in Top Gun.'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"How many people played in Top Gun?\")" + ] + }, + { + "cell_type": "markdown", + "id": "3e721cad-aa87-4526-9231-2dfc0e365939", + "metadata": {}, + "source": [ + "## Use separate LLMs for Cypher and answer generation\n", + "You can use the `cypher_llm` and `qa_llm` parameters to define different llms" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "6f9becc2-f579-45bf-9b50-2ce02bde92da", + "metadata": {}, + "outputs": [], + "source": [ + "chain = GraphCypherQAChain.from_llm(\n", + " graph=graph,\n", + " cypher_llm=ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo\"),\n", + " qa_llm=ChatOpenAI(temperature=0, model=\"gpt-3.5-turbo-16k\"),\n", + " verbose=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "ff18e3e3-3402-4683-aec4-a19898f23ca1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (a:Actor)-[:ACTED_IN]->(m:Movie {name: 'Top Gun'})\n", + "RETURN a.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'a.name': 'Tom Cruise'}, {'a.name': 'Val Kilmer'}, {'a.name': 'Anthony Edwards'}, {'a.name': 'Meg Ryan'}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Tom Cruise, Val Kilmer, Anthony Edwards, and Meg Ryan played in Top Gun.'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chain.run(\"Who played in Top Gun?\")" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "74d0a36f", + "id": "48ff7cf8-18a3-43d7-8cb1-c1b91744608d", "metadata": {}, "outputs": [], "source": [] diff --git a/libs/langchain/langchain/chains/graph_qa/cypher.py b/libs/langchain/langchain/chains/graph_qa/cypher.py index 015ff5f47b..82c85ef1c0 100644 --- a/libs/langchain/langchain/chains/graph_qa/cypher.py +++ b/libs/langchain/langchain/chains/graph_qa/cypher.py @@ -73,15 +73,28 @@ class GraphCypherQAChain(Chain): @classmethod def from_llm( cls, - llm: BaseLanguageModel, + llm: Optional[BaseLanguageModel] = None, *, qa_prompt: BasePromptTemplate = CYPHER_QA_PROMPT, cypher_prompt: BasePromptTemplate = CYPHER_GENERATION_PROMPT, + cypher_llm: Optional[BaseLanguageModel] = None, + qa_llm: Optional[BaseLanguageModel] = None, **kwargs: Any, ) -> GraphCypherQAChain: """Initialize from LLM.""" - qa_chain = LLMChain(llm=llm, prompt=qa_prompt) - cypher_generation_chain = LLMChain(llm=llm, prompt=cypher_prompt) + + if not cypher_llm and not llm: + raise ValueError("Either `llm` or `cypher_llm` parameters must be provided") + if not qa_llm and not llm: + raise ValueError("Either `llm` or `qa_llm` parameters must be provided") + if cypher_llm and qa_llm and llm: + raise ValueError( + "You can specify up to two of 'cypher_llm', 'qa_llm'" + ", and 'llm', but not all three simultaneously." + ) + + qa_chain = LLMChain(llm=qa_llm or llm, prompt=qa_prompt) + cypher_generation_chain = LLMChain(llm=cypher_llm or llm, prompt=cypher_prompt) return cls( qa_chain=qa_chain,