symfony/ai-chroma-db-store
ChromaDB Store integration for Symfony AI Store. Use ChromaDB as a vector store to manage collections and run query/get operations for embeddings and similarity search. Includes links to Chroma docs plus Symfony AI contributing and issue/PR resources.
Install the Package
composer require symfony/ai-chroma-db-store
Configure ChromaDB Connection
Add ChromaDB settings to your Laravel config (e.g., config/ai.php):
'stores' => [
'chroma' => [
'class' => \Symfony\AI\ChromaDbStore::class,
'connection' => [
'host' => env('CHROMA_HOST', 'http://localhost:8000'),
'api_key' => env('CHROMA_API_KEY'),
'collection' => env('CHROMA_COLLECTION', 'default'),
],
],
],
Register the Store in Laravel
Bind the store to Laravel’s service container in AppServiceProvider:
use Symfony\AI\Store\StoreFactoryInterface;
use Symfony\AI\ChromaDbStore;
public function register()
{
$this->app->bind(StoreFactoryInterface::class, function ($app) {
return new StoreFactory([
'chroma' => [
'class' => ChromaDbStore::class,
'connection' => $app['config']['ai.stores.chroma.connection'],
],
]);
});
}
First Use Case: Store and Query Embeddings
use Symfony\AI\Store\StoreInterface;
class VectorService {
public function __construct(private StoreInterface $store) {}
public function storeEmbedding(array $embedding, array $metadata = [])
{
return $this->store->add($embedding, $metadata);
}
public function findSimilar(array $embedding, int $limit = 5)
{
return $this->store->nearest($embedding, $limit);
}
}
CRUD Operations
$this->store->add([0.1, 0.2, ...], ['document_id' => 123]);
$this->store->update($id, [0.3, 0.4, ...]);
$this->store->remove($id);
Query Patterns
$results = $this->store->nearest($queryEmbedding, 3);
$results = $this->store->nearest($queryEmbedding, 3, [
'where' => ['document_type' => 'article'],
]);
Collection Management
$this->store->createCollection('new_collection');
$this->store->deleteCollection('old_collection');
Use Dependency Injection Bind the store to a service and inject it where needed:
class SearchService {
public function __construct(private StoreInterface $chromaStore) {}
}
Leverage Laravel’s Config
Centralize ChromaDB settings in config/ai.php and use .env for secrets:
CHROMA_HOST=http://localhost:8000
CHROMA_API_KEY=your_api_key
Queue Long-Running Operations Offload bulk operations to queues:
Queue::push(new StoreEmbeddingsJob($embeddings));
Cache Frequent Queries Cache results of expensive nearest-neighbor searches:
$cacheKey = 'similar_'.$hash($queryEmbedding);
return Cache::remember($cacheKey, now()->addMinutes(5), function () use ($queryEmbedding) {
return $this->store->nearest($queryEmbedding, 5);
});
Use Events for Observability Dispatch events for store operations:
event(new VectorStored($embedding, $metadata));
Connection Issues
Connection refused or timeouts.docker run -p 8000:8000 chromadb/chroma) and the host/port in config matches.curl http://localhost:8000/api/v1/health to test connectivity.Metadata Filtering Quirks
// Works:
$this->store->nearest($embedding, 3, ['where' => ['category' => 'tech']]);
// May fail if 'category' is stored as a number:
$this->store->nearest($embedding, 3, ['where' => ['category' => 'tech']]);
Vector Dimension Mismatches
Dimension mismatch errors.if (count($embedding) !== $expectedDimensions) {
throw new \InvalidArgumentException('Dimension mismatch');
}
Rate Limiting
429 Too Many Requests from ChromaDB.Collection Not Found
Collection not found errors.$this->store->createCollection('my_collection');
Enable ChromaDB Logging
Add to config/ai.php:
'debug' => env('APP_DEBUG', false),
Use HTTP Client Interceptor For debugging API calls, wrap the ChromaDB client:
$client = new \Symfony\Contracts\HttpClient\HttpClient([
'base_uri' => $host,
'headers' => ['Authorization' => 'Bearer '.$apiKey],
'on_request' => function ($request) {
\Log::debug('ChromaDB Request:', ['url' => $request->getUri(), 'method' => $request->getMethod()]);
},
]);
Validate Embeddings Sanitize embeddings before storing:
$embedding = array_map('floatval', $embedding);
Custom Query Builders Extend the store to support complex queries:
class CustomChromaStore extends ChromaDbStore {
public function searchByMetadata(array $metadata, int $limit = 10) {
return $this->nearest([], $limit, ['where' => $metadata]);
}
}
Batch Operations Implement batch inserts/updates:
public function batchAdd(array $embeddings, array $metadatas) {
foreach ($embeddings as $i => $embedding) {
$this->add($embedding, $metadatas[$i] ?? []);
}
}
Hybrid Search Combine keyword and vector search:
public function hybridSearch(string $keyword, array $vector, int $limit = 5) {
// 1. Filter by keyword (using ChromaDB metadata)
$filteredIds = $this->getIdsByMetadata(['content' => ['$contains' => $keyword]]);
// 2. Query vector space with filtered IDs
return $this->nearest($vector, $limit, ['where' => ['id' => ['$in' => $filteredIds]]]);
}
Fallback Mechanisms Implement a fallback store for high availability:
class FallbackChromaStore implements StoreInterface {
public function __construct(private StoreInterface $primary, private StoreInterface $fallback) {}
public function add(array $embedding, array $metadata = []) {
try {
return $this->primary->add($embedding, $metadata);
} catch (\Exception $e) {
return $this->fallback->add($embedding, $metadata);
}
}
// Implement other methods similarly
}
Default Collection
If no collection is specified, the store uses a default (e.g., default). Override in config:
'connection' => [
'collection' => 'app_embeddings',
],
API Key vs. Auth ChromaDB supports both API keys and basic auth. Configure accordingly:
// For API key:
'headers' => ['Authorization' => 'Bearer
How can I help you explore Laravel packages today?