symfony/ai-chroma-db-store
ChromaDB vector store integration for Symfony AI Store, enabling collection management and vector queries against ChromaDB.
Bottom line: Still a bridge, not a product — but a materially better bridge than the version we assessed. v0.14.0 adds count() on stores and introduces VectorDocumentInterface, which removes the two most annoying pieces of glue we were going to write (reconciliation counting and document mapping). Nothing in the changelog addresses the Laravel gap: no service provider, no config publishing, no queue integration, no observability. The recommendation is unchanged — time-boxed spike, not a roadmap commitment — but the churn risk is now demonstrated rather than theoretical: we assessed v0.8.x, the package is at v0.14.x, and this release is a textbook pre-1.0 minor that adds an interface and changes query behavior. Pin hard, and treat every bump as a change request.
count() and VectorDocumentInterface extend that surface without widening it into a framework — this is still a bridge we can audit in an afternoon and fork in a day.VectorDocumentInterface is the more significant of the two features. It means the store type-hints against an interface rather than a concrete Document. That lets our domain DTO implement it directly, collapsing the mapping layer we'd budgeted for and making test doubles trivial. It also reduces our exposure to constructor changes upstream — but only if we build against the interface from day one rather than the concrete class the earlier docs showed.count() closes our cheapest observability gap. Previously, reconciling "source-of-truth rows" vs "vectors in collection" required either a query hack or a full scan. A first-class count turns that into a one-line health metric and a viable nightly reconciliation job. This should be promoted from "nice to have later" to "in the pilot."StoreInterface + StoreFactory mean Chroma remains swappable. The new interface reinforces this — the more of the store's contract is expressed as interfaces, the cheaper our exit.Vectorizer story (we own provider choice, model version, dimension, re-embedding cost), no collection provisioning, no multi-tenancy mapping. All three remain ours, and the embedding pipeline is still the largest hidden cost in the project.symfony/ai. Upgrading one requires upgrading both in lockstep; a half-upgrade will produce interface-not-satisfied errors at container boot, not at first use. Verify the exact symfony/ai constraint in the store's composer.json before estimating.StoreInterface via StoreFactory, env-driven config (host, port, TLS, token, tenant, database, collection, metric, timeout), and an authenticating health check. Small, permanent, ours.VectorDocumentInterface on our DTO) and an ad-hoc count/reconciliation path (use count()).| Risk | Severity | Notes |
|---|---|---|
| Pre-1.0 churn on both sides | High (now evidenced) | v0.8 → v0.14 in six minors, including an interface extraction and a behavior change to query semantics. Exact pins only; caret ranges are a delayed production incident. |
| Client/core version skew | High (new) | Store v0.14 expects core v0.14. Half-upgrades fail at boot. Upgrade both in one PR, one CI run. |
| Query result-set drift | Medium (new) | The default-limit fix changes how many results come back when we don't specify a limit. Any "top N" UI or evaluation harness must set an explicit limit and assert on it. |
| Latency added to request path | High | Network round trip per query. Unchanged by this release; still the p95 problem. |
| Embedding model lock-in | High | Dimension and semantics baked into vectors. Unchanged, and still the biggest hidden cost. |
| Chroma server version drift | Medium | Token auth and tenant/database paths have moved before. Pin the server image by digest. |
| Small upstream contributor pool | Medium | The Chroma path is thin; the VectorDocumentInterface extraction is the kind of refactor that produces follow-up fixes in the next 1–2 minors. |
| Zero stars / zero dependents | Medium (misleading) | Still a read-only subtree split of the monorepo. Judge by upstream cadence — which this release confirms is active. |
limit and that our port enforces it. Otherwise result-set size becomes a silent upstream parameter.count() reflect the whole collection or the filtered set? If it's unfiltered collection count, it's a reconciliation primitive, not a UI primitive. Confirm before anyone puts it on a dashboard or a paginator.VectorDocumentInterface on our domain DTO, or keep our own type and map? Adopting it removes a layer but couples our DTO to an upstream interface that has changed once already. Default recommendation: adopt it in the adapter, keep our domain DTO clean, and map in one place — cheaper to reverse.composer require symfony/ai-chroma-db-store at an exact version, alongside the matching symfony/ai minor. Verify PHP and PSR-7/18 client compatibility with our Laravel version before merging anything.singleton VectorStoreServiceProvider reading config/vector.php, binding StoreInterface via StoreFactory. No connection on boot.EmbeddingRepository/SemanticSearch interface; one adapter delegating to StoreInterface. Application code never references the Symfony or Chroma namespace. Highest-leverage decision in the integration — it makes the Chroma bet reversible and makes the next upstream interface change a one-file edit.VectorDocumentInterface in the adapter, not the domain. Map our DTO to an adapter-level document at the boundary. One mapping function, one place to fix when the interface shifts again.count() in the health check and in a scheduled reconciliation job — not in request paths.limit. All env-driven, no hardcoded defaults in the provider.count() reconciliation and record the delta; a non-zero unexplained delta is a stop signal.StoreInterface method signatures, VectorDocumentInterface shape, document/query result shapes — so upstream drift fails our CI, not production search. Add a test asserting explicit-limit behavior so the v0.14 default-limit change can't regress silently.symfony/ai v0.14 line's Symfony component requirements are satisfied by our Laravel-bundled components. A conflicted symfony/http-client constraint remains the most plausible early blocker.VectorDocumentInterface mapping test.count() reconciliation dry run (0.5 day — new, and cheap now that count() exists).Realistic delta versus the prior plan: roughly +0.5 day for interface adoption and re-baselining, offset by roughly −1 day no longer spent building a document mapper and a count/reconciliation shim.
VectorDocumentInterface extraction is a preview of the shape of that tax: cheap if our port is in place, expensive if we coded against the concrete class.docs_v2), script creation, require review for metric/dimension changes. Dimension mismatches fail at query time with unhelpful errors.symfony/ai if upstream stalls. If no, reduce dependence.count() reconciliation delta.count() is safe to poll but not free at scale — schedule reconciliation (nightly) rather than calling it per request or per page view.limit in the adapter, assert on it in contract tests.count() matching source-of-truth does not prove the vectors are correct — only that the row count matches. Mitigation: pair count checks with a sampled quality eval; don't let a green count dashboard substitute for retrieval review.count() reconciliation against source of truth.StoreInterface, StoreFactory, VectorDocumentInterface, and how embeddings are supplied. ~1 day for a senior PHP engineer. The v0.14 interfaces make this slightly easier to explain, since the contract is now readable as interfaces rather than inferred from a concrete class.How can I help you explore Laravel packages today?