diff options
| author | maszhongming <mingz5@illinois.edu> | 2025-09-16 15:15:29 -0500 |
|---|---|---|
| committer | maszhongming <mingz5@illinois.edu> | 2025-09-16 15:15:29 -0500 |
| commit | 73c194f304f827b55081b15524479f82a1b7d94c (patch) | |
| tree | 5e8660e421915420892c5eca18f1ad680f80a861 /notebooks | |
Initial commit
Diffstat (limited to 'notebooks')
20 files changed, 16526 insertions, 0 deletions
diff --git a/notebooks/cypher_rag_example.ipynb b/notebooks/cypher_rag_example.ipynb new file mode 100644 index 0000000..c844dd6 --- /dev/null +++ b/notebooks/cypher_rag_example.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "677867a3", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chains import GraphCypherQAChain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.graphs import Neo4jGraph\n", + "from langchain.callbacks import get_openai_callback\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import openai\n", + "import pandas as pd\n", + "from neo4j.exceptions import CypherSyntaxError\n" + ] + }, + { + "cell_type": "markdown", + "id": "186eb11d", + "metadata": {}, + "source": [ + "## Choose the LLM" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fe18f3fc", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4-32k'\n" + ] + }, + { + "cell_type": "markdown", + "id": "1a040044", + "metadata": {}, + "source": [ + "## Custom function for neo4j RAG chain" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ead42cd3", + "metadata": {}, + "outputs": [], + "source": [ + "def get_neo4j_cypher_rag_chain():\n", + " load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + " username = os.environ.get('NEO4J_USER')\n", + " password = os.environ.get('NEO4J_PSW')\n", + " url = os.environ.get('NEO4J_URI')\n", + " database = os.environ.get('NEO4J_DB')\n", + "\n", + " graph = Neo4jGraph(\n", + " url=url, \n", + " username=username, \n", + " password=password,\n", + " database = database\n", + " )\n", + "\n", + " load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + " API_KEY = os.environ.get('API_KEY')\n", + " API_VERSION = os.environ.get('API_VERSION')\n", + " RESOURCE_ENDPOINT = os.environ.get('RESOURCE_ENDPOINT')\n", + " openai.api_type = \"azure\"\n", + " openai.api_key = API_KEY\n", + " openai.api_base = RESOURCE_ENDPOINT\n", + " openai.api_version = API_VERSION\n", + " chat_deployment_id = LLM_MODEL\n", + " chat_model_id = chat_deployment_id\n", + " temperature = 0\n", + " chat_model = ChatOpenAI(openai_api_key=API_KEY, \n", + " engine=chat_deployment_id, \n", + " temperature=temperature)\n", + " chain = GraphCypherQAChain.from_llm(\n", + " chat_model, \n", + " graph=graph, \n", + " verbose=True, \n", + " validate_cypher=True,\n", + " return_intermediate_steps=True\n", + " )\n", + " return chain" + ] + }, + { + "cell_type": "markdown", + "id": "cc863aed", + "metadata": {}, + "source": [ + "## Initiate neo4j RAG chain" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "9866fd11", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING! engine is not default parameter.\n", + " engine was transferred to model_kwargs.\n", + " Please confirm that engine is what you intended.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 17.5 ms, sys: 3.65 ms, total: 21.2 ms\n", + "Wall time: 28.1 s\n" + ] + } + ], + "source": [ + "%%time\n", + "neo4j_rag_chain = get_neo4j_cypher_rag_chain()\n" + ] + }, + { + "cell_type": "markdown", + "id": "3827d5c4", + "metadata": {}, + "source": [ + "## Enter question -1 " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7b9837c5", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Is Parkinson's disease associated with PINK1 gene?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "23e669ed", + "metadata": {}, + "source": [ + "## Run cypher RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9f685b8e", + "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 (d:Disease {name: \"Parkinson's disease\"}), (g:Gene {name: \"PINK1\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "Yes, Parkinson's disease is associated with the PINK1 gene.\n" + ] + } + ], + "source": [ + "\n", + "out = neo4j_rag_chain.run(query=question, return_final_only=True, verbose=True)\n", + "print(out)\n" + ] + }, + { + "cell_type": "markdown", + "id": "069bc2f2", + "metadata": {}, + "source": [ + "## Question 1 perturbed (all smallcase)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "4cf3363b", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Is parkinson's disease associated with pink1 gene?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "487fd17f", + "metadata": {}, + "source": [ + "## Run cypher RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "61d5eb0b", + "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 (d:Disease {name: \"Parkinson's Disease\"}), (g:Gene {name: \"PINK1\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "I'm sorry, but I don't have the information to answer that question.\n" + ] + } + ], + "source": [ + "\n", + "out = neo4j_rag_chain.run(query=question, return_final_only=True, verbose=True)\n", + "print(out)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6123c1a7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/cypher_rag_ragas_metric.ipynb b/notebooks/cypher_rag_ragas_metric.ipynb new file mode 100644 index 0000000..f8fffa2 --- /dev/null +++ b/notebooks/cypher_rag_ragas_metric.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "4eb50795-d6a9-4339-a083-643f51a50911", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import AzureChatOpenAI\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import openai\n", + "from langchain.chains import GraphCypherQAChain\n", + "from langchain.graphs import Neo4jGraph\n", + "from langchain.callbacks import get_openai_callback\n", + "import pandas as pd\n", + "from tqdm import tqdm\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "63905a82-6569-4e69-b757-04b187c33686", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "678addb6-d6b9-4447-893c-fb15099c7bf6", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/karthiksoman/anaconda3/envs/cypher_rag/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The class `AzureChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 0.3.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import AzureChatOpenAI`.\n", + " warn_deprecated(\n" + ] + } + ], + "source": [ + "\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "API_KEY = os.environ.get('API_KEY')\n", + "API_VERSION = os.environ.get('API_VERSION')\n", + "RESOURCE_ENDPOINT = os.environ.get('RESOURCE_ENDPOINT')\n", + "openai.api_type = \"azure\"\n", + "openai.api_key = API_KEY\n", + "openai.api_base = RESOURCE_ENDPOINT\n", + "openai.api_version = API_VERSION\n", + "chat_deployment_id = LLM_MODEL\n", + "chat_model_id = chat_deployment_id\n", + "temperature = 0\n", + "chat_model = AzureChatOpenAI(openai_api_key=API_KEY, openai_api_version=API_VERSION, azure_deployment=chat_deployment_id, azure_endpoint=RESOURCE_ENDPOINT, temperature=temperature)\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + "username = os.environ.get('NEO4J_USER')\n", + "password = os.environ.get('NEO4J_PSW')\n", + "url = os.environ.get('NEO4J_URL')\n", + "database = os.environ.get('NEO4J_DB')\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "30a068c7-42d6-4f41-bce1-5fe2a38ace5a", + "metadata": {}, + "outputs": [], + "source": [ + "graph = Neo4jGraph(url=url, username=username, password=password, database = database)\n", + "chain = GraphCypherQAChain.from_llm(chat_model, graph=graph, verbose=True, validate_cypher=True,return_intermediate_steps=True)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5b844002-f139-4dcf-9ddb-ebf42fcee2f5", + "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 (d:Disease {name: \"hypochondrogenesis\"})-[:ASSOCIATES_DaG]->(g:Gene) RETURN g.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'g.name': 'COL2A1'}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + } + ], + "source": [ + "question = \"What are the genes associated with hypochondrogenesis?\"\n", + "\n", + "cypher_rag_answer = chain.invoke({\"query\":question})\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "142b0c6d-b5b5-4c98-b5e3-c6f5f39bd30a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'query': 'What are the genes associated with hypochondrogenesis?',\n", + " 'result': 'The gene associated with hypochondrogenesis is COL2A1.',\n", + " 'intermediate_steps': [{'query': 'MATCH (d:Disease {name: \"hypochondrogenesis\"})-[:ASSOCIATES_DaG]->(g:Gene) RETURN g.name'},\n", + " {'context': [{'g.name': 'COL2A1'}]}]}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cypher_rag_answer" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4f99bfef-bcc2-462a-87b9-3c553978f8a0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'query': 'MATCH (d:Disease {name: \"hypochondrogenesis\"})-[:ASSOCIATES_DaG]->(g:Gene) RETURN g.name'},\n", + " {'context': [{'g.name': 'COL2A1'}]}]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cypher_rag_answer[\"intermediate_steps\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bd57161-2d8c-4c7e-99f5-09890b13fe27", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/cypher_rag_using_langchain.ipynb b/notebooks/cypher_rag_using_langchain.ipynb new file mode 100644 index 0000000..9a792cc --- /dev/null +++ b/notebooks/cypher_rag_using_langchain.ipynb @@ -0,0 +1,2190 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "346377c6-e7c9-46e1-9c7b-d786827f1d52", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.chdir('..')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ff58a0a-87a5-419b-8f20-88ffadf54051", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chains import GraphCypherQAChain\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.graphs import Neo4jGraph\n", + "from langchain.callbacks import get_openai_callback\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import openai\n", + "import pandas as pd\n", + "from neo4j.exceptions import CypherSyntaxError\n", + "from kg_rag.utility import *\n", + "from tqdm import tqdm\n", + "import pandas as pd\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "1d905ac1", + "metadata": {}, + "source": [ + "## Choose the LLM" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "id": "763d7ad7", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4-32k'\n" + ] + }, + { + "cell_type": "markdown", + "id": "f02bd807", + "metadata": {}, + "source": [ + "## Load test data" + ] + }, + { + "cell_type": "code", + "execution_count": 146, + "id": "43772231", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('../data/rag_comparison_data.csv')\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "8bb1d1e3", + "metadata": {}, + "source": [ + "## Custom function for neo4j RAG chain" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "id": "611fee8c", + "metadata": {}, + "outputs": [], + "source": [ + "def get_neo4j_cypher_rag_chain():\n", + " load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + " username = os.environ.get('NEO4J_USER')\n", + " password = os.environ.get('NEO4J_PSW')\n", + " url = os.environ.get('NEO4J_URI')\n", + " database = os.environ.get('NEO4J_DB')\n", + "\n", + " graph = Neo4jGraph(\n", + " url=url, \n", + " username=username, \n", + " password=password,\n", + " database = database\n", + " )\n", + "\n", + " load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + " API_KEY = os.environ.get('API_KEY')\n", + " API_VERSION = os.environ.get('API_VERSION')\n", + " RESOURCE_ENDPOINT = os.environ.get('RESOURCE_ENDPOINT')\n", + " openai.api_type = \"azure\"\n", + " openai.api_key = API_KEY\n", + " openai.api_base = RESOURCE_ENDPOINT\n", + " openai.api_version = API_VERSION\n", + " chat_deployment_id = LLM_MODEL\n", + " chat_model_id = chat_deployment_id\n", + " temperature = 0\n", + " chat_model = ChatOpenAI(openai_api_key=API_KEY, \n", + " engine=chat_deployment_id, \n", + " temperature=temperature)\n", + " chain = GraphCypherQAChain.from_llm(\n", + " chat_model, \n", + " graph=graph, \n", + " verbose=True, \n", + " validate_cypher=True,\n", + " return_intermediate_steps=True\n", + " )\n", + " return chain" + ] + }, + { + "cell_type": "markdown", + "id": "8b920685", + "metadata": {}, + "source": [ + "## Initiate neo4j RAG chain" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "id": "29b40370", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING! engine is not default parameter.\n", + " engine was transferred to model_kwargs.\n", + " Please confirm that engine is what you intended.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 14.6 ms, sys: 4.67 ms, total: 19.2 ms\n", + "Wall time: 22.1 s\n" + ] + } + ], + "source": [ + "%%time\n", + "neo4j_rag_chain = get_neo4j_cypher_rag_chain()\n" + ] + }, + { + "cell_type": "markdown", + "id": "cfa082f8", + "metadata": {}, + "source": [ + "## Run on test data" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "id": "172e0f96", + "metadata": { + "scrolled": true + }, + "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 (d:Disease {name: 'childhood-onset asthma'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'RORA'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-37}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SHANK2\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"skin benign neoplasm\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 5e-08}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypertrophic cardiomyopathy'}), (g:Gene {name: 'AMBRA1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung adenocarcinoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CYP2A6'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 8e-11}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'idiopathic generalized epilepsy'}), (g:Gene {name: 'RYR2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"PLCE1\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"gastric fundus cancer\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-22}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'VTI1A'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'hypertrophic cardiomyopathy'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'peptic ulcer disease'}), (g:Gene {name: 'TTC33'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'multiple sclerosis'}), (g:Gene {name: 'TSPAN31'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'large intestine cancer'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'ABHD12B'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 7e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'prostate carcinoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'ESR2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 7e-12}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SH2B3'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'mastocytosis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'FTCD'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"FURIN\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"major depressive disorder\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-19}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'testicular cancer'}), (g:Gene {name: 'TERT'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'SLC24A3'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'type 2 diabetes mellitus'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'g': {'license': 'CC0 1.0', 'identifier': 57419, 'ensembl': 'ENSG00000185052', 'chromosome': '20', 'name': 'SLC24A3', 'description': 'solute carrier family 24 member 3', 'source': 'Entrez Gene'}, 'd': {'identifier': 'DOID:9352', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID9352 target=\"_blank\">kwgr:topic.DOID9352</a>', 'omim_list': ['601407', '125853', '603694', '608036', '601283'], 'name': 'type 2 diabetes mellitus', 'source': 'Disease Ontology', 'mesh_list': ['D003924']}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'celiac disease'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'PLEK'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:10608', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID10608 target=\"_blank\">kwgr:topic.DOID10608</a>', 'omim_list': ['607202', '612006', '611598', '612011', '609754', '612008', '612009', '612005', '612007'], 'name': 'celiac disease', 'source': 'Disease Ontology', 'mesh_list': ['D002446']}, 'r': ({'identifier': 'DOID:10608', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID10608 target=\"_blank\">kwgr:topic.DOID10608</a>', 'omim_list': ['607202', '612006', '611598', '612011', '609754', '612008', '612009', '612005', '612007'], 'name': 'celiac disease', 'source': 'Disease Ontology', 'mesh_list': ['D002446']}, 'ASSOCIATES_DaG', {'identifier': 5341, 'license': 'CC0 1.0', 'ensembl': 'ENSG00000115956', 'chromosome': '2', 'name': 'PLEK', 'description': 'pleckstrin', 'source': 'Entrez Gene', 'chembl_id': 'CHEMBL4523171'}), 'g': {'identifier': 5341, 'license': 'CC0 1.0', 'ensembl': 'ENSG00000115956', 'chromosome': '2', 'name': 'PLEK', 'description': 'pleckstrin', 'source': 'Entrez Gene', 'chembl_id': 'CHEMBL4523171'}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"endometrial carcinoma\"}), (g:Gene {name: \"CPVL\"}) \n", + "RETURN d.name, g.name, r.gwas_pvalue\n", + "\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'allergic disease'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'ZNF652'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:1205', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID1205 target=\"_blank\">kwgr:topic.DOID1205</a>', 'omim_list': [], 'name': 'allergic disease', 'source': 'Disease Ontology', 'mesh_list': ['D006967']}, 'r': ({'identifier': 'DOID:1205', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID1205 target=\"_blank\">kwgr:topic.DOID1205</a>', 'omim_list': [], 'name': 'allergic disease', 'source': 'Disease Ontology', 'mesh_list': ['D006967']}, 'ASSOCIATES_DaG', {'license': 'CC0 1.0', 'identifier': 22834, 'ensembl': 'ENSG00000198740', 'chromosome': '17', 'name': 'ZNF652', 'description': 'zinc finger protein 652', 'source': 'Entrez Gene'}), 'g': {'license': 'CC0 1.0', 'identifier': 22834, 'ensembl': 'ENSG00000198740', 'chromosome': '17', 'name': 'ZNF652', 'description': 'zinc finger protein 652', 'source': 'Entrez Gene'}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"systemic lupus erythematosus\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"ELF3\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'GMDS'}), (d:Disease {name: 'hemorrhoid'}) \n", + "RETURN EXISTS((g)-[:ASSOCIATES_DaG]->(d)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': False}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'rheumatoid arthritis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'DPP4'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-21}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SMAD7\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"colon carcinoma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-08}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'PKIA'})-[r:ASSOCIATES_DaG]->(d:Disease {name: 'pulmonary hypertension'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'autoimmune thyroiditis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'TNFRSF14'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-11}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'psoriatic arthritis'}), (g:Gene {name: 'CNTNAP2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'primary biliary cholangitis'}), (g:Gene {name: 'CCDC88B'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"MARK3\"})-[:ASSOCIATES_DaG]->(d:Disease {name: \"otosclerosis\"}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"RHPN2\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"large intestine cancer\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-41}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'anxiety disorder'}), (g:Gene {name: 'NTRK2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atopic dermatitis'}), (g:Gene {name: 'RERE'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'PRR5L'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'asthma'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'gastric fundus cancer'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'GON4L'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-15}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 2 diabetes mellitus'}), (g:Gene {name: 'DNAH1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'isAssociated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'schizophrenia'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SLC17A3'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-20}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'FADS2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-15}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'opiate dependence'}), (g:Gene {name: 'ADGRV1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"attention deficit hyperactivity disorder\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"ST3GAL3\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 8e-14}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'C3orf49'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'cataract'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'g': {'license': 'CC0 1.0', 'identifier': 132200, 'ensembl': 'ENSG00000163632', 'chromosome': '3', 'name': 'C3orf49', 'description': 'chromosome 3 open reading frame 49', 'source': 'Entrez Gene'}, 'd': {'identifier': 'DOID:83', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID83 target=\"_blank\">kwgr:topic.DOID83</a>', 'omim_list': ['PS116200', '601371'], 'name': 'cataract', 'source': 'Disease Ontology', 'mesh_list': []}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'PLD1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'duodenal ulcer'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 5e-08}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'CHRNA3'}), (d:Disease {name: 'chronic obstructive pulmonary disease'})-[r:ASSOCIATES_DaG]->(g) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 5e-28}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'pancreatic carcinoma'}), (g:Gene {name: 'CCDC68'}) \n", + "RETURN d.name, g.name, r.gwas_pvalue\n", + "\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'HLA-DPB1'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'primary biliary cholangitis'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atopic dermatitis'}), (g:Gene {name: 'GABPB2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'HIP1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'systemic lupus erythematosus'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 6e-62}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypothyroidism'}), (g:Gene {name: 'TIMMDC1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'degenerative myopia'}), (g:Gene {name: 'MIPEP'})\n", + "RETURN d.name, g.name, r.gwas_pvalue\n", + "\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'alcoholic pancreatitis'}), (g:Gene {name: 'CASP9'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung squamous cell carcinoma'}), (g:Gene {name: 'PDS5B'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'common variable immunodeficiency'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CLEC16A'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'TERT'}), (d:Disease {name: 'lung non-small cell carcinoma'}) \n", + "RETURN EXISTS((g)-[:ASSOCIATES_DaG]->(d)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'PSMD3'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'cardiovascular system disease'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'gestational diabetes'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'CCND2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-12}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"TMEM106B\"})-[:ASSOCIATES_DaG]->(d:Disease {name: \"major depressive disorder\"}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"COL6A1\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"keratoconus\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 9e-12}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'chronic lymphocytic leukemia'}), (g:Gene {name: 'RREB1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'PARPBP'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'prostate carcinoma'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"testicular germ cell cancer\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"ZFP64\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-12}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"KLF13\"})-[r:ASSOCIATES_DaG]->(d:Disease {name: \"psoriasis\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'coronary artery disease'}), (g:Gene {name: 'ADGRL3'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"abdominal obesity-metabolic syndrome 1\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"JMJD1C\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-14}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'CUX2'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'type 1 diabetes mellitus'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'g': {'license': 'CC0 1.0', 'identifier': 23316, 'ensembl': 'ENSG00000111249', 'chromosome': '12', 'name': 'CUX2', 'description': 'cut like homeobox 2', 'source': 'Entrez Gene'}, 'd': {'identifier': 'DOID:9744', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID9744 target=\"_blank\">kwgr:topic.DOID9744</a>', 'omim_list': ['222100'], 'name': 'type 1 diabetes mellitus', 'source': 'Disease Ontology', 'mesh_list': ['D003922']}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'KCNK16'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'type 2 diabetes mellitus'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-17}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 1 diabetes mellitus'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'DGKQ'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:9744', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID9744 target=\"_blank\">kwgr:topic.DOID9744</a>', 'omim_list': ['222100'], 'name': 'type 1 diabetes mellitus', 'source': 'Disease Ontology', 'mesh_list': ['D003922']}, 'r': ({'identifier': 'DOID:9744', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID9744 target=\"_blank\">kwgr:topic.DOID9744</a>', 'omim_list': ['222100'], 'name': 'type 1 diabetes mellitus', 'source': 'Disease Ontology', 'mesh_list': ['D003922']}, 'ASSOCIATES_DaG', {'license': 'CC0 1.0', 'identifier': 1609, 'ensembl': 'ENSG00000145214', 'chromosome': '4', 'name': 'DGKQ', 'description': 'diacylglycerol kinase theta', 'source': 'Entrez Gene'}), 'g': {'license': 'CC0 1.0', 'identifier': 1609, 'ensembl': 'ENSG00000145214', 'chromosome': '4', 'name': 'DGKQ', 'description': 'diacylglycerol kinase theta', 'source': 'Entrez Gene'}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SIX6\"})-[r:ASSOCIATES_DaG]->(d:Disease {name: \"refractive error\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"MAP4K4\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"Parkinson's disease\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 8e-13}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'autism spectrum disorder'}), (g:Gene {name: 'DCC'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'multiple sclerosis'}), (g:Gene {name: 'NR1D1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'coronary artery disease'}), (g:Gene {name: 'SMAD3'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'ANO7'})-[r:ASSOCIATES_DaG]->(d:Disease {name: 'prostate carcinoma'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'ovarian carcinoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'FGFR2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-254}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lymphoid leukemia'}), (g:Gene {name: 'BMF'})\n", + "RETURN d.gwas_pvalue AS GWAS_p_value\n", + "\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'GWAS_p_value': None}]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Skin Melanoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CYP1B1'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'myositis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ATP6V1G2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 6e-49}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SPG7\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"melanoma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 9e-26}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'EYA2'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'type 2 diabetes mellitus'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SERPINA1\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"carpal tunnel syndrome\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-24}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'substance-related disorder'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'FUT2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-19}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'open-angle glaucoma'}), (g:Gene {name: 'PLEKHA7'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS IsAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'IsAssociated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'myocardial infarction'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ZNF831'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-08}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'IRF4'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'squamous cell carcinoma'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'WDHD1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"Parkinson's disease\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-16}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'cataract'}), (g:Gene {name: 'TOP1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atrial fibrillation'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'AGBL4'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'otosclerosis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SEMA4D'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 4e-09}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypothyroidism'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'RAD51B'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-11}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"SPSB1\"})-[r:ASSOCIATES_DaG]->(d:Disease {name: \"childhood-onset asthma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'major depressive disorder'}), (g:Gene {name: 'ATG7'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'WNT10A'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'alopecia'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'g': {'license': 'CC0 1.0', 'identifier': 80326, 'ensembl': 'ENSG00000135925', 'chromosome': '2', 'name': 'WNT10A', 'description': 'Wnt family member 10A', 'source': 'Entrez Gene'}, 'd': {'identifier': 'DOID:987', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID987 target=\"_blank\">kwgr:topic.DOID987</a>', 'omim_list': ['PS203655'], 'name': 'alopecia', 'source': 'Disease Ontology', 'mesh_list': ['D000505']}}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'}), (g:Gene {name: 'IL27'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'tonsillitis'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'TNFRSF13B'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 8e-26}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'cleft lip'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SFI1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 3e-08}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"multiple sclerosis\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"INAVA\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 6e-21}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'esophageal carcinoma'}), (g:Gene {name: 'CASP8'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Skin Melanoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'GPRC5A'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung squamous cell carcinoma'}), (g:Gene {name: 'BRCA2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'systemic lupus erythematosus'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'HLA-DRA'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 2e-60}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 2 diabetes mellitus'}), (g:Gene {name: 'UBE2E2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'is_associated': True}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'allergic rhinitis'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'HLA-DQA1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-43}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'systemic lupus erythematosus'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'HLA-DQA1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'r.gwas_pvalue': 1e-54}]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "CPU times: user 3.59 s, sys: 295 ms, total: 3.88 s\n", + "Wall time: 9min 27s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "neo4j_rag_answer = []\n", + "total_tokens_used = []\n", + "\n", + "for index, row in data.iterrows():\n", + " question = row['question']\n", + " with get_openai_callback() as cb:\n", + " try:\n", + " neo4j_rag_answer.append(neo4j_rag_chain.run(query=question, return_final_only=True, verbose=False))\n", + " except ValueError as e:\n", + " neo4j_rag_answer.append(None)\n", + " total_tokens_used.append(cb.total_tokens)\n", + "\n", + "data.loc[:,'neo4j_rag_answer'] = neo4j_rag_answer\n", + "data.loc[:, 'total_tokens_used'] = total_tokens_used\n" + ] + }, + { + "cell_type": "markdown", + "id": "9cd8b31b", + "metadata": {}, + "source": [ + "## Run on perturbed test data" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "id": "8e603e8f", + "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 (d:Disease {name: 'childhood-onset asthma'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'rora'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'skin benign neoplasm'}), (g:Gene {name: 'shank2'}), (d)-[r:ASSOCIATES_DaG]->(g) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypertrophic cardiomyopathy'}), (g:Gene {name: 'ambra1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung adenocarcinoma'}), (g:Gene {name: 'cyp2a6'})\n", + "MATCH (d)-[r:ASSOCIATES_DaG]->(g)\n", + "RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"idiopathic generalized epilepsy\"}), (g:Gene {name: \"ryr2\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'gastric fundus cancer'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'plce1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'vti1a'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'hypertrophic cardiomyopathy'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'peptic ulcer disease'}), (g:Gene {name: 'ttc33'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'multiple sclerosis'}), (g:Gene {name: 'tspan31'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"abhd12b\"})-[:ASSOCIATES_DaG {disease: \"large intestine cancer\"}]->(d:Disease) RETURN g.gwas_pvalue as GWAS_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'prostate carcinoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'esr2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'}), (g:Gene {name: 'sh2b3'}), (d)-[r:ASSOCIATES_DaG]->(g) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'mastocytosis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ftcd'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"furin\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"major depressive disorder\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'testicular cancer'}), (g:Gene {name: 'tert'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"slc24a3\"})-[:ASSOCIATES_DaG]-(d:Disease {name: \"type 2 diabetes mellitus\"}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'celiac disease'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'plek'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"endometrial carcinoma\"}), (g:Gene {name: \"cpvl\"}) \n", + "RETURN d.name, g.name, r.gwas_pvalue\n", + "\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'allergic disease'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'znf652'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"systemic lupus erythematosus\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"elf3\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'gmds'}), (d:Disease {name: 'hemorrhoid'}) \n", + "RETURN EXISTS((g)-[:ASSOCIATES_DaG]->(d)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'rheumatoid arthritis'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'dpp4'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"smad7\"})-[:ASSOCIATES_DaG {gwas_pvalue: pvalue}]->(d:Disease {name: \"colon carcinoma\"}) RETURN pvalue\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'pkia'})-[r:ASSOCIATES_DaG]->(d:Disease {name: 'pulmonary hypertension'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'autoimmune thyroiditis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'tnfrsf14'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'psoriatic arthritis'}), (g:Gene {name: 'cntnap2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'primary biliary cholangitis'}), (g:Gene {name: 'ccdc88b'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'mark3'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'otosclerosis'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"rhpn2\"})-[:ASSOCIATES_DaG {gwas_pvalue: pvalue}]->(d:Disease {name: \"large intestine cancer\"}) RETURN pvalue\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'anxiety disorder'}), (g:Gene {name: 'ntrk2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atopic dermatitis'}), (g:Gene {name: 'rere'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'prr5l'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'asthma'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'gastric fundus cancer'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'gon4l'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 2 diabetes mellitus'}), (g:Gene {name: 'dnah1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'schizophrenia'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'slc17a3'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'fads2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Opiate Dependence'}), (g:Gene {name: 'ADGRV1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"attention deficit hyperactivity disorder\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"st3gal3\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'c3orf49'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'cataract'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'pld1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'duodenal ulcer'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'chrna3'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'chronic obstructive pulmonary disease'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'pancreatic carcinoma'}), (g:Gene {name: 'ccdc68'}) \n", + "RETURN d.name, g.name, r.gwas_pvalue\n", + "\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'primary biliary cholangitis'}), (g:Gene {name: 'hla-dpb1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atopic dermatitis'}), (g:Gene {name: 'gabpb2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'systemic lupus erythematosus'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'hip1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypothyroidism'}), (g:Gene {name: 'timmdc1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'degenerative myopia'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'mipep'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'alcoholic pancreatitis'}), (g:Gene {name: 'casp9'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung squamous cell carcinoma'}), (g:Gene {name: 'pds5b'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'common variable immunodeficiency'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'clec16a'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'tert'}), (d:Disease {name: 'lung non-small cell carcinoma'}) \n", + "RETURN EXISTS((g)-[:ASSOCIATES_DaG]->(d)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'psmd3'})-[:ASSOCIATES_DaG]->(d:Disease {name: 'cardiovascular system disease'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'gestational diabetes'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ccnd2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'tmem106b'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'major depressive disorder'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'col6a1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'keratoconus'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'chronic lymphocytic leukemia'}), (g:Gene {name: 'rreb1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS IsAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Prostate Carcinoma'}), (g:Gene {name: 'PARPBP'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"testicular germ cell cancer\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"zfp64\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'klf13'})-[r:ASSOCIATES_DaG]->(d:Disease {name: 'psoriasis'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"coronary artery disease\"}), (g:Gene {name: \"adgrl3\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"abdominal obesity-metabolic syndrome 1\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"jmjd1c\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'cux2'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'type 1 diabetes mellitus'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'kcnk16'})-[r:ASSOCIATES_DaG]->(d:Disease {name: 'type 2 diabetes mellitus'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 1 diabetes mellitus'}), (g:Gene {name: 'dgkq'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"six6\"})-[r:ASSOCIATES_DaG]->(d:Disease {name: \"refractive error\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'map4k4'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'parkinson\\'s disease'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'autism spectrum disorder'}), (g:Gene {name: 'dcc'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS isAssociated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'multiple sclerosis'}), (g:Gene {name: 'nr1d1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'coronary artery disease'}), (g:Gene {name: 'smad3'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"ANO7\"})-[r:ASSOCIATES_DaG]->(d:Disease {name: \"Prostate Carcinoma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'ovarian carcinoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'fgfr2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lymphoid leukemia'}), (g:Gene {name: 'bmf'})\n", + "RETURN d.gwas_pvalue AS GWAS_p_value\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Skin Melanoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CYP1B1'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'myositis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'atp6v1g2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"spg7\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"melanoma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'eya2'}), (d:Disease {name: 'type 2 diabetes mellitus'}) RETURN EXISTS((g)-[:ASSOCIATES_DaG]->(d)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"serpina1\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"carpal tunnel syndrome\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'substance-related disorder'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'fut2'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'open-angle glaucoma'}), (g:Gene {name: 'plekha7'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'myocardial infarction'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'znf831'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'irf4'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'squamous cell carcinoma'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'wdhd1'})-[r:ASSOCIATES_DaG]-(d:Disease {name: 'parkinson\\'s disease'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'cataract'}), (g:Gene {name: 'top1'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'atrial fibrillation'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'agbl4'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'otosclerosis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'sema4d'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'hypothyroidism'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'rad51b'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: \"spsb1\"})-[r:ASSOCIATES_DaG]-(d:Disease {name: \"childhood-onset asthma\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'major depressive disorder'}), (g:Gene {name: 'atg7'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene {name: 'wnt10a'})-[:ASSOCIATES_DaG]-(d:Disease {name: 'alopecia'}) RETURN g, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'inflammatory bowel disease'}), (g:Gene {name: 'il27'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'tonsillitis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'tnfrsf13b'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'cleft lip'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'sfi1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"multiple sclerosis\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"inava\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'esophageal carcinoma'}), (g:Gene {name: 'casp8'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Skin Melanoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'GPRC5A'}) RETURN d, r, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'lung squamous cell carcinoma'}), (g:Gene {name: 'brca2'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'systemic lupus erythematosus'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'hla-dra'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'type 2 diabetes mellitus'}), (g:Gene {name: 'ube2e2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS is_associated\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'allergic rhinitis'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'hla-dqa1'}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"systemic lupus erythematosus\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"hla-dqa1\"}) RETURN r.gwas_pvalue\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "CPU times: user 3.52 s, sys: 292 ms, total: 3.81 s\n", + "Wall time: 9min 8s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "neo4j_rag_answer = []\n", + "total_tokens_used = []\n", + "\n", + "for index, row in data.iterrows():\n", + " question = row['question_perturbed']\n", + " with get_openai_callback() as cb:\n", + " try:\n", + " neo4j_rag_answer.append(neo4j_rag_chain.run(query=question, return_final_only=True, verbose=False))\n", + " except ValueError as e:\n", + " neo4j_rag_answer.append(None)\n", + " total_tokens_used.append(cb.total_tokens)\n", + "\n", + "data.loc[:,'neo4j_rag_answer_perturbed'] = neo4j_rag_answer\n", + "data.loc[:, 'total_tokens_used_perturbed'] = total_tokens_used\n" + ] + }, + { + "cell_type": "markdown", + "id": "5ea4a4a9", + "metadata": {}, + "source": [ + "## Save the result" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "id": "27ea4be4", + "metadata": {}, + "outputs": [], + "source": [ + "save_path = '../data/results'\n", + "os.makedirs(save_path, exist_ok=True)\n", + "data.to_csv(os.path.join(save_path, 'cypher_rag_output.csv'), index=False)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f956d94", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/disease_extraction_comparison.ipynb b/notebooks/disease_extraction_comparison.ipynb new file mode 100644 index 0000000..dcf68d7 --- /dev/null +++ b/notebooks/disease_extraction_comparison.ipynb @@ -0,0 +1,750 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "860ebc4a-63e5-462d-b6ab-9bae23d10afb", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.chdir('..')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "851d771c-15b4-4168-acf5-86bdd15d9610", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/anaconda3/envs/kg_rag_test_2/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from kg_rag.utility import *\n", + "from tqdm import tqdm\n", + "import pandas as pd\n", + "import spacy\n", + "import scispacy\n", + "from scispacy.linking import EntityLinker\n", + "from transformers import pipeline\n", + "from transformers import AutoModelForTokenClassification\n", + "from IPython.display import clear_output" + ] + }, + { + "cell_type": "markdown", + "id": "f242aeb6-99f7-496a-8fd8-1f0d964a2556", + "metadata": {}, + "source": [ + "## List the NER methods to compare" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "45fdafb8-65cc-44dd-b22d-f17e5e807b49", + "metadata": {}, + "outputs": [], + "source": [ + "method_list = ['gpt', 'biomed-ner-all', 'scispacy']\n" + ] + }, + { + "cell_type": "markdown", + "id": "ddc073a0-2508-410e-8e39-4bd94020bf8a", + "metadata": {}, + "source": [ + "## Load spacy and bert based models" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "07a1ccc1-826a-4986-b7a7-f7bf26dd1d8c", + "metadata": {}, + "outputs": [], + "source": [ + "nlp = spacy.load(\"en_core_sci_sm\") \n", + "nlp.add_pipe(\"scispacy_linker\", config={\"resolve_abbreviations\": True, \"linker_name\": \"umls\"})\n", + "\n", + "\n", + "biomed_ner_all_tokenizer = AutoTokenizer.from_pretrained(\"d4data/biomedical-ner-all\",\n", + " revision=\"main\",\n", + " cache_dir=config_data['LLM_CACHE_DIR'])\n", + "biomed_ner_all_model = AutoModelForTokenClassification.from_pretrained(\"d4data/biomedical-ner-all\", \n", + " torch_dtype=torch.float16,\n", + " revision=\"main\",\n", + " cache_dir=config_data['LLM_CACHE_DIR']\n", + " )\n", + "clear_output()" + ] + }, + { + "cell_type": "markdown", + "id": "4cf3589a-6dec-41e5-9f43-703b0171e79c", + "metadata": {}, + "source": [ + "## Load evaluation dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "108796a6-5887-464b-8394-04e04b017d0b", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('data/dataset_for_entity_retrieval_accuracy_analysis.csv')\n" + ] + }, + { + "cell_type": "markdown", + "id": "ed5fca24-2b5d-4696-bcd4-ba911dce6624", + "metadata": {}, + "source": [ + "## Custom functions" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6e262f71-eac1-4894-8390-f1f4c2e8f84f", + "metadata": {}, + "outputs": [], + "source": [ + "def entity_extraction(text, method):\n", + " if method == 'gpt':\n", + " start_time = time.time()\n", + " entity = disease_entity_extractor_compare_version(text)\n", + " run_time = time.time()-start_time\n", + " elif method == 'scispacy':\n", + " start_time = time.time()\n", + " entity = disease_entity_extractor_scispacy(text)\n", + " run_time = time.time()-start_time\n", + " elif method == 'biomed-ner-all':\n", + " start_time = time.time()\n", + " entity = disease_entity_extractor_biomed_ner(text)\n", + " run_time = time.time()-start_time\n", + " return entity, run_time\n", + "\n", + "def get_GPT_response_compare_version(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature=0):\n", + " return fetch_GPT_response(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature)\n", + " \n", + "def disease_entity_extractor_compare_version(text):\n", + " chat_model_id, chat_deployment_id = get_gpt35()\n", + " prompt_updated = system_prompts[\"DISEASE_ENTITY_EXTRACTION\"] + \"\\n\" + \"Sentence : \" + text\n", + " resp = get_GPT_response_compare_version(prompt_updated, system_prompts[\"DISEASE_ENTITY_EXTRACTION\"], chat_model_id, chat_deployment_id, temperature=0)\n", + " try:\n", + " entity_dict = json.loads(resp)\n", + " return entity_dict[\"Diseases\"]\n", + " except:\n", + " return None\n", + "\n", + "def disease_entity_extractor_scispacy(text):\n", + " doc = nlp(text)\n", + " disease_semantic_types = {\"T047\", \"T191\"} \n", + " entity = []\n", + " for ent in doc.ents:\n", + " if ent._.kb_ents:\n", + " umls_cui = ent._.kb_ents[0][0]\n", + " umls_entity = nlp.get_pipe(\"scispacy_linker\").kb.cui_to_entity[umls_cui]\n", + " if any(t in disease_semantic_types for t in umls_entity.types):\n", + " entity.append(ent.text)\n", + " return entity\n", + "\n", + "def disease_entity_extractor_biomed_ner(text):\n", + " pipe = pipeline(\"ner\", model=biomed_ner_all_model, tokenizer=biomed_ner_all_tokenizer, aggregation_strategy=\"simple\", device=0)\n", + " out = pipe(text)\n", + " return list(filter(None, map(lambda x:x['word'] if x['entity_group']=='Disease_disorder' or x['entity_group']=='Sign_symptom' else None, out)))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "65c46409-f3dd-45e6-9ea8-da84cd8db212", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing method : gpt, 1/3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "322it [03:07, 1.71it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing method : biomed-ner-all, 2/3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "322it [00:05, 63.45it/s] \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing method : scispacy, 3/3\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "322it [00:04, 72.89it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 11.3 s, sys: 1.71 s, total: 13 s\n", + "Wall time: 3min 17s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "comparison_out = []\n", + "for method_index, method in enumerate(method_list):\n", + " print(f'Processing method : {method}, {method_index+1}/{len(method_list)}')\n", + " for row_index, row in tqdm(data.iterrows()):\n", + " entity, run_time = entity_extraction(row['text'], method)\n", + " comparison_out.append((row['text'], row['node_hits'], entity, run_time, method))\n", + "\n", + "comparison_out_df = pd.DataFrame(comparison_out, columns=['input_text', 'node_hits', 'entity_extracted', 'run_time_per_text', 'ner_method'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3fbfbfed-3dd6-4e86-8fac-e0ee40d2c363", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>input_text</th>\n", + " <th>node_hits</th>\n", + " <th>entity_extracted</th>\n", + " <th>run_time_per_text</th>\n", + " <th>ner_method</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>LIRAGLUTIDE TREATS OBESITY</td>\n", + " <td>obesity</td>\n", + " <td>[obesity]</td>\n", + " <td>2.214761</td>\n", + " <td>gpt</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>disease ontology identifier for central diabet...</td>\n", + " <td>central diabetes insipidus</td>\n", + " <td>[central diabetes insipidus]</td>\n", + " <td>0.549497</td>\n", + " <td>gpt</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>Xeroderma pigmentosum, group G is not associat...</td>\n", + " <td>xeroderma pigmentosum</td>\n", + " <td>[Xeroderma pigmentosum]</td>\n", + " <td>0.926769</td>\n", + " <td>gpt</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>cherubism is not a autosomal dominant disease</td>\n", + " <td>cherubism</td>\n", + " <td>[cherubism, autosomal dominant disease]</td>\n", + " <td>0.675068</td>\n", + " <td>gpt</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>MASA SYNDROME (DISORDER) IS NOT ASSOCIATED WIT...</td>\n", + " <td>MASA syndrome</td>\n", + " <td>[MASA SYNDROME]</td>\n", + " <td>0.465556</td>\n", + " <td>gpt</td>\n", + " </tr>\n", + " <tr>\n", + " <th>...</th>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " </tr>\n", + " <tr>\n", + " <th>961</th>\n", + " <td>antineoplastic agents treats osteosarcoma</td>\n", + " <td>osteosarcoma</td>\n", + " <td>[osteosarcoma]</td>\n", + " <td>0.012946</td>\n", + " <td>scispacy</td>\n", + " </tr>\n", + " <tr>\n", + " <th>962</th>\n", + " <td>timothy syndrome associates gene cacna1c</td>\n", + " <td>Timothy syndrome</td>\n", + " <td>[syndrome]</td>\n", + " <td>0.011308</td>\n", + " <td>scispacy</td>\n", + " </tr>\n", + " <tr>\n", + " <th>963</th>\n", + " <td>piebaldism is a autosomal dominant disease</td>\n", + " <td>piebaldism</td>\n", + " <td>[autosomal dominant disease]</td>\n", + " <td>0.012271</td>\n", + " <td>scispacy</td>\n", + " </tr>\n", + " <tr>\n", + " <th>964</th>\n", + " <td>Disease ontology identifier for Loeys-Dietz sy...</td>\n", + " <td>Loeys-Dietz syndrome</td>\n", + " <td>[Loeys-Dietz syndrome]</td>\n", + " <td>0.012468</td>\n", + " <td>scispacy</td>\n", + " </tr>\n", + " <tr>\n", + " <th>965</th>\n", + " <td>NOONAN SYNDROME ASSOCIATES GENE PTPN11</td>\n", + " <td>Noonan syndrome</td>\n", + " <td>[NOONAN SYNDROME]</td>\n", + " <td>0.010858</td>\n", + " <td>scispacy</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>966 rows × 5 columns</p>\n", + "</div>" + ], + "text/plain": [ + " input_text \\\n", + "0 LIRAGLUTIDE TREATS OBESITY \n", + "1 disease ontology identifier for central diabet... \n", + "2 Xeroderma pigmentosum, group G is not associat... \n", + "3 cherubism is not a autosomal dominant disease \n", + "4 MASA SYNDROME (DISORDER) IS NOT ASSOCIATED WIT... \n", + ".. ... \n", + "961 antineoplastic agents treats osteosarcoma \n", + "962 timothy syndrome associates gene cacna1c \n", + "963 piebaldism is a autosomal dominant disease \n", + "964 Disease ontology identifier for Loeys-Dietz sy... \n", + "965 NOONAN SYNDROME ASSOCIATES GENE PTPN11 \n", + "\n", + " node_hits entity_extracted \\\n", + "0 obesity [obesity] \n", + "1 central diabetes insipidus [central diabetes insipidus] \n", + "2 xeroderma pigmentosum [Xeroderma pigmentosum] \n", + "3 cherubism [cherubism, autosomal dominant disease] \n", + "4 MASA syndrome [MASA SYNDROME] \n", + ".. ... ... \n", + "961 osteosarcoma [osteosarcoma] \n", + "962 Timothy syndrome [syndrome] \n", + "963 piebaldism [autosomal dominant disease] \n", + "964 Loeys-Dietz syndrome [Loeys-Dietz syndrome] \n", + "965 Noonan syndrome [NOONAN SYNDROME] \n", + "\n", + " run_time_per_text ner_method \n", + "0 2.214761 gpt \n", + "1 0.549497 gpt \n", + "2 0.926769 gpt \n", + "3 0.675068 gpt \n", + "4 0.465556 gpt \n", + ".. ... ... \n", + "961 0.012946 scispacy \n", + "962 0.011308 scispacy \n", + "963 0.012271 scispacy \n", + "964 0.012468 scispacy \n", + "965 0.010858 scispacy \n", + "\n", + "[966 rows x 5 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_out_df" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ebb106e7-9f63-475c-acec-61dffbda4f98", + "metadata": {}, + "outputs": [], + "source": [ + "comparison_out_df_gpt = comparison_out_df[comparison_out_df.ner_method=='gpt']\n", + "comparison_out_df_biomed_ner_all = comparison_out_df[comparison_out_df.ner_method=='biomed-ner-all']\n", + "comparison_out_df_scispacy = comparison_out_df[comparison_out_df.ner_method=='scispacy']\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "b6524af1-912a-44e0-8687-3e9ff65d14e3", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def calculate_precision_recall(row):\n", + " # Convert to lowercase and split node_hits into a list\n", + " true_entities = set([row['node_hits'].lower()])\n", + " \n", + " # Convert extracted_entity list to lowercase\n", + " predicted_entities = set([entity.lower() for entity in row['entity_extracted']])\n", + " \n", + " # Calculate true positives, false positives, and false negatives\n", + " true_positives = len(true_entities.intersection(predicted_entities))\n", + " false_positives = len(predicted_entities - true_entities)\n", + " false_negatives = len(true_entities - predicted_entities)\n", + " \n", + " # Calculate precision and recall\n", + " precision = true_positives / (true_positives + false_positives) if (true_positives + false_positives) > 0 else 0\n", + " recall = true_positives / (true_positives + false_negatives) if (true_positives + false_negatives) > 0 else 0\n", + " \n", + " return pd.Series({'precision': precision, 'recall': recall})\n", + "\n", + "comparison_out_df_gpt[['precision', 'recall']] = comparison_out_df_gpt.apply(calculate_precision_recall, axis=1)\n", + "comparison_out_df_biomed_ner_all[['precision', 'recall']] = comparison_out_df_biomed_ner_all.apply(calculate_precision_recall, axis=1)\n", + "comparison_out_df_scispacy[['precision', 'recall']] = comparison_out_df_scispacy.apply(calculate_precision_recall, axis=1)\n", + "\n", + "clear_output()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "09112cfd-43a3-4bdd-8128-e872f5ede03a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.9549689440993789\n", + "0.9968944099378882\n" + ] + } + ], + "source": [ + "print(comparison_out_df_gpt.precision.mean())\n", + "print(comparison_out_df_gpt.recall.mean())" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "3814b05f-8708-428c-8c37-27160feb3ed7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.23680124223602483\n", + "0.2795031055900621\n" + ] + } + ], + "source": [ + "print(comparison_out_df_biomed_ner_all.precision.mean())\n", + "print(comparison_out_df_biomed_ner_all.recall.mean())" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9496c72c-2976-4bdd-bde5-6b8612461853", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.5910973084886129\n", + "0.6428571428571429\n" + ] + } + ], + "source": [ + "print(comparison_out_df_scispacy.precision.mean())\n", + "print(comparison_out_df_scispacy.recall.mean())" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "075fa7ce-e463-459c-88e6-00d3db62682f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 500x300 with 2 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "# Assuming you have these dataframes already loaded\n", + "# comparison_out_df_gpt\n", + "# comparison_out_df_biomed_ner_all\n", + "# comparison_out_df_scispacy\n", + "\n", + "# Create a list of dataframes and their labels\n", + "dfs = [comparison_out_df_gpt, comparison_out_df_biomed_ner_all, comparison_out_df_scispacy]\n", + "labels = ['GPT-3.5', 'BioMed NER', 'SciSpaCy']\n", + "\n", + "# Function to calculate SEM\n", + "def sem(data):\n", + " return np.std(data, ddof=1) / np.sqrt(len(data))\n", + "\n", + "# Calculate mean and SEM for precision and recall\n", + "precision_means = [df['precision'].mean() for df in dfs]\n", + "precision_sems = [sem(df['precision']) for df in dfs]\n", + "recall_means = [df['recall'].mean() for df in dfs]\n", + "recall_sems = [sem(df['recall']) for df in dfs]\n", + "\n", + "# Set up the plot\n", + "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(5, 3))\n", + "x = np.arange(len(labels))\n", + "width = 0.35\n", + "\n", + "# Function to remove top and right spines\n", + "def remove_spines(ax):\n", + " ax.spines['top'].set_visible(False)\n", + " ax.spines['right'].set_visible(False)\n", + "\n", + "# Plot precision\n", + "ax1.bar(x, precision_means, width, yerr=precision_sems, capsize=5)\n", + "ax1.set_ylabel('Precision')\n", + "# ax1.set_title('Average Precision')\n", + "ax1.set_xticks(x)\n", + "ax1.set_xticklabels(labels, rotation=45, ha='right')\n", + "ax1.set_ylim(0, 1)\n", + "remove_spines(ax1)\n", + "\n", + "# Plot recall\n", + "ax2.bar(x, recall_means, width, yerr=recall_sems, capsize=5)\n", + "ax2.set_ylabel('Recall')\n", + "# ax2.set_title('Average Recall')\n", + "ax2.set_xticks(x)\n", + "ax2.set_xticklabels(labels, rotation=45, ha='right')\n", + "ax2.set_ylim(0, 1)\n", + "remove_spines(ax2)\n", + "\n", + "# Adjust layout and display\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "fig_path = 'data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "fig.savefig(os.path.join(fig_path, 'ner_extraction_comparison.tiff'), format='tiff', bbox_inches='tight') \n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "9af751da-eee0-4d03-9bba-137baf429eae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.9549689440993789, 0.23680124223602483, 0.5910973084886129] [0.008286258373808576, 0.022466879308773186, 0.025950253677613028]\n", + "[0.9968944099378882, 0.2795031055900621, 0.6428571428571429] [0.003105590062111801, 0.025047065948613282, 0.02674395944460631]\n" + ] + } + ], + "source": [ + "print(precision_means, precision_sems)\n", + "print(recall_means, recall_sems)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5f2faf89-cdc6-492c-9372-8f1ff6233dd5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.5822619658819637" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_out_df_gpt.run_time_per_text.mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "c3c44796-55f0-4027-8651-f53fdce6629c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.015508739844612453" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_out_df_biomed_ner_all.run_time_per_text.mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "302251b3-4748-4cd2-950a-d4e25ffec4bf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.013423655344092327" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "comparison_out_df_scispacy.run_time_per_text.mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "362efc28-28c0-46ad-95b2-3d78ca7a6540", + "metadata": {}, + "outputs": [], + "source": [ + "# # Print all labels\n", + "# # print(model.config.id2label)\n", + "\n", + "# # Or, if you want a list of just the label names\n", + "# label_names = list(model.config.id2label.values())\n", + "\n", + "# set(map(lambda x:x.split('-')[-1], label_names))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "64c523d7-3ed8-4e4a-a1a0-089bd84dd554", + "metadata": {}, + "outputs": [], + "source": [ + "# method = method_list[0]\n", + "# text = data.iloc[25].text\n", + "# entity, run_time = entity_extraction(text, method)\n", + "# print(text)\n", + "# print(entity, run_time, method)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a60d8c0-fd66-4700-911d-a3e8ac51115e", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/disease_retrieval_accuracy.ipynb b/notebooks/disease_retrieval_accuracy.ipynb new file mode 100644 index 0000000..ccb207b --- /dev/null +++ b/notebooks/disease_retrieval_accuracy.ipynb @@ -0,0 +1,153 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "945c420e-bb44-4ffb-b899-e049caf0d918", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.chdir('..')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f2bdefb3-3e59-409a-81b4-2e9ffbdfdb1a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/anaconda3/envs/kg_rag_test_2/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "from kg_rag.utility import *\n", + "from tqdm import tqdm\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "19fc98b9-64a8-40c0-9e5a-92b4392e6969", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('data/dataset_for_entity_retrieval_accuracy_analysis.csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "2851be4c-2a76-4f6d-b5f4-118e8122b155", + "metadata": {}, + "outputs": [], + "source": [ + "VECTOR_DB_PATH = config_data[\"VECTOR_DB_PATH\"]\n", + "SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL = config_data[\"SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL\"]\n", + "\n", + "vectorstore = load_chroma(VECTOR_DB_PATH, SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "7255fbab-d8b4-43a3-b870-9d67ad79d061", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "322it [00:05, 56.20it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 4.74 s, sys: 896 ms, total: 5.64 s\n", + "Wall time: 5.73 s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "correct_retrieval = 0\n", + "\n", + "for index, row in tqdm(data.iterrows()):\n", + " question = row['text']\n", + " entities = disease_entity_extractor_v2(question) \n", + " for entity in entities:\n", + " node_search_result = vectorstore.similarity_search_with_score(entity, k=1)\n", + " if node_search_result[0][0].page_content == row['node_hits']:\n", + " correct_retrieval += 1 \n", + " break\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2f997335-bff7-431c-bbd8-608513eddcc7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Retrieval accuracy is 99.7%\n" + ] + } + ], + "source": [ + "retrieval_accuracy = 100*correct_retrieval/data.shape[0]\n", + "print(f'Retrieval accuracy is {round(retrieval_accuracy,1)}%')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afe971ab-b8b9-4c88-9657-c588813b412f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/full_text_index_vs_kg_rag.ipynb b/notebooks/full_text_index_vs_kg_rag.ipynb new file mode 100644 index 0000000..782e038 --- /dev/null +++ b/notebooks/full_text_index_vs_kg_rag.ipynb @@ -0,0 +1,893 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7bed2b6f-b8b2-4256-869c-1f3fa8561d1a", + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import pandas as pd\n", + "import os\n", + "from dotenv import load_dotenv\n", + "from neo4j import GraphDatabase, basic_auth\n", + "from tqdm import tqdm\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import openai\n", + "import numpy as np\n" + ] + }, + { + "cell_type": "markdown", + "id": "b0b0240a-87ba-4e3e-b672-394cb2dd3c3a", + "metadata": {}, + "source": [ + "## Load data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4a162750-64e9-4906-84b3-7858b82a17da", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('../data/rag_comparison_data.csv')\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "ffc91ffd-d76c-427f-9cbc-50b07e62fa98", + "metadata": {}, + "source": [ + "## Custom functions" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "82a7dd0b-01a5-4501-82bc-96224074c9d0", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def connect_to_graph():\n", + " auth = basic_auth(graph_usr, graph_psw)\n", + " return GraphDatabase.driver(graph_uri, auth=auth)\n", + "\n", + "def run_cypher(cypher_query):\n", + " with connect_to_graph() as sdb:\n", + " with sdb.session() as session:\n", + " result = session.run(cypher_query)\n", + " out = []\n", + " for row in result:\n", + " out.append((row['d_name'], row['r_type'], row['g_label'], row['g_name'], row['relationship_properties']))\n", + " return out\n", + "\n", + "\n", + "def lucene_search(query, source):\n", + " source_search_uri = f\"https://spoke.rbvi.ucsf.edu/api/v1/search/{source}/{query}\"\n", + " source_search_resp = requests.get(source_search_uri)\n", + " return source_search_resp\n", + "\n", + "def get_context_using_lucene_search(query):\n", + " source = 'Disease'\n", + " source_resp = lucene_search(query, source) \n", + " if source_resp.status_code == 200:\n", + " source_resp_data = source_resp.json()\n", + " source_name = source_resp_data[0]['name']\n", + " else:\n", + " return ''\n", + " cypher = f'''\n", + " MATCH(d:Disease{{name:\"{source_name}\"}})-[r]-(g) \n", + " RETURN DISTINCT d.name AS d_name, TYPE(r) AS r_type, LABELS(g) AS g_label, g.name AS g_name, PROPERTIES(r) AS relationship_properties \n", + " '''\n", + " graph_out = run_cypher(cypher)\n", + " context = ''\n", + " if len(graph_out) > 0: \n", + " for i in graph_out:\n", + " try:\n", + " prov = ', '.join(i[3][\"sources\"]) \n", + " except:\n", + " try:\n", + " prov = i[3][\"source\"]\n", + " except:\n", + " prov = ''\n", + " context += 'Disease ' + i[0] + ' ' + i[1].split('_')[0].lower() + ' ' + i[2][0] + ' ' + i[3] + f'. Provenance of this association is {prov}. ' + '\\n' + str(i[4]) \n", + " return context\n", + "\n", + "\n", + "\n", + "def chat_completion_with_token_usage(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature):\n", + " response = openai.ChatCompletion.create(\n", + " temperature=temperature,\n", + " deployment_id=chat_deployment_id,\n", + " model=chat_model_id,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": instruction}\n", + " ]\n", + " )\n", + " return response['choices'][0]['message']['content'], response.usage.total_tokens\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "09225048-3d6e-46e0-91c3-a750c9a49c34", + "metadata": {}, + "source": [ + "## OpenAI credentials" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "07387b5e-c158-4e16-bec1-fb6dbcba80f3", + "metadata": {}, + "outputs": [], + "source": [ + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "\n", + "api_key = os.environ.get('API_KEY')\n", + "api_version = os.environ.get('API_VERSION')\n", + "resource_endpoint = os.environ.get('RESOURCE_ENDPOINT')\n", + "openai.api_type = 'azure'\n", + "openai.api_key = api_key\n", + "if resource_endpoint:\n", + " openai.api_base = resource_endpoint\n", + "if api_version:\n", + " openai.api_version = api_version\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "71f31b21-527e-42cd-9998-9ebf328af4f1", + "metadata": {}, + "source": [ + "## Graph credentials" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "7e45c21d-712a-4957-adcc-2dee2ca12e06", + "metadata": {}, + "outputs": [], + "source": [ + "load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + "graph_usr = os.environ.get('NEO4J_USER')\n", + "graph_psw = os.environ.get('NEO4J_PSW')\n", + "graph_uri = os.environ.get('NEO4J_URL')\n", + "database = os.environ.get('NEO4J_DB')\n" + ] + }, + { + "cell_type": "markdown", + "id": "532c603b-c1d3-4d8a-abea-ba10c186f726", + "metadata": {}, + "source": [ + "## Setting system prompt for LLM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d57b2ec-c5ca-49ad-9d7f-e566009838d8", + "metadata": {}, + "outputs": [], + "source": [ + "system_prompt = '''\n", + " You are an expert biomedical researcher. \n", + " For answering the Question at the end with brevity, you need to first read the Context provided. \n", + " Then give your final answer briefly, by citing the Provenance information from the context. \n", + " You can find Provenance from the Context statement 'Provenance of this association is <Provenance>'. \n", + " Do not forget to cite the Provenance information. \n", + " Note that, if Provenance is 'GWAS' report it as 'GWAS Catalog'. \n", + " If Provenance is 'DISEASES' report it as 'DISEASES database - https://diseases.jensenlab.org'. \n", + " Additionally, when providing drug or medication suggestions, give maximum information available and then advise the user to seek guidance from a healthcare professional as a precautionary measure.\n", + "'''\n", + "\n", + "chat_model = 'gpt-4-32k'\n", + "temperature = 0\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "422b4993-ebfe-4088-af9a-0a6d013649e2", + "metadata": {}, + "source": [ + "## Example query for Lucene based RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "5a412550-35f5-4b33-b15f-36a1743234a1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Parkinson's disease is associated with the PINK1 gene. Provenance of this association is not provided in the context.\n" + ] + } + ], + "source": [ + "\n", + "query = \"Is Parkinson's disease associated with PINK1 gene?\"\n", + "\n", + "context = get_context_using_lucene_search(query)\n", + "\n", + "prompt = f'''\n", + "Context: {context}\n", + "Question: {query}\n", + "'''\n", + "output, token_usage = chat_completion_with_token_usage(prompt, system_prompt, chat_model, chat_model, temperature)\n", + "\n", + "print(output)\n" + ] + }, + { + "cell_type": "markdown", + "id": "2c0d739f-d3e0-4137-9857-ab98b0dd52ee", + "metadata": {}, + "source": [ + "## Example query for Lucene based RAG (after perturbation)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "4c01aef6-a01b-4c94-a8cb-f02858b9d5d9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Parkinson's disease is associated with the PINK1 gene. Provenance of this association is not provided in the context.\n" + ] + } + ], + "source": [ + "\n", + "query = \"Is parkinson's disease associated with pink1 gene?\"\n", + "\n", + "context = get_context_using_lucene_search(query)\n", + "\n", + "prompt = f'''\n", + "Context: {context}\n", + "Question: {query}\n", + "'''\n", + "output, token_usage = chat_completion_with_token_usage(prompt, system_prompt, chat_model, chat_model, temperature)\n", + "\n", + "print(output)\n" + ] + }, + { + "cell_type": "markdown", + "id": "9b73767d-8575-47c0-95aa-923258d2af84", + "metadata": {}, + "source": [ + "## Lucene based context extraction" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "83543617-01ca-49da-aef4-8e936fd39218", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [00:43, 2.31it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 14.1 s, sys: 1.04 s, total: 15.1 s\n", + "Wall time: 43.3 s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "lucene_based_context_list = []\n", + "for row_index, row in tqdm(data.iterrows()):\n", + " query = row['question']\n", + " lucene_based_context_list.append(get_context_using_lucene_search(query))\n", + "\n", + "data['extracted_context'] = lucene_based_context_list\n", + "# data_non_empty_context = data[data.extracted_context != '']\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "85138849-4f58-45de-9a28-7eecb9612412", + "metadata": {}, + "source": [ + "## Lucene based context extraction - after query perturbation" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "24dd2e6e-c9c5-4341-b14d-e5b37ded88dc", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [01:00, 1.66it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 19.5 s, sys: 1.32 s, total: 20.8 s\n", + "Wall time: 1min\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "lucene_based_context_list = []\n", + "for row_index, row in tqdm(data.iterrows()):\n", + " query = row['question_perturbed']\n", + " lucene_based_context_list.append(get_context_using_lucene_search(query))\n", + "\n", + "data['extracted_context_after_perturbation'] = lucene_based_context_list\n", + "\n", + "# data_non_empty_context_after_perturbation = data[data.extracted_context_after_perturbation != '']\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "eaf7d711-1a8f-45d4-ba60-d8519e06c4c8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [05:10, 3.11s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.94 s, sys: 484 ms, total: 2.42 s\n", + "Wall time: 5min 10s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "full_text_track_output = []\n", + "full_text_track_token_usage = []\n", + "for row_index, row in tqdm(data.iterrows()):\n", + " query = row['question']\n", + " context = row['extracted_context']\n", + " prompt = f'''\n", + " Context: {context}\n", + " Question: {query}\n", + " '''\n", + " try:\n", + " output, token_usage = chat_completion_with_token_usage(prompt, system_prompt, chat_model, chat_model, temperature)\n", + " full_text_track_output.append(output)\n", + " full_text_track_token_usage.append(token_usage)\n", + " except:\n", + " full_text_track_output.append(None)\n", + " full_text_track_token_usage.append(None)\n", + " \n", + "data['full_text_index_answer'] = full_text_track_output\n", + "data['token_usage'] = full_text_track_token_usage\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d596ec29-dae9-4b7b-9cf4-6f515943d946", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [04:53, 2.94s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.81 s, sys: 503 ms, total: 2.31 s\n", + "Wall time: 4min 53s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "full_text_track_output = []\n", + "full_text_track_token_usage = []\n", + "for row_index, row in tqdm(data.iterrows()):\n", + " query = row['question_perturbed']\n", + " context = row['extracted_context_after_perturbation']\n", + " prompt = f'''\n", + " Context: {context}\n", + " Question: {query}\n", + " '''\n", + " try:\n", + " output, token_usage = chat_completion_with_token_usage(prompt, system_prompt, chat_model, chat_model, temperature)\n", + " full_text_track_output.append(output)\n", + " full_text_track_token_usage.append(token_usage)\n", + " except:\n", + " full_text_track_output.append(None)\n", + " full_text_track_token_usage.append(None)\n", + " \n", + "data['full_text_index_answer_after_perturbation'] = full_text_track_output\n", + "data['token_usage_after_perturbation'] = full_text_track_token_usage\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "06f551db-34a6-4aca-b591-a30b66f095c8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Full-text index based retrieval 61.0%\n" + ] + } + ], + "source": [ + "data_no_nan = data.dropna(subset=['full_text_index_answer'])\n", + "data_yes_count_df = data_no_nan[data_no_nan.full_text_index_answer.str.contains('Yes')]\n", + "data_yes_count = data_yes_count_df.shape[0]\n", + "indices_to_remove = data_yes_count_df.index.tolist()\n", + "data_no_nan = data_no_nan.drop(indices_to_remove)\n", + "data_no_nan.loc[:, 'contains_pvalue'] = data_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['full_text_index_answer']), axis=1)\n", + "data_p_value_correct_retrieval_count = data_no_nan[data_no_nan.contains_pvalue==True].shape[0]\n", + "data_total_correct_retrieval = data_yes_count + data_p_value_correct_retrieval_count\n", + "\n", + "full_text_index_based_total_correct_retrieval_percentage = 100*data_total_correct_retrieval/data.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Full-text index based retrieval {full_text_index_based_total_correct_retrieval_percentage}%')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "050699a8-ff46-4b4b-a31a-808ef0799e02", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Full-text index based retrieval after name perturbation 58.0%\n" + ] + } + ], + "source": [ + "data_no_nan = data.dropna(subset=['full_text_index_answer_after_perturbation'])\n", + "data_yes_count_df = data_no_nan[data_no_nan.full_text_index_answer_after_perturbation.str.contains('Yes')]\n", + "data_yes_count = data_yes_count_df.shape[0]\n", + "indices_to_remove = data_yes_count_df.index.tolist()\n", + "data_no_nan = data_no_nan.drop(indices_to_remove)\n", + "data_no_nan.loc[:, 'contains_pvalue'] = data_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['full_text_index_answer_after_perturbation']), axis=1)\n", + "data_p_value_correct_retrieval_count = data_no_nan[data_no_nan.contains_pvalue==True].shape[0]\n", + "data_total_correct_retrieval = data_yes_count + data_p_value_correct_retrieval_count\n", + "\n", + "full_text_index_based_total_correct_retrieval_perturbed_percentage = 100*data_total_correct_retrieval/data.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Full-text index based retrieval after name perturbation {full_text_index_based_total_correct_retrieval_perturbed_percentage}%')\n" + ] + }, + { + "cell_type": "markdown", + "id": "e4a46cb6-60ea-426a-96f6-f047985b4178", + "metadata": {}, + "source": [ + "## KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "db00c5f2-a1b7-4a77-b26f-5fc0dbdb81dc", + "metadata": {}, + "outputs": [], + "source": [ + "kg_rag = pd.read_csv('../data/results/kg_rag_output.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "dbf582a6-079b-4676-a9b7-61bbe9f544c8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for KG-RAG 97.0%\n" + ] + } + ], + "source": [ + "\n", + "kg_rag_no_nan = kg_rag.dropna(subset=['kg_rag_answer'])\n", + "kg_rag_yes_count_df = kg_rag_no_nan[kg_rag_no_nan.kg_rag_answer.str.contains('Yes')]\n", + "kg_rag_yes_count = kg_rag_yes_count_df.shape[0]\n", + "indices_to_remove = kg_rag_yes_count_df.index.tolist()\n", + "kg_rag_no_nan = kg_rag_no_nan.drop(indices_to_remove)\n", + "kg_rag_no_nan.loc[:, 'contains_pvalue'] = kg_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['kg_rag_answer']), axis=1)\n", + "kg_rag_p_value_correct_retrieval_count = kg_rag_no_nan[kg_rag_no_nan.contains_pvalue==True].shape[0]\n", + "kg_rag_total_correct_retrieval = kg_rag_yes_count + kg_rag_p_value_correct_retrieval_count\n", + "\n", + "\n", + "kg_rag_total_correct_retrieval_percentage = 100*kg_rag_total_correct_retrieval/kg_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for KG-RAG {kg_rag_total_correct_retrieval_percentage}%')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "d4212209-cf87-4e14-b5fa-342c33080117", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for KG-RAG after name perturbation 97.0%\n" + ] + } + ], + "source": [ + "\n", + "\n", + "kg_rag_no_nan = kg_rag.dropna(subset=['kg_rag_answer_perturbed'])\n", + "kg_rag_yes_count_df = kg_rag_no_nan[kg_rag_no_nan.kg_rag_answer_perturbed.str.contains('Yes')]\n", + "kg_rag_yes_count = kg_rag_yes_count_df.shape[0]\n", + "indices_to_remove = kg_rag_yes_count_df.index.tolist()\n", + "kg_rag_no_nan = kg_rag_no_nan.drop(indices_to_remove)\n", + "kg_rag_no_nan.loc[:, 'contains_pvalue'] = kg_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['kg_rag_answer_perturbed']), axis=1)\n", + "kg_rag_p_value_correct_retrieval_count = kg_rag_no_nan[kg_rag_no_nan.contains_pvalue==True].shape[0]\n", + "kg_rag_total_correct_retrieval_perturbed = kg_rag_yes_count + kg_rag_p_value_correct_retrieval_count\n", + "\n", + "\n", + "kg_rag_total_correct_retrieval_perturbed_percentage = 100*kg_rag_total_correct_retrieval_perturbed/kg_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for KG-RAG after name perturbation {kg_rag_total_correct_retrieval_perturbed_percentage}%')\n" + ] + }, + { + "cell_type": "markdown", + "id": "14046f1f-91ea-4a33-b7a0-15c42d335eec", + "metadata": {}, + "source": [ + "## Cypher-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "9fc3b113-bdd8-46cf-80a7-5611005ee613", + "metadata": {}, + "outputs": [], + "source": [ + "neo4j_rag = pd.read_csv('../data/results/cypher_rag_output.csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "acf53878-a5a9-42ff-ba51-3ec71482ca36", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Cypher-RAG 75.0%\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_70250/1568521084.py:2: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer']), axis=1)\n" + ] + } + ], + "source": [ + "\n", + "neo4j_rag_no_nan = neo4j_rag.dropna(subset=['neo4j_rag_answer'])\n", + "neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer']), axis=1)\n", + "neo4j_rag_yes_count_df = neo4j_rag_no_nan[neo4j_rag_no_nan.neo4j_rag_answer.str.contains('Yes')]\n", + "neo4j_rag_yes_count = neo4j_rag_yes_count_df.shape[0]\n", + "indices_to_remove = neo4j_rag_yes_count_df.index.tolist()\n", + "neo4j_rag_no_nan = neo4j_rag_no_nan.drop(indices_to_remove)\n", + "neo4j_rag_p_value_correct_retrieval_count = neo4j_rag_no_nan[neo4j_rag_no_nan.contains_pvalue==True].shape[0]\n", + "neo4j_rag_total_correct_retrieval = neo4j_rag_yes_count + neo4j_rag_p_value_correct_retrieval_count\n", + "\n", + "neo4j_rag_total_correct_retrieval_percentage = 100*neo4j_rag_total_correct_retrieval/neo4j_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Cypher-RAG {neo4j_rag_total_correct_retrieval_percentage}%')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "24c274c9-25b6-4db9-85cb-92149b17b685", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Cypher-RAG after name perturbation 0.0%\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_70250/1404871373.py:2: SettingWithCopyWarning: \n", + "A value is trying to be set on a copy of a slice from a DataFrame.\n", + "Try using .loc[row_indexer,col_indexer] = value instead\n", + "\n", + "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", + " neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer_perturbed']), axis=1)\n" + ] + } + ], + "source": [ + "\n", + "neo4j_rag_no_nan = neo4j_rag.dropna(subset=['neo4j_rag_answer_perturbed'])\n", + "neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer_perturbed']), axis=1)\n", + "neo4j_rag_yes_count_df = neo4j_rag_no_nan[neo4j_rag_no_nan.neo4j_rag_answer_perturbed.str.contains('Yes')]\n", + "neo4j_rag_yes_count = neo4j_rag_yes_count_df.shape[0]\n", + "indices_to_remove = neo4j_rag_yes_count_df.index.tolist()\n", + "neo4j_rag_no_nan = neo4j_rag_no_nan.drop(indices_to_remove)\n", + "neo4j_rag_p_value_correct_retrieval_count = neo4j_rag_no_nan[neo4j_rag_no_nan.contains_pvalue==True].shape[0]\n", + "neo4j_rag_total_correct_retrieval_perturbed = neo4j_rag_yes_count + neo4j_rag_p_value_correct_retrieval_count\n", + "\n", + "neo4j_rag_total_correct_retrieval_perturbed_percentage = 100*neo4j_rag_total_correct_retrieval_perturbed/neo4j_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Cypher-RAG after name perturbation {neo4j_rag_total_correct_retrieval_perturbed_percentage}%')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "723e8ae3-b3ba-4589-b4eb-70b33e2facc7", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "categories = ['Unperturbed', 'Perturbed']\n", + "full_text_index_rag_percentage = [full_text_index_based_total_correct_retrieval_percentage, full_text_index_based_total_correct_retrieval_perturbed_percentage]\n", + "neo4j_rag_percentage = [neo4j_rag_total_correct_retrieval_percentage, neo4j_rag_total_correct_retrieval_perturbed_percentage]\n", + "kg_rag_percentage = [kg_rag_total_correct_retrieval_percentage, kg_rag_total_correct_retrieval_perturbed_percentage]\n", + "\n", + "full_text_index_color = 'blue'\n", + "neo4j_color = 'red'\n", + "kg_rag_color = 'green'\n", + "\n", + "fig, ax = plt.subplots(figsize=(5, 3))\n", + "bar_width = 0.25\n", + "index = np.arange(len(categories))\n", + "\n", + "ax.bar(index - bar_width, full_text_index_rag_percentage, bar_width, color=full_text_index_color, label='Full-Text Index')\n", + "ax.bar(index, neo4j_rag_percentage, bar_width, color=neo4j_color, label='Cypher-RAG')\n", + "ax.bar(index + bar_width, kg_rag_percentage, bar_width, color=kg_rag_color, label='KG-RAG')\n", + "\n", + "ax.set_ylabel('Retrieval accuracy')\n", + "ax.set_xticks(index)\n", + "ax.set_xticklabels(categories)\n", + "ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + "\n", + "sns.despine()\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "fig.savefig(os.path.join(fig_path, 'retrieval_accuracy_three_way_comparison.svg'), format='svg', bbox_inches='tight')\n" + ] + }, + { + "cell_type": "markdown", + "id": "11a596c4-597f-48c9-87d1-8e74b5522389", + "metadata": {}, + "source": [ + "## Token usage plot for full-text, cypher-rag and kg-rag" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "799e6fd9-7fd7-4884-bda9-350a2f7a050d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 400x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There is 53.9% reduction in token usage for KG-RAG compared to Cypher-RAG\n", + "There is 65.1% reduction in token usage for KG-RAG compared compared to Full-Text Index\n" + ] + } + ], + "source": [ + "\n", + "data.loc[:, 'token_usage_combined'] = 0.5*(data.token_usage + data.token_usage_after_perturbation)\n", + "neo4j_rag.loc[:, 'token_usage'] = 0.5*(neo4j_rag.total_tokens_used + neo4j_rag.total_tokens_used_perturbed)\n", + "kg_rag.loc[:, 'token_usage'] = 0.5*(kg_rag.total_tokens_used + kg_rag.total_tokens_used_perturbed)\n", + "\n", + "neo4j_avg = neo4j_rag['token_usage'].mean()\n", + "neo4j_sem = neo4j_rag['token_usage'].sem()\n", + "\n", + "kg_avg = kg_rag['token_usage'].mean()\n", + "kg_sem = kg_rag['token_usage'].sem()\n", + "\n", + "full_text_avg = data['token_usage_combined'].mean()\n", + "full_text_sem = data['token_usage_combined'].sem()\n", + "\n", + "\n", + "fig = plt.figure(figsize=(4, 3))\n", + "plt.bar(0, full_text_avg, yerr=full_text_sem, color='blue', ecolor='black', capsize=5, label='Full-Text Index')\n", + "plt.bar(1, neo4j_avg, yerr=neo4j_sem, color='red', ecolor='black', capsize=5, label='Cypher-RAG')\n", + "plt.bar(2, kg_avg, yerr=kg_sem, color='green', ecolor='black', capsize=5, label='KG-RAG')\n", + "\n", + "plt.ylabel('Average token usage')\n", + "plt.xticks([0, 1, 2], ['Full-Text Index', 'Cypher-RAG', 'KG-RAG'], rotation=45, ha='right')\n", + "plt.tight_layout()\n", + "sns.despine()\n", + "# plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + "plt.show()\n", + "\n", + "percentage_of_reduction_cypher_to_kg = round(100*(neo4j_avg-kg_avg)/neo4j_avg,1)\n", + "percentage_of_reduction_fulltext_to_kg = round(100*(full_text_avg-kg_avg)/full_text_avg,1)\n", + "\n", + "print(f'There is {percentage_of_reduction_cypher_to_kg}% reduction in token usage for KG-RAG compared to Cypher-RAG')\n", + "print(f'There is {percentage_of_reduction_fulltext_to_kg}% reduction in token usage for KG-RAG compared compared to Full-Text Index')\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "fig.savefig(os.path.join(fig_path, 'token_usage_three_way_comparison.svg'), format='svg', bbox_inches='tight')" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "ccb52e21-9bb5-4867-bd60-fea79f11130d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10590.367088607594" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "full_text_avg" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e2627b4-9f6a-431d-af05-a17ccdc37b36", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/hyperparameter_analysis_using_single_disease_prompts.ipynb b/notebooks/hyperparameter_analysis_using_single_disease_prompts.ipynb new file mode 100644 index 0000000..d0659d8 --- /dev/null +++ b/notebooks/hyperparameter_analysis_using_single_disease_prompts.ipynb @@ -0,0 +1,364 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "f4eca598", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import json\n", + "import ast\n", + "from tqdm import tqdm\n", + "import re\n", + "import os\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "from scipy.stats import sem\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8321f533", + "metadata": {}, + "outputs": [], + "source": [ + "def jaccard_similarity(list1, list2):\n", + " if list1 is not None and list2 is not None and len(list1) > 0 and len(list2) > 0:\n", + " list1 = [item.lower() for item in list1]\n", + " list2 = [item.lower() for item in list2]\n", + "\n", + " set1 = set(list1)\n", + " set2 = set(list2)\n", + " intersection = len(set1.intersection(set2))\n", + " union = len(set1) + len(set2) - intersection\n", + " if union == 0:\n", + " return 0.0\n", + " else:\n", + " jaccard_similarity = intersection / union\n", + " return jaccard_similarity\n", + " else:\n", + " return 0.0\n", + " \n", + "def extract_answer(text):\n", + " pattern = r'{[^{}]*}'\n", + " match = re.search(pattern, text)\n", + " if match:\n", + " return match.group()\n", + " else:\n", + " return None\n", + " \n", + "def extract_by_splitting(text):\n", + " compound_list = text.split(':')[1].split(\"Diseases\")[0].split(\"], \")[0]+\"]\"\n", + " disease_list = text.split(':')[-1].split(\"}\")[0]\n", + " resp = {}\n", + " resp[\"Compounds\"] = ast.literal_eval(compound_list)\n", + " resp[\"Diseases\"] = ast.literal_eval(disease_list)\n", + " return resp\n", + " \n", + " \n", + "def get_hyperparam_perf(files):\n", + " llm_performance_list = []\n", + " for file in tqdm(files):\n", + " df = pd.read_csv(os.path.join(PARENT_PATH, file))\n", + " df.dropna(subset=[\"llm_answer\"], inplace=True)\n", + " llm_performance_list_across_questions = []\n", + " for index, row in df.iterrows():\n", + " cmp_gt = ast.literal_eval(row[\"compound_groundTruth\"])\n", + " disease_gt = ast.literal_eval(row[\"disease_groundTruth\"])\n", + " try:\n", + " llm_answer = json.loads(extract_answer(row[\"llm_answer\"]))\n", + " except:\n", + " llm_answer = extract_by_splitting(row[\"llm_answer\"])\n", + " cmp_llm = llm_answer[\"Compounds\"]\n", + " disease_llm = llm_answer[\"Diseases\"]\n", + " cmp_similarity = jaccard_similarity(cmp_gt, cmp_llm)\n", + " disease_similarity = jaccard_similarity(disease_gt, disease_llm)\n", + " llm_performance = np.mean([cmp_similarity, disease_similarity])\n", + " llm_performance_list_across_questions.append(llm_performance)\n", + " llm_performance_list.append((np.mean(llm_performance_list_across_questions), np.std(llm_performance_list_across_questions), sem(llm_performance_list_across_questions), row[\"context_volume\"]))\n", + " hyperparam_perf = pd.DataFrame(llm_performance_list, columns=[\"performance_mean\", \"performance_std\", \"performance_sem\", \"context_volume\"]) \n", + " return hyperparam_perf" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9feae00e", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "Following files can be obtained by running the run_single_disease_entity_hyperparameter_tuning.py script.\n", + "Make sure to change the parent path and filenames based on where and how you save the files\n", + "'''\n", + "\n", + "PARENT_PATH = \"../data/results\"\n", + "\n", + "\n", + "FILES_1 = [\n", + " \"minilm_based_single_disease_hyperparam_tuning_round_1_gpt_4.csv\",\n", + " \"minilm_based_single_disease_hyperparam_tuning_round_2_gpt_4.csv\",\n", + " \"minilm_based_single_disease_hyperparam_tuning_round_3_gpt_4.csv\",\n", + " \"minilm_based_single_disease_hyperparam_tuning_round_4_gpt_4.csv\",\n", + " \"minilm_based_single_disease_hyperparam_tuning_round_5_gpt_4.csv\"\n", + "]\n", + "\n", + "FILES_2 = [\n", + " \"pubmert_based_single_disease_hyperparam_tuning_round_1_gpt_4.csv\",\n", + " \"pubmert_based_single_disease_hyperparam_tuning_round_2_gpt_4.csv\",\n", + " \"pubmert_based_single_disease_hyperparam_tuning_round_3_gpt_4.csv\",\n", + " \"pubmert_based_single_disease_hyperparam_tuning_round_4_gpt_4.csv\",\n", + " \"pubmert_based_single_disease_hyperparam_tuning_round_5_gpt_4.csv\"\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7e85661a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 58.18it/s]\n", + "100%|████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 114.49it/s]\n" + ] + } + ], + "source": [ + "mini_lm_perf = get_hyperparam_perf(FILES_1)\n", + "pubmedBert_perf = get_hyperparam_perf(FILES_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "322a19e4", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 300x400 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "params = mini_lm_perf.context_volume.values\n", + "mini_lm_mean_performance = mini_lm_perf.performance_mean.values\n", + "mini_lm_std_deviation = mini_lm_perf.performance_std.values\n", + "mini_lm_sem_value = mini_lm_perf.performance_sem.values\n", + "\n", + "pubmedBert_mean_performance = pubmedBert_perf.performance_mean.values\n", + "pubmedBert_std_deviation = pubmedBert_perf.performance_std.values\n", + "pubmedBert_sem_value = pubmedBert_perf.performance_sem.values\n", + "\n", + "fig = plt.figure(figsize=(3, 4))\n", + "plt.errorbar(params, mini_lm_mean_performance, yerr=None, fmt='o-', capsize=5, label='all-MiniLM-L6-v2')\n", + "plt.errorbar(params, pubmedBert_mean_performance, yerr=None, fmt='o-', capsize=5, label='PubMedBERT', color=\"darkred\")\n", + "plt.xlabel('Context volume')\n", + "plt.ylabel('Mean Performance')\n", + "plt.grid(True)\n", + "plt.ylim(0.35,0.8)\n", + "plt.legend(bbox_to_anchor=(0.2, 0.35))\n", + "plt.show()\n", + "\n", + "fig_filename = \"../data/results/figures/context_volume_single_disease_prompt_miniLM_vs_PubMedBert.svg\"\n", + "fig.savefig(fig_filename, format='svg', bbox_inches='tight')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b1de37a4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>performance_mean</th>\n", + " <th>performance_std</th>\n", + " <th>performance_sem</th>\n", + " <th>context_volume</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>0.419761</td>\n", + " <td>0.217493</td>\n", + " <td>0.025283</td>\n", + " <td>10</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>0.622952</td>\n", + " <td>0.190095</td>\n", + " <td>0.022098</td>\n", + " <td>50</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>0.661460</td>\n", + " <td>0.177932</td>\n", + " <td>0.020684</td>\n", + " <td>100</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>0.667021</td>\n", + " <td>0.179110</td>\n", + " <td>0.020821</td>\n", + " <td>150</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>0.668674</td>\n", + " <td>0.176935</td>\n", + " <td>0.020568</td>\n", + " <td>200</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "</div>" + ], + "text/plain": [ + " performance_mean performance_std performance_sem context_volume\n", + "0 0.419761 0.217493 0.025283 10\n", + "1 0.622952 0.190095 0.022098 50\n", + "2 0.661460 0.177932 0.020684 100\n", + "3 0.667021 0.179110 0.020821 150\n", + "4 0.668674 0.176935 0.020568 200" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mini_lm_perf\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "eecab597", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.61" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(mini_lm_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2adc10b9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.67" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(pubmedBert_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a0db4b8d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "9.836065573770501" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "100*(round(pubmedBert_perf.performance_mean.mean(), 2) - round(mini_lm_perf.performance_mean.mean(), 2))/round(mini_lm_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33437dd3", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/hyperparameter_analysis_using_two_disease_prompts.ipynb b/notebooks/hyperparameter_analysis_using_two_disease_prompts.ipynb new file mode 100644 index 0000000..2fa6d46 --- /dev/null +++ b/notebooks/hyperparameter_analysis_using_two_disease_prompts.ipynb @@ -0,0 +1,272 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "cac92b88", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import json\n", + "import ast\n", + "from tqdm import tqdm\n", + "import re\n", + "import os\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "from scipy.stats import sem\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "899b592f", + "metadata": {}, + "outputs": [], + "source": [ + "def jaccard_similarity(list1, list2):\n", + " if list1 is not None and list2 is not None and len(list1) > 0 and len(list2) > 0:\n", + " list1 = [item.lower() for item in list1]\n", + " list2 = [item.lower() for item in list2]\n", + "\n", + " set1 = set(list1)\n", + " set2 = set(list2)\n", + " intersection = len(set1.intersection(set2))\n", + " union = len(set1) + len(set2) - intersection\n", + " if union == 0:\n", + " return 0.0\n", + " else:\n", + " jaccard_similarity = intersection / union\n", + " return jaccard_similarity\n", + " else:\n", + " return 0.0\n", + " \n", + "def extract_answer(text):\n", + " pattern = r'{[^{}]*}'\n", + " match = re.search(pattern, text)\n", + " if match:\n", + " return match.group()\n", + " else:\n", + " return None\n", + " \n", + "def extract_by_splitting(text):\n", + " compound_list = text.split(':')[1].split(\"Diseases\")[0].split(\"], \")[0]+\"]\"\n", + " disease_list = text.split(':')[-1].split(\"}\")[0]\n", + " resp = {}\n", + " resp[\"Compounds\"] = ast.literal_eval(compound_list)\n", + " resp[\"Diseases\"] = ast.literal_eval(disease_list)\n", + " return resp\n", + "\n", + "def get_hyperparam_perf(files):\n", + " llm_performance_list = []\n", + " for file in tqdm(files):\n", + " df = pd.read_csv(os.path.join(PARENT_PATH, file))\n", + " df.dropna(subset=[\"llm_answer\"], inplace=True)\n", + " llm_performance_list_across_questions = []\n", + " for index, row in df.iterrows():\n", + " ground_truth = ast.literal_eval(row[\"central_nodes_groundTruth\"])\n", + " try:\n", + " llm_answer = json.loads(row[\"llm_answer\"])\n", + " except:\n", + " try:\n", + " llm_answer = ast.literal_eval(row[\"llm_answer\"].split(\"Nodes:\")[-1])\n", + " except:\n", + " llm_answer = []\n", + " if not isinstance(llm_answer, list):\n", + " llm_result = llm_answer[\"Nodes\"]\n", + " else:\n", + " llm_result = llm_answer\n", + " llm_performance_list_across_questions.append(jaccard_similarity(ground_truth, llm_result))\n", + " llm_performance_list.append((np.mean(llm_performance_list_across_questions), np.std(llm_performance_list_across_questions), sem(llm_performance_list_across_questions), row[\"context_volume\"]))\n", + " hyperparam_perf = pd.DataFrame(llm_performance_list, columns=[\"performance_mean\", \"performance_std\", \"performance_sem\", \"context_volume\"])\n", + " return hyperparam_perf\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "075b3375", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "Following files can be obtained by running the run_two_disease_entity_hyperparameter_tuning.py script.\n", + "Make sure to change the parent path and filenames based on where and how you save the files\n", + "'''\n", + "\n", + "PARENT_PATH = \"../data/results\"\n", + "\n", + "\n", + "FILES_1 = [\n", + " \"minilm_based_two_disease_hyperparam_tuning_round_1_gpt_4.csv\",\n", + " \"minilm_based_two_disease_hyperparam_tuning_round_2_gpt_4.csv\",\n", + " \"minilm_based_two_disease_hyperparam_tuning_round_3_gpt_4.csv\",\n", + " \"minilm_based_two_disease_hyperparam_tuning_round_4_gpt_4.csv\",\n", + " \"minilm_based_two_disease_hyperparam_tuning_round_5_gpt_4.csv\"\n", + "]\n", + "\n", + "FILES_2 = [\n", + " \"pubmert_based_two_disease_hyperparam_tuning_round_1_gpt_4.csv\",\n", + " \"pubmert_based_two_disease_hyperparam_tuning_round_2_gpt_4.csv\",\n", + " \"pubmert_based_two_disease_hyperparam_tuning_round_3_gpt_4.csv\",\n", + " \"pubmert_based_two_disease_hyperparam_tuning_round_4_gpt_4.csv\",\n", + " \"pubmert_based_two_disease_hyperparam_tuning_round_5_gpt_4.csv\"\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "00854dfb", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 52.99it/s]\n", + "100%|█████████████████████████████████████████████████████████████████████████████████████████| 5/5 [00:00<00:00, 66.61it/s]\n" + ] + } + ], + "source": [ + "mini_lm_perf = get_hyperparam_perf(FILES_1)\n", + "pubmedBert_perf = get_hyperparam_perf(FILES_2)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a0c605d1", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 300x400 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "params = mini_lm_perf.context_volume.values\n", + "mini_lm_mean_performance = mini_lm_perf.performance_mean.values\n", + "mini_lm_std_deviation = mini_lm_perf.performance_std.values\n", + "mini_lm_sem_value = mini_lm_perf.performance_sem.values\n", + "\n", + "pubmedBert_mean_performance = pubmedBert_perf.performance_mean.values\n", + "pubmedBert_std_deviation = pubmedBert_perf.performance_std.values\n", + "pubmedBert_sem_value = pubmedBert_perf.performance_sem.values\n", + "\n", + "fig = plt.figure(figsize=(3, 4))\n", + "plt.errorbar(params, mini_lm_mean_performance, yerr=None, fmt='o-', capsize=5, label='all-MiniLM-L6-v2')\n", + "plt.errorbar(params, pubmedBert_mean_performance, yerr=None, fmt='o-', capsize=5, label='PubMedBERT', color=\"darkred\")\n", + "plt.xlabel('Context volume')\n", + "plt.ylabel('Mean Performance')\n", + "plt.grid(True)\n", + "plt.legend(bbox_to_anchor=(0.2, 0.35))\n", + "plt.show()\n", + "\n", + "fig_filename = \"../data/results/figures/context_volume_two_disease_prompt_miniLM_vs_PubMedBert.svg\"\n", + "fig.savefig(fig_filename, format='svg', bbox_inches='tight')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e7eb274c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.37" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(mini_lm_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "f6fb10e2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.4" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(pubmedBert_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d96cb0c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8.108108108108116" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "100*(round(pubmedBert_perf.performance_mean.mean(), 2) - round(mini_lm_perf.performance_mean.mean(), 2))/round(mini_lm_perf.performance_mean.mean(), 2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd4f3cdc", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/kg_rag_based_gpt_prompts.ipynb b/notebooks/kg_rag_based_gpt_prompts.ipynb new file mode 100644 index 0000000..87dc281 --- /dev/null +++ b/notebooks/kg_rag_based_gpt_prompts.ipynb @@ -0,0 +1,723 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "3d3dca32-b77f-471d-b834-20ac795f9f17", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.chdir('..')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "9da344d2-8e45-4574-aa19-4ad76c566101", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import clear_output\n", + "from kg_rag.utility import *\n", + "\n", + "clear_output()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b44bf274-41d1-4153-a65e-bfb9b90ebcc6", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def generate_response(question, llm, kg_rag_flag, evidence_flag=False, temperature=0):\n", + " CHAT_MODEL_ID = llm\n", + " CHAT_DEPLOYMENT_ID = llm\n", + " \n", + " if kg_rag_flag:\n", + " SYSTEM_PROMPT = system_prompts[\"KG_RAG_BASED_TEXT_GENERATION\"]\n", + " CONTEXT_VOLUME = int(config_data[\"CONTEXT_VOLUME\"])\n", + " QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD = float(config_data[\"QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD\"])\n", + " QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY = float(config_data[\"QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY\"])\n", + " VECTOR_DB_PATH = config_data[\"VECTOR_DB_PATH\"]\n", + " NODE_CONTEXT_PATH = config_data[\"NODE_CONTEXT_PATH\"]\n", + " SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL = config_data[\"SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL\"]\n", + " SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL = config_data[\"SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL\"]\n", + " vectorstore = load_chroma(VECTOR_DB_PATH, SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL)\n", + " embedding_function_for_context_retrieval = load_sentence_transformer(SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL)\n", + " node_context_df = pd.read_csv(NODE_CONTEXT_PATH)\n", + " context = retrieve_context(question, vectorstore, embedding_function_for_context_retrieval, node_context_df, CONTEXT_VOLUME, QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD, QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY, evidence_flag)\n", + " enriched_prompt = \"Context: \"+ context + \"\\n\" + \"Question: \" + question\n", + " question = enriched_prompt\n", + " else:\n", + " SYSTEM_PROMPT = system_prompts[\"PROMPT_BASED_TEXT_GENERATION\"]\n", + " \n", + " output = get_GPT_response(question, SYSTEM_PROMPT, CHAT_MODEL_ID, CHAT_DEPLOYMENT_ID, temperature=temperature)\n", + " stream_out(output)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "33c0771d-e6be-406b-9b17-51f6377bcb6a", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "LLM_TO_USE = 'gpt-4'\n", + "TEMPERATURE = config_data[\"LLM_TEMPERATURE\"]\n" + ] + }, + { + "cell_type": "markdown", + "id": "aab5d68e-ed47-4e36-986f-8842287d8ab6", + "metadata": {}, + "source": [ + "## Question 1:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bbbdb428-6d01-43f2-9e58-b919e7a68736", + "metadata": {}, + "outputs": [], + "source": [ + "question = 'Are there any latest drugs used for weight management in patients with Bardet-Biedl Syndrome?'\n" + ] + }, + { + "cell_type": "markdown", + "id": "19ffb33b-bce6-4cb1-8f86-76080fcf0e40", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "02374d3c-5711-4704-8b37-7eda0965c9b0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, the compound Setmelanotide is used to treat Bardet-Biedl syndrome. It is currently in phase 3 of clinical trials according to the sources ChEMBL and DrugCentral. However, it is advised to seek guidance from a healthcare professional for the most current and personalized treatment options. [Provenance: ChEMBL, DrugCentral]\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True #Used only when KG_RAG_FLAG=True\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "17be2ecd-40f1-44b5-8f79-9358264a3703", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "06bf55f2-eccf-4c26-b65a-0ed2ed30e689", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "As of my knowledge up to date, there are no specific drugs designed for weight management in patients with Bardet-Biedl Syndrome. The treatment generally involves managing the symptoms and complications. However, any new developments would be best advised by a healthcare professional.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "afa24795-71e1-4f1a-ac99-b8d106513f76", + "metadata": {}, + "source": [ + "## Question 2:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "eca290bb-fe30-4bb2-ab36-405c2151bccb", + "metadata": {}, + "outputs": [], + "source": [ + "question = 'Is it PNPLA3 or HLA-B that has a significant association with the disease liver benign neoplasm?'\n" + ] + }, + { + "cell_type": "markdown", + "id": "0cd8e67f-f769-4130-8e7d-52e0524c66df", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "03863049-4ea5-4733-aeb4-0be3f09d6b5f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The gene PNPLA3 has a more significant association with the disease liver benign neoplasm, as indicated by the lower p-value of 4e-14 compared to HLA-B's p-value of 2e-08. The provenance of this information is the GWAS Catalog.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True #Used only when KG_RAG_FLAG=True\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "30121a5b-3956-41bd-ac4a-62e32744ba99", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "8614706d-90d9-49e8-9481-30628505ba2e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "It is PNPLA3 that has a significant association with the disease liver benign neoplasm.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "8087eb26-e144-48ee-8630-09c73eb35a37", + "metadata": {}, + "source": [ + "## Question 3" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "4ed3bb71-12c8-40bf-b361-f9cd227c142d", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Is Parkinson's disease associated with PINK1 gene?\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "0d06bb9e-ed6e-4f1b-ac2e-65cf219eeb12", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Parkinson's disease is associated with the PINK1 gene. This association is reported in the DISEASES database - https://diseases.jensenlab.org.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "b17ed61e-9de1-4e2b-ad04-5c41b1167e5b", + "metadata": {}, + "source": [ + "## Question 3- perturbed (entities in smaller case)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ae0cccdb-8689-46b0-a1cb-808ec8f997e0", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Is parkinson's disease associated with pink1 gene?\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "1961ca49-f48a-46e3-bfc3-ced02fb1a2c2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Parkinson's disease is associated with the PINK1 gene. This association is reported in the DISEASES database - https://diseases.jensenlab.org.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "b7f6ee15-2e3a-4dea-bfa6-35401b6b67da", + "metadata": {}, + "source": [ + "## Question 4:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f5068a03-143d-4c29-87bf-bba1082408bd", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"What are some protein markers associated with thoracic aortic aneurysm?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "056a4de0-c0fb-48ee-93e3-7742584362c9", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "6edd6bc4-e03b-473e-996e-6705f83ee2fa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The protein markers associated with thoracic aortic aneurysm include Chondroitin sulfate proteoglycan 4 (CSPG4), Matrix Gla protein (MGP), Interleukin-2 receptor subunit alpha (IL2RA), Interleukin-1 beta (IL1B), Myosin-10 (MYH10), Tropomyosin alpha-4 chain (TPM4), Tyrosine-protein kinase Mer (MERTK), and Stabilin-1 (STAB1). The provenance of these associations is the Cell Taxonomy database.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "e95cd283-ebf1-4394-bf40-e62fc96505eb", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f4c9d96b-c78f-44d4-9a46-1254f4856324", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Some protein markers associated with thoracic aortic aneurysm include Matrix metalloproteinases (MMPs), C-reactive protein (CRP), and fibrillin-1.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "84ecf6b4-5732-453a-94c3-a524c4572b81", + "metadata": {}, + "source": [ + "## Question 5:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "0a049b56-cc9c-4777-8351-265839145690", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Are there any protein markers that show increased activity in adenocarcinoma?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "a9a82988-b1e6-441b-bafa-4b148e4054ba", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "6cd1217e-b504-4006-a099-87bc5361d85f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, there are several protein markers that show increased activity in adenocarcinoma. These include Keratin, type II cytoskeletal 7 (Cytokeratin-7) (CK-7) (Keratin-7) (K7) (Sarcolectin) (Type-II keratin Kb7), Anterior gradient protein 2 homolog (AG-2) (hAG-2) (HPC8) (Secreted cement gland protein XAG-2 homolog), Guanine deaminase (Guanase) (Guanine aminase) (3.5.4.3) (Guanine aminohydrolase) (GAH) (p51-nedasin), and Graves disease carrier protein (GDC) (Graves disease autoantigen) (GDA) (Mitochondrial solute carrier protein homolog) (Solute carrier family 25 member 16). The provenance of these associations is the Cell Taxonomy.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "7bcae3c8-130c-4121-a119-9b9bb79a21ee", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "96d8e70c-4258-4679-a5fa-1bc798eabd59", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, certain protein markers like carcinoembryonic antigen (CEA), CA 19-9, and cytokeratins can show increased activity in adenocarcinoma.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "03697e1c-6868-4c56-8876-1333bc493f44", + "metadata": {}, + "source": [ + "## Question 6:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "189ef273-bf3a-415f-8198-0e7fc4a1cac0", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Do you know if ruxolitinib is approved as a pharmacologic treatment for vitiligo?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "fffd4c16-08fa-436f-b692-d3fe9eda305e", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "8e520c41-c5d3-4b38-a744-f954c106847a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Ruxolitinib is associated with the treatment of vitiligo. This association is supported by data from ChEMBL and DrugCentral databases. However, it is always recommended to seek guidance from a healthcare professional for treatment options. (Provenance: ChEMBL, DrugCentral)\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "6b1c1e0c-2a6a-48a0-99f1-4daabb2f1f61", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "91e4eabc-2027-4bb6-b75f-0064d2a52369", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "As of my knowledge up to date, ruxolitinib is not officially approved for the treatment of vitiligo. However, some clinical trials have shown promising results. Always consult with a healthcare provider for treatment options.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "be6ca1c2-f118-41cc-93a7-5e8db134193f", + "metadata": {}, + "source": [ + "## Question 7:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "36a704be-f9d6-4968-82ec-09c4d0efe3a2", + "metadata": {}, + "outputs": [], + "source": [ + "question = \"Are there any biomarkers that show increased profile in hydrocephalus?\"\n" + ] + }, + { + "cell_type": "markdown", + "id": "cf579442-9b23-4160-be25-e4a9dd88999f", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "a9f242a8-4f31-4f58-926c-d48f3f95f584", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, the Transmembrane protein 119 (TMEM119) and P2Y purinoceptor 12 (P2RY12) show an increased profile in hydrocephalus. The provenance of this information is the Cell Taxonomy database.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "e0904315-0f47-4422-aa5c-063a3ccbc919", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "1f1ab642-9385-4b04-83cf-6ace3eee6653", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, certain biomarkers such as L1CAM, S100B, GFAP, and NSE have shown increased profiles in hydrocephalus.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "1fd3811b-546f-4ec3-8207-f9323e372744", + "metadata": {}, + "source": [ + "## Question 8:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "2a1c9337-fd39-45b0-b12a-6de9b5971b9e", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "question = 'Does drug dependence have any genetic factors? Do you have any statistical evidence from trustworthy sources for this?'\n" + ] + }, + { + "cell_type": "markdown", + "id": "93f43325-fd99-4b43-a2b3-1314c26c7d8e", + "metadata": {}, + "source": [ + "### With KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "e6852cb3-8bf9-408b-ab65-492b75c690ed", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, drug dependence does have genetic factors. The genes KAT2B and SLC25A16 have been associated with drug dependence. This information is backed by statistical evidence from the GWAS Catalog, with p-values of 4e-10 and 1e-09 respectively.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = True\n", + "EDGE_EVIDENCE_FLAG = True \n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, evidence_flag=EDGE_EVIDENCE_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "markdown", + "id": "796144e2-338d-479c-ba3b-34b0c23a209b", + "metadata": {}, + "source": [ + "### Without KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "b8079bc6-d309-4c88-9440-376aa43d972e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, drug dependence does have genetic factors. According to the National Institute on Drug Abuse, genetics account for about 40-60% of a person's vulnerability to drug addiction.\n", + "\n" + ] + } + ], + "source": [ + "KG_RAG_FLAG = False\n", + "\n", + "generate_response(question, LLM_TO_USE, KG_RAG_FLAG, temperature=TEMPERATURE)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16e1ae6d-d0e0-4b42-a8fe-517033fb9960", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/kg_rag_extended.ipynb b/notebooks/kg_rag_extended.ipynb new file mode 100644 index 0000000..f3e6d3a --- /dev/null +++ b/notebooks/kg_rag_extended.ipynb @@ -0,0 +1,495 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "c11a1651-fef4-4fc9-9eaa-cc4ca6003444", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "This notebook is a standalone script. This requires different packages which is not mentioned in the kg-rag requirements.txt file.\n", + "This notebook serves as a proof of concept that KG-RAG can be extended to other node types to answer more versatile biomedical questions.\n", + "'''\n", + "\n", + "from llama_index.core import Settings\n", + "from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding\n", + "\n", + "from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings\n", + "\n", + "from pinecone import Pinecone\n", + "from dotenv import load_dotenv, find_dotenv\n", + "import os\n", + "import json\n", + "\n", + "from joblib import Memory\n", + "from tenacity import retry, stop_after_attempt, wait_random_exponential\n", + "import requests\n", + "import pandas as pd\n", + "import numpy as np\n", + "import ast\n", + "from sklearn.metrics.pairwise import cosine_similarity\n", + "import time\n", + "import sys\n", + "\n", + "from IPython.display import clear_output\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e6665db2-ded1-40df-b64a-7a247d7511eb", + "metadata": {}, + "outputs": [], + "source": [ + "INDEX_NAME = 'spoke-nodes'\n", + "EMBEDDING_MODEL = 'text-embedding-ada-002'\n", + "CHAT_MODEL = 'gpt-35-turbo'\n", + "SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL = 'pritamdeka/S-PubMedBert-MS-MARCO'\n", + "\n", + "chat_memory = Memory('cachegpt', verbose=0)\n", + "embed_memory = Memory('cache_embedding', verbose=0)\n", + "\n", + "SPOKE_API_URI = 'https://spoke.rbvi.ucsf.edu'\n", + "\n", + "KG_RAG_PARAMS = {\n", + " 'CONTEXT_VOLUME' : 150,\n", + " 'QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD' : 75,\n", + " 'QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY' : 0.5,\n", + "}\n", + "\n", + "DEFAULT_SPOKE_API_PARAMS = {\n", + " 'cutoff_Compound_max_phase' : 3,\n", + " 'cutoff_Protein_source' : ['SwissProt'],\n", + " 'cutoff_DaG_diseases_sources' : ['knowledge', 'experiments', 'textmining'],\n", + " 'cutoff_DaG_textmining' : 3,\n", + " 'cutoff_CtD_phase' : 3,\n", + " 'cutoff_PiP_confidence' : 0.7,\n", + " 'cutoff_ACTeG_level' : ['Low', 'Medium', 'High'],\n", + " 'depth' : 1,\n", + " 'cutoff_DpL_average_prevalence' : 0.001\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9caecf10-0157-4220-9e95-7d8fa828bc80", + "metadata": {}, + "outputs": [], + "source": [ + "BIOMEDICAL_ENTITY_EXTRACTION_SYSTEM_PROMPT = '''\n", + " You are an expert biomedical name entity extractor from a sentence. \n", + " You are able to extract entities such as Diseases, Genes, Variants, Proteins, Symptoms, Side effects, Organisms, Pathways, Compounds, Reactions. \n", + " Report your response as a JSON in the following format:\n", + " {\"Entities\": <List of extracted biomedical entities from the user input>}\n", + " IMPORTANT : Report the names mentioned in the user input, not the criteria they belong to. \n", + " \n", + " Example 1:\n", + " User input : What are the proteins encoded by PINK1?\n", + " Response: {\"Entities\" : [\"PINK1\"]}\n", + " \n", + " Example 2:\n", + " User input: Other than Parkinson's disease, what diseases do SNCA connect to?\n", + " Response: {\"Entities\": [\"Parkinson's disease\", \"SNCA\"]}\n", + "'''\n", + "\n", + "\n", + "KG_RAG_BASED_TEXT_GENERATION_SYSTEM_PROMPT = '''\n", + " You are an expert biomedical researcher. \n", + " For answering the Question at the end with brevity, you need to first read the Context provided. \n", + " Then give your final answer briefly, by citing the Provenance information from the context. \n", + " You can find Provenance from the Context statement 'Provenance of this association is <Provenance>'. \n", + " Do not forget to cite the Provenance information. Note that, if Provenance is 'GWAS' report it as 'GWAS Catalog'. \n", + " If Provenance is 'DISEASES' report it as 'DISEASES database - https://diseases.jensenlab.org'. \n", + " Additionally, when providing drug or medication suggestions, give maximum information available and then advise the user to seek guidance from a healthcare professional as a precautionary measure.\n", + "'''\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "80db095c-bd5f-4cdc-b5d2-587a471e34fb", + "metadata": {}, + "outputs": [], + "source": [ + "def load_sentence_transformer(sentence_embedding_model):\n", + " return SentenceTransformerEmbeddings(model_name=sentence_embedding_model)\n", + " \n", + "def biomedical_entity_extractor(text, model):\n", + " prompt_updated = BIOMEDICAL_ENTITY_EXTRACTION_SYSTEM_PROMPT + \"\\n\" + \"Sentence : \" + text\n", + " resp = get_GPT_response(text, BIOMEDICAL_ENTITY_EXTRACTION_SYSTEM_PROMPT, model, temperature=0)\n", + " try:\n", + " entity_dict = json.loads(resp)\n", + " return entity_dict[\"Entities\"]\n", + " except:\n", + " return None\n", + "\n", + "@embed_memory.cache\n", + "def openai_embedding(embed_model, text):\n", + " node_embedding = embed_model.get_text_embedding(text)\n", + " return node_embedding \n", + "\n", + "\n", + "@chat_memory.cache\n", + "def get_GPT_response(instruction, system_prompt, chat_model_id, temperature=0.3):\n", + " return fetch_GPT_response(instruction, system_prompt, chat_model_id, temperature=temperature)\n", + "\n", + "@retry(wait=wait_random_exponential(min=10, max=30), stop=stop_after_attempt(5))\n", + "def fetch_GPT_response(instruction, system_prompt, chat_model_id, temperature):\n", + " response = client.chat.completions.create( \n", + " temperature=temperature,\n", + " model=chat_model_id,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": instruction}\n", + " ]\n", + " )\n", + " if response.choices:\n", + " return response.choices[0].message.content\n", + " else:\n", + " return 'Unexpected response'\n", + "\n", + "def retrieve_node(query, embed_model, k=1):\n", + " query_embedding = embed_model.get_text_embedding(query)\n", + " retrieved_doc = pinecone_index.query(\n", + " vector=query_embedding, \n", + " top_k=k, \n", + " include_metadata=True\n", + " )\n", + " node_name = list(map(lambda x:json.loads(x['metadata']['_node_content'])['text'], retrieved_doc['matches']))\n", + " node_type = list(map(lambda x:x['metadata']['node_type'], retrieved_doc['matches']))\n", + " return node_name, node_type\n", + "\n", + "\n", + "def get_spoke_api_resp(base_uri, end_point, params=None):\n", + " uri = base_uri + end_point\n", + " if params:\n", + " return requests.get(uri, params=params)\n", + " else:\n", + " return requests.get(uri)\n", + "\n", + "@retry(wait=wait_random_exponential(min=10, max=30), stop=stop_after_attempt(5))\n", + "def get_context_using_spoke_api(node_value, node_type, search_depth):\n", + " type_end_point = \"/api/v1/types\"\n", + " result = get_spoke_api_resp(SPOKE_API_URI, type_end_point)\n", + " data_spoke_types = result.json()\n", + " node_types = list(data_spoke_types[\"nodes\"].keys())\n", + " edge_types = list(data_spoke_types[\"edges\"].keys())\n", + " node_types_to_remove = [\"DatabaseTimestamp\", \"Version\"]\n", + " filtered_node_types = [node_type for node_type in node_types if node_type not in node_types_to_remove]\n", + " api_params = {\n", + " 'node_filters' : filtered_node_types,\n", + " 'edge_filters': edge_types,\n", + " 'cutoff_Compound_max_phase': DEFAULT_SPOKE_API_PARAMS['cutoff_Compound_max_phase'],\n", + " 'cutoff_Protein_source': DEFAULT_SPOKE_API_PARAMS['cutoff_Protein_source'],\n", + " 'cutoff_DaG_diseases_sources': DEFAULT_SPOKE_API_PARAMS['cutoff_DaG_diseases_sources'],\n", + " 'cutoff_DaG_textmining': DEFAULT_SPOKE_API_PARAMS['cutoff_DaG_textmining'],\n", + " 'cutoff_CtD_phase': DEFAULT_SPOKE_API_PARAMS['cutoff_CtD_phase'],\n", + " 'cutoff_PiP_confidence': DEFAULT_SPOKE_API_PARAMS['cutoff_PiP_confidence'],\n", + " 'cutoff_ACTeG_level': DEFAULT_SPOKE_API_PARAMS['cutoff_ACTeG_level'],\n", + " 'cutoff_DpL_average_prevalence': DEFAULT_SPOKE_API_PARAMS['cutoff_DpL_average_prevalence'],\n", + " 'depth' : search_depth\n", + " }\n", + " attribute = \"name\"\n", + " nbr_end_point = \"/api/v1/neighborhood/{}/{}/{}\".format(node_type, attribute, node_value)\n", + " result = get_spoke_api_resp(SPOKE_API_URI, nbr_end_point, params=api_params)\n", + " node_context = result.json()\n", + " if len(node_context) == 0: \n", + " return None, None\n", + " nbr_nodes = []\n", + " nbr_edges = []\n", + " for item in node_context:\n", + " if \"_\" not in item[\"data\"][\"neo4j_type\"]:\n", + " try:\n", + " if item[\"data\"][\"neo4j_type\"] == \"Protein\":\n", + " nbr_nodes.append((item[\"data\"][\"neo4j_type\"], item[\"data\"][\"id\"], item[\"data\"][\"properties\"][\"description\"]))\n", + " else:\n", + " nbr_nodes.append((item[\"data\"][\"neo4j_type\"], item[\"data\"][\"id\"], item[\"data\"][\"properties\"][\"name\"]))\n", + " except:\n", + " nbr_nodes.append((item[\"data\"][\"neo4j_type\"], item[\"data\"][\"id\"], item[\"data\"][\"properties\"][\"identifier\"]))\n", + " elif \"_\" in item[\"data\"][\"neo4j_type\"]:\n", + " try:\n", + " provenance = \", \".join(item[\"data\"][\"properties\"][\"sources\"])\n", + " except:\n", + " try:\n", + " provenance = item[\"data\"][\"properties\"][\"source\"]\n", + " if isinstance(provenance, list):\n", + " provenance = \", \".join(provenance) \n", + " except:\n", + " try: \n", + " preprint_list = ast.literal_eval(item[\"data\"][\"properties\"][\"preprint_list\"])\n", + " if len(preprint_list) > 0: \n", + " provenance = \", \".join(preprint_list)\n", + " else:\n", + " pmid_list = ast.literal_eval(item[\"data\"][\"properties\"][\"pmid_list\"])\n", + " pmid_list = map(lambda x:\"pubmedId:\"+x, pmid_list)\n", + " if len(pmid_list) > 0:\n", + " provenance = \", \".join(pmid_list)\n", + " else:\n", + " provenance = \"Based on data from Institute For Systems Biology (ISB)\"\n", + " except: \n", + " provenance = \"SPOKE-KG\" \n", + " try:\n", + " evidence = item[\"data\"][\"properties\"]\n", + " except:\n", + " evidence = None\n", + " nbr_edges.append((item[\"data\"][\"source\"], item[\"data\"][\"neo4j_type\"], item[\"data\"][\"target\"], provenance, evidence))\n", + " nbr_nodes_df = pd.DataFrame(nbr_nodes, columns=[\"node_type\", \"node_id\", \"node_name\"])\n", + " nbr_edges_df = pd.DataFrame(nbr_edges, columns=[\"source\", \"edge_type\", \"target\", \"provenance\", \"evidence\"])\n", + " merge_1 = pd.merge(nbr_edges_df, nbr_nodes_df, left_on=\"source\", right_on=\"node_id\").drop(\"node_id\", axis=1)\n", + " merge_1.loc[:,\"node_name\"] = merge_1.node_type + \" \" + merge_1.node_name\n", + " merge_1.drop([\"source\", \"node_type\"], axis=1, inplace=True)\n", + " merge_1 = merge_1.rename(columns={\"node_name\":\"source\"})\n", + " merge_2 = pd.merge(merge_1, nbr_nodes_df, left_on=\"target\", right_on=\"node_id\").drop(\"node_id\", axis=1)\n", + " merge_2.loc[:,\"node_name\"] = merge_2.node_type + \" \" + merge_2.node_name\n", + " merge_2.drop([\"target\", \"node_type\"], axis=1, inplace=True)\n", + " merge_2 = merge_2.rename(columns={\"node_name\":\"target\"})\n", + " merge_2 = merge_2[[\"source\", \"edge_type\", \"target\", \"provenance\", \"evidence\"]]\n", + " merge_2.loc[:, \"predicate\"] = merge_2.edge_type.apply(lambda x:x.split(\"_\")[0])\n", + " merge_2.loc[:, \"context\"] = merge_2.source + \" \" + merge_2.predicate.str.lower() + \" \" + merge_2.target + \" and Provenance of this association is \" + merge_2.provenance + \". \"\n", + " context = merge_2.context.str.cat(sep=' ')\n", + " # context += node_value + \" has a \" + node_context[0][\"data\"][\"properties\"][\"source\"] + \" identifier of \" + node_context[0][\"data\"][\"properties\"][\"identifier\"] + \" and Provenance of this is from \" + node_context[0][\"data\"][\"properties\"][\"source\"] + \". \"\n", + " return context, merge_2\n", + "\n", + "\n", + "def get_pruned_context(query, entities, embed_model, search_depth, edge_evidence, context_sim_threshold, context_sim_min_threshold, context_volume):\n", + " if entities:\n", + " nodes = []\n", + " node_types = []\n", + " for entity in entities:\n", + " node_name_list, node_type_list = retrieve_node(entity, openai_embed_model, k=2)\n", + " nodes.extend(node_name_list)\n", + " node_types.extend(node_type_list)\n", + " max_number_of_high_similarity_context_per_node = int(context_volume/len(nodes))\n", + " # query_embedding = openai_embedding(embed_model, query)\n", + " query_embedding = embed_model.embed_query(query)\n", + " node_context_extracted = ''\n", + " for node_idx, node in enumerate(nodes):\n", + " node_context, context_table = get_context_using_spoke_api(\n", + " node_value=node,\n", + " node_type = node_types[node_idx],\n", + " search_depth=search_depth\n", + " ) \n", + " if not node_context:\n", + " node_context_extracted += f'No context related to {node} available in SPOKE'\n", + " continue\n", + " context_table.loc[:, 'context'] = context_table.context.apply(lambda x:x.strip())\n", + " node_context_list = node_context.split(\". \")\n", + " node_context_list = list(map(lambda x:x.strip(), node_context_list))\n", + " if len(node_context_list) < 4500000000000:\n", + " node_context_list = ['empty string' if item == '' else item for item in node_context_list]\n", + " # node_context_embeddings = [openai_embedding(embed_model, node_context) for node_context in node_context_list] \n", + " node_context_embeddings = embed_model.embed_documents(node_context_list)\n", + " similarities = [cosine_similarity(np.array(query_embedding).reshape(1, -1), np.array(node_context_embedding).reshape(1, -1)) for node_context_embedding in node_context_embeddings]\n", + " similarities = sorted([(e, i) for i, e in enumerate(similarities)], reverse=True)\n", + " percentile_threshold = np.percentile([s[0] for s in similarities], context_sim_threshold)\n", + " high_similarity_indices = [s[1] for s in similarities if s[0] > percentile_threshold and s[0] > context_sim_min_threshold]\n", + " if len(high_similarity_indices) > max_number_of_high_similarity_context_per_node:\n", + " high_similarity_indices = high_similarity_indices[:max_number_of_high_similarity_context_per_node]\n", + " high_similarity_context = [node_context_list[index].strip() + '.' for index in high_similarity_indices]\n", + " if edge_evidence: \n", + " # if len(high_similarity_context) > 1:\n", + " # high_similarity_context = list(map(lambda x:x+'.', high_similarity_context))\n", + " context_table = context_table[context_table.context.isin(high_similarity_context)]\n", + " context_table.loc[:, \"context\"] = context_table.source + \" \" + context_table.predicate.str.lower() + \" \" + context_table.target + \" and Provenance of this association is \" + context_table.provenance + \" and attributes associated with this association is in the following JSON format:\\n \" + context_table.evidence.astype('str') + \"\\n\\n\" \n", + " node_context_extracted += context_table.context.str.cat(sep=' ') \n", + " else:\n", + " node_context_extracted += \". \".join(high_similarity_context)\n", + " node_context_extracted += \". \"\n", + " else:\n", + " if edge_evidence:\n", + " context_table.loc[:, \"context\"] = context_table.source + \" \" + context_table.predicate.str.lower() + \" \" + context_table.target + \" and Provenance of this association is \" + context_table.provenance + \" and attributes associated with this association is in the following JSON format:\\n \" + context_table.evidence.astype('str') + \"\\n\\n\" \n", + " node_context_extracted += context_table.context.str.cat(sep=' ')\n", + " else:\n", + " node_context_extracted += \". \".join(node_context_list) \n", + " return node_context_extracted\n", + " else:\n", + " return 'No biomedical entities detected in the given query.'\n", + "\n", + "def stream_out(output):\n", + " CHUNK_SIZE = int(round(len(output)/50))\n", + " SLEEP_TIME = 0.1\n", + " for i in range(0, len(output), CHUNK_SIZE):\n", + " print(output[i:i+CHUNK_SIZE], end='')\n", + " sys.stdout.flush()\n", + " time.sleep(SLEEP_TIME)\n", + " print(\"\\n\")\n", + "\n", + "def run(query):\n", + " entity = biomedical_entity_extractor(query, CHAT_MODEL)\n", + " kg_cntxt = get_pruned_context(\n", + " query, \n", + " entity,\n", + " bert_embed_model,\n", + " 1,\n", + " True,\n", + " KG_RAG_PARAMS['QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD'],\n", + " KG_RAG_PARAMS['QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY'],\n", + " KG_RAG_PARAMS['CONTEXT_VOLUME']\n", + " )\n", + " enriched_prompt = 'Context: '+ kg_cntxt + '\\n' + 'Question: ' + query \n", + " llm_response = get_GPT_response(\n", + " enriched_prompt, \n", + " KG_RAG_BASED_TEXT_GENERATION_SYSTEM_PROMPT, \n", + " 'gpt-35-turbo-16k', \n", + " temperature=0.1\n", + " )\n", + " stream_out(llm_response)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "0b997ed9-9676-4a27-89ac-4425ec5bfc34", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/anaconda3/envs/kg_rag_interative/lib/python3.10/site-packages/huggingface_hub/file_download.py:1132: FutureWarning: `resume_download` is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use `force_download=True`.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "api_key = os.environ.get('API_KEY')\n", + "azure_endpoint = os.environ.get('RESOURCE_ENDPOINT')\n", + "api_version = os.environ.get('API_VERSION')\n", + "\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.pinecone_config.env'))\n", + "pinecone_api_key = os.environ.get('PINECONE_API_KEY')\n", + "\n", + "\n", + "if os.environ.get('RESOURCE_ENDPOINT'):\n", + " from openai import AzureOpenAI \n", + " client = AzureOpenAI(\n", + " api_key = os.environ.get('API_KEY'), \n", + " api_version = os.environ.get('API_VERSION'),\n", + " azure_endpoint = os.environ.get('RESOURCE_ENDPOINT')\n", + " )\n", + "else:\n", + " from openai import OpenAI\n", + " client = OpenAI(api_key = os.environ.get('API_KEY'))\n", + "\n", + "openai_embed_model = AzureOpenAIEmbedding(\n", + " model=EMBEDDING_MODEL,\n", + " deployment_name=EMBEDDING_MODEL,\n", + " api_key=api_key,\n", + " azure_endpoint=azure_endpoint,\n", + " api_version=api_version,\n", + ")\n", + "\n", + "bert_embed_model = load_sentence_transformer(SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL)\n", + "\n", + "Settings.embed_model = openai_embed_model\n", + "\n", + "pc = Pinecone(api_key=pinecone_api_key)\n", + "\n", + "pinecone_index = pc.Index(INDEX_NAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "4e992a07-ef14-4737-9d41-943df6b44276", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The PAH gene encodes the protein Phenylalanine-4-hydroxylase (PAH). [Provenance: UniProt]\n", + "\n" + ] + } + ], + "source": [ + "\n", + "query = \"What protein does PAH gene encode?\"\n", + "run(query)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "d0686abc-f99e-478d-8532-e09f2fc1d759", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Phenylalanine-4-hydroxylase (PAH) catalyzes the following reactions:\n", + "1. Reaction: L-phenylalanine + tetrahydrobiopterin + oxygen <=> dihydrobiopterin + L-tyrosine + H2O\n", + " Provenance: KEGG database - https://www.genome.jp/kegg/\n", + "\n", + "2. Reaction: L-phenylalanine + tetrahydrobiopterin + oxygen <=> L-tyrosine + 4a-hydroxytetrahydrobiopterin\n", + " Provenance: KEGG database - https://www.genome.jp/kegg/\n", + "\n", + "3. Reaction: L-phenylalanine + tetrahydropteridine + oxygen <=> L-tyrosine + 4a-hydroxy-5,6,7,8-tetrahydropteridine\n", + " Provenance: KEGG database - https://www.genome.jp/kegg/\n", + "\n" + ] + } + ], + "source": [ + "\n", + "query = \"What reactions do phenylalanine-4-hydroxylase catalyse?\"\n", + "run(query)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ed98da54-55dc-4e72-a2f8-d75a59884b41", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Yes, Balaglitazone downregulates several genes. The genes that are downregulated by Balaglitazone include ADI1, ACOT9, IFRD2, CCNB1, H2BC12, RPS5, DHRS7, UGDH, KDELR2, WASHC4, LYPLA1, PRPF4, GOLT1B, HSPB1, AKR7A2, BAG3, GNAS, SOX4, DUSP6, CDC25B, FAT1, PRSS23, GRN, CANT1, HOXA10, IER3, PXN, CTNND1, BNIP3, HDAC6, KDM3A, SPDEF, ARID5B, ST6GALNAC2, DUSP4, TRAPPC6A, EPB41L2, IQGAP1, ASAH1, PHGDH, RGS2, FOXO4, TIMELESS, TCEA2, CD44, CDH3, DNAJA3, CDKN1B, PIK3R3, C2CD5, GLRX, HAT1, PTPRK, H2BC5, AKR7A2, ITFG1, KIFBP, S100A6, TRIM2, SLC2A6, ALDOC, ST3GAL5, NUCB2, PPARG, PTK2, H2BC12, APPBP2, ETV1, ERBB2, BNIP3L, TUBA1A, TGFB3, HMG20B, ALDH7A1, ACAT2, NIPAL3, ZNF33B, STMN1, DYNLT3, DNMT3A, EGF, CAST. [Provenance: CMAP/LINCS compound (trt_cp)]\n", + "\n" + ] + } + ], + "source": [ + "\n", + "query = \"Does Balaglitazone downregulate any genes?\"\n", + "run(query)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e51596f6-b24b-4e2a-84a1-db2210854349", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/kg_rag_token_usage_tracking.ipynb b/notebooks/kg_rag_token_usage_tracking.ipynb new file mode 100644 index 0000000..1840b99 --- /dev/null +++ b/notebooks/kg_rag_token_usage_tracking.ipynb @@ -0,0 +1,288 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "b86c2320-71ed-4223-9df7-0b9281cb652c", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "os.chdir('..')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8e9dc80f-43a6-4d8d-9d99-343bc6515ff8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/root/anaconda3/envs/kg_rag_test_2/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "from kg_rag.utility import *\n", + "from tqdm import tqdm\n" + ] + }, + { + "cell_type": "markdown", + "id": "3b991006-9e91-4db1-9c11-62cbf1d9c356", + "metadata": {}, + "source": [ + "## Choose the LLM" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5ae38918-24e1-4a28-b4e5-461eda38002c", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4-32k'\n" + ] + }, + { + "cell_type": "markdown", + "id": "db3c5056-15d6-4608-87c8-1e897dc4075e", + "metadata": {}, + "source": [ + "## Configure KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "fdf4d8fd-2265-4237-ba85-06a3efbf8145", + "metadata": {}, + "outputs": [], + "source": [ + "SYSTEM_PROMPT = system_prompts[\"KG_RAG_BASED_TEXT_GENERATION\"]\n", + "CONTEXT_VOLUME = int(config_data[\"CONTEXT_VOLUME\"])\n", + "QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD = float(config_data[\"QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD\"])\n", + "QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY = float(config_data[\"QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY\"])\n", + "VECTOR_DB_PATH = config_data[\"VECTOR_DB_PATH\"]\n", + "NODE_CONTEXT_PATH = config_data[\"NODE_CONTEXT_PATH\"]\n", + "SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL = config_data[\"SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL\"]\n", + "SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL = config_data[\"SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL\"]\n", + "TEMPERATURE = config_data[\"LLM_TEMPERATURE\"]\n", + "\n", + "CHAT_MODEL_ID = LLM_MODEL\n", + "EDGE_EVIDENCE = True\n", + "\n", + "CHAT_DEPLOYMENT_ID = CHAT_MODEL_ID\n", + "\n", + "\n", + "vectorstore = load_chroma(VECTOR_DB_PATH, SENTENCE_EMBEDDING_MODEL_FOR_NODE_RETRIEVAL)\n", + "embedding_function_for_context_retrieval = load_sentence_transformer(SENTENCE_EMBEDDING_MODEL_FOR_CONTEXT_RETRIEVAL)\n", + "node_context_df = pd.read_csv(NODE_CONTEXT_PATH)\n" + ] + }, + { + "cell_type": "markdown", + "id": "547cf664-8b48-4f19-a232-09a5b2fa4ffa", + "metadata": {}, + "source": [ + "## Load test data" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "00fa2491-901e-44ea-8109-2a60b23771ba", + "metadata": {}, + "outputs": [], + "source": [ + "data = pd.read_csv('data/rag_comparison_data.csv')\n" + ] + }, + { + "cell_type": "markdown", + "id": "39c207c9-49be-449b-9b70-a92cdf8095d3", + "metadata": {}, + "source": [ + "## Function for chat completion with token usage tracking" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8ca41e38-79fb-4f68-aa16-db1785b6551f", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def chat_completion_with_token_usage(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature):\n", + " response = openai.ChatCompletion.create(\n", + " temperature=temperature,\n", + " deployment_id=chat_deployment_id,\n", + " model=chat_model_id,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": instruction}\n", + " ]\n", + " )\n", + " return response['choices'][0]['message']['content'], response.usage.total_tokens\n" + ] + }, + { + "cell_type": "markdown", + "id": "4b2bbab7-72f6-414b-bdd0-0eab4ed842f2", + "metadata": {}, + "source": [ + "## Run on test data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "637671b2-a06c-4fe4-a7a6-855b0ba48fcd", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [11:13, 6.74s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3min 37s, sys: 9.86 s, total: 3min 47s\n", + "Wall time: 11min 13s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "kg_rag_answer = []\n", + "total_tokens_used = []\n", + "\n", + "for index, row in tqdm(data.iterrows()):\n", + " question = row['question']\n", + " context = retrieve_context(question, vectorstore, embedding_function_for_context_retrieval, node_context_df, CONTEXT_VOLUME, QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD, QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY, EDGE_EVIDENCE)\n", + " enriched_prompt = \"Context: \"+ context + \"\\n\" + \"Question: \" + question\n", + " output, token_usage = chat_completion_with_token_usage(enriched_prompt, SYSTEM_PROMPT, CHAT_MODEL_ID, CHAT_DEPLOYMENT_ID, temperature=TEMPERATURE)\n", + " kg_rag_answer.append(output)\n", + " total_tokens_used.append(token_usage)\n", + " \n", + "data.loc[:,'kg_rag_answer'] = kg_rag_answer\n", + "data.loc[:, 'total_tokens_used'] = total_tokens_used\n" + ] + }, + { + "cell_type": "markdown", + "id": "18e4b72c-c2a5-4b1a-8100-7ad831eb1401", + "metadata": {}, + "source": [ + "## Run on perturbed test data" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "8a042aa2-2366-4d49-a694-efd6d7b4616b", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [09:49, 5.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3min 36s, sys: 9.04 s, total: 3min 45s\n", + "Wall time: 9min 49s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "kg_rag_answer = []\n", + "total_tokens_used = []\n", + "\n", + "for index, row in tqdm(data.iterrows()):\n", + " question = row['question']\n", + " context = retrieve_context(question, vectorstore, embedding_function_for_context_retrieval, node_context_df, CONTEXT_VOLUME, QUESTION_VS_CONTEXT_SIMILARITY_PERCENTILE_THRESHOLD, QUESTION_VS_CONTEXT_MINIMUM_SIMILARITY, EDGE_EVIDENCE)\n", + " enriched_prompt = \"Context: \"+ context + \"\\n\" + \"Question: \" + question\n", + " output, token_usage = chat_completion_with_token_usage(enriched_prompt, SYSTEM_PROMPT, CHAT_MODEL_ID, CHAT_DEPLOYMENT_ID, temperature=TEMPERATURE)\n", + " kg_rag_answer.append(output)\n", + " total_tokens_used.append(token_usage)\n", + " \n", + "data.loc[:,'kg_rag_answer_perturbed'] = kg_rag_answer\n", + "data.loc[:, 'total_tokens_used_perturbed'] = total_tokens_used\n" + ] + }, + { + "cell_type": "markdown", + "id": "9c902260-1d9e-4a52-a377-f0c002c91e16", + "metadata": {}, + "source": [ + "## Save the result" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d510de56-dd39-4742-8a5a-9bb934690d95", + "metadata": {}, + "outputs": [], + "source": [ + "save_path = 'data/results'\n", + "os.makedirs(save_path, exist_ok=True)\n", + "data.to_csv(os.path.join(save_path, 'kg_rag_output.csv'), index=False)\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/mcq_analysis.ipynb b/notebooks/mcq_analysis.ipynb new file mode 100644 index 0000000..d56e574 --- /dev/null +++ b/notebooks/mcq_analysis.ipynb @@ -0,0 +1,394 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "9da3418d", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "from tqdm import tqdm\n", + "import re\n", + "from scipy import stats\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from IPython.display import clear_output\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "97f75a9b", + "metadata": {}, + "outputs": [], + "source": [ + "def extract_answer(text):\n", + " try:\n", + " text_processed = text.split('\"answer\":')[-1].split('\\n')[0].strip().split('\"')[1].strip()\n", + " except:\n", + " text_processed = text.split('\"answer\":')[-1].split('\\n')[0].strip()\n", + " return text_processed\n", + "\n", + "def correct_paranthesis_split(text):\n", + " try:\n", + " text_processed = text.split('\"answer\":')[-1].split(\"\\n\")[1].split(\":\")[-1].split('\"')[1].strip()\n", + " return text_processed\n", + " except:\n", + " return text\n", + " \n", + "def process_df(prompt_response_df, rag_response_df):\n", + " prompt_response_df.loc[:, 'extracted_answer'] = prompt_response_df['llm_answer'].apply(extract_answer)\n", + " rag_response_df.loc[:, 'extracted_answer'] = rag_response_df['llm_answer'].apply(extract_answer)\n", + "\n", + " prompt_response_df_paranthesis_split = prompt_response_df[prompt_response_df.extracted_answer==\"{\"]\n", + " if prompt_response_df_paranthesis_split.shape[0] > 0:\n", + " prompt_response_df_paranthesis_split.loc[:, \"extracted_answer\"] = prompt_response_df_paranthesis_split.llm_answer.apply(correct_paranthesis_split)\n", + " prompt_response_df_wo_paranthesis_split = prompt_response_df[prompt_response_df.extracted_answer != \"{\"]\n", + " prompt_response_df = pd.concat([prompt_response_df_wo_paranthesis_split, prompt_response_df_paranthesis_split])\n", + "\n", + " rag_response_df_paranthesis_split = rag_response_df[rag_response_df.extracted_answer==\"{\"]\n", + " if rag_response_df_paranthesis_split.shape[0] > 0:\n", + " rag_response_df_paranthesis_split.loc[:, \"extracted_answer\"] = rag_response_df_paranthesis_split.llm_answer.apply(correct_paranthesis_split)\n", + " rag_response_df_wo_paranthesis_split = rag_response_df[rag_response_df.extracted_answer != \"{\"]\n", + " rag_response_df = pd.concat([rag_response_df_wo_paranthesis_split, rag_response_df_paranthesis_split])\n", + " return prompt_response_df, rag_response_df\n", + "\n", + "def evaluate(df):\n", + " correct = df[df.correct_answer == df.extracted_answer]\n", + " incorrect = df[df.correct_answer != df.extracted_answer]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "\n", + "def bootstrap(prompt_response_df, rag_response_df, niter=1000, nsample=150):\n", + " prompt_correct_frac_list = []\n", + " rag_correct_frac_list = []\n", + " for i in tqdm(range(niter)):\n", + " prompt_response_df_sample = prompt_response_df.sample(n=nsample, random_state=i)\n", + " prompt_correct_frac, prompt_incorrect_frac = evaluate(prompt_response_df_sample)\n", + " rag_response_df_sample = rag_response_df.iloc[prompt_response_df_sample.index]\n", + " rag_correct_frac, rag_incorrect_frac = evaluate(rag_response_df_sample)\n", + " prompt_correct_frac_list.append(prompt_correct_frac)\n", + " rag_correct_frac_list.append(rag_correct_frac)\n", + " return prompt_correct_frac_list, rag_correct_frac_list\n", + "\n", + "def plot_figure(prompt_correct_frac_list, rag_correct_frac_list):\n", + " fig = plt.figure(figsize=(5, 3))\n", + " ax = plt.gca()\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "\n", + " for artist in ax.lines:\n", + " artist.set_edgecolor(\"black\")\n", + " plt.xlabel(\"Accuracy\")\n", + " plt.ylabel(\"Density\")\n", + " plt.legend(bbox_to_anchor=(0.55, 0.9))\n", + " plt.xlim(0.1,0.9)\n", + " ax.axvline(np.mean(prompt_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " ax.axvline(np.mean(rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " sns.despine(top=True, right=True)\n", + " plt.show()\n", + " return fig\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "60388260", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "Following files can be obtained by running the run_mcq_qa.py script.\n", + "Make sure to change the parent path and filenames based on where and how you save the files\n", + "'''\n", + "\n", + "data_path ='../data/results'\n", + "\n", + "llama_prompt_path = os.path.join(data_path, 'Llama_2_13b_chat_hf_prompt_based_mcq_from_monarch_and_robokop_response.csv')\n", + "llama_kg_rag_path = os.path.join(data_path, 'Llama_2_13b_chat_hf_PubMedBert_entity_recognition_based_node_retrieval_rag_based_mcq_from_monarch_and_robokop_response.csv')\n", + "\n", + "gpt_35_prompt_path = os.path.join(data_path, 'gpt_35_turbo_prompt_based_mcq_from_monarch_and_robokop_response.csv')\n", + "gpt_35_kg_rag_path = os.path.join(data_path, 'gpt_35_turbo_PubMedBert_entity_recognition_based_node_retrieval_rag_based_mcq_from_monarch_and_robokop_response.csv')\n", + "\n", + "gpt_4_prompt_path = os.path.join(data_path, 'gpt_4_prompt_based_mcq_from_monarch_and_robokop_response.csv')\n", + "gpt_4_kg_rag_path = os.path.join(data_path, 'gpt_4_PubMedBert_entity_recognition_based_node_retrieval_rag_based_mcq_from_monarch_and_robokop_response.csv')\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "95cd1d6e", + "metadata": {}, + "outputs": [], + "source": [ + "llama_prompt_df = pd.read_csv(llama_prompt_path)\n", + "llama_kg_rag_df = pd.read_csv(llama_kg_rag_path)\n", + "\n", + "gpt_35_prompt_df = pd.read_csv(gpt_35_prompt_path)\n", + "gpt_35_kg_rag_df = pd.read_csv(gpt_35_kg_rag_path)\n", + "\n", + "gpt_4_prompt_df = pd.read_csv(gpt_4_prompt_path)\n", + "gpt_4_kg_rag_df = pd.read_csv(gpt_4_kg_rag_path)\n", + "\n", + "\n", + "llama_prompt_df, llama_kg_rag_df = process_df(llama_prompt_df, llama_kg_rag_df)\n", + "gpt_35_prompt_df, gpt_35_kg_rag_df = process_df(gpt_35_prompt_df, gpt_35_kg_rag_df)\n", + "gpt_4_prompt_df, gpt_4_kg_rag_df = process_df(gpt_4_prompt_df, gpt_4_kg_rag_df)\n", + "\n", + "clear_output()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0caf126f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1539.94it/s]\n", + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1526.29it/s]\n", + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1545.39it/s]\n" + ] + } + ], + "source": [ + "llama_prompt_correct_frac_list, llama_rag_correct_frac_list = bootstrap(llama_prompt_df, llama_kg_rag_df)\n", + "\n", + "gpt_35_prompt_correct_frac_list, gpt_35_rag_correct_frac_list = bootstrap(gpt_35_prompt_df, gpt_35_kg_rag_df)\n", + "\n", + "gpt_4_prompt_correct_frac_list, gpt_4_rag_correct_frac_list = bootstrap(gpt_4_prompt_df, gpt_4_kg_rag_df)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b3ff7f46", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:55: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:56: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdEAAAEmCAYAAAA9VKo6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAABXx0lEQVR4nO3deVxU9foH8M8ZBoZhFVRERBBDccnQNJe01DTNtFzyZrmklt0sy8ys9Lrbz7xamldL0xK0cqtc8laaZkqWN3fU1FBxAREFWQVkYGa+vz8Oc+YM68xwZs6Z4Xm/XvPyMMs5z4DwzHd7vhxjjIEQQgghNlPJHQAhhBDiqiiJEkIIIXaiJEoIIYTYiZIoIYQQYidKooQQQoidKIkSQgghdqIkSgghhNiJkighhBBiJ7dPoowx5Ofng2pKEEIIkZpa7gAc7e7duwgMDEReXh4CAgLkDqfOW7ZsGfLz8xEQEICpU6fKHQ6pAv2cCLEO5+5l//Lz8ymJKkh4eDjS0tLQpEkT3LhxQ+5wSBXo50SIddy+O5cQQghxFEqihBBCiJ0oiRJCCCF2oiRKCCGE2ImSKCGEEGInSqKEEEKInSiJEkIIIXaSNYn+9ttveOqppxAWFgaO47Bz584qn/vKK6+A4zgsX77cafERxzEYAJ1O7igIIaR2ZE2ihYWFiI2NxSeffFLt83bu3IkjR44gLCzMSZERR+nceSD8/Yfj1q2BaNwYqOZzE5GJITMT/WJiMKRzZwzo1UvucAhRNFnL/g0YMAADBgyo9jlpaWl4/fXX8fPPP2PgwIFOiow4wrlzwK+/rsHdu/zXOTnAiBHAqVNAmzbyxkZ4xqIiFG7YgI8ffZS/w9MThsxMeDRsKG9ghCiUosdEjUYjxowZg3feeQdt27aVOxxSCzod8OyzQF6e5f0lJcD778sTE6lI99tvYIWF5jtKS1F84IB8ARGicIpOoosXL4ZarcbkyZOtfo1Op0N+fr7Fjchv2TLg/Hn+ODgYGDMG8Pbmv962jW+VEnmx0lKUJCZWuF//998wFhQ4PyBCXIBik+iJEyfwn//8B+vXrwfHcVa/btGiRQgMDBRuTZs2dWCUxBq5ucDixfwxxwG9ewNaLdCiBX9faSnw/feyhUfK6K9cEWZ7qYKDoQoN5R9gDKWmT0CEEAuKTaKHDh1CRkYGIiIioFaroVarcf36dbz99tto1qxZla+bMWMG8vLyhFtqaqrzgiaVio83d+N6eXXCnj3h2L69E6KizM/Zu1ee2IhZaVKScNzz44/R6l//Qq81awAA+suX5QqLEEVT7H6iY8aMQd++fS3u69+/P8aMGYPx48dX+TqNRgONRuPo8IiVGAPWrjV/rVLdQmFhGgAgJARQqwG9HkhI4J9rQ6cDkZj+6lX+gONwOz8fN7OzgbLtA/XXr4MZDOA8PGSMkBDlkTWJFhQU4LLoE+7Vq1eRmJiI4OBgREREoH79+hbP9/T0RGhoKGJiYpwdKrHTuXPA33/zx6GhEGbmAoBKxd934wZw8yZw9SrQvLk8cdZ1xrw8sNxcAADn62t+wPSppqQEhtu3oaZlZoRYkLU79/jx4+jQoQM6dOgAAJg6dSo6dOiAOXPmyBkWkZB4rLOyBNmokfn4xAnHx0Mqp09JEY45Pz/zAyrznwgDbc5NSAWytkR79eoFxpjVz7927ZrjgiEO8euv5uOICOD0acvHGzQwH584AfzjH86Ji1gypKUJx6rKWqLlnkMI4Sl2YhFxfTod8Mcf/LGfnzC8ZkGcRE+edE5cpCLDzZvCcaXduQAMt245MyRCXAIlUeIwp0+b6+M2blz5c3x8ANM8MFpFIQ/GmDlBenmBU1t2UHFlC3qNd+6A6fXODo8QRaMkShzm+HHzcVVV4zgOCArij9PSKlY0Io5nzMnhF+sC4LTaCo9zPj5lTzTCmJnpzNAIUTxKosRhxBOFqiu9akqiAHDhguPiIZUzirppK02iptJS4IvTE0LMKIkShzl71nwcHFz18+rVMx9TEnU+cWJU1ZBEqSVKiCXFFlsgro0xc0L09wc8PfnjLl2WQK8vglrtIzw3MND8ukuXnBgkAWCZGE0Jc+G4cSjS6eCj0Vi0Tg137jg9PkKUjJIocYgbNwBTzXJxd2109MgKz6UkKi+LLtqyJDqiZ0/hLmYqJcUYjJRECbFA3bnEIUxVigDL7trK+PubV1JQiVbnYkYjjFlZ/Bfe3pVu9sBxHLiyKdTGnBwwo9GZIRKiaJREiUOIk6G4pVkZlYpPpADfErWh/gapJZaXBxgMACAkykqZHjMYwGh7QUIE1J1LHCI52XwsLrKQm5sEo1EPlUqNevViLJ6Tnw8UFgJ37lQ/m5dIx2BqhcJyAtHFGzegNxqhVqnQMjwcnEYDJnqNqqbuBQAGgwGlZUtnCKkNLy8vqFTKbPNREiUOUVUS/fHHPigsTIOvbxOMGmWuxWpqiQJ8IXpKos5hFCdRUUv0ydmzcTMrC2H16+NyfLzlDN3sbOC++6o8J2MMt27dQm5ZQXtCakulUiEqKgpeXl5yh1IBJVHiEFeu8P+qVIC4ilxVxEn02jWgc2eHhEXKMWZnC8fiRFkeJ/rjZczJqfacpgQaEhICHx+fSsdZCbGW0WjEzZs3kZ6ejoiICMX9f6IkSiTHGN+aBPiaudb0wpRviRLnECdErppP+eJWqrGaFqbBYBASaPmtDAmxV8OGDXHz5k3o9Xp4mtbLKYQyO5mJS8vLM+8bKk6O1aEkKg+hJcpx5sW8lbGyJWoaA/Xx8anyOYTYytSNayibBKcklESJ5ERbU1rVlQvwLVaT1FRp4yGVY4wJrUpOo6m2m4zjOCGR1tSdKzyfEIko+f8TJVEiOXESFSfH6mi1gIdHxdcTx2F37wrLW1Dd8pYyQpeuTgdWXOzAyAhxHTQmSiRnTxLlOP65eXnA9ev8uKqCP3y6BfHYZnXjoeLnmJa5GHNz4REaavW1OnUCnL0daWio5U5CddXBgwfRu3dv5OTkoJ4VS5Oc5dq1a4iKisKpU6fQvn17ucOxGyVRIjlxd6y1SdT0XNN4al5ezZWOSO1YJFFrWqLicVEbk+itW/xWd0o2btw4bNiwAQCgVqvRtGlTDBs2DPPnz4evteMSTuQuScjVURIlkhP/sbTlb4/4uSkplEQdzdqZuYJySdQeHMdvxO5IRUX2V7164oknEB8fj9LSUhw6dAgTJkxAYWEhVq9eXeG5paWlipspSpyPxkSJ5OxNouJW640bVT+PSMMiEVrZnSu81s7d0318gFGjHHurTZLWaDQIDQ1F06ZNMXLkSIwaNQo7d+4EAMybNw/t27dHXFwcmjdvDo1GA8YYUlJSMHjwYPj5+SEgIADPPvssbt++LZxT/LqIiAj4+fnh1VdfhcFgwJIlSxAaGoqQkBAsXLjQIhaO47B69WoMGDAAWq0WUVFR+Pbbb4XHo6KiAAAdOnQAx3Ho1atXte/tjz/+QGxsLLy9vdGlSxecFe1VmJWVheeffx7h4eHw8fFBu3btsHnzZovXf/fdd2jXrh20Wi3q16+Pvn37orCwUHg8Pj4erVu3hre3N1q1aoVVq1ZZvP7o0aPo0KEDvL290alTJ5w6darmH4gLkDWJ/vbbb3jqqacQFhYGjuOE/6wA/ynvvffeQ7t27eDr64uwsDC88MILuHnzpnwBE6uYkqhaXXHVxNChxzByZCqGDj1W4XXihEszdB1PXAO3fEv00NKluBgXh0NLl1b6HGMdqZ+r1WotShdevnwZ33zzDbZt24bExEQAwJAhQ5CdnY2EhATs27cPycnJGDFihMV5kpOTsXv3buzZswebN29GXFwcBg4ciBs3biAhIQGLFy/GrFmz8Oeff1q8bvbs2XjmmWdw+vRpjB49Gs8//zwulO0xePToUQDAL7/8gvT0dGzfvr3a9/LOO+/go48+wrFjxxASEoKnn35aeG/FxcXo2LEjfvjhB/z111/45z//iTFjxuDIkSMAgPT0dDz//PN48cUXceHCBRw8eBDDhg3jd/gB8Pnnn2PmzJlYuHAhLly4gA8++ACzZ88WuscLCwsxaNAgxMTE4MSJE5g3bx6mTZtmz49EcWTtzi0sLERsbCzGjx+PZ555xuKxoqIinDx5ErNnz0ZsbCxycnIwZcoUPP300zhOswUUzfQ5x9e34uQgH5/GVb6OWqLOJbQmVSrz1OgyjSvbRV30iYjZ2RJ1JUePHsWmTZvQp08f4b6SkhJ89dVXaFhWl3Lfvn04c+YMrl69iqZNmwIAvvrqK7Rt2xbHjh3DQw89BICvuhMXFwd/f3+0adMGvXv3RlJSEn766SeoVCrExMRg8eLFOHjwILp27Spc7x//+AcmTJgAAHj//fexb98+rFy5EqtWrRJiqF+/PkKtGJ+eO3cuHn/8cQDAhg0bEB4ejh07duDZZ59FkyZNLJLaG2+8gT179uDbb79Fly5dkJ6eDr1ej2HDhiEyMhIA0K5dO+H577//PpYuXYphw4YB4FvJ58+fx5o1azB27Fhs3LgRBoMBcXFx8PHxQdu2bXHjxg28+uqrNv5UlEfWJDpgwAAMGDCg0scCAwOxb98+i/tWrlyJzp07IyUlBREREc4Ikdjo7l1zoQVbu9WoJeo8jDEhiXJeXlatw+NUKj6Rlpba3Z2rdD/88AP8/Pyg1+tRWlqKwYMHY+XKlcLjkZGRQvICgAsXLqBp06ZCAgWANm3aoF69erhw4YKQRJs1awZ/UUWRRo0awcPDw6KoeqNGjZCRkWERT7du3Sp8bWoB20p8ruDgYMTExAitWoPBgH//+9/YunUr0tLSoNPpoNPphAlVsbGx6NOnD9q1a4f+/fujX79+GD58OIKCgpCZmYnU1FS89NJLePnll4Vr6PV6BJZt4XThwgXExsZaFOEo/95clUtNLMrLywPHcYqapk0siXvbbZ3QSEnUeVhREaDX81/YUNSb8/QEKy0FKygAMxjAlWvBurrevXtj9erV8PT0RFhYWIWJQ+Vn6TLGKv0AUv7+8ufhOK7S+4xW7NUqZeEB07mWLl2Kjz/+GMuXLxeG0KZMmYKSkhIAgIeHB/bt24fDhw9j7969WLlyJWbOnIkjR44IifHzzz9Hly5dLM7vUfb/g7nx/oYuM7GouLgY06dPx8iRIxEg3hakHJ1Oh/z8fIsbcZ70dPNxZS3RCxfW4syZZbhwYW2Fx7y8+HFUQPnLIVyduDu2spm56/bswYqdO7Fuzx7LB0TPdcd9RX19fREdHY3IyEirZt62adMGKSkpSBV96jt//jzy8vLQunXrWsdTfoz0zz//RKtWrQDYXgpPfK6cnBxcvHhRONehQ4cwePBgjB49GrGxsWjevDkuXbpk8XqO49C9e3fMnz8fp06dgpeXF3bs2IFGjRqhSZMmuHLlCqKjoy1upslPbdq0wenTp3Hv3r0q35urcomWaGlpKZ577jkYjcYKM77KW7RoEebPn++kyEh5NSXRkycXCFuhtW79T4vHOI5vjebl8WOiVHDBccQTg7hKksWirVuFrdBeeuIJ83PFBRfy86EKCrLpukVFwMaNdoVs0zWcpW/fvnjggQcwatQoLF++HHq9Hq+99hp69uyJTp061fr83377LTp16oQePXpg48aNOHr0KNatWwcACAkJgVarxZ49exAeHg5vb2+h+7QyCxYsQP369dGoUSPMnDkTDRo0wJAhQwAA0dHR2LZtGw4fPoygoCAsW7YMt27dEj4IHDlyBPv370e/fv0QEhKCI0eOIDMzU3h83rx5mDx5MgICAjBgwADodDocP34cOTk5mDp1KkaOHImZM2fipZdewqxZs3Dt2jV89NFHtf7+KIHiW6KlpaV49tlncfXqVezbt6/aVigAzJgxA3l5ecItlfoFnaqmJFoTU29ZYSG/STdxDIvZtTZ251Z6Disxxv9sHXlzZs+haVVBUFAQHn30UfTt2xfNmzfH1q1bJTn//PnzsWXLFjzwwAPYsGEDNm7ciDZt2gDgC0KsWLECa9asQVhYGAYPHlztuf7973/jzTffRMeOHZGeno5du3YJrdnZs2fjwQcfRP/+/dGrVy+EhoYKCRYAAgIC8Ntvv+HJJ59Ey5YtMWvWLCxdulSY0zJhwgR88cUXWL9+Pdq1a4eePXti/fr1QkvUz88P//3vf3H+/Hl06NABM2fOxOLFiyX5HsmNYwrprOY4Djt27LD4wZkS6KVLl3DgwAGLAX1r5efnIzAwEHl5eTUmYFJ777wDmD5gDhoEhIVZPr5xY3ilm3KbHDgAmHqRzp0Dyv5eEIkV//ILdH/8AQBQR0dDVe53I3r8eItNuU0MOTkwlG2z4923LzTdu1uet7gYV69eRVRUFLxF+5NS2T/bVfY3sa6q6v+VEsjanVtQUIDLly8LX1+9ehWJiYkIDg5GWFgYhg8fjpMnT+KHH36AwWDArbLfwuDgYEXucE6ka4kC/LgoJVHHMJqmUMPKakWm59rZEnXlZEZIdWRNosePH0fv3r2Fr6dOnQoAGDt2LObNm4ddu3YBQIW6kAcOHKixOgeRh5RJlNaKOo5FArShdF1dLLhASHVkTaK9evWqduqzQnqaiQ1MXXYeHjb9bRaIkygVp3IcYWatSmXbMhVxwQVRa5ZIj/7+uQbFTywirsWURH187JtZK2690jIXx2CMmbtzbfykw3GcsA6JWqKEUBIlEtLpgOxs/tjeIuDUEnUCnQ4oq5lqy3ioiWlclBUUgFlRHIAQd0ZJlEhGXLFMq7XvHFqtuQVLLVHHsJhUZE+fuynxMgYm2sWDkLrIJYotENdgzaSiwMCW8PIKhFbbqNLHVSo+kRYVURJ1FGsmFbUIC0Ogjw9CKimxyXl6WhZcENWEJaSuoSRKJCNeB1hVS3TQoF9rPI+vL59Eb9/my7uq6X+ppJgVLdHd5fa2FONochEhAurOJZIRJ9HabIxseq3RaNlFTKRhLCgQjmvVnQvLrmFC6iL6jE8kI1USLV9woXzVI1I7Fq1HO5KoPS3RgrVrLZK3M6j8/OD3z3/W/MQ6Zv369ZgyZQpyc3PlDsXCwYMH0bt3b+Tk5LjUTl3UEiWSkbolCtAMXUeodUtUXLXIyiRqLCgAu3vXqTdbk/a4ceMqlNj77rvv4O3tjSVLlgj35efnY/bs2Wjbti20Wi3q16+Phx56CEuWLEFOTk6112jWrBk4jgPHcdBqtWjVqhU+/PDDSteEHj58GB4eHnhCtAGAWElJCT788EM8+OCD8PX1RWBgIGJjYzFr1izcpF8cp6GWKJGMNWOiv/46CsXFd+Dt3QCPPVb5dh6URB3Lmpbo+KVLkZWfj/oBAYh/+22LxyxaovasFbUncduibPlObX3xxReYNGkSPv30U0yYMAEAkJ2djR49eiA/Px/vv/8+OnbsCC8vL1y+fBmbNm3Cpk2bMGnSpGrPu2DBArz88ssoLi7GL7/8gldffRUBAQF45ZVXLJ4XFxeHN954A1988QVSUlIQEREhPKbT6dCvXz+cOXMG8+fPR/fu3REYGIjk5GTs3LkTK1euxKJFiyT5PpDqURIlkrEmiaanJwgF6KtSvjuXSEtoPXp4gFNV3hl16K+/hAL0FXh48OuQGLO9i9bTE17t2tkYsW1Kzp6tdSJdsmQJ5syZg02bNuGZZ54R7v/Xv/6FlJQUJCUloUkT8//hVq1aYdCgQVZVGfL390doaCgAfveT1atXY+/evRZJtLCwEN988w2OHTuGW7duYf369ZgzZ47w+Mcff4zff/8dx48fR4cOHYT7o6Oj0b9/f6vi2LlzJ959912kpKTgkUceQVxcHJo2bQoASE5OxtSpU/Hnn3+isLAQrVu3xqJFi9C3b1/h9atWrcLHH3+M1NRUBAYG4pFHHsF3330HgC/o8eGHH+Kzzz5Deno6WrZsidmzZ2P48OHC63/66SdMmTIFqamp6Nq1K8aOHVtjzEpE3blEMqYkqtHwf2ftRVWLHIcxBlaW+OzqykVZ1SJTwQU3rFo0ffp0vP/++/jhhx8sEqjRaMTWrVsxevRoiwQqxtlQposxhoMHD+LChQsVNgDfunUrYmJiEBMTg9GjRyM+Pt4iMW7evBmPP/64RQK1JY6ioiIsXLgQGzZswB9//IH8/Hw899xzwuMFBQV48skn8csvv+DUqVPo378/nnrqKaSkpADg655PnjwZCxYsQFJSEvbs2YNHH31UeP2sWbMQHx+P1atX49y5c3jrrbcwevRoJCQkAABSU1MxbNgwPPnkk0hMTMSECRMwffp0q793SkJJlEiCMfM60dqMhwKWLVHx2lMiAZ2OXzcE1KpbVahaVFwMJlH3qRLs3r0bixcvxvfff2/R6gKAzMxM5ObmIiYmxuL+jh07ws/PD35+fnj++edrvMZ7770HPz8/aDQa9O7dG4wxTJ482eI569atw+jRowEATzzxBAoKCrB//37h8YsXL1aIY+jQoUIcDz/8cLUxlJaW4pNPPkG3bt3QsWNHbNiwAYcPH8bRo0cBALGxsXjllVfQrl07tGjRAv/3f/+H5s2bC5uCpKSkwNfXF4MGDUJkZCQ6dOggvIfCwkIsW7YMcXFx6N+/P5o3b45x48Zh9OjRWLNmDQBg9erVaN68OT7++GPExMRg1KhRGDduXI3fOyWiJEokkZcHFBfzx7VNohoNX3QBoJao1Go9qaiS1zInz7p1pAceeADNmjXDnDlzcLeKSVPlW3k7duxAYmIi+vfvj3v37gEAPvjgAyGh+fn5CS04AHjnnXeQmJiIhIQE9O7dGzNnzrRIeklJSTh69KjQMlSr1RgxYgTi4uKqjWPVqlVITEzEiy++iKKiomrfp1qtRqdOnYSvW7VqhXr16uHChQsA+ET47rvvok2bNqhXrx78/Pzw999/C+/j8ccfR2RkJJo3b44xY8Zg48aNwjXPnz+P4uJiPP744xbfgy+//BLJyckAgAsXLqBr164W76Fbt27VxqxUNCZKJFHbLdDEOI5vjd69SxOLpGaR8GpTxaLcWlFVUFAtolKOJk2aYNu2bejduzeeeOIJ7NmzB/5lFZkaNmyIevXq4e+//7Z4jWnCj7+/v7BsZOLEiXj22WeF54SJ1mk1aNAA0dHRiI6OxrZt2xAdHY2uXbsKLd9169ZBr9dbdBkzxuDp6YmcnBwEBQWhRYsWFeJo3LgxAH6/ZWtU1uVruu+dd97Bzz//jI8++gjR0dHQarUYPnw4SkpKhPd68uRJHDx4EHv37sWcOXMwb948HDt2DMayeso//vhjhW5vjUYjvB93QS1RIgkpk6j4HNnZ5hYuqb1a182t5LXutptLREQEEhISkJGRgX79+iG/7P2pVCo8++yz+Prrr5FWQxdJcHCwkCijo6OhruIDS1BQEN544w1MmzYNjDHo9Xp8+eWXWLp0KRITE4Xb6dOnERkZiY0b+Rntzz//PPbt24dTp07Z9R71ej2Oi3ZKT0pKQm5uLlq1agUAOHToEMaNG4ehQ4eiXbt2CA0NxbVr1yzOoVar0bdvXyxZsgRnzpzBtWvX8Ouvv6JNmzbQaDRISUmx+B5ER0cLE5fatGmDP//80+J85b92FdQSJZKQOomWHxeNiqr9OUm5lmhtlpqIkoJN3bmlpfzsWUeSYIw2PDxcWPzfr18//PzzzwgMDMQHH3yAgwcPokuXLliwYAE6deoEX19fnDlzBv/73/9w//3323ytSZMmYfHixdi2bRvUajVycnLw0ksvITAw0OJ5w4cPx7p16/D666/jrbfewo8//ojHHnsM8+bNwyOPPIKgoCBcvHgRu3fvhkcNM/s8PT3xxhtvYMWKFfD09MTrr7+Orl27onPnzgD4Wb7bt2/HU089BY7jMHv2bKGFCQA//PADrly5gkcffRRBQUH46aefYDQaERMTA39/f0ybNg1vvfUWjEajsCTo8OHD8PPzw9ixYzFx4kQsXboUU6dOxSuvvIITJ05g/fr1Nn/vlIBaokQS4iRq7w4uYjRD1zEkGxOtTem/0lLH3iTSpEkTJCQkIDc3F48//jhyc3NRv359HD16FC+88AI+/PBDdO7cGe3atcO8efMwYsQIfP755zZfp2HDhhgzZgzmzZuHdevWoW/fvhUSKAA888wzSExMxMmTJ+Ht7Y39+/dj+vTpiI+PR48ePdC6dWtMmTIF3bt3x86dO6u9po+PD9577z2MHDkS3bp1g1arxZYtW4THP/74YwQFBeHhhx/GU089hf79++PBBx8UHq9Xrx62b9+Oxx57DK1bt8Znn32GzZs3o23btgCA999/H3PmzMGiRYvQunVr9O/fH//9738RVfZpOCIiAtu2bcN///tfxMbG4rPPPsMHH3xg8/dOCTjmTp3TlcjPz0dgYCDy8vIQEBAgdzhu6+23gWXL+ONBg6ou1bdxY7iwTnTUqBtVni8xESibKIitWwHR8BKphaKdO1F6+jQAwLN1a3BVfOKJHj9eWCd6OT6+wuOsuBil58/z53ngAfgMHQoAKC4uxtWrVxEVFQVvb2/h+VT2j9RGVf+vlIC6c4kkxK1FcVdsea1avYySkjx4eVX8pC1Gm3M7hrV1c8f364f8oiIEVNU3b2PpP0pmxF1REiWSECe66sZEO3aca9X5qGqRYwitQY6rtiLGzJrWO6pU/M1opO3QSJ0m65job7/9hqeeegphYWHgOK5CPz5jDPPmzUNYWBi0Wi169eqFc+fOyRMsqZYpiXp5SVMalernOoYwCcjT06bqOuWJqxbRdmikLpM1iRYWFiI2NhaffPJJpY8vWbIEy5YtwyeffIJjx44hNDQUjz/+eJWLoIk8GDO3FqvryrUFtUSlx4xGsLIF8ZwEO50LE5N0OrCy9YOE1DWyducOGDAAAwYMqPQxxhiWL1+OmTNnYtiwYQCADRs2oFGjRti0aVOFHQ+IfHJzpatWZOLpyd9KS6klKhVWWGj+QoLuAs7TE6ZZicaCAniIFvm7+XxF4mRK/v+k2CUuV69exa1bt9CvXz/hPo1Gg549e+Lw4cMyRkbKE7cUa0qiGzeGY+1aDhs3htd4XlNrNC2Nb+2S2mE2LG+JHj8ePk8/jejx46t+UiWbc5sKqddUdo4QW5gqJdW0/lUOip1YdKtsS5BGjRpZ3N+oUSNcv369ytfpdDrodDrh63w3q6aiRDdEK1X8/KQ7r68v38otKuJr87rQZveKZDF2KWV3rujcHh4eqFevHjIyMgDw6xFrM/ZKiNFoRGZmJnx8fKqs/CQn5UVUTvlfQMZYtb+UixYtwvz58x0dFhFJTTUfSzUmClQsuEBJtHZsaYlapYrNuU17ZZoSKSG1pVKpEBERocgPZIpNoqZfxFu3bgmFlQH+F7N861RsxowZmDp1qvB1fn6+UK+ROIYjW6ImaWlAWTEUYiepqhVVdg6Lc3McGjdujJCQEJS60TZpRD5eXl5QVbGBvNwUm0SjoqIQGhqKffv2CRvPlpSUICEhAYsXL67ydRqNRtgpgDiHOIlK2RKlGbrSkqxubhmukjFRMQ8PD0WOYREiJVmTaEFBAS5fvix8ffXqVSQmJiI4OBgRERGYMmUKPvjgA7Ro0QItWrTABx98AB8fH4wcOVLGqEl5jurOpSQqLaNodq4US1xsrVpEiDuSNYkeP34cvXv3Fr42dcOOHTsW69evx7vvvot79+7htddeQ05ODrp06YK9e/cK+/sRZTDtN6xW8xtqS4WK0EvL2pJ/1uI8PPiqRwYDVS0idZasSbRXr17Vrv/hOA7z5s3DvHnznBcUsQlj5iTq58dXk5MKtUSlJXTneniAk2p8ydMTMBhgzM+vcdIfIe5ImSO1xGVkZQH37vHHUk4qAvgt1Ux/kymJ1p4w+UfCZQLCuKheD4iWlhFSV1ASJbUiXrIrdRJVqcxdujeq3jWNWIGVlAh7bUqyvKVMZWtFCalLFDs7l7gGW5No795fw2DQwcPDusFTX1+gsBDIyABKSvgC98R24gRnTRKNmzoVutJSaGp6rjiJ5ufDo2FDu2MkxBVREiW1cu2a+dia+V5hYb1sOr94XDQ9HYiMtOnlpIyty1sebdfOqvPWtMyFEHdH3bmkVq5eNR87YtK0OIlSl679bG2JWosTdQ1Qdy6piyiJklqxtSVqK5qhKw2pl7dUdi5GdapJHUTduaRWTC1RDw/rtkG7efOgMCZqTdcutUSlYWvJv9/OnhXGRKvr2qWJRaSuoyRK7MaYuSVq7RrRAwdGo7AwDb6+TTBqVM1ZkZKoNCyKz1uxxOXFZctwMysLYfXr43J8fNVPpJYoqeOoO5fYLSODnzkLAAEBjrkGdedKw+ig7lyO44TzGSmJkjqIkiix25Ur5mNHVWIUdxFTS9R+wpioSsX3vUvI1KXLCgvBDAZJz02I0tmVRK+Kp2SSOkucRB3VElWrAW9v/piSqP2Elqinp/Sl+UQzdGmZC6lr7Eqi0dHR6N27N77++msUFxdLHRNxEcnJ5mNHJVHA3KV78yZADR3bsdJSoSSflMtbTLhyBRcIqUvsSqKnT59Ghw4d8PbbbyM0NBSvvPIKjh49KnVsROGc0Z0LmJOoXs+PwxLbOGqNqHBO8VpRSqKkjrErid5///1YtmwZ0tLSEB8fj1u3bqFHjx5o27Ytli1bhszMTKnjJArkrJaouJygeO9SYh2HrRGt5JwsL0/68xOiYLWaWKRWqzF06FB88803WLx4MZKTkzFt2jSEh4fjhRdeQHp6ulRxEgUyJVGt1jF/m01ohm7tiFuH1BIlRFq1SqLHjx/Ha6+9hsaNG2PZsmWYNm0akpOT8euvvyItLQ2DBw+WKk6iMEVFfC1bwLGtUMAyiVJL1HaObolSEiV1mV3FFpYtW4b4+HgkJSXhySefxJdffoknn3wSqrKNfqOiorBmzRq0atVK0mCJcji6Zq4YFVyoHYuWqCO2waHuXFKH2ZVEV69ejRdffBHjx49HaGhopc+JiIjAunXrahUcUS57l7dYU6WoPEqitWPPxKJqqxSVw3Ecv8ylpARGSqKkjrErie7btw8RERFCy9OEMYbU1FRERETAy8sLY8eOlSRIojzOmlQEWE4soiRqO4tyfA4avOY8PcFKSsCKisBKSx0y9kqIEtk1Jnrffffhzp07Fe7Pzs5GVFRUrYMiyueMQgsmajWgKdvDm8ZEbSd056rV4FSOKVJG46KkrrLrN4oxVun9BQUF8DaVl5GAXq/HrFmzEBUVBa1Wi+bNm2PBggUwGo2SXYPYx5ktUcDcpZuWBtCP33rMaBQmFjm0dShOorm5jrsOIQpjU3fu1KlTAfBjIHPmzIGPqLCpwWDAkSNH0L59e8mCW7x4MT777DNs2LABbdu2xfHjxzF+/HgEBgbizTfflOw6xHamlqiHB7/ExVonTsxHSUkevLwC0bHjXKtf5+sLZGcDpaVAZibQqJGNAddRrKCA324HsEh0NVm4eTPyi4oQ4OODmc8/X+PzOVNXAQBGSZTUITYl0VOnTgHgW6Jnz56Fl+iX0svLC7GxsZg2bZpkwf3vf//D4MGDMXDgQABAs2bNsHnzZhw/flyyaxDbibdA8/e3bgs0k7///lzYCs3WJGpy4wYlUWvZOzM3fu9eYSs0q5IotURJHWVTEj1w4AAAYPz48fjPf/6DAAf34/Xo0QOfffYZLl68iJYtW+L06dP4/fffsXz5codel1Tv1i3AVDLZGV25QMXJRR07Oue6rk685MSR3bmUREldZdfs3Hgbpr/XxnvvvYe8vDy0atUKHh4eMBgMWLhwIZ6v5pOxTqeDrqzYNgDk0yQHyTmrZq4YFVywj8UkH0esEa3k3JRESV1idRIdNmwY1q9fj4CAAAwbNqza527fvr3WgQHA1q1b8fXXX2PTpk1o27YtEhMTMWXKFISFhVW5fGbRokWYP3++JNcnlXNmoQUTWitqH/G6TYcUWjCdW6Xil8+UlsKYk+Ow6xCiNFYn0cDAQGEfwsDAQIcFJPbOO+9g+vTpeO655wAA7dq1w/Xr17Fo0aIqk+iMGTOECVAA3xJt2rSpU+KtK0zjoYDzkiitFbWPs5Ko6fystJTfnLukxOHXI0QJrE6i4i5cZ3XnFhUVVSjo4OHhUe0SF41GA41opiCRnhxJVDQRnJKoDSzK8Dm4AAKn0YAVFgIAjDk58KDZX6QOsGtM9N69e2CMCUtcrl+/jh07dqBNmzbo16+fZME99dRTWLhwISIiItC2bVucOnUKy5Ytw4svvijZNYjtrl83HzsriXp5CZXlKInaQGiJenoKPUmOIl7mQkmU1BV2JdHBgwdj2LBhmDhxInJzc9G5c2d4eXnhzp07WLZsGV599VVJglu5ciVmz56N1157DRkZGQgLC8Mrr7yCOXPmSHJ+Yh9TS9TT07FzVcrz9TUnUcZsW1pTF5nK8AGO78oFYC4rBcCYleX46xGiAHZVLDp58iQeeeQRAMB3332H0NBQXL9+HV9++SVWrFghWXD+/v5Yvnw5rl+/jnv37iE5ORn/93//Z7E+lTiX0QikpPDHfn7OTWSmyUU6HVBJ1UlSjsV4qBOGOMTXMGRnO/x6hCiBXS3RoqIi+Jf14+3duxfDhg2DSqVC165dcV3c10fczu3bfGsQsK8rt3HjniguvgNv7wY2v7b85twNG9p+/brEYqmJjR88H7n/fmTl56O+DQuBLbpzKYmSOsKuJBodHY2dO3di6NCh+Pnnn/HWW28BADIyMhxegIHIy9QKBSxnzFrrscc22n3t8stcJKww6ZbESdTW7tz4t9+2+XqcWs3vFqDXU3cuqTPs6s6dM2cOpk2bhmbNmqFLly7o1q0bAL5V2qFDB0kDJMoi7miwJ4nWhvh6aWnOvbYrqk0StZepNcru3gUTFT0hxF3Z1RIdPnw4evTogfT0dMTGxgr39+nTB0OHDpUsOKI8tW2J1gYVXLANkyOJensLy1wMd+5A3aSJU65LiFzsSqIAEBoaitDQUIv7OnfuXOuAiLIpJYlS6b+a1WZM1F6caCtE4507ACVR4ubsSqKFhYX497//jf379yMjI6NC8YMr4uKqxK2Ik5c9SfSHHx7DvXu3odU2wqBBv9r02vITi0j1hCTq6WnzZtwDZs5ERm4uQurVw+6FC61+nTiJGjIybLomIa7IriQ6YcIEJCQkYMyYMWjcuLHDF3ET5TAlUY6zrCJkrby8iygsTENJSV7NTy7Hy0uYt0LduTVgOp15jagdy1su3byJm1lZyCs7h7U40eayxsxMm69LiKuxK4nu3r0bP/74I7p37y51PEThTEnUxwewsXFTaxzHt0bz8qglWhM5JhUB4CtwqFSA0UgtUVIn2PVnMCgoCMHBwVLHQhROpwNMfxfFXavOZLru3bsA7XJXNfFOKs4otCBci+OE1ijLywMzbTxLiJuyK4m+//77mDNnDops7Oohrk3c+nP2pCITmqFrHYvtyJxc4UvcpWu4fdup1ybE2ezqzl26dCmSk5PRqFEjNGvWDJ7ldoc4efKkJMERZREnLblbogDftdymjTxxKJ1cLVGgYhJVR0Y69fqEOJNdSXTIkCESh0FcgdKSKI2LVs1iTNTZSVQ048yQnu7UaxPibHYl0blz50odB3EB4qSlhCRK3blVE1qiHMdPaXYii5YoJVHi5uyeX5mbm4svvvgCM2bMQHZZsemTJ08ijZoHbksJLVEq/VczxpiQRDmNxulL0DiVSlgvaszMBNPrnXp9QpzJro+oZ86cQd++fREYGIhr167h5ZdfRnBwMHbs2CFsiUbcD7VEXQO7excwGPgvnNyVa8L5+PAzc41GGG7dgjo8XJY4CHE0u5Lo1KlTMW7cOCxZskTYEg0ABgwYgJEjR0oWHFEWcdKyp9ACADz44ByUlhbA09O+6b3e3sIyRCr9VwWLSUV2zsydMWIECouL4SuqQGQLztcXKOuhMty8SUmUuC27kuixY8ewZs2aCvc3adIEt27dqnVQRJlMLVGtFvDwsO8crVv/s1YxmAou3L1L3blVEe/lae+kopeeeKJWMVhMLqIfFHFjdo2Jent7I7+Sle5JSUloSDsluyWDATDNEbG3FSoVU5dudjZAS5UrknN5i3BdrZb/xANKosS92ZVEBw8ejAULFqC0tBQAX6UkJSUF06dPxzPPPCNpgEQZMjLMw2xyjYea0Lho9RSRRFUqYZauMSsL7N49WeIgxNHsSqIfffQRMjMzERISgnv37qFnz56Ijo6Gv78/Ftqw4wNxHTdvmo9rk0SLitJRUHADRUX2L32gJFo9KaoVpWdn48adO0gXdQ3bihP9oPTi/0CEuBG7xkQDAgLw+++/48CBAzhx4gSMRiMefPBB9O3bV+r4kJaWhvfeew+7d+/GvXv30LJlS6xbtw4dO3aU/FqkalLNzN2x4yEUFqbB17cJRo2yLwOKl7lQEq1ISKJ2bIFm8sjbb+NmVhbC6tfH5fh4u85RflzU87777DoPIUpmcxI1Go1Yv349tm/fjmvXroHjOERFRSE0NBSMMUnXpOXk5KB79+7o3bs3du/ejZCQECQnJ6NevXqSXYNYR5xElTImCtAM3fJquwWalFS+vigbAaBxUeK2bEqijDE8/fTT+OmnnxAbG4t27dqBMYYLFy5g3Lhx2L59O3bu3ClZcIsXL0bTpk0RL/ok3KxZM8nOT6wnVXeuFKg7t2pSzMyVjEbDT+M2GGBIS5P8QzYhSmBTX8/69evx22+/Yf/+/Th16hQ2b96MLVu24PTp0/jll1/w66+/SlpoYdeuXejUqRP+8Y9/ICQkBB06dMDnn38u2fmJ9cRJVO6WqLg7l1qilqRYIyoVjuOELl1WWAhGe9cRN2RTEt28eTP+9a9/oXfv3hUee+yxxzB9+nRs3LhRsuCuXLmC1atXo0WLFvj5558xceJETJ48udpErdPpkJ+fb3EjtaeklqhWa94QnJKoJYtJRXK3RFFuXJQmFxE3ZFMSPXPmDJ6oZhH2gAEDcPr06VoHZWKasPTBBx+gQ4cOeOWVV/Dyyy9j9erVVb5m0aJFCAwMFG5NmzaVLJ66zDSkpVLJ/7fZVHABoO7c8pSwvEVMJfrERUmUuCObkmh2djYaNWpU5eONGjVCjviTcC01btwYbcptGNm6dWukpKRU+ZoZM2YgLy9PuKVSU0USpr9/vr7CGnpZiQsuFBbKG4uSKC2JWrREqZoZcUM2TSwyGAxQV7OtkoeHB/QS7tjQvXt3JCUlWdx38eJFRFazya9Go4FGAX883IlOB2Rl8cdyj4ealB8XbdVKvliUxGCaWOThYX9tRil5evJbsen1MNy8SZOLiNuxeXbuuHHjqkxSOp1OkqBM3nrrLTz88MP44IMP8Oyzz+Lo0aNYu3Yt1q5dK+l1SPXEW0LKPR5qIk6iKSmURAGAGQxgeXkA+ElFSkhWHMeB02rB7t4FKyoCKygAJ9q0ghBXZ1MSHTt2bI3PeeGFF+wOpryHHnoIO3bswIwZM7BgwQJERUVh+fLlGDVqlGTXIDVT0hpRk/JJlADGvDyAMf4LBfXGmJIowHfpqiiJEjdiUxKNt7NySW0MGjQIgwYNcvp1iZmUy1sGDtwPo1EPlcquYlkCSqIVSblG9Kf334feaITazopHYuXHRT1btKj1OQlRitr9JSN1gpTLW+rVi6ndCcqIk+j165Kc0uVJOamopYT7f5oK0QOA8fZtyc5LiBLU/mMmcXtKKrRgQi3RihRVrUiE8/Y2b4uWkSFzNIRIi5IoqZESk6iXl3nY79o1WUNRDCVVKxLjOI5PpACMd+6ASTiDnxC5UXcuqZFUO7gAwOXLm6DXF0Gt9kF09MhancvPj19+c+MGoNfzKynqMiGJcpzdW6CZbE1IQJFOBx+NBiN69qx1bJy3N7+nKGMwZmXBo5r15oS4kjr+Z4dYw9QSVav5ZX+1ceTIu8JWaLVNov7+/PpVvZ6PMSKidrG5MsaYOYlKsLxl5vr1wlZokiRRrRYoi8+QmUlJlLgN6s4lNVJatSIT8bhoXe/SZQUFQGkpAGWNh5qYunMBwEjjosSNUBIl1bp7l78ByhkPNQkIMB9fvSpfHEqg1ElFJuIkarhzR8ZICJEWJVFSLSXt3lKeeM3+lSvyxaEESk+i0GiEbgxjZqbMwRAiHUqipFpKrFZkQknUTOlJ1GKGbnY2mMEgc0SESIOSKKmWklui4u5cSqLKTqKAqEvXaLSIlxBXRkmUVEvK5S1SU6v5DboBIDlZ3ljkZhAnJaUnUQBG07ZAhLg4SqKkWkruzgWAwED+39u3zROg6hrGmLllp9EoYveWSomSO00uIu6CkiiplpJbooBll25dbY2ywkKgpASAcrtygXItUUqixE1QsQVSLalL/mm1oRb/1papJQoAly4B7dtLclqXIu4alSqJNgoKsvhXCpREiTuiJEqqdeMG/6+3N+DhUfvzDRt2vPYnESmfROsiRyTRP5Ytk+Q8YpxKxZcjLCmBISsLjDHldj0TYiXqziVVMhiA9HT+WFwdSEnESTQpSb445GQxM1fU2lMiIckXF4MVFckbDCESoCRKqnT7Np9IAWWOhwKWSfTvv+WLQ04GB7REHYW6dIm7oSRKqmTqygWUm0TVanPRhaQkgDF545GD0J0rwe4tjkbLXIi7oTFRUiVHJNHffnsFOl02NJpgPProGknOGRjIL2/JywNu3QIaN5bktC6BiQoXcBIub3n900+Rc/cugvz98cmkSZKcE7BsKdMyF+IOKImSKjkiiaam/ihshSaVoCBzrOfO1bEkmpdn7nOXsCt3z/HjwlZoUqKWKHE3LtWdu2jRInAchylTpsgdSp2Qmmo+VurEIoBPoibnzskXhxwsxkMVPqkIAL8hrYr/s0NjosQduEwSPXbsGNauXYsHHnhA7lDqDHESVeqYKFC3k6g4EblCEuU4TujSNebkUCF64vJcIokWFBRg1KhR+PzzzxEk4eJvUj1XTKJ//SVfHHJwtSQKiOIUlyskxEW5RBKdNGkSBg4ciL59+8odSp1iSqLe3vwsWKXy8jLP0P3rL8BolDceZxJPzlH68haBKE7q0iWuTsF/GnlbtmzByZMncezYMauer9PpoNPphK/z8/MdFZpb0+vNJf+UPB5qEhzMz9C9exe4fh2IipI7IucQkpBaDU7Jn3RExC1mw5078JQxFkJqS9Et0dTUVLz55pv4+uuv4W1lV9WiRYsQGBgo3Jo2bergKN3TzZvmSZ+ukkRNTp+WLw5nMt67xxefh+t05QI0Q5e4F0Un0RMnTiAjIwMdO3aEWq2GWq1GQkICVqxYAbVaDUMlkxJmzJiBvLw84ZYqHtgjVrt+3XzsCklUvBIjMVG2MJzKFcdDAapaRNyLovt/+vTpg7Nnz1rcN378eLRq1QrvvfcePCqpiK7RaKBxlbEhBXO1JNqggfn41Cn54nAmY2amcOxSSVRciD4zkwrRE5em6CTq7++P+++/3+I+X19f1K9fv8L9RFriJGqatCOF++57HjpdDjQaaWdZ+/vzSxBLS+tOEjU4MIk+++ijyCkoQJCDPkFx3t5gJSVASQnY3bvgxBvDEuJCFJ1EiXwc1RLt2vVD6U4mwnF8l+6tW/ys4qwsyy5ed2TRnavVSnruD8aPl/R85XHe3mBlk/6Md+5ARUmUuCiXS6IHDx6UO4Q64epV87GULVFHatCAT6IA3xp19xVRQkvUw0PZa5AqYTFDNzMT6ubNZYyGEPspemIRkY8piXp6SlqS1aHE46InT8oXhzMwnY6vmws+IbnamKLF5CJRtzQhroaSKKnAYABSUvhjf3++q9QV1KXJRY4cD3UGcfezgZIocWGu1QdEnCItjZ+gA0jflbt1aysUFd2Ej08YRoyQdhftevX4nk2Dwf1bosaMDOFY6vFQAGj/6qtIz85G4+BgJK5eLfn5OQ8PYSaYISODZugSl0UtUVLBlSvmY6mTqF5fgNLSu9DrC6Q9MfjNQUxFFy5eBNy5WJVBnEQd0BItKC7G3Xv3UFBcLPm5TYTkX1wMdveuw65DiCNREiUVXL5sPg4MlC8Oe4i7dN25cpHFGlEHtESdwWJykehDASGuhJIoqUCcRF1t5UFdGRcVko5aDc7TNavPipO/kZIocVGUREkFrtwSFa8NddckaiwqAivgu8NdcVKRicXkIkqixEVREiUVmJIox7lGyT+x4GDzbGJ3raFrvH1bOHbVrlygXHeuaYEvIS6GkiixYDTyk3IAvitX5WL/Q9RqfpYuAJw7B5SUyBqOQxjcJYmqVEIiNWZmglWyoQQhSudifyKJo6WmAvfu8cemZORqTF26paXAhQvyxuII7pJEAVH8RiPt6EJcEiVRYiEpyXzsauOhJu6+LZrRwctbnMliXJS6dIkLoiRKLPwtqn/g6i1RwP2WuTCj0TwJR6Phixa4MM7HRzimJEpcEVUsIhbOnTMfB0m7WxkAoEePz2Aw3IOHh+O6Id05iRqzswG9HoBju3JXvPYainU6eDu4cLJFSzQ93aHXIsQRKIkSC3/9ZT52RBKNjBwk/UnL0Wr52717fBJlzHXq/9ZE3FpTOTCJPvnQQw47txjn6Wku/3frFpX/Iy6HunOJgDFzS9TPD/Dykjee2jC1RrOyzNujuQOj6M2Iu0JdmfA+dDoYc3LkDYYQG1ESJYLUVKBsdy2HtEKdyVRDFwDOnJEvDqm508xcE5V4XPTmTRkjIcR2lESJQFzhRzyuKKXMzBO4fft/yMw84ZgLlHHHJMoYM48bmnZBcZCTly/jyN9/46S4fJWDcJREiQujMVEiEC8HEdegldLevYNRWJgGX98mGDXqhmMuAsskevaswy7jVKygAKywEACfeBw5dvjswoW4mZWFsPr1cTk+3mHXASiJEtdGLVEiEO/BKU5CrqhePfNkIndJouLZq+4yHgqIJheBf4/MaJQ5IkKsR0mUCI4d4//18nLdQgsmarX5PVy4IKwKcWniVpo7JVEA4Hx9+YOSEqpcRFyKopPookWL8NBDD8Hf3x8hISEYMmQIksQldYhk0tIAU0OnYUP3WBJiak3rdOZ6wK5M3BJVuVkSVZmSKABDWpqMkRBiG0Un0YSEBEyaNAl//vkn9u3bB71ej379+qGwbFyISOfIEfNxw4byxSEldxoXZYyZW6IeHq69/qgS4pa1/objxsoJkZqiJxbt2bPH4uv4+HiEhITgxIkTePTRR2WKyj0dPmw+DgmRLw4plU+iI0bIF0ttsfx88x6iDp5UJAeLyUWURIkLUXRLtLy8skWMwa4+60WB/vjDfBwaKl8cUnKnZS7iLk5O1PXpLjgPD2HdqzEjA6y4WOaICLGOoluiYowxTJ06FT169MD9999f5fN0Oh10Op3wdX5+vjPCc2mFhcDx4/xxYCDg4huDCPz9hYpyLt+dK+7idLfxUBPOzw+sbB8+fVoaPO+7T+aICKmZy7REX3/9dZw5cwabN2+u9nmLFi1CYGCgcGvatKmTInRd//ufefZqWJi8sUiJ48yt0WvXAFf+PCXu4nTHlihg+b4MKSkyRkKI9Vwiib7xxhvYtWsXDhw4gPDw8GqfO2PGDOTl5Qm31NRUJ0Xpun791XzcuLF8cTiCO0wuYnq9eVKRRsOvq3RD4hm6evq9JS5C0d25jDG88cYb2LFjBw4ePIioqKgaX6PRaKBx8PZN7uaXX8zHjm6J/uMfFwAwAM6ZGFN+XLR7d6dcVlKGtDTAYAAAqPz8nHLNU59+6sSfEo/TaMw7uty4AWYwuPx+qcT9KTqJTpo0CZs2bcL3338Pf39/3CrbwSIwMBBaNym+LbfsbOBEWRnb4GDA0cNtXl7+jr1AOeIawOKyhq5Ef/26cMw5KYn6yzTuqvLz43dyKS2FIT0d6hp6ngiRm6K7c1evXo28vDz06tULjRs3Fm5bt26VOzS3sW8fYKqy1qSJvLE4grgl6qobdOuvXROOndUSlYv4Q4JB9OGBEKVSdEuUMSZ3CG5v927zsTvOwfLyAgIC+ElFZ87wE6jUiv5fb4mVlpon2Xh5uV2RhfJU/v4wlB3rr12DxhX730md4kJ/TojUDAbgp5/4Y7XaOZOKzpxZhpKSfHh5BeCBB6Y6/oLgd6TJzwfu3QOSkoC2bZ1yWUnoU1LM46H+/k4rsrBi507kFxUhwMcHk4cMcco1AQCicVH99es0LkoUj5JoHXb0KJCZyR+Hh/PV5Bzt7NllwlZozkyiV67wxydPulgSvXRJOFYFBDjtuiu+/17YCs2ZSZTjOKj8/WHMzhYmGKkjI512fUJspegxUeJYO3eaj93575R4b1RTUQlXwBiDXlQ5n/N37qQsuYjfpz45WcZICKkZJdE6ijFg+3b+mOPqThI1bffmCowZGfxMVfCJhXOlwdxaUFESJS6Ekmgddfo0cPkyfxwa6j6l/irj7c1PLgL47tzSUnnjsVbpX38Jx6p69eQLxMk4Ly+hjq7h5k0YywrvE6JElETrKPEqoebN5YvDWUw70+h0rrHUhTGGkjqaRAGAE43/iseFCVEaSqJ1kNEImEoQcxxgRSEol9eokflYvGONUhmuXQPLzQXAJxR3LfVXFVVgoHBcmpQkYySEVI+SaB2UkACY1rGHhzu+SpESiJPo77/LF4e1SkxlpACo6uDWf5yvr7CgV5+cDFZSInNEhFSOkmgd9MUX5uOWLeWLw5mCg/nlhwD/IULJdTyMeXkoPX+e/0KtrnNduUDZUhfT+9brqTVKFIuSaB2Tng58+y1/rNG496xcMZXKXEwiMxM4d07eeKqj+/NPIcurGjQAp6qbv6aqoCDhuNRVt+Ahbq9uzJkngmXLzLNTW7d2fgm8+vUfhK9vU3h7N3TuhcHvUGOqoPfzz0A1e7vLxlhQgBLTYlaOg0dD53+fAKD9ffchvEEDNBCNTTob5+dnrl50+TKMBQVuXzuYuB6OuXmB2vz8fAQGBiIvLw8BTqz4okSpqUBMDF/+zsMDeP75ujEeapKTY26F9+ljuQWcUtzbvRslR48CAFQNG0LtjgWNbaBPS4Px9m0AgOaxx+D9yCMyR0SIpbrZT1QHGQzAyy/zCRQA2rSpWwkUAOrVA0zr+BMS+KSqJIbsbHMrVKWCR2iovAEpgIeoUkbJiRNgpi2HCFEISqJ1QEkJ8MorfBcmwCfPBx+UNyY5cBzQrBl/rNcD338vazgVFO/dK+xLpwoJqXPLWirDaTTCmlGWl4fSCxdkjogQS5RE3RhjwK5dQPv2wLp1/H0cB/TuzU8qqovEhSW+/lq+OMorvXgRetMMVE9PeIjX5NRxHqZKGQB0hw7RFolEUWhikZtKTgZeeonvtjRRqfgEKufm23v2PI3i4kx4ezfEE0/scvr1Q0LM+4vu389/n+67z+lhWGA6He6Z9qQD4NGkiezbfw3/v//Dnbw8NAgMxHezZskaC+fvD87HB6yoCMbbt1F6/jy8XGkrHuLWqCXqhvbvBzp2tEygISHAkCHyJ4ysrJPIyPgTWVknZbk+xwGtWpm//s9/ZAnDQvHevWB5eQD4hCFe2iGXxORkHE1KQqICCsBzHAcP0Wa3xb/8AuYqBZCJ26Mk6mb27wcGDgTK/ibD3x/o1w8YPNhyN5O6rFUr896pn38O3LwpXyylf/+NkpNlHyhUKqgjIpy28bYr4QIChC3SWG4udOJPiITIiJKoGzl9Ghg6lC+yDgAREcAzz/CTaejvspm3t3lj7uJiYPp0eeIwZGaiSLSpq0eTJuDq6mB1DTiOgzo8XPiPrDt8GPpr1+QNihBQEnUbN28CgwYBd+/yX0dG8i1QLy9541Kq9u3Nk6u++gr44QfnXt+Ym4vCjRuFTzyqevWgoq6CanFarblblzEUffstDNnZ8gZF6jxKom4gL4/vwr1xg/86JIQvJlBHq8VZxdsb6NzZ/PULLwB//+2ca+tTUlAQF2ceB9Vq4REZSd24VlA1amTu1i0qQuGGDTBkZsocFanLXOLP7KpVqxAVFQVvb2907NgRhw4dkjskxbhzB+jfH0hM5L/28+NboM4u5+eKWrUyrxvNyeE/eIi28Kw1VlICQ3Y2DLduQX/9OkoSE1G4dSsK4+PBTF0GGg3U0dGyz8Z1FRzHQR0VBa5sF3mWn4+CL77gCzHQ0hciA8X/qd26dSumTJmCVatWoXv37lizZg0GDBiA8+fPIyIiQu7wHM5o5LtoDQZAq+VbUBzHL9H4/nvgX/8yt0C9vYEnn6x7lYjsxXFAr17Af/8LZGXxXeJduwKLFgH//Gfla2kZAwoL+X99fS1b+8aiIugvX+ZvKSlCS7PK6/v58QmBiirYhFOroW7RAvrLl8Hu3QNKSnDvhx+gO3oUmm7d4NmmDTgaxyBOovjauV26dMGDDz6I1atXC/e1bt0aQ4YMwaJFi2p8vZJr5965w1cRKi3l/zDn5ABpafzaxaQkc7F0az32GL/ll5L9+GM47t1Lg1bbBAMH3pA7HAD85KLdu/kPKmItWgChoXypxLQ0fgccTw8DBrRMQj3tPQR46xDmn4/YpnfwYGgqtGrr97xUNWjAj4EqtAu35auv4mZ2NsKCg3FR9LunKEYjDKmpYEVFFR7i/Pzg0aQJVEFBUPn58S1XtRqcVsu3/Gmsg0hE0S3RkpISnDhxAtPLTZ/s168fDh8+XOlrdDoddKbpqQDyyloD+fn5jgvUDn/+CTz9tHkmrRR+/VW6czkOX9bu3j0jvvtOWT+T8i5d4m8mGo9SHHxlLZoEVIy7VM/frHbjhrkLQYGMZZtgG0tKkH3qlMzR2KG4mP+UWglVgwbwe+klSqR1mL+/v3RzEJiCpaWlMQDsjz/+sLh/4cKFrGXLlpW+Zu7cuQwA3ehGN7rRjW6V3jIyMiTLU4puiZqU/8TAGKvyU8SMGTMwdepU4evc3FxERkYiJSUFgTLujWiv/Px8NG3aFKmpqYrrjraWq78HV48fcP334OrxA67/Hlw9fsD8HrwkHDNXdBJt0KABPDw8cOvWLYv7MzIy0KiKAt0ajQaaSmaEBAYGuuwPHgACAgJcOn7A9d+Dq8cPuP57cPX4Add/D64eP1CxYVYbih4U8PLyQseOHbFv3z6L+/ft24eHH35YpqgIIYQQnqJbogAwdepUjBkzBp06dUK3bt2wdu1apKSkYOLEiXKHRgghpI5TfBIdMWIEsrKysGDBAqSnp+P+++/HTz/9hMjISKter9FoMHfu3Eq7eF2Bq8cPuP57cPX4Add/D64eP+D678HV4wcc8x4Uv06UEEIIUSpFj4kSQgghSkZJlBBCCLETJVFCCCHETpRECSGEEDu5RRK1Zau09PR0jBw5EjExMVCpVJgyZYrzAq2CLfFv374djz/+OBo2bIiAgAB069YNP//8sxOjrZwt7+H3339H9+7dUb9+fWi1WrRq1Qoff/yxE6OtyN7t9v744w+o1Wq0b9/esQFawZb3cPDgQXAcV+H2t7M2Va2ErT8DnU6HmTNnIjIyEhqNBvfddx/i4uKcFG1FtsQ/bty4Sr//bdu2dWLEFdn6M9i4cSNiY2Ph4+ODxo0bY/z48cjKynJStBXZGv+nn36K1q1bQ6vVIiYmBl9++aXtF5WsgKBMtmzZwjw9Pdnnn3/Ozp8/z958803m6+vLrl+/Xunzr169yiZPnsw2bNjA2rdvz958803nBlyOrfG/+eabbPHixezo0aPs4sWLbMaMGczT05OdPHnSyZGb2foeTp48yTZt2sT++usvdvXqVfbVV18xHx8ftmbNGidHzrM1fpPc3FzWvHlz1q9fPxYbG+ucYKtg63s4cOAAA8CSkpJYenq6cNPr9U6OnGfPz+Dpp59mXbp0Yfv27WNXr15lR44cqVBn21lsjT83N9fi+56amsqCg4PZ3LlznRu4iK3v4dChQ0ylUrH//Oc/7MqVK+zQoUOsbdu2bMiQIU6OnGdr/KtWrWL+/v5sy5YtLDk5mW3evJn5+fmxXbt22XRdl0+inTt3ZhMnTrS4r1WrVmz69Ok1vrZnz56yJ9HaxG/Spk0bNn/+fKlDs5oU72Ho0KFs9OjRUodmFXvjHzFiBJs1axabO3eu7EnU1vdgSqI5OTlOiK5mtsa/e/duFhgYyLKyspwRXo1q+zuwY8cOxnEcu3btmiPCs4qt7+HDDz9kzZs3t7hvxYoVLDw83GExVsfW+Lt168amTZtmcd+bb77JunfvbtN1Xbo717RVWr9+/Szur26rNCWRIn6j0Yi7d+8iWKaNRKV4D6dOncLhw4fRs2dPR4RYLXvjj4+PR3JyMubOnevoEGtUm59Bhw4d0LhxY/Tp0wcHDhxwZJhVsif+Xbt2oVOnTliyZAmaNGmCli1bYtq0abh3754zQrYgxe/AunXr0LdvX6uLyEjNnvfw8MMP48aNG/jpp5/AGMPt27fx3XffYeDAgc4I2YI98et0Onh7e1vcp9VqcfToUZSWllp9bZdOonfu3IHBYKhQjL5Ro0YVitYrkRTxL126FIWFhXj22WcdEWKNavMewsPDodFo0KlTJ0yaNAkTJkxwZKiVsif+S5cuYfr06di4cSPUavmLftnzHho3boy1a9di27Zt2L59O2JiYtCnTx/89ttvzgjZgj3xX7lyBb///jv++usv7NixA8uXL8d3332HSZMmOSNkC7X9PU5PT8fu3btl+f9vYs97ePjhh7Fx40aMGDECXl5eCA0NRb169bBy5UpnhGzBnvj79++PL774AidOnABjDMePH0dcXBxKS0txp4q9aCsj/18ACdiyVZoS2Rv/5s2bMW/ePHz//fcICQlxVHhWsec9HDp0CAUFBfjzzz8xffp0REdH4/nnn3dkmFWyNn6DwYCRI0di/vz5aNmypbPCs4otP4OYmBjExMQIX3fr1g2pqan46KOP8Oijjzo0zqrYEr/RaATHcdi4caOwxeGyZcswfPhwfPrpp9BqtQ6Ptzx7f4/Xr1+PevXqYciQIQ6KzHq2vIfz589j8uTJmDNnDvr374/09HS88847mDhxItatW+eMcCuwJf7Zs2fj1q1b6Nq1KxhjaNSoEcaNG4clS5bAw8PD6mu6dEvUnq3SlKQ28W/duhUvvfQSvvnmG/Tt29eRYVarNu8hKioK7dq1w8svv4y33noL8+bNc2CklbM1/rt37+L48eN4/fXXoVaroVarsWDBApw+fRpqtRq//vqrs0IXSPV70LVrV1y6dEnq8GpkT/yNGzdGkyZNLPYIbt26NRhjuHHjhkPjLa8233/GGOLi4jBmzBhJ97i0lT3vYdGiRejevTveeecdPPDAA+jfvz9WrVqFuLg4pKenOyNsgT3xa7VaxMXFoaioCNeuXUNKSgqaNWsGf39/NGjQwOpru3QSdfWt0uyNf/PmzRg3bhw2bdoky/iDmFQ/A8YYdDqd1OHVyNb4AwICcPbsWSQmJgq3iRMnIiYmBomJiejSpYuzQhdI9TM4deoUGjduLHV4NbIn/u7du+PmzZsoKCgQ7rt48SJUKhXCw8MdGm95tfn+JyQk4PLly3jppZccGWKN7HkPRUVFUKksU4ipBcecXJK9Nj8DT09PhIeHw8PDA1u2bMGgQYMqvK9q2TQNSYFM05rXrVvHzp8/z6ZMmcJ8fX2FWW7Tp09nY8aMsXjNqVOn2KlTp1jHjh3ZyJEj2alTp9i5c+fkCN/m+Ddt2sTUajX79NNPLabI5+bmyhI/Y7a/h08++YTt2rWLXbx4kV28eJHFxcWxgIAANnPmTJeIvzwlzM619T18/PHHbMeOHezixYvsr7/+YtOnT2cA2LZt21wi/rt377Lw8HA2fPhwdu7cOZaQkMBatGjBJkyY4BLxm4wePZp16dLF2eFWytb3EB8fz9RqNVu1ahVLTk5mv//+O+vUqRPr3LmzS8SflJTEvvrqK3bx4kV25MgRNmLECBYcHMyuXr1q03VdPokyxtinn37KIiMjmZeXF3vwwQdZQkKC8NjYsWNZz549LZ4PoMItMjLSuUGL2BJ/z549K41/7Nixzg9cxJb3sGLFCta2bVvm4+PDAgICWIcOHdiqVauYwWCQIXKerf+HxJSQRBmz7T0sXryY3Xfffczb25sFBQWxHj16sB9//FGGqM1s/RlcuHCB9e3bl2m1WhYeHs6mTp3KioqKnBy1ma3x5+bmMq1Wy9auXevkSKtm63tYsWIFa9OmDdNqtaxx48Zs1KhR7MaNG06O2syW+M+fP8/at2/PtFotCwgIYIMHD2Z///23zdekrdAIIYQQO7n0mCghhBAiJ0qihBBCiJ0oiRJCCCF2oiRKCCGE2ImSKCGEEGInSqKEEEKInSiJEkIIIXaiJEoIIYTYiZIoITI4fPgwPDw88MQTT8gdCiGkFqhiESEymDBhAvz8/PDFF1/g/PnziIiIkCWO0tJSeHp6ynJtQtwBtUQJcbLCwkJ88803ePXVVzFo0CCsX7/e4vFdu3ahU6dO8Pb2RoMGDTBs2DDhMZ1Oh3fffRdNmzaFRqNBixYthL0bTftSiu3cudNiP8V58+ahffv2iIuLQ/PmzaHRaMAYw549e9CjRw/Uq1cP9evXx6BBg5CcnGxxrhs3buC5555DcHAwfH190alTJxw5cgTXrl2DSqXC8ePHLZ6/cuVKREZGOn1HD0KciZIoIU62detWYVPs0aNHIz4+Xkg0P/74I4YNG4aBAwfi1KlT2L9/Pzp16iS89oUXXsCWLVuwYsUKXLhwAZ999hn8/Pxsuv7ly5fxzTffYNu2bUhMTATAJ/apU6fi2LFj2L9/P1QqFYYOHQqj0QgAKCgoQM+ePXHz5k3s2rULp0+fxrvvvguj0YhmzZqhb9++iI+Pt7hOfHw8xo0bZ9XG1IS4rFqVzCeE2Ozhhx9my5cvZ4wxVlpayho0aMD27dvHGGOsW7dubNSoUZW+LikpiQEQnltefHw8CwwMtLhvx44dTPxrPnfuXObp6ckyMjKqjTEjI4MBYGfPnmWMMbZmzRrm7+/PsrKyKn3+1q1bWVBQECsuLmaMMZaYmMg4jrN5WylCXA21RAlxoqSkJBw9ehTPPfccAECtVmPEiBGIi4sDACQmJqJPnz6VvjYxMREeHh7o2bNnrWKIjIxEw4YNLe5LTk7GyJEj0bx5cwQEBCAqKgoAkJKSIly7Q4cOCA4OrvScQ4YMgVqtxo4dOwAAcXFx6N27N5o1a1arWAlROrXcARBSl6xbtw56vR5NmjQR7mOMwdPTEzk5OdBqtVW+trrHAEClUlUYfywtLa3wPF9f3wr3PfXUU2jatCk+//xzhIWFwWg04v7770dJSYlV1/by8sKYMWMQHx+PYcOGYdOmTVi+fHm1ryHEHVBLlBAn0ev1+PLLL7F06VIkJiYKt9OnTyMyMhIbN27EAw88gP3791f6+nbt2sFoNCIhIaHSxxs2bIi7d++isLBQuM805lmdrKwsXLhwAbNmzUKfPn3QunVr5OTkWDzngQceQGJiIrKzs6s8z4QJE/DLL79g1apVKC0ttZgQRYjbkrs/mZC6YseOHczLy4vl5uZWeOxf//oXa9++PTtw4ABTqVRszpw57Pz58+zMmTNs8eLFwvPGjRvHmjZtynbs2MGuXLnCDhw4wLZu3coYYywrK4v5+vqyyZMns0uXLrGNGzeysLCwCmOisbGxFtc2GAysfv36bPTo0ezSpUts//797KGHHmIA2I4dOxhjjOl0OtayZUv2yCOPsN9//50lJyez7777jh0+fNjiXA8//DDz8vJiEydOlOi7RoiyUUuUECdZt24d+vbti8DAwAqPPfPMM0hMTERAQAC+/fZb7Nq1C+3bt8djjz2GI0eOCM9bvXo1hg8fjtdeew2tWrXCyy+/LLQ8g4OD8fXXX+Onn35Cu3btsHnzZsybN6/GuFQqFbZs2YITJ07g/vvvx1tvvYUPP/zQ4jleXl7Yu3cvQkJC8OSTT6Jdu3b497//DQ8PD4vnvfTSSygpKcGLL75ox3eIENdDxRYIIZJZuHAhtmzZgrNnz8odCiFOQS1RQkitFRQU4NixY1i5ciUmT54sdziEOA0lUUJIrb3++uvo0aMHevbsSV25pE6h7lxCCCHETtQSJYQQQuxESZQQQgixEyVRQgghxE6URAkhhBA7URIlhBBC7ERJlBBCCLETJVFCCCHETpRECSGEEDtREiWEEELs9P+HN2xoi8cdxQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.30657333333333336\n", + "0.027685378411316283\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.5257333333333334\n", + "0.029079507866842894\n" + ] + } + ], + "source": [ + "llama_fig = plot_figure(llama_prompt_correct_frac_list, llama_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "llama_fig.savefig(os.path.join(fig_path, 'llama_mcq.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(llama_prompt_correct_frac_list))\n", + "print(np.std(llama_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(llama_rag_correct_frac_list))\n", + "print(np.std(llama_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "aabc5899", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:55: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:56: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.6313199999999999\n", + "0.027403808332257598\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.7942533333333334\n", + "0.02310455077829185\n" + ] + } + ], + "source": [ + "gpt_35_fig = plot_figure(gpt_35_prompt_correct_frac_list, gpt_35_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "gpt_35_fig.savefig(os.path.join(fig_path, 'gpt_35_mcq.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(gpt_35_prompt_correct_frac_list))\n", + "print(np.std(gpt_35_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(gpt_35_rag_correct_frac_list))\n", + "print(np.std(gpt_35_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "9a0a4fc0", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:55: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_51967/731637856.py:56: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.6847333333333333\n", + "0.027653330118932635\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.7417666666666666\n", + "0.0259921141887304\n" + ] + } + ], + "source": [ + "gpt_4_fig = plot_figure(gpt_4_prompt_correct_frac_list, gpt_4_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "gpt_4_fig.savefig(os.path.join(fig_path, 'gpt_4_mcq.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(gpt_4_prompt_correct_frac_list))\n", + "print(np.std(gpt_4_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(gpt_4_rag_correct_frac_list))\n", + "print(np.std(gpt_4_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83c8f3c2", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/mcq_cypher_rag_eval.ipynb b/notebooks/mcq_cypher_rag_eval.ipynb new file mode 100644 index 0000000..63e2da8 --- /dev/null +++ b/notebooks/mcq_cypher_rag_eval.ipynb @@ -0,0 +1,216 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "a5caaba0-2c5d-4555-90eb-a7f8db555c2d", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import openai\n", + "from dotenv import load_dotenv, find_dotenv\n", + "import os\n", + "import json\n", + "from tqdm import tqdm\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "c17b66f4-c35b-4751-8dbd-44b827a81a39", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag = pd.read_csv('../data/results/cypher_rag_mcq_output.csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4e8372a7-d61b-4b27-8161-3ab084c091e8", + "metadata": {}, + "outputs": [], + "source": [ + "llm_for_evaluation = 'gpt-4'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3930c00b-4647-4444-a2b6-f6a1030bd388", + "metadata": {}, + "outputs": [], + "source": [ + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "api_key = os.environ.get('API_KEY')\n", + "api_version = os.environ.get('API_VERSION')\n", + "resource_endpoint = os.environ.get('RESOURCE_ENDPOINT')\n", + "openai.api_type = 'azure'\n", + "openai.api_key = api_key\n", + "if resource_endpoint:\n", + " openai.api_base = resource_endpoint\n", + "if api_version:\n", + " openai.api_version = api_version" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "77dbdd34-f3a5-40b4-b0c7-1b6d2d6c5835", + "metadata": {}, + "outputs": [], + "source": [ + "def fetch_GPT_response(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature=0):\n", + " # print('Calling OpenAI...')\n", + " response = openai.ChatCompletion.create(\n", + " temperature=temperature,\n", + " deployment_id=chat_deployment_id,\n", + " model=chat_model_id,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": instruction}\n", + " ]\n", + " )\n", + " if 'choices' in response \\\n", + " and isinstance(response['choices'], list) \\\n", + " and len(response) >= 0 \\\n", + " and 'message' in response['choices'][0] \\\n", + " and 'content' in response['choices'][0]['message']:\n", + " return response['choices'][0]['message']['content']\n", + " else:\n", + " return 'Unexpected response'\n", + "\n", + "def get_GPT_response(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature=0):\n", + " return fetch_GPT_response(instruction, system_prompt, chat_model_id, chat_deployment_id, temperature)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8285a1c7-4654-4728-b0d0-2a1300af26df", + "metadata": {}, + "outputs": [], + "source": [ + "system_prompt = '''\n", + "You are an expert evaluator of mcq question. You will be provided with an MCQ question which has 5 options out of which one option is correct.\n", + "You will also be provided with the correct label.\n", + "You will then provided with an answer.\n", + "You need to verify if that answer is correct or not, by checking it with the question and the label.\n", + "If the answer is correct, you return True, if the answer is not correct, you return False.\n", + "Return your answer in JSON format as follows:\n", + "{\"response\": <\"True\"/\"False\">}\n", + "\n", + "Example 1:\n", + "Question: Out of the given list, which Gene is associated with psoriasis and Takayasu's arteritis. Given list is: SHTN1, HLA-B, SLC14A2, BTBD9, DTNB\n", + "Label: HLA-B\n", + "Answer: The gene HLA-B is associated with both psoriasis and Takayasu's arteritis.\n", + "Your response: {\"response\": \"True\", \"reason\": \"Answer is in agreement with the label.\"}\n", + "\n", + "Example 2:\n", + "Question: Out of the given list, which Gene is associated with psoriasis and myelodysplastic syndrome. Given list is: NOD2, CHEK2, HLA-B, GCKR, PKNOX2\n", + "Label: HLA-B\n", + "Answer: The genes associated with psoriasis and myelodysplastic syndrome from the given list are HLA-B and CHEK2.\n", + "Your response: {\"response\": \"False\", \"reason\":\"Answer returns two options HLA-B and CHEK2, but the label says the correct answer is only HLA-B\"}\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "76dfe699-2678-442c-b005-ec76a5989d69", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "306it [11:29, 2.25s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 4.33 s, sys: 473 ms, total: 4.81 s\n", + "Wall time: 11min 29s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "cypher_rag_eval = []\n", + "for index, row in tqdm(cypher_rag.iterrows()):\n", + " question = row.text\n", + " label = row.label\n", + " answer = row.cypher_rag_answer\n", + " prompt = f'''\n", + " Question: {question}\n", + " Label: {label}\n", + " Answer: {answer}\n", + " '''\n", + " out = json.loads(get_GPT_response(prompt, system_prompt, llm_for_evaluation, llm_for_evaluation))\n", + " cypher_rag_eval.append(out[\"response\"])\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c788084a-42df-48ab-9b3f-8feeef320a5a", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag['cypher_rag_eval'] = cypher_rag_eval" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "afbdf643-59b7-4af1-bf95-fe032f0dc4d9", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag.to_csv('../data/results/cypher_rag_mcq_output_with_eval.csv', index=False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86bcafaf-3945-4d63-a0a9-227736d7c672", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/mcq_cypher_rag_vs_kg_rag.ipynb b/notebooks/mcq_cypher_rag_vs_kg_rag.ipynb new file mode 100644 index 0000000..fac059f --- /dev/null +++ b/notebooks/mcq_cypher_rag_vs_kg_rag.ipynb @@ -0,0 +1,233 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "2712dac1-b37c-41b9-867b-6f53e5f1da33", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "from tqdm import tqdm\n", + "import re\n", + "from scipy import stats\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from IPython.display import clear_output\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "30cdc471-b72e-4f73-9086-909913988e6b", + "metadata": {}, + "outputs": [], + "source": [ + "def extract_answer(text):\n", + " try:\n", + " text_processed = text.split('\"answer\":')[-1].split('\\n')[0].strip().split('\"')[1].strip()\n", + " except:\n", + " text_processed = text.split('\"answer\":')[-1].split('\\n')[0].strip()\n", + " return text_processed\n", + "\n", + "def correct_paranthesis_split(text):\n", + " try:\n", + " text_processed = text.split('\"answer\":')[-1].split(\"\\n\")[1].split(\":\")[-1].split('\"')[1].strip()\n", + " return text_processed\n", + " except:\n", + " return text\n", + " \n", + "def process_df(rag_response_df):\n", + " rag_response_df.loc[:, 'extracted_answer'] = rag_response_df['llm_answer'].apply(extract_answer)\n", + "\n", + "\n", + " rag_response_df_paranthesis_split = rag_response_df[rag_response_df.extracted_answer==\"{\"]\n", + " if rag_response_df_paranthesis_split.shape[0] > 0:\n", + " rag_response_df_paranthesis_split.loc[:, \"extracted_answer\"] = rag_response_df_paranthesis_split.llm_answer.apply(correct_paranthesis_split)\n", + " rag_response_df_wo_paranthesis_split = rag_response_df[rag_response_df.extracted_answer != \"{\"]\n", + " rag_response_df = pd.concat([rag_response_df_wo_paranthesis_split, rag_response_df_paranthesis_split])\n", + " return rag_response_df\n", + "\n", + "def evaluate(df):\n", + " correct = df[df.correct_answer == df.extracted_answer]\n", + " incorrect = df[df.correct_answer != df.extracted_answer]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "def evaluate_2(df):\n", + " correct = df[df.cypher_rag_eval == True]\n", + " incorrect = df[df.cypher_rag_eval == False]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "\n", + "def bootstrap(cypher_rag, kg_rag, niter=1000, nsample=150):\n", + " cypher_rag_correct_frac_list = []\n", + " kg_rag_correct_frac_list = []\n", + " for i in tqdm(range(niter)):\n", + " cypher_rag_response_df_sample = cypher_rag.sample(n=nsample, random_state=i)\n", + " cypher_rag_correct_frac, cypher_rag_incorrect_frac = evaluate_2(cypher_rag_response_df_sample)\n", + " kg_rag_response_df_sample = kg_rag.iloc[cypher_rag_response_df_sample.index]\n", + " kg_rag_correct_frac, kg_rag_incorrect_frac = evaluate(kg_rag_response_df_sample)\n", + " cypher_rag_correct_frac_list.append(cypher_rag_correct_frac)\n", + " kg_rag_correct_frac_list.append(kg_rag_correct_frac)\n", + " return cypher_rag_correct_frac_list, kg_rag_correct_frac_list\n", + "\n", + "def plot_figure(cypher_rag_correct_frac_list, kg_rag_correct_frac_list):\n", + " fig = plt.figure(figsize=(5, 3))\n", + " ax = plt.gca()\n", + " sns.kdeplot(cypher_rag_correct_frac_list, color=\"blue\", shade=True, label=\"Cypher-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + " sns.kdeplot(kg_rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "\n", + " for artist in ax.lines:\n", + " artist.set_edgecolor(\"black\")\n", + " plt.xlabel(\"Accuracy\")\n", + " plt.ylabel(\"Density\")\n", + " plt.legend(bbox_to_anchor=(0.45, 0.9))\n", + " plt.xlim(0.1,0.9)\n", + " ax.axvline(np.mean(cypher_rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " ax.axvline(np.mean(kg_rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " sns.despine(top=True, right=True)\n", + " plt.show()\n", + " return fig\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2c03e505-4232-4aa0-96db-9238aa4eb285", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag = pd.read_csv('../data/results/cypher_rag_mcq_output_with_eval.csv')\n", + "kg_rag = pd.read_csv('../data/results/gpt_4_PubMedBert_entity_recognition_based_node_retrieval_rag_based_mcq_from_monarch_and_robokop_response.csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1864df4c-9d34-4dd8-84b0-86c145bd86f1", + "metadata": {}, + "outputs": [], + "source": [ + "kg_rag = process_df(kg_rag)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "82a61695-9db0-438b-895f-72dd8dbe6698", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████| 1000/1000 [00:00<00:00, 1203.58it/s]\n" + ] + } + ], + "source": [ + "cypher_rag_correct_frac_list, kg_rag_correct_frac_list = bootstrap(cypher_rag, kg_rag)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e4b076c6-d63b-46ab-a44e-42b0a141cdad", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_63840/889265924.py:56: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(cypher_rag_correct_frac_list, color=\"blue\", shade=True, label=\"Cypher-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_63840/889265924.py:57: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(kg_rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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axe78847mUajYaGhoWzixIksKyvL5nPSVmiEEEKIndx6TJQQQghREiVRQgghxE6URAkhhBA7URIlhBBC7ERJlBBCCLETJVFCCCHETpRECSGEEDtREiWEEELsREmUEAX89ddfUKvVGDFihNKhEEIcQBWLCFHAU089BX9/fyQmJiIjIwNRUVGKxCH3jieENDbUEiVEZsXFxdi0aROef/55jBgxAsnJyVb3/9///R/69OkDb29vNGvWDKNHjxbu0+l0mDNnDqKjo6HRaBAbGyts5pycnIygoCCr1/r+++/BcZxw/Z133kH37t2xZs0axMTECPvQbtu2Dffccw+CgoIQGhqKhx56COfOnbN6ratXr2LcuHEICQmBn58fevfujf379+PixYtQqVRITU21evyyZcvQunVrq51WCGlsKIkSIrOvv/4aHTt2RIcOHTBhwgSsXbtW2Drqp59+wujRozF8+HAcPnwYKSkpVps1T5o0CRs2bMCHH36IU6dO4ZNPPoG/v79N58/MzMR3332HzZs3Iz09HQC/r2V8fDxSU1ORkpIClUqF0aNHCwmwuLgYAwcORFZWFn744QccOXIEs2fPhslkQps2bRAXF4ekpCSr8yQlJWHKlCmy7itJiOwcLJpPCLFR//792bJlyxhj/E4YzZo1Yzt37mSMMdavXz82fvz4Gp+XkZHBALAdO3bUeH9SUhLTarVWt23ZsoWJf83nzZvHPD09WU5OTp0x3rx5kwFgx44dY4wx9sknn7CAgAB269atGh+/adMmFhwczMrLyxljjB06dIhxHMcuXLhQ53kIcXf0FZEQGWVkZODAgQMYN24cAMDDwwNjx44VumTT09MxZMiQGp+bnp4OtVqNgQMHOhRD69atERYWZnXb2bNnMW7cOLRt2xaBgYFo06YNAODy5cvCuXv06IGQkJAaX3PUqFFQq9XYsmULAL5refDgwcLrENJYeSgdACFNSWJiIgwGg9VEIsYYNBoNVqxYAR8fn1qfW9d9AKBSqYRuYTO9Xl/tcX5+ftVue/jhh9G6dWt89tlniIqKgslkQufOnVFRUdGgc3t5eWHSpElISkrCmDFj8NVXX2H58uV1PoeQxoBaooTIxGAwYN26dViyZAnS09OFy5EjRxAVFYUNGzaga9euSElJqfH5Xbp0gclkwu7du2u8PywsDEVFRSgpKRFuM4951uXWrVvIyMjAm2++iSFDhuDOO+/E7du3rR7TtWtXpKenIy8vr9bXeeqpp/Drr79i1apVMBgMGDNmTL3nJsTtKd2fTEhTsWXLFubl5cXy8/Or3Td79mzWu3dvtnPnTqZSqdjbb7/NTp48yY4ePcoWLVokPG7KlCksOjqabdmyhZ0/f57t3LmTbdq0iTHG2K1bt5ifnx976aWXWGZmJlu/fj2LioqqNibarVs3q3MbjUYWGhrKJkyYwM6ePctSUlJYnz59GAC2ZcsWxhhjOp2O3XHHHezee+9le/fuZefOnWPffvst+/PPP61eq3///szLy4s999xzEv3UCHFt1BIlRCaJiYmIi4uDVqutdt+jjz6K1NRUhISE4JtvvsEPP/yA7t274/7778eBAweEx61evRr/+Mc/MH36dHTs2BFPP/200PIMCQnBl19+iZ9//hldunTBhg0b8M4779Qbl0qlwsaNG3Ho0CF07twZs2bNwuLFi60e4+Xlhe3btyM8PBzDhw9Hly5dsGjRIqjVaqvHPfnkk6ioqMC0adPs+AkR4n6o2AIhRDILFizAN998g6NHjyodCiGyoJYoIcRhxcXFOH78OFasWIEXX3xR6XAIkQ0lUUKIw1544QX06tULgwYNoq5c0qRQdy4hhBBiJ2qJEkIIIXaiJEoIIYTYiZIoIYQQYidKooQQQoidKIkSQgghdqIkSgghhNiJkighhBBiJ0qihBBCiJ0oiRJCCCF2+n9kxJP+Wm6p+AAAAABJRU5ErkJggg==", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Cypher-RAG based mean and std---\n", + "0.51674\n", + "0.02966020828577499\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.7417666666666666\n", + "0.0259921141887304\n" + ] + } + ], + "source": [ + "cypher_rag_vs_kg_rag_fig = plot_figure(cypher_rag_correct_frac_list, kg_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "cypher_rag_vs_kg_rag_fig.savefig(os.path.join(fig_path, 'cypher_rag_vs_kg_rag_mcq.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Cypher-RAG based mean and std---')\n", + "print(np.mean(cypher_rag_correct_frac_list))\n", + "print(np.std(cypher_rag_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(kg_rag_correct_frac_list))\n", + "print(np.std(kg_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b623550-d435-48cc-8c91-801262989bce", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/mcq_using_cypher_rag.ipynb b/notebooks/mcq_using_cypher_rag.ipynb new file mode 100644 index 0000000..51a393f --- /dev/null +++ b/notebooks/mcq_using_cypher_rag.ipynb @@ -0,0 +1,763 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "ad38bed4-0077-4097-81dc-8db1d23255ad", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import AzureChatOpenAI\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import openai\n", + "from langchain.chains import GraphCypherQAChain\n", + "from langchain.graphs import Neo4jGraph\n", + "from langchain.callbacks import get_openai_callback\n", + "import pandas as pd\n", + "from tqdm import tqdm\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d035a52f-442b-43f2-a7ba-a04006937f0a", + "metadata": {}, + "outputs": [], + "source": [ + "curated_data = pd.read_csv('../data/benchmark_data/mcq_questions.csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ddb263ec-9bd5-4caf-8950-13b400a75b98", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ff7f9255-e5fd-4eec-aade-2f7cacb8b8cd", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/karthiksoman/anaconda3/envs/cypher_rag/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The class `AzureChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 0.3.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import AzureChatOpenAI`.\n", + " warn_deprecated(\n" + ] + } + ], + "source": [ + "\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "API_KEY = os.environ.get('API_KEY')\n", + "API_VERSION = os.environ.get('API_VERSION')\n", + "RESOURCE_ENDPOINT = os.environ.get('RESOURCE_ENDPOINT')\n", + "openai.api_type = \"azure\"\n", + "openai.api_key = API_KEY\n", + "openai.api_base = RESOURCE_ENDPOINT\n", + "openai.api_version = API_VERSION\n", + "chat_deployment_id = LLM_MODEL\n", + "chat_model_id = chat_deployment_id\n", + "temperature = 0\n", + "chat_model = AzureChatOpenAI(openai_api_key=API_KEY, openai_api_version=API_VERSION, azure_deployment=chat_deployment_id, azure_endpoint=RESOURCE_ENDPOINT, temperature=temperature)\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + "username = os.environ.get('NEO4J_USER')\n", + "password = os.environ.get('NEO4J_PSW')\n", + "url = os.environ.get('NEO4J_URL')\n", + "database = os.environ.get('NEO4J_DB')\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9f0c1ded-fd30-49cb-be0d-369bc5a906bd", + "metadata": {}, + "outputs": [], + "source": [ + "graph = Neo4jGraph(url=url, username=username, password=password, database = database)\n", + "chain = GraphCypherQAChain.from_llm(chat_model, graph=graph, verbose=True, validate_cypher=True,return_intermediate_steps=True)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "922ed8a6-500f-4937-92d2-2df6271798e6", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "0it [00:00, ?it/s]" + ] + }, + { + "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;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "282it [00:09, 29.53it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "282it [00:21, 29.53it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs7426056', 'rs2736100', 'rs2187668', 'rs2107595', 'rs7405776'] AND c.disease IN ['central nervous system cancer', 'lung adenocarcinoma'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "284it [00:28, 7.63it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease)-[:ASSOCIATES_DaG]->(g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound)\n", + "WHERE d.name IN ['thoracic aortic aneurysm', 'abdominal aortic aneurysm'] AND c.variant IN ['rs1642764', 'rs595244', 'rs139606545', 'rs12077210', 'rs12917707']\n", + "RETURN c.variant AS Variant, d.name AS Disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "285it [00:41, 4.53it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs8077245', 'rs11712066', 'rs11209026', 'rs10830962', 'rs6010620'] AND c.name IN ['Crohn\\'s disease', 'ankylosing spondylitis'] RETURN g.variant, c.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "286it [00:49, 3.41it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs1047891', 'rs9268905', 'rs3197999', 'rs1025128', 'rs4624820'] AND c.disease IN ['Crohn\\'s disease', 'sclerosing cholangitis'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "286it [01:01, 3.41it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease)-[:ASSOCIATES_DaG]->(g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) \n", + "WHERE d.name IN ['lung adenocarcinoma', 'central nervous system cancer'] AND c.variant IN ['rs10490924', 'rs10830962', 'rs2736100', 'rs2391769', 'rs9272143'] \n", + "RETURN c.variant, d.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "288it [01:10, 1.70it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs11759064', 'rs975730', 'rs1150757', 'rs2294008', 'rs7453920'] AND c.disease IN ['gastric fundus cancer', 'duodenal ulcer'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "289it [01:18, 1.37it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.FeatureDeprecationWarning} {category: DEPRECATION} {title: This feature is deprecated and will be removed in future versions.} {description: The semantics of using colon in the separation of alternative relationship types will change in a future version. (Please use ':RESPONSE_TO_mGrC|ADVRESPONSE_TO_mGarC' instead)} {position: line: 1, column: 34, offset: 33} for query: \"MATCH (g:Gene)-[:RESPONSE_TO_mGrC|:ADVRESPONSE_TO_mGarC]->(c:Compound) \\nWHERE g.variant IN ['rs2294008', 'rs2072499', 'rs3197999', 'rs1537377', 'rs988958'] \\nAND c.disease IN ['gastric fundus cancer', 'atrophic gastritis'] \\nRETURN g.variant, c.disease\"\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC|:ADVRESPONSE_TO_mGarC]->(c:Compound) \n", + "WHERE g.variant IN ['rs2294008', 'rs2072499', 'rs3197999', 'rs1537377', 'rs988958'] \n", + "AND c.disease IN ['gastric fundus cancer', 'atrophic gastritis'] \n", + "RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "290it [01:25, 1.13it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs254020', 'rs4625', 'rs6059655', 'rs11738191', 'rs2963222'] AND c.name IN ['keratinocyte carcinoma', 'skin sensitivity to sun'] RETURN g.variant, c.name;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "291it [01:35, 1.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESISTANT_TO_mGrC]->(c:Compound) \n", + "WHERE g.variant IN ['rs6679677', 'rs12187903', 'rs1333047', 'rs11585651', 'rs55730499'] \n", + "AND c.disease IN ['keratinocyte carcinoma', 'anti-neutrophil antibody associated vasculitis'] \n", + "RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "292it [01:40, 1.45s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs7936312', 'rs325485', 'rs13191786', 'rs72928038', 'rs7523907'] AND c.name IN ['keratinocyte carcinoma', 'autoimmune disease'] RETURN g.variant, c.name;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "293it [01:46, 1.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs1950829', 'rs13263709', 'rs1126809', 'rs34871267', 'rs2431108'] AND c.disease IN ['keratinocyte carcinoma', 'age-related hearing impairment'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "294it [01:57, 2.59s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs34243448', 'rs1893592', 'rs1765871', 'rs229541', 'rs10455872'] AND c.disease IN ['aortic stenosis', 'large artery stroke'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "295it [02:03, 2.94s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs1042704', 'rs6059655', 'rs34396849', 'rs10052804', 'rs11747125'] AND c.name IN ['skin sensitivity to sun', 'keratinocyte carcinoma'] RETURN g.variant, c.name;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "296it [02:08, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs61815704', 'rs4149909', 'rs36001488', 'rs1333047', 'rs1126809'] AND c.name IN ['skin sensitivity to sun', 'age-related hearing impairment'] RETURN g.variant, c.name\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "297it [02:18, 4.31s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "298it [02:28, 5.38s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "299it [02:35, 5.76s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs259919', 'rs10455872', 'rs11958220', 'rs72928038', 'rs141343442'] AND c.disease IN ['autoimmune disease', 'keratinocyte carcinoma'] RETURN g.variant, c.disease;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "300it [02:41, 5.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs2310752', 'rs7528604', 'rs6679677', 'rs34691223', 'rs2963222'] AND c.disease IN ['autoimmune disease', 'anti-neutrophil antibody associated vasculitis'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "301it [02:50, 6.52s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs62324212', 'rs10059133', 'rs149943', 'rs12931267', 'rs17156671'] AND c.disease IN ['autoimmune disease', 'atopic asthma'] RETURN g.variant, c.disease;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "302it [02:55, 6.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs10455872', 'rs35781323', 'rs4615152', 'rs761934676', 'rs11965538'] AND c.disease IN ['large artery stroke', 'aortic stenosis'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "303it [03:00, 5.95s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs259919', 'rs2503199', 'rs325485', 'rs1126809', 'rs229541'] AND c.disease IN ['age-related hearing impairment', 'keratinocyte carcinoma'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "304it [03:08, 6.37s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs1126809', 'rs416223', 'rs12722502', 'rs9419958', 'rs1333049'] AND c.name IN ['age-related hearing impairment', 'skin sensitivity to sun'] RETURN g.variant, c.name;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "305it [03:18, 7.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (g:Gene)-[:RESPONSE_TO_mGrC]->(c:Compound) WHERE g.variant IN ['rs2447827', 'rs1937455', 'rs62324212', 'rs12205199', 'rs4482879'] AND c.disease IN ['atopic asthma', 'autoimmune disease'] RETURN g.variant, c.disease\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "306it [03:26, 1.48it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "CPU times: user 1.83 s, sys: 194 ms, total: 2.03 s\n", + "Wall time: 3min 26s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "cypher_rag_out = []\n", + "for index, row in tqdm(curated_data.iterrows()):\n", + " question = row['text']\n", + " with get_openai_callback() as cb:\n", + " try:\n", + " cypher_rag_answer = chain.run(query=question, return_final_only=True, verbose=False)\n", + " except ValueError as e:\n", + " cypher_rag_answer = None\n", + " \n", + " cypher_rag_out.append((row['text'], row['correct_node'], cypher_rag_answer, cb.total_tokens)) \n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "b99f74b5-f7c0-4cd1-9825-f832d6676542", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag_out_df = pd.DataFrame(cypher_rag_out, columns=['text', 'label', 'cypher_rag_answer', 'total_tokens'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "77e75f27-fdc8-460c-8bd4-af90c8712a34", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "save_path = '../data/results'\n", + "os.makedirs(save_path, exist_ok=True)\n", + "cypher_rag_out_df.to_csv(os.path.join(save_path, 'cypher_rag_mcq_output.csv'), index=False)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2392ef3e-af62-4cb0-abb2-dbe7f0da8108", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/rag_comparison.ipynb b/notebooks/rag_comparison.ipynb new file mode 100644 index 0000000..035dd65 --- /dev/null +++ b/notebooks/rag_comparison.ipynb @@ -0,0 +1,382 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "id": "d514b0e6", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import os\n", + "\n", + "from IPython.display import clear_output\n" + ] + }, + { + "cell_type": "markdown", + "id": "349f3171", + "metadata": {}, + "source": [ + "## Load RAG output files" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "109057cd", + "metadata": {}, + "outputs": [], + "source": [ + "neo4j_rag = pd.read_csv('../data/results/cypher_rag_output.csv')\n", + "kg_rag = pd.read_csv('../data/results/kg_rag_output.csv')\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "38565176", + "metadata": {}, + "source": [ + "## Token usage comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "12e415b1", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 300x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There is 53.9% reduction in token usage for KG-RAG compared to Cypher-RAG\n" + ] + } + ], + "source": [ + "neo4j_rag.loc[:, 'token_usage'] = 0.5*(neo4j_rag.total_tokens_used + neo4j_rag.total_tokens_used_perturbed)\n", + "kg_rag.loc[:, 'token_usage'] = 0.5*(kg_rag.total_tokens_used + kg_rag.total_tokens_used_perturbed)\n", + "\n", + "neo4j_avg = neo4j_rag['token_usage'].mean()\n", + "neo4j_sem = neo4j_rag['token_usage'].sem()\n", + "\n", + "kg_avg = kg_rag['token_usage'].mean()\n", + "kg_sem = kg_rag['token_usage'].sem()\n", + "\n", + "\n", + "fig = plt.figure(figsize=(3, 3))\n", + "\n", + "plt.bar(0, neo4j_avg, yerr=neo4j_sem, color='red', ecolor='black', capsize=5, label='Cypher-RAG')\n", + "\n", + "plt.bar(1, kg_avg, yerr=kg_sem, color='green', ecolor='black', capsize=5, label='KG-RAG')\n", + "\n", + "plt.ylabel('Average token usage')\n", + "plt.xticks([0, 1], ['Cypher-RAG', 'KG-RAG'])\n", + "\n", + "sns.despine()\n", + "\n", + "plt.legend(loc='center left', bbox_to_anchor=(0.6, 0.75))\n", + "\n", + "plt.show()\n", + "\n", + "percentage_of_reduction_in_token_usage = round(100*(neo4j_avg-kg_avg)/neo4j_avg,1)\n", + "print(f'There is {percentage_of_reduction_in_token_usage}% reduction in token usage for KG-RAG compared to Cypher-RAG')\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "fig.savefig(os.path.join(fig_path, 'token_usage_comparison.svg'), format='svg', bbox_inches='tight') \n" + ] + }, + { + "cell_type": "markdown", + "id": "8ea726fd", + "metadata": {}, + "source": [ + "## Retrieval accuracy comparison" + ] + }, + { + "cell_type": "markdown", + "id": "5004ceb3", + "metadata": {}, + "source": [ + "### Cypher-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "757f36d5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Cypher-RAG 75.0%\n", + "Correct retrieval percentage for KG-RAG 97.0%\n" + ] + } + ], + "source": [ + "\n", + "neo4j_rag_no_nan = neo4j_rag.dropna(subset=['neo4j_rag_answer'])\n", + "neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer']), axis=1)\n", + "neo4j_rag_yes_count_df = neo4j_rag_no_nan[neo4j_rag_no_nan.neo4j_rag_answer.str.contains('Yes')]\n", + "neo4j_rag_yes_count = neo4j_rag_yes_count_df.shape[0]\n", + "indices_to_remove = neo4j_rag_yes_count_df.index.tolist()\n", + "neo4j_rag_no_nan = neo4j_rag_no_nan.drop(indices_to_remove)\n", + "neo4j_rag_p_value_correct_retrieval_count = neo4j_rag_no_nan[neo4j_rag_no_nan.contains_pvalue==True].shape[0]\n", + "neo4j_rag_total_correct_retrieval = neo4j_rag_yes_count + neo4j_rag_p_value_correct_retrieval_count\n", + "\n", + "kg_rag_no_nan = kg_rag.dropna(subset=['kg_rag_answer'])\n", + "kg_rag_yes_count_df = kg_rag_no_nan[kg_rag_no_nan.kg_rag_answer.str.contains('Yes')]\n", + "kg_rag_yes_count = kg_rag_yes_count_df.shape[0]\n", + "indices_to_remove = kg_rag_yes_count_df.index.tolist()\n", + "kg_rag_no_nan = kg_rag_no_nan.drop(indices_to_remove)\n", + "kg_rag_no_nan.loc[:, 'contains_pvalue'] = kg_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['kg_rag_answer']), axis=1)\n", + "kg_rag_p_value_correct_retrieval_count = kg_rag_no_nan[kg_rag_no_nan.contains_pvalue==True].shape[0]\n", + "kg_rag_total_correct_retrieval = kg_rag_yes_count + kg_rag_p_value_correct_retrieval_count\n", + "\n", + "clear_output()\n", + "\n", + "neo4j_rag_total_correct_retrieval_percentage = 100*neo4j_rag_total_correct_retrieval/neo4j_rag.shape[0]\n", + "kg_rag_total_correct_retrieval_percentage = 100*kg_rag_total_correct_retrieval/kg_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Cypher-RAG {neo4j_rag_total_correct_retrieval_percentage}%')\n", + "print(f'Correct retrieval percentage for KG-RAG {kg_rag_total_correct_retrieval_percentage}%')\n" + ] + }, + { + "cell_type": "markdown", + "id": "360a6019", + "metadata": {}, + "source": [ + "### KG-RAG" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0a433581", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Correct retrieval percentage for Cypher-RAG after name perturbation 0.0%\n", + "Correct retrieval percentage for KG-RAG after name perturbation 97.0%\n" + ] + } + ], + "source": [ + "\n", + "neo4j_rag_no_nan = neo4j_rag.dropna(subset=['neo4j_rag_answer_perturbed'])\n", + "neo4j_rag_no_nan.loc[:, 'contains_pvalue'] = neo4j_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['neo4j_rag_answer_perturbed']), axis=1)\n", + "neo4j_rag_yes_count_df = neo4j_rag_no_nan[neo4j_rag_no_nan.neo4j_rag_answer_perturbed.str.contains('Yes')]\n", + "neo4j_rag_yes_count = neo4j_rag_yes_count_df.shape[0]\n", + "indices_to_remove = neo4j_rag_yes_count_df.index.tolist()\n", + "neo4j_rag_no_nan = neo4j_rag_no_nan.drop(indices_to_remove)\n", + "neo4j_rag_p_value_correct_retrieval_count = neo4j_rag_no_nan[neo4j_rag_no_nan.contains_pvalue==True].shape[0]\n", + "neo4j_rag_total_correct_retrieval_perturbed = neo4j_rag_yes_count + neo4j_rag_p_value_correct_retrieval_count\n", + "\n", + "kg_rag_no_nan = kg_rag.dropna(subset=['kg_rag_answer_perturbed'])\n", + "kg_rag_yes_count_df = kg_rag_no_nan[kg_rag_no_nan.kg_rag_answer_perturbed.str.contains('Yes')]\n", + "kg_rag_yes_count = kg_rag_yes_count_df.shape[0]\n", + "indices_to_remove = kg_rag_yes_count_df.index.tolist()\n", + "kg_rag_no_nan = kg_rag_no_nan.drop(indices_to_remove)\n", + "kg_rag_no_nan.loc[:, 'contains_pvalue'] = kg_rag_no_nan.apply(lambda row: str(row['gwas_pvalue']) in str(row['kg_rag_answer_perturbed']), axis=1)\n", + "kg_rag_p_value_correct_retrieval_count = kg_rag_no_nan[kg_rag_no_nan.contains_pvalue==True].shape[0]\n", + "kg_rag_total_correct_retrieval_perturbed = kg_rag_yes_count + kg_rag_p_value_correct_retrieval_count\n", + "\n", + "clear_output()\n", + "\n", + "neo4j_rag_total_correct_retrieval_perturbed_percentage = 100*neo4j_rag_total_correct_retrieval_perturbed/neo4j_rag.shape[0]\n", + "kg_rag_total_correct_retrieval_perturbed_percentage = 100*kg_rag_total_correct_retrieval_perturbed/kg_rag.shape[0]\n", + "\n", + "print(f'Correct retrieval percentage for Cypher-RAG after name perturbation {neo4j_rag_total_correct_retrieval_perturbed_percentage}%')\n", + "print(f'Correct retrieval percentage for KG-RAG after name perturbation {kg_rag_total_correct_retrieval_perturbed_percentage}%')\n" + ] + }, + { + "cell_type": "markdown", + "id": "d72ebbfa", + "metadata": {}, + "source": [ + "### Bar plot" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e6d8690d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAEhCAYAAAB7mQezAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAyJklEQVR4nO3deVRU9f8/8OewjcjIICibIaDggvuSgpZWYLh8co2MDx5xSctQUbSUUnEnLddcMhfET+6aS5qWIbiEu+LyURENA03gU8mMuLDN+/uHP+/PG6iMDjMDPh/nzDnM+955z3MunHlx7/ve+1YIIQSIiIj+HwtTByAiIvPCwkBERDIsDEREJMPCQEREMiwMREQkw8JAREQyLAxERCTDwkBERDIsDACEENBqteC1fkRELAwAgDt37kCtVuPOnTumjkJEZHJWpnzzgwcP4ssvv8SpU6dw69YtbNu2DT179pSWCyEQExOD5cuXIzc3F+3bt8fSpUvh6+srrfP3339jxIgR+OGHH2BhYYE+ffpgwYIFUKlUJvhEROanuLgYhYWFpo5BJmRtbQ1LS8syr2/SwnD37l00a9YMgwYNQu/evUssnz17NhYuXIj4+Hh4e3tj4sSJCA4OxsWLF1GlShUAQFhYGG7duoV9+/ahsLAQAwcOxNChQ7Fu3TpjfxwisyKEQFZWFnJzc00dhcyAg4MDXF1doVAonrmuwlxuoqdQKGR7DEIIuLu7Y8yYMRg7diwAQKPRwMXFBatXr8b777+PS5cuwc/PDydOnEDr1q0BAHv37kXXrl1x48YNuLu7l+m9tVot1Go1NBoN7O3ty+XzERnbrVu3kJubC2dnZ1StWrVMXwhU+QghcO/ePeTk5MDBwQFubm7PfI1J9xieJj09HVlZWQgKCpLa1Go12rZtiyNHjuD999/HkSNH4ODgIBUFAAgKCoKFhQWOHTuGXr16ldp3fn4+8vPzpedarbb8PgiRCRQXF0tFwcnJydRxyMRsbW0BADk5OXB2dn7mYSWzHXzOysoCALi4uMjaXVxcpGVZWVlwdnaWLbeysoKjo6O0TmliY2OhVqulh4eHh4HTE5nWozGFqlWrmjgJmYtHfwtlGW8y28JQnqKjo6HRaKRHZmamqSMRlQsePqJH9PlbMNvC4OrqCgDIzs6WtWdnZ0vLXF1dkZOTI1teVFSEv//+W1qnNEqlEvb29rIHERE9ZLaFwdvbG66urkhISJDatFotjh07hoCAAABAQEAAcnNzcerUKWmd/fv3Q6fToW3btkbPTEQVh5eXF+bPn2/qGGbJpIUhLy8PKSkpSElJAfBwwDklJQUZGRlQKBQYNWoUpk+fjp07d+L8+fPo378/3N3dpTOXGjZsiM6dO2PIkCE4fvw4fv31VwwfPhzvv/9+mc9IInrpKBTGezynrKwsjBgxAnXq1IFSqYSHhwfeeecd2T+KFckbb7wBhUIBhUKBKlWqoF69eoiNjS31bgtHjhyBpaUlunXrVmpfBQUF+PLLL9GyZUvY2dlBrVajWbNmmDBhAv744w/DBBYmlJiYKACUeISHhwshhNDpdGLixInCxcVFKJVKERgYKFJTU2V9/PXXXyI0NFSoVCphb28vBg4cKO7cuaNXDo1GIwAIjUZjqI9GZFL3798XFy9eFPfv3y+5EDDe4zmkp6cLd3d34efnJ7Zs2SJSU1PFhQsXxJw5c0T9+vVfcMv8f56enmLevHkG608IIfLz80tt79ixoxgyZIi4deuWuH79uli1apWwsrISS5YsKbHu4MGDRWRkpFCpVOLmzZuyZQ8ePBAdOnQQDg4OYsGCBeLkyZPi999/F0lJSeLDDz8U48ePf2K2p/5N/INJC4O5YGGgyqYiF4YuXbqIWrVqiby8vBLLbt++LQYOHCi6desmay8oKBA1a9YUK1asEEI8/CKOiIgQERERwt7eXjg5OYkJEyYInU4nvcbT01PMmDFDDBw4UKhUKuHh4SGWLVsm6zcjI0OEhIQItVotqlevLrp37y7S09Ol5eHh4aJHjx5i+vTpws3NTXh5eZX6mTp27CgiIyNlbS1bthS9evWStd25c0eoVCpx+fJl0bdvXzFjxgzZ8tjYWGFhYSFOnz5d6vs8/vn+SZ/CYLbXMZCcYorpzy4RMWZxLaTRcJsb399//429e/dixowZsLOzK7HcwcEBH3zwATp06IBbt25JF2vt2rUL9+7dQ9++faV14+PjMXjwYBw/fhwnT57E0KFDUbt2bQwZMkRaZ86cOZg2bRo+++wzbNmyBcOGDUPHjh1Rv359FBYWIjg4GAEBATh06BCsrKwwffp0dO7cGefOnYONjQ0AICEhAfb29ti3b1+ZPqMQAocPH8bly5dlt/cBgE2bNqFBgwaoX78++vXrh1GjRiE6Olo6o2j9+vXo1KkTWrRoUWrfhjoLzWwHn4no5XP16lUIIdCgQYMnrtOuXTvUr18f//nPf6S2uLg4hISEyO6R5uHhgXnz5qF+/foICwvDiBEjMG/ePFlfXbt2xccffwwfHx+MGzcONWrUQGJiIgBg48aN0Ol0WLFiBZo0aYKGDRsiLi4OGRkZSEpKkvqws7PDihUr0KhRIzRq1OiJuZcsWQKVSgWlUokOHTpAp9Nh5MiRsnVWrlyJfv36AQA6d+4MjUaDAwcOSMuvXLmC+vXry17Tq1cvqFQqqFQqtGvX7onvrw8WBiIyG6KMd+j54IMPEBcXB+DhKex79uzBoEGDZOv4+/vL/oMOCAhAWloaiouLpbamTZtKPysUCtkp8GfPnsXVq1dRrVo16YvX0dERDx48wLVr16TXNWnSRNp7WLt2rbSuSqXCoUOHpPXCwsKQkpKCX3/9FV26dMHnn38u+yJPTU3F8ePHERoaCuDhxbp9+/bFypUrn7otlixZgpSUFAwaNAj37t0r0/Z7Fh5KIiKz4evrC4VCgcuXLz91vf79+2P8+PE4cuQIkpOT4e3tjddff13v97O2tpY9VygU0Ol0AB6eNdmqVSusXbu2xOtq1qwp/fz4Ia/u3bvLTpWvVauW9LNarYaPjw+Ah4eMfHx84O/vL932Z+XKlSgqKpKdUSmEgFKpxKJFi6BWq+Hr64vU1FRZlkeH0xwdHfX78E/BPQYiMhuOjo4IDg7G4sWLcffu3RLLH90p1snJCT179kRcXBxWr16NgQMHllj32LFjsudHjx6Fr69vmW8/3bJlS6SlpcHZ2Rk+Pj6yh1qtLvU11apVk6336B5F/6RSqRAZGYmxY8dCCIGioiKsWbMGc+bMkU7hT0lJwdmzZ+Hu7o7169cDAEJDQ7Fv3z6cOXOmTJ/hebEwEJFZWbx4MYqLi9GmTRts3boVaWlpuHTpEhYuXChd3Ao8PJwUHx+PS5cuITw8vEQ/GRkZiIqKQmpqKtavX4+vv/4akZGRZc4RFhaGGjVqoEePHjh06BDS09ORlJSEkSNH4saNGy/8OT/88ENcuXIFW7duxa5du3D79m0MHjwYjRs3lj369OkjHU4aPXo0AgICEBgYiAULFuD06dNIT0/HTz/9hD179ug158LT8FAS0cvGPO60/0R16tTB6dOnMWPGDIwZMwa3bt1CzZo10apVKyxdulRaLygoCG5ubmjUqFGpF7T2798f9+/fR5s2bWBpaYnIyEgMHTq0zDmqVq2KgwcPYty4cejduzfu3LmDWrVqITAw0CC30XF0dET//v0xefJkeHt7IygoqNQ9kT59+mD27Nk4d+4cmjZtioSEBMyfPx9xcXGIjo6GTqeDt7c3unTpgtGjR79wLsCM5mMwpYowHwNPnTS+irzNHzx4gPT0dHh7e0uTWlU2eXl5qFWrFuLi4kpM9PXGG2+gefPmvOXFY/T5m+AeAxFVKDqdDn/++SfmzJkDBwcHdO/e3dSRKh0WBiKqUDIyMuDt7Y1XXnkFq1evhpUVv8YMjVuUiCoULy+vZ17v8PgFaKQ/npVEREQyLAxERCTDwkBERDIsDEREJMPCQEREMiwMREQkw8JAREQyvI6B6CVjzFt9PM8tPQYMGIDc3Fxs375datuyZQv69esn3T8pKysLsbGx2L17N27cuCHd0rpfv34IDw9H1apVn9j/43M0VKtWDfXr18eECRPQo0ePEuvGxsZiwoQJ+OKLL/DJJ5+UWP4iOcwZ9xiIyKytWLECYWFhWLp0KcaMGYPffvsNLVq0wM8//4yZM2fizJkzOHLkCD799FPs2rULv/zyyzP7jIuLw61bt3Dy5Em0b98e7777Ls6fP19ivVWrVuHTTz/FqlWrSiwzRA5zxT0GIjJbs2fPRkxMDDZs2IBevXoBAD7++GNYWVnh5MmTskly6tSpgx49epRpFjgHBwe4urrC1dUV06ZNw4IFC5CYmIgmTZpI6xw4cAD379/H1KlTsWbNGiQnJ8tmXDNEDnPFPQYiMkvjxo3DtGnTsGvXLqko/PXXX/j5558REREh+zJ+3OOHip6lqKhImuvg0fScj6xcuRKhoaGwtrZGaGiobIpNQ+cwNywMRGR29uzZg9mzZ2PHjh0IDAyU2q9evQohBOrXry9bv0aNGtI8y+PGjXtm/6GhoVCpVFAqlRg9ejS8vLzw3nvvScu1Wq00rgEA/fr1w6ZNm5CXl2fQHOaKhYGIzE7Tpk3h5eWFmJgY6cv4aY4fP46UlBQ0atQI+fn5AICPPvpI+pJWqVSy9efNm4eUlBTs2bMHfn5+WLFihWzO5PXr16Nu3bpo1qwZAKB58+bw9PTExo0b9c5REbEwEJHZqVWrFpKSknDz5k107twZd+7cAQD4+PhAoVAgNTVVtn6dOnVKzLE8depU2fzJj3N1dYWPjw/efvttxMXFoW/fvsjJyZGWr1y5Ev/9739hZWUlPS5evCgNQuuToyJiYSAis+Tp6YkDBw4gKytLKg5OTk7o1KkTFi1ahLt37z719c7OzvDx8ZEeT9KmTRu0atUKM2bMAACcP38eJ0+eRFJSkqywJCUl4ciRI7h8+bJeOSoiFgYiMlseHh5ISkpCTk4OgoODodVqsWTJEhQVFaF169bYuHEjLl26hNTUVHz33Xe4fPkyLC0t9X6fUaNGYdmyZbh58yZWrlyJNm3aoEOHDmjcuLH06NChA1599VVpELo8cpgLnq5K9JKpaHN3v/LKK0hKSsKbb76J4OBg/PTTTzhz5gxmzpyJ6Oho3LhxA0qlEn5+fhg7diw+/vhjvd+jc+fO8Pb2xowZM7Bp06YnDhz36dMHc+bMwcyZM1G3bl2D5zAXClGRT7Y1EK1WC7VaDY1GA3t7e1PHKVVFnpi+oqrI21yfid/p5aDP3wQPJRERkQwLAxERybAwEBGRDAsDERHJsDAQVWI8t4Qe0edvgYWBqBKytrYGANy7d8/ESchcPPpbePS38TS8joGoErK0tISDg4N0m4eqVatW6Lt90vMTQuDevXvIycmBg4NDmS68Y2EgqqRcXV0BQHYPIHp5PZqDoizMujAUFxdj8uTJ+O6775CVlQV3d3cMGDAAEyZMkP77EUIgJiYGy5cvR25uLtq3b4+lS5fC19fXxOmJTEuhUMDNzQ3Ozs4oLCw0dRwyIWtra71u0WHWhWHWrFlYunQp4uPj0ahRI5w8eRIDBw6EWq3GyJEjATyc4WnhwoWIj4+Ht7c3Jk6ciODgYFy8eJFXfBLh4WGlinzfHjI+sy4MycnJ6NGjB7p16wYA8PLywvr163H8+HEAD/cW5s+fL5vIe82aNXBxccH27dvx/vvvmyw7EVFFZdZnJbVr1w4JCQm4cuUKAODs2bM4fPgwunTpAgBIT09HVlYWgoKCpNeo1Wq0bdsWR44ceWK/+fn50Gq1sgcRET1k1nsM48ePh1arRYMGDWBpaYni4mLMmDEDYWFhAICsrCwAgIuLi+x1Li4u0rLSxMbGYsqUKeUXnIioAjPrPYZNmzZh7dq1WLduHU6fPo34+Hh89dVXiI+Pf6F+o6OjodFopEdmZqaBEhMRVXxmvcfwySefYPz48dJYQZMmTfD7778jNjYW4eHh0qlX2dnZcHNzk16XnZ2N5s2bP7FfpVIJpVJZrtmJiCoqs95juHfvHiws5BEtLS2h0+kAAN7e3nB1dUVCQoK0XKvV4tixYwgICDBqViKiysKs9xjeeecdzJgxA7Vr10ajRo1w5swZzJ07F4MGDQLw8DztUaNGYfr06fD19ZVOV3V3d0fPnj1NG56IqIIy68Lw9ddfY+LEifj444+Rk5MDd3d3fPjhh5g0aZK0zqeffoq7d+9i6NChyM3NxWuvvYa9e/fyGgYioufEqT3BqT3LilN7Gt/Lts3JPOg9xhATE4Pff/+9PLIQEZEZ0Lsw7NixA3Xr1kVgYCDWrVuH/Pz88shFREQmondhSElJwYkTJ9CoUSNERkbC1dUVw4YNw4kTJ8ojHxERGdlzna7aokULLFy4EH/88QdWrlyJGzduoH379mjatCkWLFgAjUZj6JxERGQkL3QdgxAChYWFKCgogBAC1atXx6JFi+Dh4YGNGzcaKiMRERnRcxWGU6dOYfjw4XBzc8Po0aPRokULXLp0CQcOHEBaWhpmzJgh3Ra70lAoTPsgIjISvQtDkyZN4O/vj/T0dKxcuRKZmZn44osv4OPjI60TGhqK//3vfwYNSkRExqH3BW7vvfceBg0ahFq1aj1xnRo1aki3rSAioopF78IwceLE8shBRERmQu9DSX369MGsWbNKtM+ePRshISEGCUVERKajd2E4ePAgunbtWqK9S5cuOHjwoEFCERGR6ehdGPLy8mBjY1Oi3dramlNkEhFVAs91VlJp1yhs2LABfn5+BglFRESm81yDz71798a1a9fw1ltvAQASEhKwfv16bN682eABiYjIuPQuDO+88w62b9+OmTNnYsuWLbC1tUXTpk3xyy+/oGPHjuWRkYiIjOi5Jurp1q0bunXrZugsRERkBsx6zmciIjI+vfcYiouLMW/ePGzatAkZGRkoKCiQLf/7778NFo6IiIxP7z2GKVOmYO7cuejbty80Gg2ioqLQu3dvWFhYYPLkyeUQkYiIjEnvwrB27VosX74cY8aMgZWVFUJDQ7FixQpMmjQJR48eLY+MRERkRHoXhqysLDRp0gQAoFKppEl5/vWvf2H37t2GTUdEREand2F45ZVXcOvWLQBA3bp18fPPPwMATpw4AaVSadh0RERkdHoXhl69eiEhIQEAMGLECEycOBG+vr7o378/Bg0aZPCARERkXHqflfTFF19IP/ft2xeenp5ITk6Gr68v3nnnHYOGIyIi49OrMBQWFuLDDz/ExIkT4e3tDQDw9/eHv79/uYQjIiLj0+tQkrW1NbZu3VpeWYiIyAzoPcbQs2dPbN++vRyiEBGROdB7jMHX1xdTp07Fr7/+ilatWsHOzk62fOTIkQYLR0RExqcQQgh9XvBobKHUzhQK/Pbbby8cyti0Wi3UajU0Gg3s7e1LX0mhMG6of779ZJO+PQBAxOj1p1LhKaaY9ncOvHzbnMyD3nsM6enp5ZGDiIjMBO+uSkREMnrvMTzrIrZVq1Y9dxgiIjI9vQvD7du3Zc8LCwtx4cIF5ObmSlN9EhFRxaV3Ydi2bVuJNp1Oh2HDhqFu3boGCUVERKZjkDEGCwsLREVFYd68eYbojoiITMhgg8/Xrl1DUVGRobojIiIT0ftQUlRUlOy5EAK3bt3C7t27ER4ebrBgRERkGnrvMZw5c0b2OHfuHABgzpw5mD9/vqHz4ebNm+jXrx+cnJxga2uLJk2a4OTJk9JyIQQmTZoENzc32NraIigoCGlpaQbPQUT0stB7jyExMbE8cpTq9u3baN++Pd58803s2bMHNWvWRFpaGqpXry6tM3v2bCxcuBDx8fHw9vbGxIkTERwcjIsXL6JKlSpGy0pEVFk815XPRUVF8PX1lbWnpaXB2toaXl5ehsqGWbNmwcPDA3FxcVLb47fkEEJg/vz5mDBhAnr06AEAWLNmDVxcXLB9+3a8//77BstCRPSy0PtQ0oABA5CcnFyi/dixYxgwYIAhMkl27tyJ1q1bIyQkBM7OzmjRogWWL18uLU9PT0dWVhaCgoKkNrVajbZt2+LIkSNP7Dc/Px9arVb2ICKih55rjKF9+/Yl2v39/ZGSkmKITJLffvsNS5cuha+vL3766ScMGzYMI0eORHx8PAAgKysLAODi4iJ7nYuLi7SsNLGxsVCr1dLDw8PDoLmJiCoyvQuDQqHAnTt3SrRrNBoUFxcbJNQjOp0OLVu2xMyZM9GiRQsMHToUQ4YMwTfffPNC/UZHR0Oj0UiPzMxMAyUmIqr49C4MHTp0QGxsrKwIFBcXIzY2Fq+99ppBw7m5ucHPz0/W1rBhQ2RkZAAAXF1dAQDZ2dmydbKzs6VlpVEqlbC3t5c9iIjoIb0Hn2fNmoUOHTqgfv36eP311wEAhw4dglarxf79+w0arn379khNTZW1XblyBZ6engAeDkS7uroiISEBzZs3B/BwboVjx45h2LBhBs1CRPSy0HuPwc/PD+fOncN7772HnJwc3LlzB/3798fly5fRuHFjg4YbPXo0jh49ipkzZ+Lq1atYt24dvv32W0RERAB4eFhr1KhRmD59Onbu3Inz58+jf//+cHd3R8+ePQ2ahYjoZaH3HgMAuLu7Y+bMmYbOUsKrr76Kbdu2ITo6GlOnToW3tzfmz5+PsLAwaZ1PP/0Ud+/exdChQ5Gbm4vXXnsNe/fu5TUMRETPSe+pPePi4qBSqRASEiJr37x5M+7du1chb4vBqT3L5mWbZpJTe9LLSu9DSbGxsahRo0aJdmdnZ6PsRRARUfnSuzBkZGTIrj5+xNPTUzpbiIiIKi69C4Ozs7N047zHnT17Fk5OTgYJRUREpqN3YQgNDcXIkSORmJiI4uJiFBcXY//+/YiMjOS9iYiIKgG9z0qaNm0arl+/jsDAQFhZPXy5TqdD//79OcZARFQJ6F0YbGxssHHjRkybNg1nz56V5kh4dNEZERFVbM91HQMA1KtXD/Xq1TNkFiIiMgPPVRhu3LiBnTt3IiMjAwUFBbJlc+fONUgwIiIyDb0LQ0JCArp37446depIt8G4fv06hBBo2bJleWQkIiIj0vuspOjoaIwdOxbnz59HlSpVsHXrVmRmZqJjx44lroYmIqKKR+/CcOnSJfTv3x8AYGVlhfv370OlUmHq1KmYNWuWwQMSEZFx6V0Y7OzspHEFNzc3XLt2TVr2559/Gi4ZERGZhN5jDP7+/jh8+DAaNmyIrl27YsyYMTh//jy+//57+Pv7l0dGIiIyIr0Lw9y5c5GXlwcAmDJlCvLy8rBx40b4+vryjCQiokpA78JQp04d6Wc7O7sXnn+ZiIjMi95jDEREVLmxMBARkQwLAxERybAwEBGRDAsDERHJlOmspKioqDJ3yFNWiYgqtjIVhjNnzpSpM4VC8UJhiIjI9MpUGBITE8s7BxERmQmOMRARkcxzTdRz8uRJbNq0qdSJer7//nuDBCMiItPQe49hw4YNaNeuHS5duoRt27ahsLAQ//3vf7F//36o1eryyEhEREakd2GYOXMm5s2bhx9++AE2NjZYsGABLl++jPfeew+1a9cuj4xERGREeheGa9euoVu3bgAAGxsb3L17FwqFAqNHj8a3335r8IBERGRceheG6tWr486dOwCAWrVq4cKFCwCA3Nxc3Lt3z7DpiIjI6PQefO7QoQP27duHJk2aICQkBJGRkdi/fz/27duHwMDA8shIRERGpHdhWLRoER48eAAA+Pzzz2FtbY3k5GT06dMHEyZMMHhAIiIyLr0Lg6Ojo/SzhYUFxo8fb9BARERkWnqPMQQFBWH16tXQarXlkYeIiExM78LQqFEjREdHw9XVFSEhIdixYwcKCwvLIxsREZmA3oVhwYIFuHnzJrZv3w47Ozv0798fLi4uGDp0KA4cOFAeGYmIyIie615JFhYWePvtt7F69WpkZ2dj2bJlOH78ON566y1D5yMiIiN7rnslPZKVlYUNGzbgu+++w7lz59CmTRtD5SIiIhPRe49Bq9UiLi4OnTp1goeHB5YuXYru3bsjLS0NR48eLY+Mki+++AIKhQKjRo2S2h48eICIiAg4OTlBpVKhT58+yM7OLtccRESVmd57DC4uLqhevTr69u2L2NhYtG7dujxylXDixAksW7YMTZs2lbWPHj0au3fvxubNm6FWqzF8+HD07t0bv/76q1FyERFVNnoXhp07dyIwMBAWFsabyiEvLw9hYWFYvnw5pk+fLrVrNBqsXLkS69atk8Y34uLi0LBhQxw9ehT+/v5Gy0hEVFno/e3eqVMn6HQ6/PLLL1i2bJl036Q//vgDeXl5Bg8IABEREejWrRuCgoJk7adOnUJhYaGsvUGDBqhduzaOHDnyxP7y8/Oh1WplDyIiekjvPYbff/8dnTt3RkZGBvLz89GpUydUq1YNs2bNQn5+Pr755huDBtywYQNOnz6NEydOlFiWlZUFGxsbODg4yNpdXFyQlZX1xD5jY2MxZcoUg+YkIqos9N5jiIyMROvWrXH79m3Y2tpK7b169UJCQoJBw2VmZiIyMhJr165FlSpVDNZvdHQ0NBqN9MjMzDRY30REFZ3eewyHDh1CcnIybGxsZO1eXl64efOmwYIBDw8V5eTkoGXLllJbcXExDh48iEWLFuGnn35CQUEBcnNzZXsN2dnZcHV1fWK/SqUSSqXSoFmJiCoLvQuDTqdDcXFxifYbN26gWrVqBgn1SGBgIM6fPy9rGzhwIBo0aIBx48bBw8MD1tbWSEhIQJ8+fQAAqampyMjIQEBAgEGzEBG9LPQuDG+//Tbmz58vzdamUCiQl5eHmJgYdO3a1aDhqlWrhsaNG8va7Ozs4OTkJLUPHjwYUVFRcHR0hL29PUaMGIGAgACekURE9Jz0Lgxz5sxBcHAw/Pz88ODBA/z73/9GWloaatSogfXr15dHxqeaN28eLCws0KdPH+Tn5yM4OBhLliwxeg4iospCIYQQ+r6oqKgIGzZswLlz55CXl4eWLVsiLCxMNhhdkWi1WqjVamg0Gtjb25e+kkJh3FD/fPvJJn17AICI0ftPpUJTTDHt7xx4+bY5mYfnuleSlZUV+vXrZ+gsRERkBspUGHbu3IkuXbrA2toaO3fufOq63bt3N0gwIiIyjTIVhp49eyIrKwvOzs7o2bPnE9dTKBSlnrFEREQVR5kKg06nK/VnIiKqfPS68rmwsBCBgYFIS0srrzxERGRiehUGa2trnDt3rryyEBGRGdD7Xkn9+vXDypUryyMLERGZAb1PVy0qKsKqVavwyy+/oFWrVrCzs5Mtnzt3rsHCERGR8eldGC5cuCDd1O7KlSsGD0RERKald2FITEwsjxxERGQm9B5jGDRokDRr2+Pu3r2LQYMGGSQUERGZjt6FIT4+Hvfv3y/Rfv/+faxZs8YgoYiIyHTKfChJq9VCCAEhBO7cuSObUa24uBg//vgjnJ2dyyUkEREZT5kLg4ODAxQKBRQKBerVq1diuUKh4DzKRESVQJkLQ2JiIoQQeOutt7B161Y4OjpKy2xsbODp6Ql3d/dyCUlERMZT5sLQsWNHAEB6ejpq164NhYnnJyAiovKh9+Czp6cnDh8+jH79+qFdu3a4efMmAOA///kPDh8+bPCARERkXHoXhq1btyI4OBi2trY4ffo08vPzAQAajQYzZ840eEAiIjIuvQvD9OnT8c0332D58uWwtraW2tu3b4/Tp08bNBwRERmf3oUhNTUVHTp0KNGuVquRm5triExERGRCehcGV1dXXL16tUT74cOHUadOHYOEIiIi09G7MAwZMgSRkZE4duwYFAoF/vjjD6xduxZjx47FsGHDyiMjEREZkd430Rs/fjx0Oh0CAwNx7949dOjQAUqlEmPHjsWIESPKIyMRERmRQgghnueFBQUFuHr1KvLy8uDn5weVSoX79+/D1tbW0BnLnVarhVqthkajgb29fekrmfi6DcVkk749AEDEPNefSoWlmGL6a3Vetm1O5kHvQ0mP2NjYwM/PD23atIG1tTXmzp0Lb29vQ2YjIiITKHNhyM/PR3R0NFq3bo127dph+/btAIC4uDh4e3tj3rx5GD16dHnlJCIiIynzGMOkSZOwbNkyBAUFITk5GSEhIRg4cCCOHj2KuXPnIiQkBJaWluWZlYiIjKDMhWHz5s1Ys2YNunfvjgsXLqBp06YoKirC2bNned8kIqJKpMyHkm7cuIFWrVoBABo3bgylUonRo0ezKBARVTJlLgzFxcWwsbGRnltZWUGlUpVLKCIiMp0yH0oSQmDAgAFQKpUAgAcPHuCjjz6CnZ2dbL3vv//esAmJiMioylwYwsPDZc/79etn8DBERGR6ZS4McXFx5ZmDiIjMxHNf4EZERJUTCwMREcmwMBARkQwLAxERyZh1YYiNjcWrr76KatWqwdnZGT179kRqaqpsnQcPHiAiIgJOTk5QqVTo06cPsrOzTZSYiKjiM+vCcODAAURERODo0aPYt28fCgsL8fbbb+Pu3bvSOqNHj8YPP/yAzZs348CBA/jjjz/Qu3dvE6YmIqrYnns+BlP43//+B2dnZxw4cAAdOnSARqNBzZo1sW7dOrz77rsAgMuXL6Nhw4Y4cuQI/P39y9Qv52Mom5dtbgDOx0AvK7PeY/gnjUYDAHB0dAQAnDp1CoWFhQgKCpLWadCgAWrXro0jR448sZ/8/HxotVrZg4iIHqowhUGn02HUqFFo3749GjduDADIysqCjY0NHBwcZOu6uLggKyvriX3FxsZCrVZLDw8Pj/KMTkRUoVSYwhAREYELFy5gw4YNL9xXdHQ0NBqN9MjMzDRAQiKiyqHMt8QwpeHDh2PXrl04ePAgXnnlFand1dUVBQUFyM3Nle01ZGdnw9XV9Yn9KZVK6WaAREQkZ9Z7DEIIDB8+HNu2bcP+/ftLzCndqlUrWFtbIyEhQWpLTU1FRkYGAgICjB2XiKhSMOs9hoiICKxbtw47duxAtWrVpHEDtVoNW1tbqNVqDB48GFFRUXB0dIS9vT1GjBiBgICAMp+RREREcmZdGJYuXQoAeOONN2TtcXFxGDBgAABg3rx5sLCwQJ8+fZCfn4/g4GAsWbLEyEmJiCoPsy4MZbnEokqVKli8eDEWL15shERERJWfWY8xEBGR8bEwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRDAsDERHJsDAQEZEMCwMREcmwMBARkQwLAxERybAwEBGRTKUpDIsXL4aXlxeqVKmCtm3b4vjx46aORERUIVWKwrBx40ZERUUhJiYGp0+fRrNmzRAcHIycnBxTRyMiqnAUQghh6hAvqm3btnj11VexaNEiAIBOp4OHhwdGjBiB8ePHl1g/Pz8f+fn50nONRoPatWsjMzMT9vb2pb+JWl0u2ctKXfJjGJ0mWmPqCEaljjXt7xwo2zavVq0aFAqFEdLQy6LCF4aCggJUrVoVW7ZsQc+ePaX28PBw5ObmYseOHSVeM3nyZEyZMsWIKYnKj0ajefI/NETPwcrUAV7Un3/+ieLiYri4uMjaXVxccPny5VJfEx0djaioKOm5TqfD33//DScnJ7P8z0ur1cLDw+PpezRkUBVpm1erVs3UEaiSqfCF4XkolUoolUpZm4ODg2nC6MHe3t7sv6QqG25zehlV+MHnGjVqwNLSEtnZ2bL27OxsuLq6migVEVHFVeELg42NDVq1aoWEhASpTafTISEhAQEBASZMRkRUMVWKQ0lRUVEIDw9H69at0aZNG8yfPx93797FwIEDTR3NIJRKJWJiYkoc/qLyw21OL7MKf1bSI4sWLcKXX36JrKwsNG/eHAsXLkTbtm1NHYuIqMKpNIWBiIgMo8KPMRARkWGxMBARkQwLAxERybAwvGTeeOMNjBo1yuD9rl69ukJcJGhoAwYMkN2KxVCSkpKgUCiQm5tr8L6JnuWlLgxP+pI0py+58voirwgGDBgAhUIBhUIBGxsb+Pj4YOrUqSgqKnqhPsvji5yoMqkU1zFURgUFBbCxsTHb/oylc+fOiIuLQ35+Pn788UdERETA2toa0dHRevVTXFxs0PtgGbo/InPyUu8xlMWj/zC/+uoruLm5wcnJCRERESgsLJTW8fLywrRp0xAaGgo7OzvUqlULixcvlvWTm5uLDz74ADVr1oS9vT3eeustnD17Vlo+efJkNG/eHCtWrIC3tzeqVKmCAQMG4MCBA1iwYIH0n/P169dL3aPZvn277IuqtP4eKSoqwvDhw6FWq1GjRg1MnDgRj5+1nJ+fj7Fjx6JWrVqws7ND27ZtkZSUJHu/1atXo3bt2qhatSp69eqFv/7660U28xMplUq4urrC09MTw4YNQ1BQEHbu3PnMjI+20c6dO+Hn5welUolBgwYhPj4eO3bskLZnUlJSqYdtUlJSpO39pP4yMjKk9adMmSL9bj/66CMUFBRIy3Q6HWJjY+Ht7Q1bW1s0a9YMW7ZskX3OH3/8EfXq1YOtrS3efPNN6X2JTIF7DGWQmJgINzc3JCYm4urVq+jbty+aN2+OIUOGSOt8+eWX+OyzzzBlyhT89NNPiIyMRL169dCpUycAQEhICGxtbbFnzx6o1WosW7YMgYGBuHLlChwdHQEAV69exdatW/H999/D0tISnp6euHLlCho3boypU6cCAGrWrFnm3P/s75H4+HgMHjwYx48fx8mTJzF06FDUrl1b+jzDhw/HxYsXsWHDBri7u2Pbtm3o3Lkzzp8/D19fXxw7dgyDBw9GbGwsevbsib179yImJuaFt3NZ2Nra4q+//npmRgC4d+8eZs2ahRUrVsDJyQlubm64f/8+tFot4uLiAACOjo5ITk4u03v/sz9nZ2cAQEJCAqpUqYKkpCRcv34dAwcOhJOTE2bMmAEAiI2NxXfffYdvvvkGvr6+OHjwIPr164eaNWuiY8eOyMzMRO/evREREYGhQ4fi5MmTGDNmTDlsPaIyEi+xjh07isjIyBLtcXFxQq1WCyGECA8PF56enqKoqEhaHhISIvr27Ss99/T0FJ07d5b10bdvX9GlSxchhBCHDh0S9vb24sGDB7J16tatK5YtWyaEECImJkZYW1uLnJycZ2Z8PN8j27ZtE4//Op/WX8OGDYVOp5Paxo0bJxo2bCiEEOL3338XlpaW4ubNm7LXBQYGiujoaCGEEKGhoaJr164lPu8/M72o8PBw0aNHDyGEEDqdTuzbt08olUoxYMCAZ2aMi4sTAERKSsoT+3wkMTFRABC3b9+W2s6cOSMAiPT09Gf25+joKO7evSu1LV26VKhUKlFcXCwePHggqlatKpKTk2WvGzx4sAgNDRVCCBEdHS38/Pxky8eNG1ciE5GxcI+hDBo1aiT7j9vNzQ3nz5+XrfPPG/YFBARg/vz5AICzZ88iLy8PTk5OsnXu37+Pa9euSc89PT312iN4lif15+/vLzvsFBAQgDlz5qC4uBjnz59HcXEx6tWrJ3tNfn6+lP/SpUvo1auXbHlAQAD27t1rsOyP7Nq1CyqVCoWFhdDpdPj3v/+Nd999F6tXr35qRuDhDRabNm1qsCxP6q9Zs2aoWrWq9DwgIAB5eXnIzMxEXl4e7t27J+05PlJQUIAWLVoAeLg9/3n7Ft4AkkzppS4M9vb20GhKTp2Ym5sL9WNTeVpbW8uWKxQK6HS6Mr9PXl4e3NzcShynB+TzQNjZ2ZWpPwsLC9mYAADZmIe+/T0uLy8PlpaWOHXqlKwYAoBKpdK7vxf15ptvYunSpbCxsYG7uzusrKywcePGMmW0tbUt0wCxhcXDobbHt2lp27Os/T0uLy8PALB7927UqlVLtow36CNz9VIXhvr16+Pnn38u0X769OkS/40+y9GjR0s8b9iwIQCgZcuWyMrKgpWVFby8vPTq18bGBsXFxbK2mjVr4s6dO7h796705Z+SklLmPo8dO1Yiq6+vLywtLdGiRQsUFxcjJycHr7/+eqmvb9iwYal9lAc7Ozv4+PjI2sqS8UmetD0B4NatW6hevToA/bbn2bNncf/+fdja2gJ4uC1UKhU8PDzg6OgoDVR37Nix1Nc3bNgQO3fulLWV1/YkKouX+qykYcOG4cqVKxg5ciTOnTuH1NRUzJ07F+vXr9d78O/XX3/F7NmzceXKFSxevBibN29GZGQkACAoKAgBAQHo2bMnfv75Z1y/fh3Jycn4/PPPcfLkyaf26+XlhWPHjuH69ev4888/odPp0LZtW1StWhWfffYZrl27hnXr1mH16tVlzpqRkYGoqCikpqZi/fr1+Prrr6Ws9erVQ1hYGPr374/vv/8e6enpOH78OGJjY7F7924AwMiRI7F371589dVXSEtLw6JFi8rlMNKTlCXjk3h5eUm/6z///BOFhYXw8fGBh4cHJk+ejLS0NOzevRtz5swpc56CggIMHjwYFy9exI8//oiYmBgMHz4cFhYWqFatGsaOHYvRo0cjPj4e165dw+nTp/H1118jPj4eAPDRRx8hLS0Nn3zyCVJTU/X+fRIZnKkHOUzt+PHjolOnTqJmzZpCrVaLtm3bim3btknLSxusjIyMFB07dpSee3p6iilTpoiQkBBRtWpV4erqKhYsWCB7jVarFSNGjBDu7u7C2tpaeHh4iLCwMJGRkSGEeDhY3KxZsxL5UlNThb+/v7C1tZUNhm7btk34+PgIW1tb8a9//Ut8++23JQafS+uvY8eO4uOPPxYfffSRsLe3F9WrVxefffaZbDC6oKBATJo0SXh5eQlra2vh5uYmevXqJc6dOyets3LlSvHKK68IW1tb8c4774ivvvqqXAef/+lZGUsboBdCiJycHNGpUyehUqkEAJGYmCiEEOLw4cOiSZMmokqVKuL1118XmzdvLjH4XFp/jzJOmjRJODk5CZVKJYYMGSI70UCn04n58+eL+vXrC2tra1GzZk0RHBwsDhw4IK3zww8/CB8fH6FUKsXrr78uVq1axcFnMhnedtsAvLy8MGrUqJf2CmUiqlxe6kNJRERUEgsDERHJ8FASERHJcI+BiIhkWBiIiEiGhYGIiGRYGIiISIaFgYiIZFgYiIhIhoWBiIhkWBiIiEjm/wCdJXLMmTxGVwAAAABJRU5ErkJggg==", + "text/plain": [ + "<Figure size 400x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "categories = ['Unperturbed', 'Perturbed']\n", + "neo4j_rag_percentage = [neo4j_rag_total_correct_retrieval_percentage, neo4j_rag_total_correct_retrieval_perturbed_percentage]\n", + "kg_rag_percentage = [kg_rag_total_correct_retrieval_percentage, kg_rag_total_correct_retrieval_perturbed_percentage]\n", + "\n", + "neo4j_color = 'red'\n", + "kg_rag_color = 'green'\n", + "\n", + "fig, ax = plt.subplots(figsize=(4, 3))\n", + "\n", + "bar_width = 0.35\n", + "index = range(len(categories))\n", + "\n", + "ax.bar(index, neo4j_rag_percentage, bar_width, color=neo4j_color, label='Cypher-RAG')\n", + "ax.bar([i + bar_width for i in index], kg_rag_percentage, bar_width, color=kg_rag_color, label='KG-RAG')\n", + "\n", + "ax.set_ylabel('Retrieval accuracy')\n", + "ax.set_xticks([i + bar_width / 2 for i in index])\n", + "ax.set_xticklabels(categories)\n", + "\n", + "\n", + "ax.legend(loc='center left', bbox_to_anchor=(1, 0.9))\n", + "\n", + "sns.despine()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "fig.savefig(os.path.join(fig_path, 'retrieval_accuracy_comparison.svg'), format='svg', bbox_inches='tight') \n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "ecf8bd99", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[75.0, 0.0]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "neo4j_rag_percentage" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "5f316867", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[97.0, 97.0]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg_rag_percentage" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "269c8dc7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8006" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(neo4j_avg)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "56494f88", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3693" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "round(kg_avg)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/rag_comparison_questions.ipynb b/notebooks/rag_comparison_questions.ipynb new file mode 100644 index 0000000..2eadac4 --- /dev/null +++ b/notebooks/rag_comparison_questions.ipynb @@ -0,0 +1,272 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 171, + "id": "403d179c", + "metadata": {}, + "outputs": [], + "source": [ + "from neo4j import GraphDatabase, basic_auth\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import pickle\n", + "import random\n", + "import pandas as pd\n" + ] + }, + { + "cell_type": "markdown", + "id": "80ee9a49", + "metadata": {}, + "source": [ + "## Set number of questions to generate" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "id": "fa80e37b", + "metadata": {}, + "outputs": [], + "source": [ + "N_QUESTIONS = 100\n" + ] + }, + { + "cell_type": "markdown", + "id": "ac046718", + "metadata": {}, + "source": [ + "## Load KG credentials" + ] + }, + { + "cell_type": "code", + "execution_count": 173, + "id": "8d41be45", + "metadata": {}, + "outputs": [], + "source": [ + "load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + "username = os.environ.get('NEO4J_USER')\n", + "password = os.environ.get('NEO4J_PSW')\n", + "url = os.environ.get('NEO4J_URI')\n", + "database = os.environ.get('NEO4J_DB')\n" + ] + }, + { + "cell_type": "markdown", + "id": "cf3354e7", + "metadata": {}, + "source": [ + "## Load disease names stored in vectorDB" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "id": "2ec9d667", + "metadata": {}, + "outputs": [], + "source": [ + "with open('../data/disease_with_relation_to_genes.pickle', 'rb') as f:\n", + " disease_names = pickle.load(f)\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "654a9a58", + "metadata": {}, + "source": [ + "## Extract GWAS Disease-Gene relation from the KG" + ] + }, + { + "cell_type": "code", + "execution_count": 175, + "id": "c280e781", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 158 ms, sys: 19.6 ms, total: 178 ms\n", + "Wall time: 550 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "auth = basic_auth(username, password)\n", + "sdb = GraphDatabase.driver(url, auth=auth)\n", + "\n", + "gwas_query = '''\n", + " MATCH (d:Disease)-[r:ASSOCIATES_DaG]->(g:Gene)\n", + " WHERE r.sources = ['GWAS']\n", + " WITH d, g, r.gwas_pvalue AS pvalue\n", + " ORDER BY pvalue\n", + " WITH d, COLLECT(g)[0] AS gene_with_lowest_pvalue, pvalue\n", + " RETURN d.name AS disease_name, gene_with_lowest_pvalue.name AS gene_name, pvalue\n", + "'''\n", + "\n", + "with sdb.session() as session:\n", + " with session.begin_transaction() as tx:\n", + " result = tx.run(gwas_query)\n", + " out_list = []\n", + " for row in result:\n", + " out_list.append((row['disease_name'], row['gene_name'], row['pvalue']))\n", + "\n", + "gwas_disease_names = pd.DataFrame(out_list, columns=['disease_name', 'gene_name', 'gwas_pvalue']).drop_duplicates()\n", + "sdb.close()\n", + "\n", + "gwas_disease_names = gwas_disease_names[gwas_disease_names.disease_name.isin(disease_names)]\n" + ] + }, + { + "cell_type": "markdown", + "id": "0db2757f", + "metadata": {}, + "source": [ + "## Create test questions from the extracted relationships" + ] + }, + { + "cell_type": "code", + "execution_count": 176, + "id": "9fe85753", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 97.3 ms, sys: 1.08 ms, total: 98.4 ms\n", + "Wall time: 97.7 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "template_questions = [\n", + " 'Is {} associated with {}?',\n", + " 'What is the GWAS p-value for the association between {} and {}?'\n", + "]\n", + "\n", + "test_questions = []\n", + "random.seed(42)\n", + "for index,row in gwas_disease_names.iterrows():\n", + " selected_question = random.choice(template_questions)\n", + " if random.random() < 0.5:\n", + " test_questions.append(selected_question.format(row['disease_name'], row['gene_name']))\n", + " else:\n", + " test_questions.append(selected_question.format(row['gene_name'], row['disease_name']))\n", + "\n", + "gwas_disease_names.loc[:,'question'] = test_questions\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "2f1800f5", + "metadata": {}, + "source": [ + "## Create perturbed test questions (lower case names) from the extracted relationships" + ] + }, + { + "cell_type": "code", + "execution_count": 177, + "id": "c788c8d2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 96 ms, sys: 962 µs, total: 97 ms\n", + "Wall time: 96.3 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "template_questions = [\n", + " 'Is {} associated with {}?',\n", + " 'What is the GWAS p-value for the association between {} and {}?'\n", + "]\n", + "\n", + "test_questions_perturbed = []\n", + "random.seed(42)\n", + "for index,row in gwas_disease_names.iterrows():\n", + " selected_question = random.choice(template_questions)\n", + " if random.random() < 0.5:\n", + " test_questions_perturbed.append(selected_question.format(row['disease_name'].lower(), row['gene_name'].lower()))\n", + " else:\n", + " test_questions_perturbed.append(selected_question.format(row['gene_name'].lower(), row['disease_name'].lower()))\n", + "\n", + "gwas_disease_names.loc[:,'question_perturbed'] = test_questions_perturbed\n", + "\n", + "gwas_disease_names_selected = gwas_disease_names.sample(N_QUESTIONS, random_state=42)\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "06eed996", + "metadata": {}, + "source": [ + "## Save the test data" + ] + }, + { + "cell_type": "code", + "execution_count": 178, + "id": "7f02bb5b", + "metadata": {}, + "outputs": [], + "source": [ + "gwas_disease_names_selected = gwas_disease_names.sample(N_QUESTIONS, random_state=42)\n", + "\n", + "gwas_disease_names_selected.to_csv('../data/rag_comparison_data.csv', index=False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea680eb0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/true_false_analysis.ipynb b/notebooks/true_false_analysis.ipynb new file mode 100644 index 0000000..f27a14a --- /dev/null +++ b/notebooks/true_false_analysis.ipynb @@ -0,0 +1,448 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "e38c27d7-ebfe-406f-aa9f-07f9d6662d52", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "from tqdm import tqdm\n", + "import re\n", + "from scipy import stats\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f3c91843", + "metadata": {}, + "outputs": [], + "source": [ + "def extract_answer(text):\n", + " pattern = r\"(True|False|Don't know)\"\n", + " matches = re.findall(pattern, text)\n", + " return matches\n", + "\n", + "def process_df(prompt_response_df, rag_response_df):\n", + " prompt_response_df.loc[:, \"answer_count\"] = prompt_response_df.extracted_answer.apply(lambda x:len(x))\n", + " prompt_response_df_multiple_answers = prompt_response_df[prompt_response_df.answer_count > 1]\n", + " prompt_response_df_single_answer = prompt_response_df.drop(prompt_response_df_multiple_answers.index)\n", + " prompt_response_df_single_answer.drop(\"answer_count\", axis=1, inplace=True)\n", + " prompt_response_df_multiple_answers_ = []\n", + " for index, row in prompt_response_df_multiple_answers.iterrows():\n", + " if row[\"extracted_answer\"][0] == row[\"extracted_answer\"][1]:\n", + " prompt_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], row[\"extracted_answer\"][0]))\n", + " else:\n", + " prompt_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], None))\n", + " prompt_response_df_multiple_answers_ = pd.DataFrame(prompt_response_df_multiple_answers_, columns=[\"question\", \"label\", \"llm_answer\", \"extracted_answer\"])\n", + " prompt_response_df_final = pd.concat([prompt_response_df_single_answer, prompt_response_df_multiple_answers_], ignore_index=True)\n", + " prompt_response_df_final = prompt_response_df_final.explode(\"extracted_answer\")\n", + "\n", + " rag_response_df.loc[:, \"answer_count\"] = rag_response_df.extracted_answer.apply(lambda x:len(x))\n", + " rag_response_df_multiple_answers = rag_response_df[rag_response_df.answer_count > 1]\n", + " rag_response_df_single_answer = rag_response_df.drop(rag_response_df_multiple_answers.index)\n", + " rag_response_df_single_answer.drop(\"answer_count\", axis=1, inplace=True)\n", + " rag_response_df_multiple_answers_ = []\n", + " for index, row in rag_response_df_multiple_answers.iterrows():\n", + " if row[\"extracted_answer\"][0] == row[\"extracted_answer\"][1]:\n", + " rag_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], row[\"extracted_answer\"][0]))\n", + " else:\n", + " rag_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], None))\n", + " rag_response_df_multiple_answers_ = pd.DataFrame(rag_response_df_multiple_answers_, columns=[\"question\", \"label\", \"llm_answer\", \"extracted_answer\"])\n", + " rag_response_df_final = pd.concat([rag_response_df_single_answer, rag_response_df_multiple_answers_], ignore_index=True)\n", + " rag_response_df_final = rag_response_df_final.explode(\"extracted_answer\")\n", + " \n", + " prompt_incorrect_answers_because_of_na = prompt_response_df_final[prompt_response_df_final.extracted_answer.isna()]\n", + " rag_incorrect_answers_because_of_na = rag_response_df_final[rag_response_df_final.extracted_answer.isna()]\n", + "\n", + " row_index_to_drop = list(prompt_incorrect_answers_because_of_na.index.values) + list(rag_incorrect_answers_because_of_na.index.values)\n", + "\n", + " prompt_response_df_final.drop(row_index_to_drop, inplace=True)\n", + " rag_response_df_final.drop(row_index_to_drop, inplace=True)\n", + "\n", + " prompt_response_df_final = prompt_response_df_final.reset_index()\n", + " rag_response_df_final = rag_response_df_final.reset_index()\n", + " response_transform = {\n", + " \"True\" : True,\n", + " \"False\" : False\n", + " }\n", + "\n", + " prompt_response_df_final.extracted_answer = prompt_response_df_final.extracted_answer.apply(lambda x:response_transform[x])\n", + " rag_response_df_final.extracted_answer = rag_response_df_final.extracted_answer.apply(lambda x:response_transform[x])\n", + "\n", + " return prompt_response_df_final, rag_response_df_final\n", + "\n", + "\n", + "def evaluate(df):\n", + " correct = df[df.label == df.extracted_answer]\n", + " incorrect = df[df.label != df.extracted_answer]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "\n", + "def bootstrap(prompt_response_df_final, rag_response_df_final, niter = 1000, nsample = 150):\n", + " prompt_correct_frac_list = []\n", + " rag_correct_frac_list = []\n", + " for i in tqdm(range(niter)):\n", + " prompt_response_df_final_sample = prompt_response_df_final.sample(n=nsample, random_state=i)\n", + " prompt_correct_frac, prompt_incorrect_frac = evaluate(prompt_response_df_final_sample)\n", + " rag_response_df_final_sample = rag_response_df_final.iloc[prompt_response_df_final_sample.index]\n", + " rag_correct_frac, rag_incorrect_frac = evaluate(rag_response_df_final_sample)\n", + " prompt_correct_frac_list.append(prompt_correct_frac)\n", + " rag_correct_frac_list.append(rag_correct_frac)\n", + " return prompt_correct_frac_list, rag_correct_frac_list\n", + "\n", + "def plot_figure(prompt_correct_frac_list, rag_correct_frac_list):\n", + " fig = plt.figure(figsize=(5, 3))\n", + " ax = plt.gca()\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "\n", + " for artist in ax.lines:\n", + " artist.set_edgecolor(\"black\")\n", + "\n", + " plt.xlabel(\"Accuracy\")\n", + " plt.ylabel(\"Density\")\n", + " plt.legend(loc=\"upper left\")\n", + " plt.xlim(0.75,1)\n", + "\n", + " ax.axvline(np.mean(prompt_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " ax.axvline(np.mean(rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + "\n", + " sns.despine(top=True, right=True)\n", + "\n", + " plt.show()\n", + " return fig\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a5723e54-a5ef-48cd-85d1-88d0fe7ea78e", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "Following files can be obtained by running the run_true_false_generation.py script.\n", + "Make sure to change the parent path and filenames based on where and how you save the files\n", + "'''\n", + "\n", + "data_path ='../data/results'\n", + "\n", + "llama_prompt_path = os.path.join(data_path, 'Llama_2_13b_chat_hf_prompt_based_true_false_binary_response.csv')\n", + "llama_kg_rag_path = os.path.join(data_path, 'Llama_2_13b_chat_hf_PubMedBert_and_entity_recognition_based_node_retrieval_rag_based_true_false_binary_response.csv')\n", + "\n", + "gpt_35_prompt_path = os.path.join(data_path, 'gpt_35_turbo_prompt_based_true_false_binary_response.csv')\n", + "gpt_35_kg_rag_path = os.path.join(data_path, 'gpt_35_turbo_PubMedBert_and_entity_recognition_based_node_retrieval_rag_based_true_false_binary_response.csv')\n", + "\n", + "gpt_4_prompt_path = os.path.join(data_path, 'gpt_4_prompt_based_true_false_binary_response.csv')\n", + "gpt_4_kg_rag_path = os.path.join(data_path, 'gpt_4_PubMedBert_and_entity_recognition_based_node_retrieval_rag_based_true_false_binary_response.csv')\n", + "\n", + "curated_data = pd.read_csv('../data/benchmark_data/true_false_questions.csv').drop('Unnamed: 0', axis=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "47f3c405", + "metadata": {}, + "outputs": [], + "source": [ + "llama_prompt_df = pd.read_csv(llama_prompt_path)\n", + "llama_prompt_df = pd.merge(curated_data, llama_prompt_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "\n", + "llama_kg_rag_df = pd.read_csv(llama_kg_rag_path)\n", + "llama_kg_rag_df = pd.merge(curated_data, llama_kg_rag_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "\n", + "gpt_35_prompt_df = pd.read_csv(gpt_35_prompt_path)\n", + "gpt_35_prompt_df = pd.merge(curated_data, gpt_35_prompt_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "\n", + "gpt_35_kg_rag_df = pd.read_csv(gpt_35_kg_rag_path)\n", + "gpt_35_kg_rag_df = pd.merge(curated_data, gpt_35_kg_rag_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "\n", + "gpt_4_prompt_df = pd.read_csv(gpt_4_prompt_path)\n", + "gpt_4_prompt_df = pd.merge(curated_data, gpt_4_prompt_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "\n", + "gpt_4_kg_rag_df = pd.read_csv(gpt_4_kg_rag_path)\n", + "gpt_4_kg_rag_df = pd.merge(curated_data, gpt_4_kg_rag_df, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0ca02159", + "metadata": {}, + "outputs": [], + "source": [ + "llama_prompt_df.loc[:, 'extracted_answer'] = llama_prompt_df['llm_answer'].apply(extract_answer)\n", + "llama_kg_rag_df.loc[:, 'extracted_answer'] = llama_kg_rag_df['llm_answer'].apply(extract_answer)\n", + "\n", + "gpt_35_prompt_df.loc[:, 'extracted_answer'] = gpt_35_prompt_df['llm_answer'].apply(extract_answer)\n", + "gpt_35_kg_rag_df.loc[:, 'extracted_answer'] = gpt_35_kg_rag_df['llm_answer'].apply(extract_answer)\n", + "\n", + "gpt_4_prompt_df.loc[:, 'extracted_answer'] = gpt_4_prompt_df['llm_answer'].apply(extract_answer)\n", + "gpt_4_kg_rag_df.loc[:, 'extracted_answer'] = gpt_4_kg_rag_df['llm_answer'].apply(extract_answer)\n", + "\n", + "llama_prompt_df, llama_kg_rag_df = process_df(llama_prompt_df, llama_kg_rag_df)\n", + "\n", + "gpt_35_prompt_df, gpt_35_kg_rag_df = process_df(gpt_35_prompt_df, gpt_35_kg_rag_df)\n", + "\n", + "gpt_4_prompt_df, gpt_4_kg_rag_df = process_df(gpt_4_prompt_df, gpt_4_kg_rag_df)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "90ccd105", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1323.05it/s]\n", + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1207.89it/s]\n", + "100%|█████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<00:00, 1168.13it/s]\n" + ] + } + ], + "source": [ + "llama_prompt_correct_frac_list, llama_rag_correct_frac_list = bootstrap(llama_prompt_df, llama_kg_rag_df)\n", + "\n", + "gpt_35_prompt_correct_frac_list, gpt_35_rag_correct_frac_list = bootstrap(gpt_35_prompt_df, gpt_35_kg_rag_df)\n", + "\n", + "gpt_4_prompt_correct_frac_list, gpt_4_rag_correct_frac_list = bootstrap(gpt_4_prompt_df, gpt_4_kg_rag_df)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "428528e7", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:80: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:81: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.8909533333333334\n", + "0.018290921852717596\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.9394266666666666\n", + "0.013815617571751504\n" + ] + } + ], + "source": [ + "llama_fig = plot_figure(llama_prompt_correct_frac_list, llama_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "llama_fig.savefig(os.path.join(fig_path, 'llama_true_false.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(llama_prompt_correct_frac_list))\n", + "print(np.std(llama_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(llama_rag_correct_frac_list))\n", + "print(np.std(llama_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "49f9f1ae", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:80: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:81: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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Wo3OnTujsrKyUe/t5OSEyZMnIzExEWPHjsXmzZuxcuXKel9DiK2iFishZqJUKrFx40YsX74cKSkpwuXChQsICwvDpk2b0KVLFxw6dKjW10dHR0OtViM5ObnWx1u1aoX79++jtLRUuE8zhlqfgoICpKWl4b333sOjjz6KBx54AIWFhXrP6dKlC1JSUnD37t06jzN16lT88ssvWLVqFRQKhd6kK0Lsith90YTYi6SkJObk5MTu3btX47F3332Xde3alR0+fJhJJBI2b948lpqayi5evMiWLFkiPC8uLo6FhoaypKQkdu3aNXb48GG2bds2xhhjBQUFzM3Njb3xxhvsypUrbNOmTSwoKKjGGGtMTIzee6tUKubr68smTZrErly5wg4dOsR69erFALCkpCTGGGNyuZxFRkayhx56iP32228sIyODbd++nR0/flzvWP369WNOTk7s5ZdfNtJZI8T6UIuVEDNZt24dhgwZAi8vrxqPjRs3DikpKfD09MSPP/6IXbt2oWvXrnjkkUdw8uRJ4XmrV6/GU089hVdffRUdOnTAiy++KLRQfXx88P3332Pv3r2Ijo7Gli1bEB8f32BcEokEW7duxdmzZ9G5c2fMmDEDy5Yt03uOk5MTDhw4AD8/Pzz22GOIjo7Gxx9/DKlUqve8F154AZWVlXj++ecNOEOE2AYqEEEIMZqFCxdi69atuHTpktihECIaarESQpqtpKQEp0+fxhdffIE33nhD7HAIERUlVkJIs73++usYMGAABg4cSN3AxO5RVzAhhBBiRNRiJYQQQoyIEishhBBiRJRYCSGEECOixEoIIYQYESVWQgghxIgosRJCCCFGRImVEEIIMSJKrIQQQogRUWIlhBBCjOj/AYlGRDIbrpPcAAAAAElFTkSuQmCC\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.87268\n", + "0.020258766003880886\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.9521866666666666\n", + "0.012250017687062069\n" + ] + } + ], + "source": [ + "gpt_35_fig = plot_figure(gpt_35_prompt_correct_frac_list, gpt_35_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "gpt_35_fig.savefig(os.path.join(fig_path, 'gpt_35_true_false.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(gpt_35_prompt_correct_frac_list))\n", + "print(np.std(gpt_35_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(gpt_35_rag_correct_frac_list))\n", + "print(np.std(gpt_35_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e9f75a7f", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:80: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(prompt_correct_frac_list, color=\"blue\", shade=True, label=\"Prompt based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_52094/309868377.py:81: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG based\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Prompt based mean and std---\n", + "0.9039666666666666\n", + "0.017877328908114005\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.9459866666666666\n", + "0.013465339868632277\n" + ] + } + ], + "source": [ + "gpt_4_fig = plot_figure(gpt_4_prompt_correct_frac_list, gpt_4_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "gpt_4_fig.savefig(os.path.join(fig_path, 'gpt_4_true_false.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Prompt based mean and std---')\n", + "print(np.mean(gpt_4_prompt_correct_frac_list))\n", + "print(np.std(gpt_4_prompt_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(gpt_4_rag_correct_frac_list))\n", + "print(np.std(gpt_4_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00bc1f64", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/true_false_cypher_rag_vs_kg_rag.ipynb b/notebooks/true_false_cypher_rag_vs_kg_rag.ipynb new file mode 100644 index 0000000..9e98fb2 --- /dev/null +++ b/notebooks/true_false_cypher_rag_vs_kg_rag.ipynb @@ -0,0 +1,533 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "038208fa-0a00-47cf-90b3-1f131c6b13b3", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import os\n", + "from tqdm import tqdm\n", + "import re\n", + "from scipy import stats\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from IPython.display import clear_output\n" + ] + }, + { + "cell_type": "markdown", + "id": "33583b95-7796-4100-ad7a-89803377abbb", + "metadata": {}, + "source": [ + "## Custom functions" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "491eabed-bbb6-4cc4-be9c-3c95559ed36d", + "metadata": {}, + "outputs": [], + "source": [ + "def extract_answer(text):\n", + " pattern = r\"(True|False|Don't know)\"\n", + " matches = re.findall(pattern, text)\n", + " return matches\n", + "\n", + "def process_df(rag_response_df):\n", + " rag_response_df.loc[:, \"answer_count\"] = rag_response_df.extracted_answer.apply(lambda x:len(x))\n", + " rag_response_df_multiple_answers = rag_response_df[rag_response_df.answer_count > 1]\n", + " rag_response_df_single_answer = rag_response_df.drop(rag_response_df_multiple_answers.index)\n", + " rag_response_df_single_answer.drop(\"answer_count\", axis=1, inplace=True)\n", + " rag_response_df_multiple_answers_ = []\n", + " for index, row in rag_response_df_multiple_answers.iterrows():\n", + " if row[\"extracted_answer\"][0] == row[\"extracted_answer\"][1]:\n", + " rag_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], row[\"extracted_answer\"][0]))\n", + " else:\n", + " rag_response_df_multiple_answers_.append((row[\"question\"], row[\"label\"], row[\"llm_answer\"], None))\n", + " rag_response_df_multiple_answers_ = pd.DataFrame(rag_response_df_multiple_answers_, columns=[\"question\", \"label\", \"llm_answer\", \"extracted_answer\"])\n", + " rag_response_df_final = pd.concat([rag_response_df_single_answer, rag_response_df_multiple_answers_], ignore_index=True)\n", + " rag_response_df_final = rag_response_df_final.explode(\"extracted_answer\")\n", + " \n", + " rag_incorrect_answers_because_of_na = rag_response_df_final[rag_response_df_final.extracted_answer.isna()]\n", + "\n", + " row_index_to_drop = list(rag_incorrect_answers_because_of_na.index.values)\n", + "\n", + " rag_response_df_final.drop(row_index_to_drop, inplace=True)\n", + "\n", + " rag_response_df_final = rag_response_df_final.reset_index()\n", + " response_transform = {\n", + " \"True\" : True,\n", + " \"False\" : False\n", + " }\n", + "\n", + " rag_response_df_final.extracted_answer = rag_response_df_final.extracted_answer.apply(lambda x:response_transform[x])\n", + "\n", + " return rag_response_df_final\n", + "\n", + "\n", + "def evaluate(df):\n", + " correct = df[df.label == df.extracted_answer]\n", + " incorrect = df[df.label != df.extracted_answer]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "def evaluate_2(df):\n", + " correct = df[df.cypher_rag_final_answer == df.label]\n", + " incorrect = df[df.cypher_rag_final_answer != df.label]\n", + " correct_frac = correct.shape[0]/df.shape[0]\n", + " incorrect_frac = incorrect.shape[0]/df.shape[0]\n", + " return correct_frac, incorrect_frac\n", + "\n", + "\n", + "def bootstrap(cypher_rag, kg_rag, niter = 1000, nsample = 150):\n", + " cypher_rag_correct_frac_list = []\n", + " kg_rag_correct_frac_list = []\n", + " for i in tqdm(range(niter)):\n", + " cypher_rag_ = cypher_rag.sample(n=nsample, random_state=i)\n", + " cypher_rag_correct_frac, cypher_rag_incorrect_frac = evaluate_2(cypher_rag_)\n", + " kg_rag_ = kg_rag.iloc[cypher_rag_.index]\n", + " kg_rag_correct_frac, kg_rag_incorrect_frac = evaluate(kg_rag_)\n", + " cypher_rag_correct_frac_list.append(cypher_rag_correct_frac)\n", + " kg_rag_correct_frac_list.append(kg_rag_correct_frac)\n", + " return cypher_rag_correct_frac_list, kg_rag_correct_frac_list\n", + "\n", + "def plot_figure(cypher_rag_correct_frac_list, kg_rag_correct_frac_list):\n", + " fig = plt.figure(figsize=(5, 3))\n", + " ax = plt.gca()\n", + "\n", + " sns.kdeplot(cypher_rag_correct_frac_list, color=\"blue\", shade=True, label=\"Cypher-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + " sns.kdeplot(kg_rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "\n", + " for artist in ax.lines:\n", + " artist.set_edgecolor(\"black\")\n", + "\n", + " plt.xlabel(\"Accuracy\")\n", + " plt.ylabel(\"Density\")\n", + " plt.legend(loc=\"upper left\")\n", + " plt.xlim(0,1)\n", + "\n", + " ax.axvline(np.mean(cypher_rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + " ax.axvline(np.mean(kg_rag_correct_frac_list), color='black', linestyle='--', lw=2)\n", + "\n", + " sns.despine(top=True, right=True)\n", + " plt.legend(bbox_to_anchor=(0.3, 0.9))\n", + "\n", + " plt.show()\n", + " return fig\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "ba398cb5-2fcf-48d1-bfb5-449821cb13d5", + "metadata": {}, + "source": [ + "## Load data and process it" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "c71243a2-b043-40fa-ab6c-700e0ad58452", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag = pd.read_csv('../data/results/cypher_rag_true_false_output.csv')\n", + "kg_rag = pd.read_csv('../data/results/gpt_4_PubMedBert_and_entity_recognition_based_node_retrieval_rag_based_true_false_binary_response.csv')\n", + "curated_data = pd.read_csv('../data/benchmark_data/true_false_questions.csv').drop('Unnamed: 0', axis=1)\n", + "\n", + "kg_rag = pd.merge(curated_data, kg_rag, left_on='text', right_on='question').drop(['text', 'label_y'], axis=1).rename(columns={'label_x':'label'})\n", + "kg_rag.loc[:, 'extracted_answer'] = kg_rag['llm_answer'].apply(extract_answer)\n", + "kg_rag = process_df(kg_rag)\n" + ] + }, + { + "cell_type": "markdown", + "id": "1cca48bf-85b9-442b-8913-c6584aa09f9d", + "metadata": {}, + "source": [ + "## Bootstrap" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "395594eb-4048-49b6-8f2d-dbe2ea38e595", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████████████████████████████████| 1000/1000 [00:01<00:00, 894.39it/s]\n" + ] + } + ], + "source": [ + "cypher_rag_correct_frac_list, kg_rag_correct_frac_list = bootstrap(cypher_rag, kg_rag)\n" + ] + }, + { + "cell_type": "markdown", + "id": "016fd3c3-6e9c-4de7-b4cd-706c4ee69e0d", + "metadata": {}, + "source": [ + "## Plot the figure" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "ec2376b0-e4ff-4f38-be91-9c8dc8dca074", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_39048/2066733470.py:69: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(cypher_rag_correct_frac_list, color=\"blue\", shade=True, label=\"Cypher-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n", + "/var/folders/p1/h56gxdhs5vgb0ztp7h4z606h0000gn/T/ipykernel_39048/2066733470.py:70: FutureWarning: \n", + "\n", + "`shade` is now deprecated in favor of `fill`; setting `fill=True`.\n", + "This will become an error in seaborn v0.14.0; please update your code.\n", + "\n", + " sns.kdeplot(kg_rag_correct_frac_list, color=\"lightcoral\", shade=True, label=\"KG-RAG\", ax=ax, lw=2, linestyle=\"-\", alpha=0.6)\n" + ] + }, + { + "data": { + "image/png": "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2LFjB3r06OGKUFXF1vvWoUMHnDhxAikpKdLrgQcewL333ouUlBRERka6MnxF2POz1q9fP6SlpUl/cADAb7/9hvDw8HqRQAH77ltBQUGlRGn+Q0RwevQqOSwX2DbmSX02btwodDqdSEpKEidPnhRPPPGECA4OFunp6UIIIR599FHx8ssvS8d///33wtvbW/zjH/8Qv/76q5g/f369fMTFlnv29ttvCx8fH/H555+Lq1evSq/c3Fyl/gmKsPW+VVQfR+faes8uXLggGjZsKJ555hmRmpoqvvzyS9GsWTPxxhtvKPVPUISt923+/PmiYcOGYsOGDeLs2bNi165dom3btuKhhx5S6p/gcrm5ueLYsWPi2LFjAoBYunSpOHbsmPj999+FEEK8/PLL4tFHH5WONz/i8tJLL4lff/1VrFixon4+4iKEEO+9955o2bKl8PHxEb169RI//vij9Nk999wjJk6caHH8p59+Ktq1ayd8fHxEp06dxLZt21wcsfJsuWetWrUSACq95s+f7/rAFWbrz5pcfUyiQth+z3744QfRu3dvodPpRJs2bcSbb74pSktLXRy18my5byUlJeK1114Tbdu2Fb6+viIyMlJMmzZN/PHHH64PXCF79uyp8veU+T5NnDhR3HPPPZW+061bN+Hj4yPatGkjEhMTbb4ul0IjIiKyk1v3iRIRESmJSZSIiMhOTKJERER2YhIlIiKyE5MoERGRnZhEiYiI7MQkSkREZCcmUSIiIjsxiRIREdmJSZRIAQcOHICXlxfuu+8+pUMhojrgtH9ECpg6dSoCAwORkJCA1NRUREREKBJHfVlejMhZWIkSuVheXh42bdqEp59+Gvfddx+SkpIsPv/vf/+Lnj17wtfXF02aNMGoUaOkzwwGA2bPno3IyEjodDpER0cjISEBAJCUlITg4GCLc23duhUajUZ6/9prr6Fbt25YvXo1oqKipIXVd+zYgbvuugvBwcFo3Lgx/vKXv+DMmTMW57p06RLGjRuHkJAQBAQEoEePHjh48CDOnz8PrVaLw4cPWxy/fPlytGrVymJZMyJPwyRK5GKffvopOnTogPbt2+ORRx7BmjVrpDUft23bhlGjRmH48OE4duwYkpOT0atXL+m7EyZMwIYNG/Duu+/i119/xYcffojAwECbrp+WloZ///vf2Lx5M1JSUgAA+fn5iIuLw+HDh5GcnAytVotRo0ZJCTAvLw/33HMPLl++jP/85z/4+eefMWvWLBiNRrRu3RqxsbFITEy0uE5iYiImTZrEBaHJs9Vp7Rkislnfvn3F8uXLhRCmJayaNGki9uzZI4QQok+fPmL8+PFVfi81NVUAELt3767y88TERKHX6y32bdmyRcj/b25ePzcjI6PGGK9fvy4ASOvsfvjhh6Jhw4YiMzOzyuM3bdokGjVqJIqKioQQQhw5ckRoNBpx7ty5Gq9D5O74JyKRC6WmpuLQoUMYN24cAMDb2xtjx46VmmRTUlIwaNCgKr+bkpICLy8v3HPPPXWKoVWrVmjatKnFvtOnT2PcuHFo06YNgoKC0Lp1awDAhQsXpGv/6U9/QkhISJXnHDlyJLy8vLBlyxYApqble++9VzoPkafyVjoAovokISEBpaWlFgOJhBDQ6XR4//334efnV+13a/oMALRardQsbFZSUlLpuICAgEr77r//frRq1Qoff/wxIiIiYDQa0blzZxQXF1t1bR8fH0yYMAGJiYkYPXo01q9fj3feeafG7xB5AlaiRC5SWlqKtWvXYsmSJUhJSZFeP//8MyIiIrBhwwZ06dIFycnJVX4/JiYGRqMR+/btq/Lzpk2bIjc3F/n5+dI+c59nTTIzM5Gamoq5c+di0KBB6NixI/744w+LY7p06YKUlBTcvHmz2vNMnToVX3/9NVauXInS0lKMHj261msTuT2l25OJ6ostW7YIHx8fkZWVVemzWbNmiR49eog9e/YIrVYr5s2bJ06ePCmOHz8u3n77bem4SZMmicjISLFlyxZx9uxZsWfPHrFp0yYhhBCZmZkiICBAPPvssyItLU2sW7dOREREVOoT7dq1q8W1y8rKROPGjcUjjzwiTp8+LZKTk0XPnj0FALFlyxYhhBAGg0G0a9dO9O/fX3z33XfizJkz4vPPPxc//PCDxbn69u0rfHx8xFNPPeWgu0akbqxEiVwkISEBsbGx0Ov1lT4bM2YMDh8+jJCQEHz22Wf4z3/+g27dumHgwIE4dOiQdNyqVavw4IMPYtq0aejQoQMef/xxqfIMCQnBv/71L2zfvh0xMTHYsGEDXnvttVrj0mq12LhxI44cOYLOnTtj5syZWLx4scUxPj4+2LVrF5o1a4bhw4cjJiYGb7/9Nry8vCyOe+yxx1BcXIwpU6bYcYeI3A8nWyAih1m4cCE+++wzHD9+XOlQiFyClSgR1VleXh5++eUXvP/++5gxY4bS4RC5DJMoEdXZM888g+7du2PAgAFsyqV6hc25REREdmIlSkREZCcmUSIiIjsxiRIREdmJSZSIiMhOTKJERER2YhIlIiKyE5MoERGRnZhEiYiI7PT/AlWBT73nAugAAAAASUVORK5CYII=", + "text/plain": [ + "<Figure size 500x300 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---Cypher-RAG based mean and std---\n", + "0.11178666666666666\n", + "0.018260066934281605\n", + "\n", + "---KG-RAG based mean and std---\n", + "0.9459866666666666\n", + "0.013465339868632277\n" + ] + } + ], + "source": [ + "cypher_rag_vs_kg_rag_fig = plot_figure(cypher_rag_correct_frac_list, kg_rag_correct_frac_list)\n", + "\n", + "fig_path = '../data/results/figures'\n", + "os.makedirs(fig_path, exist_ok=True)\n", + "cypher_rag_vs_kg_rag_fig.savefig(os.path.join(fig_path, 'cypher_rag_vs_kg_rag_true_false.svg'), format='svg', bbox_inches='tight') \n", + "\n", + "print('---Cypher-RAG based mean and std---')\n", + "print(np.mean(cypher_rag_correct_frac_list))\n", + "print(np.std(cypher_rag_correct_frac_list))\n", + "print('')\n", + "print('---KG-RAG based mean and std---')\n", + "print(np.mean(kg_rag_correct_frac_list))\n", + "print(np.std(kg_rag_correct_frac_list))\n" + ] + }, + { + "cell_type": "markdown", + "id": "e2611e5f-ffcc-4e36-8d24-7097bd017db3", + "metadata": {}, + "source": [ + "## Missed questions by Cypher-rag" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "id": "edc899fb-d41a-4ec0-b89b-fce27a0cc2df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cypher-RAG missed 72.02572347266882% of questions\n" + ] + } + ], + "source": [ + "missed_question_percentage = 100*cypher_rag[cypher_rag.cypher_rag_final_answer.isna()].shape[0]/cypher_rag.shape[0]\n", + "print(f\"Cypher-RAG missed {missed_question_percentage}% of questions\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "19b610c1-4e9a-464a-8646-c548dc1e71c6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<div>\n", + "<style scoped>\n", + " .dataframe tbody tr th:only-of-type {\n", + " vertical-align: middle;\n", + " }\n", + "\n", + " .dataframe tbody tr th {\n", + " vertical-align: top;\n", + " }\n", + "\n", + " .dataframe thead th {\n", + " text-align: right;\n", + " }\n", + "</style>\n", + "<table border=\"1\" class=\"dataframe\">\n", + " <thead>\n", + " <tr style=\"text-align: right;\">\n", + " <th></th>\n", + " <th>text</th>\n", + " <th>label</th>\n", + " <th>cypher_rag_answer</th>\n", + " <th>cypher_rag_final_answer</th>\n", + " <th>total_tokens</th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " <tr>\n", + " <th>0</th>\n", + " <td>enhanced S-cone syndrome is not a vitreoretina...</td>\n", + " <td>False</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>3817</td>\n", + " </tr>\n", + " <tr>\n", + " <th>1</th>\n", + " <td>metronidazole treats crohn's disease</td>\n", + " <td>True</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4049</td>\n", + " </tr>\n", + " <tr>\n", + " <th>2</th>\n", + " <td>KLEEFSTRA SYNDROME 1 is not associated with Ge...</td>\n", + " <td>False</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>3861</td>\n", + " </tr>\n", + " <tr>\n", + " <th>3</th>\n", + " <td>Juvenile polyposis syndrome associates Gene SMAD4</td>\n", + " <td>True</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4054</td>\n", + " </tr>\n", + " <tr>\n", + " <th>4</th>\n", + " <td>Disease ontology identifier for congenital gen...</td>\n", + " <td>False</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>3856</td>\n", + " </tr>\n", + " <tr>\n", + " <th>...</th>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " <td>...</td>\n", + " </tr>\n", + " <tr>\n", + " <th>304</th>\n", + " <td>Noonan Syndrome associates Gene SOS1</td>\n", + " <td>True</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4044</td>\n", + " </tr>\n", + " <tr>\n", + " <th>306</th>\n", + " <td>Congenital amegakaryocytic thrombocytopenia is...</td>\n", + " <td>False</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4090</td>\n", + " </tr>\n", + " <tr>\n", + " <th>307</th>\n", + " <td>Leigh Disease associates Gene NDUFS4</td>\n", + " <td>True</td>\n", + " <td>NaN</td>\n", + " <td>NaN</td>\n", + " <td>3908</td>\n", + " </tr>\n", + " <tr>\n", + " <th>308</th>\n", + " <td>Sandhoff Disease is not associated with Gene HEXB</td>\n", + " <td>False</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4064</td>\n", + " </tr>\n", + " <tr>\n", + " <th>310</th>\n", + " <td>Juvenile polyposis syndrome associates Gene BM...</td>\n", + " <td>True</td>\n", + " <td>I'm sorry, but I don't have the information to...</td>\n", + " <td>NaN</td>\n", + " <td>4065</td>\n", + " </tr>\n", + " </tbody>\n", + "</table>\n", + "<p>224 rows × 5 columns</p>\n", + "</div>" + ], + "text/plain": [ + " text label \\\n", + "0 enhanced S-cone syndrome is not a vitreoretina... False \n", + "1 metronidazole treats crohn's disease True \n", + "2 KLEEFSTRA SYNDROME 1 is not associated with Ge... False \n", + "3 Juvenile polyposis syndrome associates Gene SMAD4 True \n", + "4 Disease ontology identifier for congenital gen... False \n", + ".. ... ... \n", + "304 Noonan Syndrome associates Gene SOS1 True \n", + "306 Congenital amegakaryocytic thrombocytopenia is... False \n", + "307 Leigh Disease associates Gene NDUFS4 True \n", + "308 Sandhoff Disease is not associated with Gene HEXB False \n", + "310 Juvenile polyposis syndrome associates Gene BM... True \n", + "\n", + " cypher_rag_answer \\\n", + "0 NaN \n", + "1 I'm sorry, but I don't have the information to... \n", + "2 NaN \n", + "3 I'm sorry, but I don't have the information to... \n", + "4 NaN \n", + ".. ... \n", + "304 I'm sorry, but I don't have the information to... \n", + "306 I'm sorry, but I don't have the information to... \n", + "307 NaN \n", + "308 I'm sorry, but I don't have the information to... \n", + "310 I'm sorry, but I don't have the information to... \n", + "\n", + " cypher_rag_final_answer total_tokens \n", + "0 NaN 3817 \n", + "1 NaN 4049 \n", + "2 NaN 3861 \n", + "3 NaN 4054 \n", + "4 NaN 3856 \n", + ".. ... ... \n", + "304 NaN 4044 \n", + "306 NaN 4090 \n", + "307 NaN 3908 \n", + "308 NaN 4064 \n", + "310 NaN 4065 \n", + "\n", + "[224 rows x 5 columns]" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cypher_rag[cypher_rag.cypher_rag_final_answer.isna()]" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "6e69e08b-daff-4cda-948e-f623ad1c5960", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\"I'm sorry, but I don't have the information to answer that question.\"" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cypher_rag[cypher_rag.cypher_rag_final_answer.isna()].iloc[219].cypher_rag_answer" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "62bb42fd-cc62-4562-ba1c-406717fa31ed", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "index 304\n", + "label True\n", + "question Noonan Syndrome associates Gene SOS1\n", + "llm_answer {\\n \"answer\": \"True\"\\n}\n", + "extracted_answer True\n", + "Name: 304, dtype: object" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg_rag.iloc[304]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "faa4837a-9052-4350-9038-67ddcb1de8c5", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/true_false_using_cypher_rag.ipynb b/notebooks/true_false_using_cypher_rag.ipynb new file mode 100644 index 0000000..7cbef2d --- /dev/null +++ b/notebooks/true_false_using_cypher_rag.ipynb @@ -0,0 +1,6702 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "3a23118a-0b21-4ec6-8d6c-deee50798809", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.chat_models import AzureChatOpenAI\n", + "from dotenv import load_dotenv\n", + "import os\n", + "import openai\n", + "from langchain.chains import GraphCypherQAChain\n", + "from langchain.graphs import Neo4jGraph\n", + "from langchain.callbacks import get_openai_callback\n", + "import pandas as pd\n", + "from tqdm import tqdm\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "50667110-d8d3-46cf-842e-1885fa73eaaa", + "metadata": {}, + "outputs": [], + "source": [ + "curated_data = pd.read_csv('../data/benchmark_data/true_false_questions.csv').drop('Unnamed: 0', axis=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b2258878-d4f9-4721-8280-e9f01ac60428", + "metadata": {}, + "outputs": [], + "source": [ + "LLM_MODEL = 'gpt-4'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "14ae89f4-7ddb-483b-b38e-d05ed4f21926", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/karthiksoman/anaconda3/envs/cypher_rag/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The class `AzureChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 0.3.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import AzureChatOpenAI`.\n", + " warn_deprecated(\n" + ] + } + ], + "source": [ + "\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.gpt_config.env'))\n", + "API_KEY = os.environ.get('API_KEY')\n", + "API_VERSION = os.environ.get('API_VERSION')\n", + "RESOURCE_ENDPOINT = os.environ.get('RESOURCE_ENDPOINT')\n", + "openai.api_type = \"azure\"\n", + "openai.api_key = API_KEY\n", + "openai.api_base = RESOURCE_ENDPOINT\n", + "openai.api_version = API_VERSION\n", + "chat_deployment_id = LLM_MODEL\n", + "chat_model_id = chat_deployment_id\n", + "temperature = 0\n", + "chat_model = AzureChatOpenAI(openai_api_key=API_KEY, openai_api_version=API_VERSION, azure_deployment=chat_deployment_id, azure_endpoint=RESOURCE_ENDPOINT, temperature=temperature)\n", + "load_dotenv(os.path.join(os.path.expanduser('~'), '.spoke_neo4j_config.env'))\n", + "username = os.environ.get('NEO4J_USER')\n", + "password = os.environ.get('NEO4J_PSW')\n", + "url = os.environ.get('NEO4J_URL')\n", + "database = os.environ.get('NEO4J_DB')\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "480fa890-7ee8-44b8-ac85-ed6f29fb1d56", + "metadata": {}, + "outputs": [], + "source": [ + "graph = Neo4jGraph(url=url, username=username, password=password, database = database)\n", + "chain = GraphCypherQAChain.from_llm(chat_model, graph=graph, verbose=True, validate_cypher=True,return_intermediate_steps=True)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7c3b61f9-691a-4b18-95d0-577b2a30d356", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "0it [00:00, ?it/s]/Users/karthiksoman/anaconda3/envs/cypher_rag/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:119: LangChainDeprecationWarning: The method `Chain.run` was deprecated in langchain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n", + " warn_deprecated(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "1it [00:02, 2.02s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'metronidazole'})-[:TREATS_CtD]->(d:Disease {name: \"crohn's disease\"}) RETURN c, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2it [00:08, 4.87s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "3it [00:11, 3.78s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"KLEEFSTRA SYNDROME 1\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"EHMT1\"}) RETURN NOT EXISTS(r) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Juvenile polyposis syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SMAD4\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "4it [00:14, 3.70s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "5it [00:17, 3.19s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for congenital generalized lipodystrophy type 2. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "6it [00:19, 2.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for Marfan syndrome. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "7it [00:32, 6.15s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: 'cystic fibrosis'})-[:LOCALIZES_DlA]->(a:Anatomy {name: 'respiratory system'}) RETURN d, a\n", + "\n", + "This statement will return the 'cystic fibrosis' disease node and the 'respiratory system' anatomy node if there is a LOCALIZES_DlA relationship between them, which would indicate that cystic fibrosis is a disorder of the respiratory system.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'alpha-Mannosidosis'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'MAN2B1'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "8it [00:40, 6.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Wolcott-Rallison syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'EIF2AK3'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "9it [00:45, 6.21s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Neurofibromatosis 2\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"NF2\"})\n", + "RETURN NOT EXISTS((d)-[r]->(g)) AS Result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10it [00:49, 5.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownPropertyKeyWarning} {category: UNRECOGNIZED} {title: The provided property key is not in the database} {description: One of the property names in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing property name is: syndromic)} {position: line: 1, column: 56, offset: 55} for query: 'MATCH (d:Disease {name: \"Angelman syndrome\"}) RETURN d.syndromic'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Angelman syndrome\"}) RETURN d.syndromic\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d.syndromic': None}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "11it [00:51, 4.42s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'colchicine'})-[:TREATS_CtD]->(d:Disease {name: 'familial mediterranean fever'}) RETURN c, d\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "12it [00:54, 3.97s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Marfan Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"FBN1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "13it [00:58, 4.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "14it [01:05, 4.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can help you construct a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: 'Mowat-Wilson syndrome'}) RETURN d\n", + "\n", + "This statement will return the node representing the Mowat-Wilson syndrome in the graph database. You can then examine the properties of this node to determine if it is a syndromic intellectual disability.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "15it [01:06, 3.80s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "16it [01:09, 3.48s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. The schema provided does not include a property for Disease ontology identifier.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Tangier Disease'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ABCA1'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "17it [01:13, 3.66s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "18it [01:16, 3.54s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'central diabetes insipidus'}) RETURN d.identifier\n", + "\n", + "This Cypher statement will return the disease ontology identifier for central diabetes insipidus. Compare the returned value with \"DOID:350\" to determine if the statement is true or false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Ulnar-mammary syndrome\"}), (g:Gene {name: \"TBX3\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "19it [01:20, 3.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'bevacizumab'})-[:TREATS_CtD]->(d:Disease {name: 'hereditary hemorrhagic telangiectasia'}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "20it [01:24, 3.84s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Liver carcinoma'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'MET'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "21it [01:27, 3.61s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Antithrombin III Deficiency\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SERPINC1\"}) RETURN NOT EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "22it [01:31, 3.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Mastocytosis'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'KIT'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "23it [01:34, 3.50s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "24it [01:37, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. The schema provided does not include a property for Disease ontology identifier. Therefore, it is not possible to confirm if the Disease ontology identifier for Farber lipogranulomatosis is DOID:0050464.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Familial Mediterranean Fever'}), (g:Gene {name: 'MEFV'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "25it [01:42, 3.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "26it [01:45, 3.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Wiskott-Aldrich syndrome\"}) RETURN d.identifier\n", + "\n", + "This Cypher statement will return the Disease ontology identifier for Wiskott-Aldrich syndrome. You can then compare the returned value with \"DOID:9169\" to verify if the statement is true or false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "27it [01:46, 2.81s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Juvenile Myoclonic Epilepsy'}), (g:Gene {name: 'EFHC1'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "28it [01:50, 3.26s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "29it [01:54, 3.38s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Very long chain acyl-CoA dehydrogenase deficiency\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ACADVL\"})\n", + "RETURN NOT EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS Result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "30it [01:57, 3.43s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "31it [01:59, 2.77s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Fibrodysplasia Ossificans Progressiva\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ACVR1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "32it [02:02, 2.86s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "33it [02:06, 3.26s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Canavan Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ASPA\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for Canavan Disease and the Gene node for ASPA if there is an ASSOCIATES_DaG relationship between them. If it returns a result, the statement is true. If it does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Chediak-Higashi syndrome\"}) RETURN d.name, d.obsolete\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d.name': 'Chediak-Higashi syndrome', 'd.obsolete': None}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "34it [02:09, 3.25s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Hereditary hemorrhagic telangiectasia\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ENG\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "35it [02:12, 3.18s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Lafora Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NHLRC1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "36it [02:16, 3.41s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Pheochromocytoma'}), (g:Gene {name: 'RET'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "37it [02:19, 3.38s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Xeroderma pigmentosum, group B\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ERCC3\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "38it [02:24, 3.84s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Acute intermittent porphyria\"}), (g:Gene {name: \"HMBS\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "39it [02:27, 3.61s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "40it [02:28, 2.79s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'vitelliform macular dystrophy'})-[:ISA_DiD]->(p:Disease {name: 'macular degeneration'}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "41it [02:32, 2.94s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Spinocerebellar Ataxia Type 5\"}), (g:Gene {name: \"SPTBN2\"})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "42it [02:39, 4.31s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "43it [02:44, 4.43s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Pelizaeus-Merzbacher disease\"}) RETURN d.identifier AS Disease_ontology_identifier\n", + "\n", + "The statement can be true or false depending on the result of the above query. If the result is \"DOID:5688\", then the statement is true. If the result is different from \"DOID:5688\", then the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Robinow syndrome, autosomal recessive\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ROR2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "44it [02:49, 4.67s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "45it [02:53, 4.49s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for Loeys-Dietz syndrome. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Cystic Fibrosis'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'CFTR'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "46it [02:57, 4.33s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Greig cephalopolysyndactyly syndrome\"}), (g:Gene {name: \"GLI3\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "47it [03:02, 4.56s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "48it [03:03, 3.55s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. Alkaptonuria is a disorder of tyrosine metabolism.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Timothy syndrome'}), (g:Gene {name: 'CACNA1C'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "49it [03:07, 3.45s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "50it [03:08, 2.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "51it [03:09, 2.33s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'Factor IX'}), (d:Disease {name: 'Hemophilia B'}) \n", + "RETURN EXISTS((c)-[:TREATS_CtD]->(d)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "52it [03:13, 2.80s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Mucopolysaccharidosis VI'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'ARSB'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "53it [03:20, 3.99s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"HEMOCHROMATOSIS, TYPE 4\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SLC40A1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "54it [03:24, 3.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Charcot-Marie-Tooth Disease, Type Ib\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"MPZ\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "55it [03:27, 3.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "56it [03:29, 3.19s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThe question is not asking for a Cypher statement to be generated. Therefore, it's not possible to provide a Cypher statement as an answer.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Denys-Drash Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"WT1\"}) RETURN COUNT(*) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "57it [03:35, 3.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Cherubism\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SH3BP2\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "58it [03:41, 4.70s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"PITT-HOPKINS SYNDROME\"}), (g:Gene {name: \"TCF4\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "59it [03:48, 5.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "60it [03:49, 4.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Paroxysmal Nonkinesigenic Dyskinesia 1\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"PNKD\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "61it [03:55, 4.63s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Enhanced S-Cone Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NR2E3\"}) RETURN COUNT(*) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "62it [03:58, 4.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "63it [04:04, 4.67s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The statement is incorrect because Canavan disease is not an inborn aminoacylase deficiency. It is actually a rare inherited disorder that damages the ability of nerve cells (neurons) in the brain to send and receive messages. This disease is characterized by the degeneration of myelin, a substance that forms a layer (the myelin sheath), around certain nerve cells. Canavan disease is caused by mutations in the ASPA gene, which provides instructions for making the enzyme aspartoacylase, not aminoacylase.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "64it [04:10, 5.20s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Aniridia'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'PAX6'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "65it [04:16, 5.30s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Congenital contractural arachnodactyly\"}), (g:Gene {name: \"FBN2\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "66it [04:21, 5.29s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Muenke Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'FGFR3'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "67it [04:24, 4.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "68it [04:26, 3.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "69it [04:27, 2.85s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Johanson-Blizzard syndrome\"}), (g:Gene {name: \"UBR1\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "70it [04:31, 3.24s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"MASA SYNDROME\"}), (g:Gene {name: \"L1CAM\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "71it [04:36, 3.77s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Autosomal dominant hypophosphatemic rickets\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"FGF23\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "72it [04:40, 3.94s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Acrodermatitis enteropathica\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SLC39A4\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "73it [04:44, 3.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Rothmund-Thomson syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RECQL4\"}) RETURN COUNT(*) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "74it [04:48, 3.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Cleidocranial Dysplasia\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RUNX2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "75it [04:53, 4.32s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "76it [05:02, 5.71s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"LONG QT SYNDROME 3\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SCN5A\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node with the name \"LONG QT SYNDROME 3\" and the Gene node with the name \"SCN5A\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true; otherwise, it is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Infantile hypophosphatasia\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ALPL\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "77it [05:05, 4.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "78it [05:06, 3.83s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "79it [05:11, 4.20s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Ataxia Telangiectasia\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ATM\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for Ataxia Telangiectasia and the Gene node for ATM if there is an ASSOCIATES_DaG relationship between them. If it returns a result, the statement is true. If it does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'alpha-galactosidase'}), (d:Disease {name: 'fabry disease'}) \n", + "RETURN EXISTS((c)-[:TREATS_CtD]->(d)) AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "80it [05:16, 4.37s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "81it [05:20, 4.25s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "82it [05:22, 3.63s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The schema does not provide a relationship type that associates a disease (such as Piebaldism) with a gene.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Pfeiffer Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'FGFR2'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "83it [05:27, 4.08s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "84it [05:34, 4.82s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can help you generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: \"Bernard-Soulier syndrome\"}) RETURN d\n", + "\n", + "This statement will return the node representing the Bernard-Soulier syndrome in the graph database. You can then examine the properties of this node to determine if it is an inherited bleeding disorder, platelet-type.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Burkitt Lymphoma'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'MYC'}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "85it [05:39, 4.80s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Ornithine carbamoyltransferase deficiency\"}), (g:Gene {name: \"OTC\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "86it [05:44, 4.92s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Nail-Patella Syndrome\"}), (g:Gene {name: \"LMX1B\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "87it [05:49, 4.83s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Tetralogy of Fallot\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ZFPM2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "88it [05:53, 4.67s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Hartnup Disease\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"SLC6A19\"}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "89it [05:58, 4.71s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "90it [05:59, 3.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "91it [06:13, 6.81s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can help you construct a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: 'familial Mediterranean fever'})-[:ISA_DiD]->(p:Disease {name: 'primary immunodeficiency due to a genetic defect in innate immunity'})\n", + "RETURN d, p\n", + "\n", + "This Cypher statement will return the 'familial Mediterranean fever' node and its parent node 'primary immunodeficiency due to a genetic defect in innate immunity' if it exists. If the query returns no results, it means that 'familial Mediterranean fever' is not a 'primary immunodeficiency due to a genetic defect in innate immunity'.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Hemophilia B'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'F9'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "92it [06:17, 5.96s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "93it [06:22, 5.61s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: \"Rapp-Hodgkin syndrome\"}) RETURN d\n", + "\n", + "This statement will return the node representing the disease \"Rapp-Hodgkin syndrome\" and all its properties. You can then examine the returned properties to determine if it is an autosomal dominant disease.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Borjeson-Forssman-Lehmann syndrome\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"PHF6\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "94it [06:29, 6.21s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Multiple Endocrine Neoplasia Type 2b\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RET\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "95it [06:37, 6.60s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "96it [06:41, 5.78s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Choroideremia'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CHM'}) RETURN NOT EXISTS(r) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Wolman Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"LIPA\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "97it [06:45, 5.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Adenine phosphoribosyltransferase deficiency\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"APRT\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "98it [06:57, 7.45s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Holt-Oram syndrome'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'TBX5'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:0060468', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID0060468 target=\"_blank\">kwgr:topic.DOID0060468</a>', 'omim_list': [], 'name': 'Holt-Oram syndrome', 'source': 'Disease Ontology', 'mesh_list': ['C535326']}, 'g': {'license': 'CC0 1.0', 'identifier': 6910, 'ensembl': 'ENSG00000089225', 'sources': ['Entrez Gene'], 'synonyms': ['HOS'], 'chromosome': '12', 'name': 'TBX5', 'description': 'T-box transcription factor 5', 'source': 'Entrez Gene', 'chembl_id': 'CHEMBL1687681'}}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "99it [07:02, 6.48s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100it [07:04, 5.35s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task is asking for a Cypher statement to query a graph database, not for a true or false answer to a medical question. Therefore, it's not possible to generate a Cypher statement based on the provided question.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "101it [07:15, 6.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "102it [07:16, 5.19s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "103it [07:19, 4.40s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. Fatal familial insomnia is a type of insomnia. It is a rare genetic degenerative brain disorder characterized by an inability to sleep that may be initially mild, but progressively worsens, leading to significant physical and mental deterioration.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "104it [07:24, 4.58s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'osteosarcoma'})-[:ISA_DiD]->(d2:Disease {name: 'sarcoma'}) RETURN COUNT(d) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "105it [07:29, 4.78s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'immune checkpoint inhibitors' AND d.name = 'melanoma' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "106it [07:37, 5.78s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "107it [07:39, 4.51s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "108it [07:40, 3.61s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"KUFOR-RAKEB SYNDROME\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ATP13A2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "109it [07:45, 3.95s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Loeys-Dietz Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"TGFBR1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "110it [07:54, 5.39s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "111it [07:56, 4.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement to be generated. It is asking for a validation of a fact, not a query to a graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Angelman Syndrome\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"UBE3A\"}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "112it [08:01, 4.55s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "113it [08:03, 3.79s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis question cannot be answered with a Cypher statement as it is a medical question, not a database query. Cypher is a graph query language that is used to query Neo4j Database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: '6-mercaptopurine'}), (d:Disease {name: \"crohn's disease\"}) \n", + "RETURN EXISTS((c)-[:TREATS_CtD]->(d)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "114it [08:07, 4.08s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownPropertyKeyWarning} {category: UNRECOGNIZED} {title: The provided property key is not in the database} {description: One of the property names in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing property name is: syndromic)} {position: line: 1, column: 56, offset: 55} for query: 'MATCH (d:Disease {name: \"Wolcott-Rallison syndrome\"}) RETURN d.syndromic'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Wolcott-Rallison syndrome\"}) RETURN d.syndromic\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d.syndromic': None}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "115it [08:12, 4.29s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "116it [08:14, 3.56s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"spinocerebellar ataxia type 5\"}) RETURN d.identifier == \"DOID:0050882\" AS result\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Pseudopseudohypoparathyroidism'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'GNAS'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "117it [08:18, 3.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "118it [08:22, 3.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The term \"alveolar rhabdomyosarcoma\" refers to a specific subtype of rhabdomyosarcoma. Therefore, it is a type of rhabdomyosarcoma.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "119it [08:25, 3.49s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "120it [08:26, 2.86s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not ask for a Cypher statement to be generated.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Omenn Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'RAG2'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "121it [08:34, 4.33s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "122it [08:35, 3.37s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Progeria'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'LMNA'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "123it [08:42, 4.52s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'mercaptopurine'})-[:TREATS_CtD]->(d:Disease {name: \"crohn's disease\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "124it [08:49, 5.09s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Peutz-Jeghers Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"STK11\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "125it [08:53, 4.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "126it [08:58, 4.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can help you construct a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: \"Noonan syndrome\"}) RETURN d\n", + "\n", + "This statement will return the node representing Noonan syndrome in the graph database, if it exists. You can then examine the properties of this node to determine if it is a multiple congenital anomalies/dysmorphic syndrome-variable intellectual disability syndrome.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"RAPP-HODGKIN SYNDROME\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"TP63\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "127it [09:03, 4.92s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Bernard-Soulier Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"GP1BA\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "128it [09:08, 4.98s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "129it [09:17, 6.33s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Werner Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'WRN'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "130it [09:22, 5.95s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "131it [09:24, 4.56s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "132it [09:26, 3.77s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "133it [09:31, 4.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Alveolar rhabdomyosarcoma\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PAX3\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Alveolar rhabdomyosarcoma\" and the Gene node for \"PAX3\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true. If it does not return a result, the statement is false. The reason will be determined by the presence or absence of this relationship in the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'CHARGE Syndrome'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'CHD7'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "134it [09:35, 4.13s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "135it [09:37, 3.49s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Pelizaeus-Merzbacher Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PLP1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "136it [09:43, 4.28s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Microvillus inclusion disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"MYO5B\"}) RETURN NOT COUNT(g) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "137it [09:49, 4.74s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "138it [09:56, 5.41s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: 'DiGeorge syndrome'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'T-cell immunodeficiency'})\n", + "RETURN d, g\n", + "\n", + "This statement will return any relationships between the disease 'DiGeorge syndrome' and the gene 'T-cell immunodeficiency'. If there are no results, it could suggest that DiGeorge syndrome is not associated with T-cell immunodeficiency in the database. However, the absence of results does not definitively prove that the statement is false, as the database may not contain all known information.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'melanoma'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'BRAF'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "139it [10:00, 5.06s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Basal ganglia disease, biotin-responsive\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SLC19A3\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "140it [10:05, 4.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Coffin-Siris syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ARID1B\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "141it [10:09, 4.68s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Sitosterolemia'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ABCG8'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "142it [10:14, 4.69s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Alexander Disease\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"GFAP\"}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "143it [10:18, 4.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'pembrolizumab'})-[:TREATS_CtD]->(d:Disease {name: 'melanoma'}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "144it [10:22, 4.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "145it [10:24, 3.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "146it [10:26, 3.26s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task is asking for a Cypher statement to be generated, not for a true or false question to be answered. Therefore, it is not possible to complete this task as it is currently written.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "147it [10:39, 6.17s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Norrie disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NDP\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Norrie disease\" and the Gene node for \"NDP\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true; if it does not, the statement is false. The reason will be whether or not the graph database contains this specific relationship.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Hyperkalemic periodic paralysis\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SCN4A\"}) RETURN NOT COUNT(g) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "148it [10:46, 6.25s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "149it [10:48, 4.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'ataxia telangiectasia'}) RETURN d.identifier == 'DOID:0060010' AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Xeroderma pigmentosum, group A\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"XPA\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "150it [10:51, 4.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'antineoplastic agents' AND d.name = 'osteosarcoma' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "151it [10:57, 4.94s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Jervell-Lange Nielsen Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"KCNQ1\"}) RETURN NOT EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "152it [11:01, 4.55s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "153it [11:02, 3.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"POLYCYSTIC KIDNEY DISEASE 1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PKD1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "154it [11:05, 3.40s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "155it [11:11, 4.24s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Tangier disease'}) RETURN d.identifier AS Disease_ontology_identifier\n", + "\n", + "This Cypher statement will return the disease ontology identifier for Tangier disease. If the returned identifier is 'DOID:1388', then the statement is true. If not, the statement is false. The truthfulness of the statement can only be determined by executing the query on the actual graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "156it [11:13, 3.50s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for Smith-Lemli-Opitz syndrome. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "157it [11:16, 3.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task is asking for a Cypher statement, but the question provided is not suitable for generating a Cypher statement. It seems to be a factual question about biology rather than a request for a database query. Please provide a question that requires querying a graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "158it [11:17, 2.72s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Vitelliform Macular Dystrophy\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"BEST1\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "159it [11:20, 2.84s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "160it [11:25, 3.40s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Smith-Magenis syndrome\"}) RETURN d.identifier == \"DOID:12271\" AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Noonan Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RAF1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "161it [11:28, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Bernard-Soulier Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"GP1BB\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "162it [11:34, 4.12s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Neurofibromatosis 1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NF1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "163it [11:37, 3.86s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Brugada Syndrome\"}), (g:Gene {name: \"SCN5A\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "164it [11:40, 3.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "165it [11:44, 3.72s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Smith-Lemli-Opitz Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"DHCR7\"}) RETURN NOT EXISTS(d) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Biotinidase Deficiency'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'BTD'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "166it [11:54, 5.59s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3m\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "167it [12:02, 6.24s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "168it [12:10, 6.79s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: \"Li-Fraumeni syndrome\"}) RETURN d\n", + "\n", + "This statement will return the node representing the disease \"Li-Fraumeni syndrome\" and all its properties. You can then check the returned properties to determine if it is an autosomal dominant disease.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'WHIM syndrome'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'CXCR4'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "169it [12:14, 6.02s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "170it [12:18, 5.29s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Alstrom Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'ALMS1'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "171it [12:22, 4.91s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Gyrate Atrophy\"}), (g:Gene {name: \"OAT\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "172it [12:27, 4.96s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "173it [12:28, 3.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "174it [12:29, 2.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Xeroderma Pigmentosum, Complementation Group D\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ERCC2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "175it [12:32, 3.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "176it [12:38, 3.83s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Argininosuccinic Aciduria'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'ASL'}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for Argininosuccinic Aciduria and the Gene node for ASL if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true. If it does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "177it [12:44, 4.56s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Lesch-Nyhan Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"HPRT1\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Lesch-Nyhan Syndrome\" and the Gene node for \"HPRT1\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true. If the query does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Creutzfeldt-Jakob disease\"}), (g:Gene {name: \"PRNP\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "178it [12:47, 4.10s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"BIETTI CRYSTALLINE CORNEORETINAL DYSTROPHY\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"CYP4V2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "179it [12:51, 3.86s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "180it [12:52, 3.06s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"XERODERMA PIGMENTOSUM, COMPLEMENTATION GROUP E\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"DDB2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "181it [12:58, 3.99s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "182it [13:00, 3.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for ornithine carbamoyltransferase deficiency. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Saethre-Chotzen Syndrome\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"TWIST1\"}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "183it [13:04, 3.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "184it [13:09, 4.07s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The Cypher statement to verify this would be:\n", + "\n", + "MATCH (c:Compound {name: 'Prothrombin Complex Concentrates'})-[:TREATS_CtD]->(d:Disease {name: 'Hemophilia B'}) RETURN c, d\n", + "\n", + "If this query returns any results, then Prothrombin Complex Concentrates does treat Hemophilia B. If it does not return any results, then Prothrombin Complex Concentrates does not treat Hemophilia B. However, in reality, Prothrombin Complex Concentrates are not typically used to treat Hemophilia B. Hemophilia B is a bleeding disorder caused by a lack of blood clotting factor IX, and it is typically treated with factor IX concentrates, not Prothrombin Complex Concentrates.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "185it [13:13, 3.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement to be generated. It is asking for a factual information which is not related to generating a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "186it [13:15, 3.36s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement. It is asking for a factual answer about a medical condition, not a query to a graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "187it [13:17, 3.08s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse\n", + "\n", + "Reason: The question does not provide enough information to generate a Cypher statement. It does not specify the relationship type or the node properties to be used in the query.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Carney Complex\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"PRKAR1A\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "188it [13:21, 3.18s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "189it [13:22, 2.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for Werner syndrome. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "190it [13:23, 2.19s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"DOYNE HONEYCOMB RETINAL DYSTROPHY\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"EFEMP1\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "191it [13:28, 2.85s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Central Diabetes Insipidus\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"AVP\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "192it [13:31, 2.95s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "193it [13:33, 2.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for popliteal pterygium syndrome. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Fragile X Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"FMR1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "194it [13:41, 4.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Loeys-Dietz Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"TGFBR2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "195it [13:45, 4.30s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"XERODERMA PIGMENTOSUM, COMPLEMENTATION GROUP C\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"XPC\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "196it [13:49, 4.11s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"CHARCOT-MARIE-TOOTH DISEASE, TYPE 4C\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SH3TC2\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "197it [13:53, 4.16s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "198it [13:54, 3.16s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "199it [13:57, 3.11s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Sandhoff disease\"})-[:LOCALIZES_DlA]->(a:Anatomy {name: \"Eye\"}) RETURN d, a\n", + "\n", + "This Cypher statement will return any relationships in the graph database where Sandhoff disease localizes to the Eye. If it returns any results, then the statement is true. If it does not return any results, then the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "200it [13:58, 2.51s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Congenital Generalized Lipodystrophy Type 2\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"BSCL2\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "201it [14:03, 3.30s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Noonan Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PTPN11\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "202it [14:07, 3.41s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Juvenile Spinal Muscular Atrophy\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SMN1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "203it [14:10, 3.27s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "204it [14:26, 7.27s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"CHARCOT-MARIE-TOOTH DISEASE, TYPE 4J\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"FIG4\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node with the name \"CHARCOT-MARIE-TOOTH DISEASE, TYPE 4J\" and the Gene node with the name \"FIG4\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true; otherwise, it is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Alkaptonuria'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'HGD'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "205it [14:30, 6.11s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Cystinuria'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SLC7A9'}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "206it [14:34, 5.60s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Popliteal pterygium syndrome\"}), (g:Gene {name: \"IRF6\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "207it [14:40, 5.53s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Aspartylglucosaminuria'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'AGA'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "208it [14:52, 7.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Nijmegen Breakage Syndrome\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"NBN\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "209it [14:56, 6.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Mowat-Wilson syndrome\"})-[r:ASSOCIATES_DaG]-(g:Gene {name: \"ZEB2\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "210it [15:00, 5.74s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "211it [15:02, 4.77s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Sarcoma'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'TP53'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "212it [15:06, 4.41s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "213it [15:07, 3.39s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "214it [15:10, 3.15s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Gray Platelet Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NBEAL2\"}) RETURN NOT EXISTS(d) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Ethylmalonic encephalopathy\"}), (g:Gene {name: \"ETHE1\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "215it [15:16, 4.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"L-2-HYDROXYGLUTARIC ACIDURIA\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"L2HGDH\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "216it [15:22, 4.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "217it [15:23, 3.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "218it [15:24, 2.87s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownPropertyKeyWarning} {category: UNRECOGNIZED} {title: The provided property key is not in the database} {description: One of the property names in your query is not available in the database, make sure you didn't misspell it or that the label is available when you run this statement in your application (the missing property name is: syndromic)} {position: line: 1, column: 56, offset: 55} for query: 'MATCH (d:Disease {name: \"Coffin-Siris syndrome\"}) RETURN d.syndromic'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Coffin-Siris syndrome\"}) RETURN d.syndromic\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d.syndromic': None}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "219it [15:27, 2.89s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Nance-Horan syndrome'}), (g:Gene {name: 'NHS'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "220it [15:31, 3.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "221it [15:32, 2.54s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "222it [15:33, 2.19s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Maple Syrup Urine Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"DBT\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "223it [15:40, 3.45s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Spinocerebellar Ataxia Type 1\"}), (g:Gene {name: \"ATXN1\"})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "224it [15:45, 4.03s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "225it [15:46, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'agalsidase alfa'})-[r:TREATS_CtD]->(d:Disease {name: 'fabry disease'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "226it [15:52, 4.05s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "227it [15:54, 3.20s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'agalsidase beta' AND d.name = 'fabry disease' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "228it [15:57, 3.28s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Unverricht-Lundborg Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"CSTB\"}) RETURN NOT COUNT(g) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "229it [16:03, 4.13s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'L-2-hydroxyglutaric aciduria'})-[:ISA_DiD]->(d2:Disease {name: '2-hydroxyglutaric aciduria'}) RETURN d, d2\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:0050574', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID0050574 target=\"_blank\">kwgr:topic.DOID0050574</a>', 'omim_list': [], 'name': 'L-2-hydroxyglutaric aciduria', 'source': 'Disease Ontology', 'mesh_list': []}, 'd2': {'identifier': 'DOID:0050573', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID0050573 target=\"_blank\">kwgr:topic.DOID0050573</a>', 'omim_list': [], 'name': '2-hydroxyglutaric aciduria', 'source': 'Disease Ontology', 'mesh_list': ['C535306']}}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "230it [16:07, 4.12s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "231it [16:12, 4.24s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Refsum Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PHYH\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Refsum Disease\" and the Gene node for \"PHYH\" if there is an \"ASSOCIATES_DaG\" relationship between them. If the query returns a result, the statement is true. If it does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Achondroplasia'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'FGFR3'}) RETURN COUNT(r) > 0 AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'AssociationExists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "232it [16:18, 4.87s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "233it [16:23, 4.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mAs an AI model, I am not capable of answering true or false questions. However, I can generate a Cypher statement to query a graph database based on the provided schema. Here is an example:\n", + "\n", + "MATCH (d:Disease {name: 'pseudoachondroplasia'})-[:ISA_DiD]->(d2:Disease {name: 'osteochondrodysplasia'}) RETURN d, d2\n", + "\n", + "This statement will return the 'pseudoachondroplasia' node if it is a subtype of 'osteochondrodysplasia' in the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"LATE-ONSET RETINAL DEGENERATION\"}), (g:Gene {name: \"C1QTNF5\"})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "234it [16:27, 4.53s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'immunosuppressive agents' AND d.name = \"crohn's disease\" RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "235it [16:30, 4.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "236it [16:31, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "237it [16:35, 3.30s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Mulibrey Nanism'})-[r:ASSOCIATES_DaG]-(g:Gene {name: 'TRIM37'}) RETURN NOT EXISTS(r) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "238it [16:37, 3.05s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Xeroderma pigmentosum, group G\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ERCC5\"}) RETURN NOT EXISTS(d) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "239it [16:39, 2.70s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to determine the Disease ontology identifier for Lafora disease. A Cypher query would be needed to retrieve this information from the graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Brachydactyly type C'}), (g:Gene {name: 'GDF5'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "240it [16:44, 3.42s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Cystinuria'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'SLC3A1'}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "241it [16:48, 3.55s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Obesity'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'MC4R'}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "242it [16:51, 3.51s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "243it [16:52, 2.75s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThe question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'everolimus'})-[r:TREATS_CtD]->(d:Disease {name: 'tuberous sclerosis'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "244it [16:55, 2.86s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Autosomal Recessive Polycystic Kidney Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PKHD1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "245it [17:00, 3.27s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'amiloride' AND d.name = 'cystic fibrosis' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "246it [17:04, 3.45s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Liver carcinoma'}), (g:Gene {name: 'TP53'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "247it [17:08, 3.70s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Adrenoleukodystrophy\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ABCD1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "248it [17:13, 4.14s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Tuberous Sclerosis'}), (g:Gene {name: 'TSC2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249it [17:20, 5.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Myoclonic dystonia'}), (g:Gene {name: 'SGCE'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "250it [17:24, 4.64s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Long QT Syndrome 1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"KCNQ1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "251it [17:27, 4.27s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Smith-Magenis syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RAI1\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': True}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "252it [17:33, 4.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "253it [17:39, 5.28s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. The schema provided does not include a property for Disease ontology identifier. Therefore, it is not possible to confirm if the Disease ontology identifier for autosomal dominant hypophosphatemic rickets is DOID:0050948.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'nitisinone'})-[:TREATS_CtD]->(d:Disease {name: 'alkaptonuria'}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "254it [17:44, 5.09s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'immune checkpoint inhibitor' AND d.name = 'melanoma' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "255it [17:48, 4.59s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Li-Fraumeni Syndrome'}), (g:Gene {name: 'TP53'}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "256it [17:51, 4.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "257it [17:53, 3.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThe task does not require a Cypher statement to be generated. The task seems to be asking for a validation of a statement rather than a Cypher query.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Hyperargininemia'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'ARG1'}) RETURN COUNT(*) > 0 AS Hyperargininemia_associated_with_ARG1;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'Hyperargininemia_associated_with_ARG1': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "258it [17:59, 4.22s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Fabry Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"GLA\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "259it [18:02, 3.87s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {identifier: \"DOID:0111136\"}) RETURN d.name AS DiseaseName\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'DiseaseName': 'congenital generalized lipodystrophy type 2'}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "260it [18:07, 4.36s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "261it [18:11, 4.33s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task cannot be completed as it requires a Cypher statement to query a graph database, but the provided question is a factual statement that needs to be verified against a specific database. The question does not provide enough information to construct a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Waardenburg Syndrome Type 1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"PAX3\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "262it [18:15, 4.17s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Osteosarcoma'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'TP53'}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "263it [18:19, 4.13s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "264it [18:22, 3.81s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. It does not specify what kind of relationship or property to look for between Mucopolysaccharidosis II and Gene IDS.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Xeroderma pigmentosum, group F\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ERCC4\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "265it [18:26, 3.74s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "266it [18:27, 2.93s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "267it [18:29, 2.57s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Ellis-Van Creveld Syndrome'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'EVC2'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "268it [18:34, 3.49s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "269it [18:40, 4.07s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"X-linked agammaglobulinemia\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"BTK\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"X-linked agammaglobulinemia\" and the Gene node for \"BTK\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true. If the query does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "270it [18:42, 3.59s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThe question cannot be answered with a Cypher statement as it is not a request to generate a Cypher statement to query a graph database. It is a question about medical treatment which requires medical knowledge or a medical database to answer.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound {name: 'liraglutide'})-[r:TREATS_CtD]->(d:Disease {name: 'obesity'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "271it [18:46, 3.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Chediak-Higashi Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"LYST\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "272it [18:50, 3.74s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"FANCONI ANEMIA, COMPLEMENTATION GROUP D2\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"FANCD2\"}) RETURN COUNT(*) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "273it [18:54, 3.96s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Wiskott-Aldrich Syndrome\"})-[r:ASSOCIATES_DaG]->(g:Gene {name: \"WAS\"}) RETURN COUNT(r) > 0 AS association_exists;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "274it [18:59, 4.04s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Pseudoxanthoma Elasticum\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ABCC6\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "275it [19:01, 3.64s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "276it [19:02, 2.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Hajdu-Cheney Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NOTCH2\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "277it [19:06, 3.07s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "278it [19:07, 2.53s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "279it [19:09, 2.39s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. Antibiotics can be used to manage and treat infections associated with cystic fibrosis, but they do not treat the underlying cause of cystic fibrosis, which is a genetic disorder.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Mosaic variegated aneuploidy syndrome 1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"BUB1B\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "280it [19:13, 2.73s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Noonan Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'KRAS'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "281it [19:16, 2.82s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Coffin-Lowry syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"RPS6KA3\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'d': {'identifier': 'DOID:3783', 'Linkout': '<a href=https://staging.knowwheregraph.org/browse/#kwgr:topic.DOID3783 target=\"_blank\">kwgr:topic.DOID3783</a>', 'omim_list': [], 'name': 'Coffin-Lowry syndrome', 'source': 'Disease Ontology', 'mesh_list': ['D038921']}, 'g': {'license': 'CC0 1.0', 'identifier': 6197, 'ensembl': 'ENSG00000177189', 'sources': ['Entrez Gene'], 'synonyms': ['CLS', 'HU-3', 'ISPK-1', 'MAPKAPK1B', 'MRX19', 'RSK', 'RSK2', 'S6K-alpha3', 'XLID19', 'p90-RSK2', 'pp90RSK2'], 'chromosome': 'X', 'name': 'RPS6KA3', 'description': 'ribosomal protein S6 kinase A3', 'source': 'Entrez Gene', 'chembl_id': 'CHEMBL2345'}}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "282it [19:19, 2.97s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "283it [19:21, 2.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. The relationship between Laron Syndrome and Gene GHR is not specified in the provided schema.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "284it [19:26, 3.24s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Leigh Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SURF1\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Leigh Disease\" and the Gene node for \"SURF1\" if there is an ASSOCIATES_DaG relationship between them. If the query returns a result, the statement is true. If the query does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "285it [19:28, 3.02s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'DiGeorge Syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'TBX1'}) RETURN NOT EXISTS(r) AS result;\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "286it [19:30, 2.53s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement. It is asking for a validation of a fact, not a query to a graph database.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'TIBIAL MUSCULAR DYSTROPHY, TARDIVE'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'TTN'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "287it [19:33, 2.85s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (c:Compound)-[:TREATS_CtD]->(d:Disease) WHERE c.name = 'protein-tyrosine kinase inhibitor' AND d.name = 'sarcoma' RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "288it [19:37, 3.08s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Lafora Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"EPM2A\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "289it [19:40, 3.03s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Pseudoachondroplasia'})-[:ASSOCIATES_DaG]->(g:Gene {name: 'COMP'}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "290it [19:43, 3.08s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Charcot-Marie-Tooth disease, Type 4B1\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"MTMR2\"}) RETURN COUNT(*) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "291it [19:47, 3.48s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "292it [19:51, 3.44s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Farber Lipogranulomatosis\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"ASAH1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "293it [19:55, 3.65s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "294it [19:58, 3.48s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mFalse. The question does not provide enough information to generate a Cypher statement. The schema provided does not include a property for Disease ontology identifier. Therefore, it is not possible to confirm if the Disease ontology identifier for Lesch-Nyhan syndrome is DOID:1919.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Polycythemia Vera'}), (g:Gene {name: 'JAK2'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "295it [20:01, 3.29s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "296it [20:02, 2.62s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "297it [20:03, 2.09s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "298it [20:07, 2.68s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThis task is asking for a Cypher statement, not a True or False answer. Here is a Cypher statement that could be used to query a graph database to find if macrolide antibiotics treat cystic fibrosis:\n", + "\n", + "MATCH (c:Compound {name: 'macrolide antibiotics'})-[:TREATS_CtD]->(d:Disease {name: 'cystic fibrosis'}) RETURN c, d\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Pierson syndrome'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'LAMB2'}) RETURN COUNT(r) > 0 AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'association_exists': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "299it [20:11, 3.06s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"CAMPOMELIC DYSPLASIA\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SOX9\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "300it [20:14, 3.23s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Fatal Familial Insomnia'}), (g:Gene {name: 'PRNP'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "301it [20:18, 3.31s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "302it [20:19, 2.63s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mThe question does not require a Cypher statement.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Tay-Sachs Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"HEXA\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "303it [20:22, 2.84s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'beta-Mannosidosis'}), (g:Gene {name: 'MANBA'})\n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS AssociationExists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "304it [20:25, 2.90s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Noonan Syndrome\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"SOS1\"}) RETURN d, g\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "305it [20:28, 2.98s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: 'Obesity'})-[r:ASSOCIATES_DaG]->(g:Gene {name: 'PPARG'}) RETURN COUNT(r) > 0 AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'result': False}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "306it [20:31, 2.88s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Congenital amegakaryocytic thrombocytopenia\"}), (g:Gene {name: \"MPL\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS association_exists\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "307it [20:35, 3.16s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "308it [20:40, 3.82s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Leigh Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"NDUFS4\"}) RETURN d, g\n", + "\n", + "This Cypher statement will return the Disease node for \"Leigh Disease\" and the Gene node for \"NDUFS4\" if there is an \"ASSOCIATES_DaG\" relationship between them. If the query returns a result, the statement is true. If it does not return a result, the statement is false.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Sandhoff Disease\"})-[:ASSOCIATES_DaG]->(g:Gene {name: \"HEXB\"}) RETURN NOT EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "309it [20:45, 4.03s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Doyne honeycomb retinal dystrophy\"}) RETURN d.identifier AS Disease_ontology_identifier;\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[{'Disease_ontology_identifier': 'DOID:0060745'}]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "310it [20:48, 3.71s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new GraphCypherQAChain chain...\u001b[0m\n", + "Generated Cypher:\n", + "\u001b[32;1m\u001b[1;3mMATCH (d:Disease {name: \"Juvenile polyposis syndrome\"}), (g:Gene {name: \"BMPR1A\"}) \n", + "RETURN EXISTS((d)-[:ASSOCIATES_DaG]->(g)) AS result\u001b[0m\n", + "Full Context:\n", + "\u001b[32;1m\u001b[1;3m[]\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "311it [20:51, 4.03s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "CPU times: user 15.8 s, sys: 2.02 s, total: 17.9 s\n", + "Wall time: 20min 51s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "cypher_rag_out = []\n", + "for index, row in tqdm(curated_data.iterrows()):\n", + " question = 'State if the following Question is True or False and state the reason. \\nQuestion: ' + row['text']\n", + " with get_openai_callback() as cb:\n", + " try:\n", + " cypher_rag_answer = chain.run(query=question, return_final_only=True, verbose=False)\n", + " if 'false' in cypher_rag_answer.lower():\n", + " cypher_rag_final_answer = 'False'\n", + " elif 'true' in cypher_rag_answer.lower():\n", + " cypher_rag_final_answer = 'True'\n", + " else:\n", + " cypher_rag_final_answer = None\n", + " except ValueError as e:\n", + " cypher_rag_answer = None\n", + " cypher_rag_final_answer = None\n", + " \n", + " cypher_rag_out.append((row['text'], row['label'], cypher_rag_answer, cypher_rag_final_answer, cb.total_tokens))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e3b6a32d-421b-4340-a45c-520c4286163b", + "metadata": {}, + "outputs": [], + "source": [ + "cypher_rag_out_df = pd.DataFrame(cypher_rag_out, columns=['text', 'label', 'cypher_rag_answer', 'cypher_rag_final_answer', 'total_tokens'])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0a072c59-0814-4d56-af97-8fcd762a2c25", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "save_path = '../data/results'\n", + "os.makedirs(save_path, exist_ok=True)\n", + "cypher_rag_out_df.to_csv(os.path.join(save_path, 'cypher_rag_true_false_output.csv'), index=False)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73c183a0-4bcb-4845-993d-3d294e3ed9de", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (cypher_rag)", + "language": "python", + "name": "cypher_rag" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} |
