AWS Builder Center
Building Knowledge Graphs from unstructured Text with Lettria Perseus and Amazon Neptune

Building Knowledge Graphs from unstructured Text with Lettria Perseus and Amazon Neptune

This post demonstrates how to automatically transform unstructured documents into queryable knowledge graphs using Lettria's Perseus SDK and Amazon Neptune.

Organizations accumulate vast amounts of unstructured text data—technical documentation, research papers, customer feedback, and internal reports. While this content holds valuable insights and relationships between entities, extracting structured knowledge from it remains a complex challenge. 
Traditional approaches to building knowledge graphs require significant effort: defining schemas, manually annotating entities, identifying relationships, and developing custom extraction logic. This process demands specialized expertise in natural language processing, graph theory, and domain knowledge. For many organizations, these requirements create substantial barriers to leveraging their unstructured data assets. 
Knowledge graphs offer powerful capabilities once constructed. They enable semantic search across interconnected concepts, power recommendation systems by traversing relationship patterns, and support question-answering systems that reason over structured knowledge. However, the path from raw text to functional graph database has historically required extensive development effort and ongoing maintenance. 
This post demonstrates how to automatically transform unstructured documents into queryable knowledge graphs using Lettria 's Perseus SDK and Amazon Neptune. 

Solution Overview 

Transform unstructured text into knowledge graph
This solution combines Lettria's Perseus SDK  with Amazon Neptune to automate knowledge graph construction. The architecture streamlines the process: ingest markdown or text documents, extract entities and relationships using Perseus, and load the resulting graph into Neptune for querying and analysis. 
Perseus SDK handles the complexity of natural language understanding. It processes documents through Lettria's  models to identify entities (people, organizations, concepts, technologies), extract relationships between them, and generate graph database statements. The SDK outputs openCypher queries ready for Neptune, eliminating the need for custom extraction logic or manual graph construction. 
Amazon Neptune  provides the graph database infrastructure. Running in an Amazon Virtual Private Cloud (VPC) with automated backups and high availability, Neptune stores the generated knowledge graph and enables fast traversal queries. The combination delivers an end-to-end solution: from unstructured text to queryable graph in minutes rather than days. 

Implementation 

This section walks through deploying the complete architecture. The reference implementation includes a Jupyter notebook with all steps, CloudFormation templates for infrastructure, and example documents. The notebook runs on standard CPU instances—no GPU required locally as all processing happens through the Perseus API. You can find the resources in the following repository . 

Security considerations 

This notebook and CloudFormation Template are provided as samples to demonstrate capabilities. Security is a shared responsibility between AWS and you. AWS manages the security of Neptune's underlying infrastructure, including automatic OS patching and physical security. You are responsible for: (1) Configuring VPC and security groups to control network access, (2) Managing IAM policies and authentication, (3) Encrypting data at rest and in transit, (4) Implementing proper input validation in queries, and (5) Meeting your compliance requirements. This solution implements several security best practices: Neptune is deployed in private subnets with VPC-only access, IAM authentication is enabled, and connections use SSL/TLS encryption. 

Prerequisites 

To execute this solution, you will need: 
  • AWS permissions for CloudFormation, Neptune, EC2, and S3. Sample policy here .
  • AWS Permissions to create a notebook instance. Sample policy here . 
  • Lettria API key (get one on lettria’s  platform) 
  • Python 3.10 or later 
  • AWS CLI configured for us-east-1 (works with all regions where Amazon Neptune is available) 

Deploying Infrastructure 

The CloudFormation template provisions a complete VPC environment optimized for Neptune. Deploy the infrastructure with: 
1
2
3
4
5
6
aws cloudformation create-stack \
--stack-name perseus-neptune-demo \
--template-body file://infrastructure.yaml \
--parameters \
ParameterKey=StackName,ParameterValue=perseus-neptune-demo \
ParameterKey=NeptuneInstanceClass,ParameterValue=db.t3.medium
The template creates: 
- VPC with DNS enabled (10.0.0.0/16) 
- One public subnet and two private subnets across availability zones 
- Single NAT gateway for cost efficiency 
- Neptune cluster in private subnets with VPC-only security group 
- CloudFormation exports for easy endpoint access 
Deployment is completed in approximately 10-15 minutes. Neptune requires subnets in at least two availability zones for high availability, which this template provides while minimizing networking costs with a single NAT gateway. 
Retrieve the Neptune endpoint after deployment: 
1
2
3
4
aws cloudformation describe-stacks \
--stack-name perseus-neptune-demo \
--query 'Stacks[0].Outputs[?OutputKey==`NeptuneClusterEndpoint`].OutputValue' \
--output text

