Skip to main content

LangChain integration for Apache AGE (graph) + pgvector (vector) on PostgreSQL

Project description

langchain-age

LangChain integration for Apache AGE (graph) + pgvector (vector) on PostgreSQL.

Drop-in replacement for langchain-neo4j — same API, runs on PostgreSQL instead of Neo4j.

from langchain_age import AGEGraph, AGEVector, AGEGraphCypherQAChain

v0.1.1 — Initial stable release. The public API (AGEGraph, AGEVector, AGEGraphCypherQAChain) is considered stable. Breaking changes in 0.1.x will be avoided where possible.

Tested with

  • Python 3.10–3.14
  • PostgreSQL 18 + Apache AGE 1.7.0 + pgvector 0.8.2

Known limitations

  • AGE does not support parameterised Cypher ($param) — langchain-age provides mogrify-based safe value escaping as a workaround
  • The [graph] extra installs apache-age-python from GitHub (the PyPI version is outdated and psycopg2-based)
  • Async methods use run_in_executor wrapping (not native psycopg.AsyncConnection yet)

Installation

Three install modes depending on what you need:

# Vector only (pgvector)
pip install "langchain-age[vector]"

# Graph + Vector (everything)
pip install "langchain-age[all]"
pip install "apache-age-python @ git+https://github.com/apache/age.git#subdirectory=drivers/python"

Note: The Apache AGE Python driver must be installed separately from GitHub. The PyPI version (0.0.7) is outdated and uses psycopg2. The GitHub version uses psycopg3. This is the official SDK maintained by the Apache AGE project.

Quick Start

1. Start the database

cd docker
docker compose up -d

Single container: PostgreSQL 18 + Apache AGE 1.7.0 + pgvector.

2. Graph mode

from langchain_age import AGEGraph

graph = AGEGraph(
    "host=localhost port=5433 dbname=langchain_age user=langchain password=langchain",
    graph_name="my_graph",
)

graph.query("CREATE (:Person {name: 'Alice', age: 30})")
results = graph.query("MATCH (n:Person) RETURN n.name AS name")
# [{'name': 'Alice'}]

3. Vector mode

from langchain_age import AGEVector, DistanceStrategy

store = AGEVector(
    connection_string="host=localhost port=5433 dbname=langchain_age user=langchain password=langchain",
    embedding_function=my_embeddings,
    collection_name="docs",
    distance_strategy=DistanceStrategy.COSINE,
)

store.add_texts(["Apache AGE adds Cypher to PostgreSQL."])
results = store.similarity_search("graph database", k=5)

4. Graph + Vector (GraphRAG)

# Vectorise existing graph nodes
store = AGEVector.from_existing_graph(
    embedding=my_embeddings,
    connection_string="...",
    graph_name="my_graph",
    node_label="Document",
    text_node_properties=["title", "content"],
)

5. Cypher QA Chain

from langchain_age import AGEGraph, AGEGraphCypherQAChain
from langchain_openai import ChatOpenAI

chain = AGEGraphCypherQAChain.from_llm(
    ChatOpenAI(model="gpt-4o-mini"),
    graph=AGEGraph("...", "movies"),
    allow_dangerous_requests=True,
)
answer = chain.run("Which movies did Tom Hanks act in?")

6. Long-term Memory & Checkpointing

Uses the same PostgreSQL instance via langgraph-checkpoint-postgres:

from langgraph.store.postgres import PostgresStore

with PostgresStore.from_conn_string("host=localhost port=5433 ...") as store:
    store.setup()
    store.put(("users", "123"), "prefs", {"theme": "dark"})

AGE graph tables, pgvector tables, and LangGraph store tables coexist in the same database.

Features

Component Class Description
Graph AGEGraph GraphStore backed by Apache AGE. Cypher execution, schema introspection, GraphDocument upserts.
Vector AGEVector VectorStore backed by pgvector. Cosine/L2/IP distance, HNSW & IVFFlat indexes, hybrid search (vector + full-text via RRF), MMR.
Chain AGEGraphCypherQAChain LLM generates Cypher, executes against AGE, returns natural-language answer.

Security

  • SQL identifier validation at construction (validate_sql_identifier)
  • Cypher identifier backtick-quoting for all 25 AGE reserved words (escape_cypher_identifier)
  • OpenCypher-standard string escaping with '' doubling (escape_cypher_string)
  • allow_dangerous_requests gate on the QA chain
  • Double-quoted SQL table/index names throughout

