3 Commits

Author SHA1 Message Date
501c224540 Update README.md 2025-12-27 05:07:01 -08:00
64c45ee66c Update README.md 2025-12-27 04:33:07 -08:00
b221ae4b42 Update README.md 2025-12-27 03:30:28 -08:00
4 changed files with 38 additions and 35 deletions

View File

@@ -1,15 +1,10 @@
# dspy-neo4j-knowledge-graph
# text-to-cypher
LLM-driven automated knowledge graph construction from text using DSPy and Neo4j.
![Knowledge Graph](img/kg.png)
## Project Structure
```sh
dspy-neo4j-knowledge-graph/
text-to-cypher/
├── README.md
├── examples/
│ └── wikipedia-abstracts-v0_0_1.ndjson
├── img/
├── main.py
├── pyproject.toml
├── uv.lock
@@ -79,7 +74,7 @@ MODAIC_TOKEN=<your-modaic-token>
Run Neo4j locally using Docker:
```sh
docker run \
--name dspy-kg \
--name text-to-cypher \
--publish=7474:7474 \
--publish=7687:7687 \
--env "NEO4J_AUTH=none" \
@@ -153,8 +148,8 @@ neo4j.query(cypher.statement.replace('```', ''))
### Stop Neo4j Docker Container
```sh
docker stop dspy-kg
docker rm dspy-kg
docker stop text-to-cypher
docker rm text-to-cypher
```
### Remove Virtual Environment

44
main.py
View File

@@ -13,20 +13,24 @@ neo4j = Neo4j(
password=os.getenv("NEO4J_PASSWORD"),
)
class CypherFromText(dspy.Signature):
"""Instructions:
Create a Cypher MERGE statement to model all entities and relationships found in the text following these guidelines:
- Refer to the provided schema and use existing or similar nodes, properties or relationships before creating new ones.
- Use generic categories for node and relationship labels."""
text = dspy.InputField(
desc="Text to model using nodes, properties and relationships."
class CypherFromQuestion(dspy.Signature):
"""Task: Generate Cypher statement to query a graph database.
Instructions: Use only the provided relationship types and properties in the schema.
Do not use any other relationship types or properties that are not provided in the schema.
Do not include any explanations or apologies in your responses.
Do not respond to any questions that might ask anything else than for you to construct a Cypher statement.
Do not include any text except the generated Cypher statement.
"""
question = dspy.InputField(
desc="Question to model using a cypher statement. Use only the provided relationship types and properties in the schema."
)
neo4j_schema = dspy.InputField(
desc="Current graph schema in Neo4j as a list of NODES and RELATIONSHIPS."
)
statement = dspy.OutputField(
desc="Cypher statement to merge nodes and relationships found in the text."
)
statement = dspy.OutputField(desc="Cypher statement to query the graph database.")
class GenerateCypherConfig(PrecompiledConfig):
model: str = "openai/gpt-4o"
@@ -42,18 +46,20 @@ class GenerateCypher(PrecompiledProgram):
model=config.model,
max_tokens=config.max_tokens,
)
self.generate_cypher = dspy.ChainOfThought(CypherFromText)
self.generate_cypher = dspy.ChainOfThought(CypherFromQuestion)
self.generate_cypher.set_lm(self.lm)
def forward(self, text: str, neo4j_schema: list[str]):
return self.generate_cypher(text=text, neo4j_schema=neo4j_schema)
def forward(self, question: str, neo4j_schema: list[str]):
return self.generate_cypher(question=question, neo4j_schema=neo4j_schema)
generate_cypher = GenerateCypher(GenerateCypherConfig())
if __name__ == "__main__":
"""
from pathlib import Path
import json
"""
examples_path = Path(__file__).parent / "examples" / "wikipedia-abstracts-v0_0_1.ndjson"
with open(examples_path, "r") as f:
for line in f:
@@ -67,7 +73,9 @@ if __name__ == "__main__":
schema = neo4j.fmt_schema()
print("SCHEMA:\n", schema)
"""
generate_cypher.push_to_hub("farouk1/text-to-cypher", with_code=True, tag="v0.0.6", commit_message="Update README.md")
generate_cypher.push_to_hub(
"farouk1/text-to-cypher",
with_code=True,
tag="v0.0.9",
commit_message="Update README.md",
)

View File

@@ -4,11 +4,11 @@
"train": [],
"demos": [],
"signature": {
"instructions": "Instructions:\nCreate a Cypher MERGE statement to model all entities and relationships found in the text following these guidelines:\n- Refer to the provided schema and use existing or similar nodes, properties or relationships before creating new ones.\n- Use generic categories for node and relationship labels.",
"instructions": "Task: Generate Cypher statement to query a graph database.\nInstructions: Use only the provided relationship types and properties in the schema.\nDo not use any other relationship types or properties that are not provided in the schema.\nDo not include any explanations or apologies in your responses.\nDo not respond to any questions that might ask anything else than for you to construct a Cypher statement.\nDo not include any text except the generated Cypher statement.",
"fields": [
{
"prefix": "Text:",
"description": "Text to model using nodes, properties and relationships."
"prefix": "Question:",
"description": "Question to model using a cypher statement. Use only the provided relationship types and properties in the schema."
},
{
"prefix": "Neo 4 J Schema:",
@@ -20,7 +20,7 @@
},
{
"prefix": "Statement:",
"description": "Cypher statement to merge nodes and relationships found in the text."
"description": "Cypher statement to query the graph database."
}
]
},

View File

@@ -4,4 +4,4 @@ version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = ["datasets>=4.4.2", "dspy>=3.0.4", "modaic>=0.8.2", "neo4j~=5.18.0", "python-dotenv~=1.0.1"]
dependencies = ["datasets>=4.4.2", "dspy>=3.0.4", "modaic>=0.8.2", "neo4j~=5.18.0", "python-dotenv~=1.0.1", "sacrebleu>=2.5.1"]