Create a graph notebook instance 

To facilitate the connection with Amazon Neptune cluster, a Graph Notebook will be used. You can create the notebook directly from the console. 
You can find more details on how to connect to Amazon Neptune here .  
Then you can open JupyterLab. 
Once Jupyter has successfully started, download the sample notebook  locally from the repository and drop it in the left pane to upload it to the Graph notebook as pictured here: 
Then we can open it and start running cells. 

Installing Dependencies 

The solution requires Perseus SDK, AWS SDK and usual python libraries.  
1
pip install perseus-client boto3 nest_asyncio

Configuring the Environment 

Configure your stack name and Lettria API key: 
1
2
3
4
5
NEPTUNE_HOST = "" # e.g., "perseus-neptune-demo-cluster.cluster-abc123.us-east-1.neptune.amazonaws.com"
NEPTUNE_PORT = 8182
LETTRIA_API_KEY = "" # Your Lettria API key
FILE_PATH = "./sample-document.md" # Path to your input document
OUTPUT_PATH = "./output/graph" # Output path (will create .cql and .ttl files)
You can upload a sample document to the notebook by using drag-and-drop, just like we did with the sample notebook. 

Building the Knowledge Graph 

Perseus SDK processes documents and generates graph representations. The workflow reads your input document, sends it to Lettria's API for entity extraction and relationship identification, and returns openCypher statements for Neptune: 
1
2
3
4
5
6
7
8
9
10
11
12
def build_knowledge_graph(file_path: str, output_path: str):
"""Build knowledge graph from document using Perseus SDK."""
# [...] 
with PerseusClient() as client: 
job = client.build_graph(
file_path=file_path, 
output_path=output_path, 
)
# [...]
logging.info(f"Graph generation completed in {elapsed_time:.1f} seconds")

return f"{output_path}.cql" 
Processing time varies with document size. The SDK generates two output files: a CQL file containing openCypher statements for Neptune, and a TTL file with RDF triples for semantic web applications. 

Loading Data into Neptune 

With the CQL file generated, load the graph into Neptune. The loading process splits the file into individual openCypher statements and executes them sequentially: 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def load_graph_to_neptune(neptune_client, cql_file_path): 
"""Load openCypher statements into Neptune.""" 
 
with open(cql_file_path, 'r') as f: 
cql_content = f.read() 
 
statements = [stmt.strip() for stmt in cql_content.split(';') if stmt.strip()] 
total_statements = len(statements) 
 
logging.info(f"Found {total_statements} openCypher statements to execute") 
 
successful = 0 

for i, statement in enumerate(statements, 1): 
if i % 10 == 0: 
logging.info(f"Progress: {i}/{total_statements} statements processed...") 

try: 
neptune_client.execute_open_cypher_query( 
openCypherQuery=statement 
) 
successful += 1 
except Exception as e: 
logging.error(f"Statement {i} failed: {e}") 

success_rate = (successful / total_statements * 100) 
logging.info(f"Loading complete: {successful}/{total_statements} ({success_rate:.1f}%)") 
 
return successful 

Querying the Knowledge Graph 

 Once loaded, query the graph to extract insights. Neptune supports multiple query languages; openCypher provides a declarative syntax familiar to SQL users: 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Get graph statistics 
response = neptune_client.execute_open_cypher_query( 
openCypherQuery="MATCH (n) RETURN count(n) as total_nodes" 
) 

total_nodes = response['results'][0]['total_nodes'] 
 
response = neptune_client.execute_open_cypher_query( 
openCypherQuery="MATCH ()-[r]->() RETURN count(r) as total_relationships" 
) 