langchain-neo4j API Compatibility

Feature langchain-neo4j langchain-age
from_existing_graph() Neo4jVector.from_existing_graph() AGEVector.from_existing_graph()
from_existing_index() Neo4jVector.from_existing_index() AGEVector.from_existing_index()
similarity_search_with_relevance_scores() Yes Yes
as_retriever() Yes Yes
Hybrid search Lucene full-text PostgreSQL tsvector + RRF
include_types / exclude_types Yes Yes
add_graph_documents() Yes Yes
Context manager Yes Yes
Batch insert UNWIND ... IN TRANSACTIONS OF 1000 ROWS executemany with batch_size=1000

AGE vs Neo4j

Neo4j Apache AGE
Cypher execution Bolt protocol SQL-wrapped: SELECT * FROM cypher(...)
Connection neo4j:// PostgreSQL DSN
Vector search Native index pgvector extension
APOC Available Not available
Data types Native graph agtype (JSON superset)
Parameterised Cypher Yes ($param) mogrify-based (%s placeholders)

langchain-age handles SQL wrapping automatically — you write plain Cypher.

Documentation

Language Getting Started Tutorial API Reference
English getting-started.md tutorial.md api-reference.md
Korean getting-started.md tutorial.md api-reference.md

Notebooks

Notebook Description
01_graph.ipynb AGEGraph: Cypher CRUD, schema, GraphDocument
02_vector.ipynb AGEVector: similarity, hybrid, MMR, filters, HNSW
03_graph_vector.ipynb GraphRAG: from_existing_graph, QA chain

01 requires no API key. 02–03 use OpenAI via getpass.

Running Tests

# Unit tests (no DB required) — 65 tests
pytest tests/unit/

# Integration tests (requires Docker container) — 53 tests
export LANGCHAIN_AGE_TEST_DSN="host=localhost port=5433 dbname=langchain_age user=langchain password=langchain"
pytest tests/integration/

Project Structure

langchain-age/
├── docker/                          # PG18 + AGE + pgvector container
│   ├── Dockerfile
│   ├── docker-compose.yml
│   └── init/01_init_extensions.sql
├── langchain_age/
│   ├── __init__.py                  # Lazy imports (3-mode support)
│   ├── graphs/
│   │   └── age_graph.py             # AGEGraph (GraphStore)
│   ├── vectorstores/
│   │   └── age_vector.py            # AGEVector (VectorStore)
│   ├── chains/
│   │   └── graph_cypher_qa_chain.py # AGEGraphCypherQAChain
│   └── utils/
│       ├── agtype.py                # Vertex/Edge/Path → dict conversion
│       └── cypher.py                # SQL wrapping, escaping, validation
├── tests/
│   ├── conftest.py                  # Auto-skip integration when DSN unset
│   ├── unit/                        # 65 tests, no DB
│   └── integration/                 # 53 tests, live DB
├── pyproject.toml
├── LICENSE                          # MIT
├── CHANGELOG.md                     # Version history
└── .github/workflows/ci.yml        # Lint + unit (3.10–3.13) + integration

Python Support

Tested on Python 3.10, 3.11, 3.12, 3.13, 3.14.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_age-0.1.1.tar.gz (59.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langchain_age-0.1.1-py3-none-any.whl (34.1 kB view details)

Uploaded Python 3

File details

Details for the file langchain_age-0.1.1.tar.gz.

File metadata

  • Download URL: langchain_age-0.1.1.tar.gz
  • Upload date:
  • Size: 59.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langchain_age-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a6d304ec2597a7d75d97c5ed5cab750d6163e7f91325d63bc1e7a79a721d2b0d
MD5 978ba53a198cb118510a201a8e475c8f
BLAKE2b-256 3bcf72fcab6c7a667e4a728d5427e6b94e8d4dd8994eddb4671b340863a268bb

See more details on using hashes here.

File details

Details for the file langchain_age-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: langchain_age-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 34.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langchain_age-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f1bc45d1af3f2bd6afa405509c398c9567312d19ed569692f70f883f801353bc
MD5 00b730b001cf81f842ed02a1f30d2f47
BLAKE2b-256 11ce02a5a24559f9c9e62ae607483c38b09ef88e1476e1b9ba3245b09a22fa58

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page