|
79 | 79 | use Symfony\AI\Store\Bridge\MongoDb\Store as MongoDbStore; |
80 | 80 | use Symfony\AI\Store\Bridge\Neo4j\Store as Neo4jStore; |
81 | 81 | use Symfony\AI\Store\Bridge\Pinecone\Store as PineconeStore; |
| 82 | +use Symfony\AI\Store\Bridge\Postgres\HybridStore; |
82 | 83 | use Symfony\AI\Store\Bridge\Postgres\Store as PostgresStore; |
83 | 84 | use Symfony\AI\Store\Bridge\Qdrant\Store as QdrantStore; |
84 | 85 | use Symfony\AI\Store\Bridge\Redis\Store as RedisStore; |
@@ -1366,6 +1367,81 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde |
1366 | 1367 | } |
1367 | 1368 | } |
1368 | 1369 |
|
| 1370 | + if ('postgres_hybrid' === $type) { |
| 1371 | + foreach ($stores as $name => $store) { |
| 1372 | + $definition = new Definition(HybridStore::class); |
| 1373 | + |
| 1374 | + // Handle connection (PDO service reference, DBAL connection, or DSN) |
| 1375 | + if (\array_key_exists('connection', $store)) { |
| 1376 | + // Direct PDO service reference |
| 1377 | + $serviceId = ltrim($store['connection'], '@'); |
| 1378 | + $connection = new Reference($serviceId); |
| 1379 | + $arguments = [ |
| 1380 | + $connection, |
| 1381 | + $store['table_name'], |
| 1382 | + ]; |
| 1383 | + } elseif (\array_key_exists('dbal_connection', $store)) { |
| 1384 | + // DBAL connection - extract native PDO |
| 1385 | + $connection = (new Definition(\PDO::class)) |
| 1386 | + ->setFactory([new Reference($store['dbal_connection']), 'getNativeConnection']); |
| 1387 | + $arguments = [ |
| 1388 | + $connection, |
| 1389 | + $store['table_name'], |
| 1390 | + ]; |
| 1391 | + } else { |
| 1392 | + // Create new PDO instance from DSN |
| 1393 | + $pdo = new Definition(\PDO::class); |
| 1394 | + $pdo->setArguments([ |
| 1395 | + $store['dsn'], |
| 1396 | + $store['username'] ?? null, |
| 1397 | + $store['password'] ?? null], |
| 1398 | + ); |
| 1399 | + |
| 1400 | + $arguments = [ |
| 1401 | + $pdo, |
| 1402 | + $store['table_name'], |
| 1403 | + ]; |
| 1404 | + } |
| 1405 | + |
| 1406 | + // Add optional parameters |
| 1407 | + if (\array_key_exists('vector_field', $store)) { |
| 1408 | + $arguments[2] = $store['vector_field']; |
| 1409 | + } |
| 1410 | + |
| 1411 | + if (\array_key_exists('content_field', $store)) { |
| 1412 | + $arguments[3] = $store['content_field']; |
| 1413 | + } |
| 1414 | + |
| 1415 | + if (\array_key_exists('semantic_ratio', $store)) { |
| 1416 | + $arguments[4] = $store['semantic_ratio']; |
| 1417 | + } |
| 1418 | + |
| 1419 | + if (\array_key_exists('distance', $store)) { |
| 1420 | + $arguments[5] = $store['distance']; |
| 1421 | + } |
| 1422 | + |
| 1423 | + if (\array_key_exists('language', $store)) { |
| 1424 | + $arguments[6] = $store['language']; |
| 1425 | + } |
| 1426 | + |
| 1427 | + if (\array_key_exists('rrf_k', $store)) { |
| 1428 | + $arguments[7] = $store['rrf_k']; |
| 1429 | + } |
| 1430 | + |
| 1431 | + if (\array_key_exists('default_max_score', $store)) { |
| 1432 | + $arguments[8] = $store['default_max_score']; |
| 1433 | + } |
| 1434 | + |
| 1435 | + $definition |
| 1436 | + ->addTag('ai.store') |
| 1437 | + ->setArguments($arguments); |
| 1438 | + |
| 1439 | + $container->setDefinition('ai.store.'.$type.'.'.$name, $definition); |
| 1440 | + $container->registerAliasForArgument('ai.store.'.$type.'.'.$name, StoreInterface::class, $name); |
| 1441 | + $container->registerAliasForArgument('ai.store.'.$type.'.'.$name, StoreInterface::class, $type.'_'.$name); |
| 1442 | + } |
| 1443 | + } |
| 1444 | + |
1369 | 1445 | if ('supabase' === $type) { |
1370 | 1446 | foreach ($stores as $name => $store) { |
1371 | 1447 | $arguments = [ |
|
0 commit comments