total_rels = response['results'][0]['total_relationships'] 
 
print(f"Graph contains {total_nodes} nodes and {total_rels} relationships") 
Example query to explore relationships: 
1
2
3
4
5
6
7
8
9
10
11
12
# Find relationships from specific entities 
query = """ 
MATCH (n)-[r]->(m) 
WHERE n.label CONTAINS 'Neptune' 
RETURN n.label as source, type(r) as relationship, m.label as target 
LIMIT 10 
"""


response = neptune_client.execute_open_cypher_query(openCypherQuery=query) 
 
for result in response['results']: 
print(f"{result['source']} --[{result['relationship']}]--> {result['target']}") 
These queries demonstrate the graph's capabilities for traversing relationships and discovering connections between entities extracted from your documents. 

Results and Performance 

Testing with a 7KB technical document about Amazon Neptune demonstrates the solution's capabilities. The document discusses graph database features, query languages, security capabilities, and integration patterns. 
Perseus processing extracted: 
- 18 entity nodes (services, technologies, features) 
- 24 relationship edges (supports, provides, integrates, implements) 
- 67 openCypher CREATE statements 

Cost estimation

Monthly cost based on us-east-1 pricing.
Amazon Neptune: 1 instance (db.t3.medium) est ~$72 with < 10GB of storage
Notebook hosted via Amazon Sagemaker AI: 1 instance (ml.t3.medium) est ~$37
NAT Gateway cost: assuming 10GB of data processing ~$33

Clean up resources

To avoid unnecessary cost, don’t forget to remove resources once you have finished the test.
  • Delete the notebook instance directly in Amazon Neptune Graph.
  • Remove cloudformation stack
1
aws cloudformation delete-stack --stack-name perseus-neptune-demo

Next Steps 

This solution provides a foundation for knowledge graph applications. Consider these extensions: 
  • Multi-Document Knowledge Graphs: Process multiple related documents and merge their graphs. Perseus maintains consistent entity identification across documents, enabling you to build comprehensive knowledge bases spanning your entire document corpus. 
  • Custom Query Development: Leverage openCypher's expressive syntax to build domain-specific queries. The declarative language supports complex graph patterns, making it straightforward to encode business logic as graph traversals. 
  • Application Integration: Expose your knowledge graph through APIs. Build semantic search endpoints that traverse relationships, recommendation engines that identify similar entities, or question-answering systems that reason over the structured knowledge. 
  • Real-time Updates: Implement workflows that process new documents as they arrive. Combine Amazon EventBridge, AWS Lambda, and Perseus SDK to maintain current knowledge graphs as your document collection evolves. 
  • Bring-your-own-ontology: Lettria  allow users to provide graph schema via Turtle ontologies. This allows them to define a more predictable knowledge graph structure, making queries more precise. It also enables nodes, relationships, and their associated metadata to be tailored to a specific use case. Additionally, users can generate ontologies from a document using the Perseus service (currently only via the console, soon through the SDK). This provides a quick way to produce a graph schema without starting from scratch. 
Start by processing your own documents. Technical documentation, research papers, product specifications, and internal wiki pages all contain valuable structured information waiting to be extracted. The complete implementation with notebook, CloudFormation templates, and example code is available in the accompanying repository. 

Conclusion 

Building knowledge graphs from unstructured text transforms static documents into dynamic, queryable knowledge bases. The combination of Lettria's Perseus SDK  and Amazon Neptune eliminates traditional implementation complexity, providing a managed solution that scales with your requirements. 
The architecture delivers value quickly: deploy infrastructure in 15 minutes, process your first document in minutes, and query the resulting graph immediately. This accelerated timeline—compared to weeks or months for traditional implementations—enables organizations to experiment with knowledge graph applications and demonstrate value before committing to extensive development efforts. 
For organizations managing significant document collections, this solution provides a practical path to unlock structured insights from unstructured content. Whether building internal knowledge bases, powering semantic search, or enabling AI applications that reason over enterprise knowledge, automated knowledge graph construction offers immediate benefits and long-term strategic value.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article