symfony/ai-neo4j-store
Neo4j vector store integration for Symfony AI Store. Persist embeddings in Neo4j and run vector similarity searches through its native vector indexes, giving Symfony AI applications a graph-database-backed store.
add() / remove() / similarity-search-with-filter surface is thin and well-defined — and v0.14.0 tightens it further with an explicit VectorDocumentInterface and a StoreFactory for construction. Writing and maintaining a Neo4j vector adapter ourselves is still a few weeks of engineering plus permanent ownership of index configuration, filter translation, and driver upgrades. Buying here (MIT, zero license cost for the package itself) remains the correct default for a first iteration — provided we accept the Symfony coupling below.count capabilities make retrieval meterable. We can now ask a store how much it holds without pulling records. That turns several previously-ungrounded product questions into cheap ones:
StoreFactory reduces adoption friction, but only on the Symfony side. Standardised, DSN-style store construction removes hand-rolled wiring for the bridges that support it. It does not remove the need for a Laravel binding; it just means our binding can be thinner. Net: a small, real reduction in the integration cost we priced in earlier.VectorDocumentInterface landed as a feature in a minor release. That is exactly the kind of change that reshapes the type we'd bind against, and it validates the "wrap it behind our own contract on day one" recommendation rather than weakening it.count, #1755) arrived from an outside contributor. That is the first evidence of a contributor base beyond the core team, and it is a mild positive for the package's durability. It does not change the recommendation: with negligible dependents and no production references, the honest decision remains "evaluate, don't standardize." Re-verify the star/dependent counts before any roadmap write-up — they are the weakest-sampled input in this assessment.Criteria for adoption
WHERE clause on columns in Postgres would solve it, this is the wrong tool.count support makes this a genuine differentiator versus thin stores that force full scans to answer "how many?"composer.json will need attention on every bump, and our adapter — not our application code — must absorb interface changes.Look elsewhere if
StoreFactory helps with construction, but you will still hand-write container bindings and a small adapter, and absorb mismatches between Symfony's conventions and Laravel's (HTTP client, config, DI scoping). For a team without Symfony familiarity, that friction is recurring, not one-time.To executives — one paragraph: "We have a candidate for testing whether our AI features get meaningfully better when search understands relationships, not just similarity — 'find me documents like this one, but only inside this customer's world.' This package is a small, MIT-licensed connector that lets us try that without building a retrieval layer from scratch, and its latest release added two things that matter to the business case: the ability to count what's stored, which is how we'd meter usage and price the feature, and a standard construction path that trims our integration work. I'm recommending a time-boxed spike, not a platform commitment: the package is still early — pre-1.0, negligible adoption, minimal documentation, and it changed a core interface in its most recent release — and the real cost is standing up and operating Neo4j. The decision I need is approval for a short evaluation with a defined kill criterion: if graph-aware retrieval doesn't measurably beat what we have, we stop and keep the current store."
To engineering — the ask: "Treat this as a thin adapter, not an architecture — and v0.14.0 is the proof. VectorDocumentInterface landed as a feature in a minor, so the types we'd bind to are still moving. Wrap it in a Laravel-side contract (VectorStore interface of our own) so the Symfony types never leak past one binding in a service provider, and so swapping to pgvector or a dedicated vector DB is a one-class change. Use the new StoreFactory to reduce construction boilerplate rather than hand-rolling it, and wire the new count() into our spike instrumentation — we want volume alongside latency and relevance in the comparison. Validate four things: (1) the actual interfaces the sibling store package exposes today, since the README still doesn't say and the changelog is a link list; (2) whether filter-plus-similarity in a single Cypher query measurably beats fetching-then-filtering in PHP at our realistic dataset size; (3) the upgrade story, given lockstep minors and an interface that just changed; (4) whether count() is cheap enough to call on a request path or only in background jobs — don't assume. Pin versions, containerize Neo4j for local dev, and write the schema (labels, properties, embedding dimensions, index DDL) down as a migration artifact — not tribal knowledge."
Framing to hold everyone to: this is a spike with a decision gate, evaluated against our existing store on latency, relevance quality, and operational cost. One more substantial release improves the odds the package survives; it does not by itself prove it works in production for anyone. Success means we can state, in numbers, that graph context improved retrieval enough to justify a new database in our stack. Failure means we learned that cheaply — which is also a good outcome, and the reason to run it.
How can I help you explore Laravel packages today?