Skip to content

Commit 73418c9

Browse files
committed
refactor(store): WeaviateStoreFactory introduced
1 parent 070c478 commit 73418c9

File tree

12 files changed

+198
-111
lines changed

12 files changed

+198
-111
lines changed

UPGRADE.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
UPGRADE FROM 0.5 to 0.6
2+
=======================
3+
4+
Store
5+
-----
6+
7+
* The `endpointUrl` parameter for `QdrantStore` has been removed
8+
* The `apiKey` parameter for `QdrantStore` has been removed
9+
* The `endpointUrl` parameter for `WeaviateStore` has been removed
10+
* The `apiKey` parameter for `WeaviateStore` has been removed
11+
112
UPGRADE FROM 0.4 to 0.5
213
=======================
314

examples/rag/weaviate.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
1818
use Symfony\AI\Platform\Message\Message;
1919
use Symfony\AI\Platform\Message\MessageBag;
20-
use Symfony\AI\Store\Bridge\Weaviate\Store;
20+
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory;
2121
use Symfony\AI\Store\Document\Metadata;
2222
use Symfony\AI\Store\Document\TextDocument;
2323
use Symfony\AI\Store\Document\Vectorizer;
@@ -28,12 +28,7 @@
2828
require_once dirname(__DIR__).'/bootstrap.php';
2929

3030
// initialize the store
31-
$store = new Store(
32-
httpClient: http_client(),
33-
endpointUrl: env('WEAVIATE_HOST'),
34-
apiKey: env('WEAVIATE_API_KEY'),
35-
collection: 'Movies',
36-
);
31+
$store = StoreFactory::create('Movies', env('WEAVIATE_HOST'), env('WEAVIATE_API_KEY'));
3732

3833
// initialize the index
3934
$store->setup();

src/ai-bundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Add `TraceableAgent`
99
* Add `TraceableStore`
1010
* Add `setup_options` configuration for PostgreSQL store to pass extra fields to `ai:store:setup`
11+
* Add support for custom HttpClient for `Qdrant` and `Weaviate` stores
1112

1213
0.5
1314
---

src/ai-bundle/config/store/weaviate.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
->useAttributeAsKey('name')
1818
->arrayPrototype()
1919
->children()
20-
->stringNode('endpoint')->cannotBeEmpty()->end()
21-
->stringNode('api_key')->isRequired()->end()
22-
->stringNode('collection')->end()
20+
->stringNode('endpoint')->end()
21+
->stringNode('api_key')->end()
22+
->stringNode('http_client')
23+
->defaultValue('http_client')
24+
->end()
25+
->stringNode('collection')
26+
->info('The name of the store will be used if the "collection" is not set')
27+
->end()
2328
->end()
2429
->end();

src/ai-bundle/src/AiBundle.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
use Symfony\AI\Store\Bridge\Typesense\Store as TypesenseStore;
114114
use Symfony\AI\Store\Bridge\Vektor\Store as VektorStore;
115115
use Symfony\AI\Store\Bridge\Weaviate\Store as WeaviateStore;
116+
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory as WeaviateStoreFactory;
116117
use Symfony\AI\Store\Distance\DistanceCalculator;
117118
use Symfony\AI\Store\Distance\DistanceStrategy;
118119
use Symfony\AI\Store\Document\Vectorizer;
@@ -2005,14 +2006,14 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde
20052006
}
20062007

20072008
foreach ($stores as $name => $store) {
2008-
$definition = new Definition(WeaviateStore::class);
2009-
$definition
2009+
$definition = (new Definition(WeaviateStore::class))
2010+
->setFactory(WeaviateStoreFactory::class.'::create')
20102011
->setLazy(true)
20112012
->setArguments([
2012-
new Reference('http_client'),
2013+
$store['collection'] ?? $name,
20132014
$store['endpoint'],
20142015
$store['api_key'],
2015-
$store['collection'] ?? $name,
2016+
new Reference($store['http_client']),
20162017
])
20172018
->addTag('proxy', ['interface' => StoreInterface::class])
20182019
->addTag('proxy', ['interface' => ManagedStoreInterface::class])

src/ai-bundle/tests/DependencyInjection/AiBundleTest.php

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
use Symfony\AI\Store\Bridge\Typesense\Store as TypesenseStore;
7575
use Symfony\AI\Store\Bridge\Vektor\Store as VektorStore;
7676
use Symfony\AI\Store\Bridge\Weaviate\Store as WeaviateStore;
77+
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory as WeaviateStoreFactory;
7778
use Symfony\AI\Store\Distance\DistanceCalculator;
7879
use Symfony\AI\Store\Distance\DistanceStrategy;
7980
use Symfony\AI\Store\Document\Filter\TextContainsFilter;
@@ -3513,7 +3514,7 @@ public function testTypesenseStoreWithCustomCollectionCanBeConfigured()
35133514
$this->assertTrue($container->hasAlias(StoreInterface::class));
35143515
}
35153516

3516-
public function testWevaviateStoreCanBeConfigured()
3517+
public function testWeaviateStoreCanBeConfigured()
35173518
{
35183519
$container = $this->buildContainer([
35193520
'ai' => [
@@ -3532,14 +3533,15 @@ public function testWevaviateStoreCanBeConfigured()
35323533

35333534
$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
35343535
$this->assertSame(WeaviateStore::class, $definition->getClass());
3535-
3536+
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
35363537
$this->assertTrue($definition->isLazy());
3538+
35373539
$this->assertCount(4, $definition->getArguments());
3538-
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
3539-
$this->assertSame('http_client', (string) $definition->getArgument(0));
3540+
$this->assertSame('my_weaviate_store', $definition->getArgument(0));
35403541
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
35413542
$this->assertSame('bar', $definition->getArgument(2));
3542-
$this->assertSame('my_weaviate_store', $definition->getArgument(3));
3543+
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
3544+
$this->assertSame('http_client', (string) $definition->getArgument(3));
35433545

35443546
$this->assertTrue($definition->hasTag('proxy'));
35453547
$this->assertSame([
@@ -3553,10 +3555,7 @@ public function testWevaviateStoreCanBeConfigured()
35533555
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $weaviate_my_weaviate_store'));
35543556
$this->assertTrue($container->hasAlias(StoreInterface::class.' $weaviateMyWeaviateStore'));
35553557
$this->assertTrue($container->hasAlias(StoreInterface::class));
3556-
}
35573558

3558-
public function testWevaviateStoreWithCustomCollectionCanBeConfigured()
3559-
{
35603559
$container = $this->buildContainer([
35613560
'ai' => [
35623561
'store' => [
@@ -3574,15 +3573,58 @@ public function testWevaviateStoreWithCustomCollectionCanBeConfigured()
35743573
$this->assertTrue($container->hasDefinition('ai.store.weaviate.my_weaviate_store'));
35753574

35763575
$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
3576+
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
35773577
$this->assertSame(WeaviateStore::class, $definition->getClass());
3578+
$this->assertTrue($definition->isLazy());
3579+
3580+
$this->assertCount(4, $definition->getArguments());
3581+
$this->assertSame('my_weaviate_collection', $definition->getArgument(0));
3582+
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
3583+
$this->assertSame('bar', $definition->getArgument(2));
3584+
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
3585+
$this->assertSame('http_client', (string) $definition->getArgument(3));
3586+
3587+
$this->assertTrue($definition->hasTag('proxy'));
3588+
$this->assertSame([
3589+
['interface' => StoreInterface::class],
3590+
['interface' => ManagedStoreInterface::class],
3591+
], $definition->getTag('proxy'));
3592+
$this->assertTrue($definition->hasTag('ai.store'));
3593+
3594+
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $my_weaviate_store'));
3595+
$this->assertTrue($container->hasAlias(StoreInterface::class.' $myWeaviateStore'));
3596+
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $weaviate_my_weaviate_store'));
3597+
$this->assertTrue($container->hasAlias(StoreInterface::class.' $weaviateMyWeaviateStore'));
3598+
$this->assertTrue($container->hasAlias(StoreInterface::class));
3599+
3600+
$container = $this->buildContainer([
3601+
'ai' => [
3602+
'store' => [
3603+
'weaviate' => [
3604+
'my_weaviate_store' => [
3605+
'endpoint' => 'http://localhost:8080',
3606+
'api_key' => 'bar',
3607+
'collection' => 'my_weaviate_collection',
3608+
'http_client' => 'scoped_http_client',
3609+
],
3610+
],
3611+
],
3612+
],
3613+
]);
35783614

3615+
$this->assertTrue($container->hasDefinition('ai.store.weaviate.my_weaviate_store'));
3616+
3617+
$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
3618+
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
3619+
$this->assertSame(WeaviateStore::class, $definition->getClass());
35793620
$this->assertTrue($definition->isLazy());
3621+
35803622
$this->assertCount(4, $definition->getArguments());
3581-
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
3582-
$this->assertSame('http_client', (string) $definition->getArgument(0));
3623+
$this->assertSame('my_weaviate_collection', $definition->getArgument(0));
35833624
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
35843625
$this->assertSame('bar', $definition->getArgument(2));
3585-
$this->assertSame('my_weaviate_collection', $definition->getArgument(3));
3626+
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
3627+
$this->assertSame('scoped_http_client', (string) $definition->getArgument(3));
35863628

35873629
$this->assertTrue($definition->hasTag('proxy'));
35883630
$this->assertSame([

src/store/src/Bridge/Weaviate/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
0.6
5+
---
6+
7+
* [BC BREAK] The `endpointUrl` parameter for `Store` has been removed
8+
* [BC BREAK] The `apiKey` parameter for `Store` has been removed
9+
410
0.1
511
---
612

src/store/src/Bridge/Weaviate/Store.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ final class Store implements ManagedStoreInterface, StoreInterface
3030
{
3131
public function __construct(
3232
private readonly HttpClientInterface $httpClient,
33-
private readonly string $endpointUrl,
34-
#[\SensitiveParameter] private readonly string $apiKey,
3533
private readonly string $collection,
3634
) {
3735
}
@@ -137,17 +135,11 @@ public function drop(array $options = []): void
137135
*/
138136
private function request(string $method, string $endpoint, array $payload): array
139137
{
140-
$url = \sprintf('%s/%s', $this->endpointUrl, $endpoint);
141-
142-
$finalPayload = [
143-
'auth_bearer' => $this->apiKey,
144-
];
145-
146138
if ([] !== $payload) {
147139
$finalPayload['json'] = $payload;
148140
}
149141

150-
$response = $this->httpClient->request($method, $url, $finalPayload);
142+
$response = $this->httpClient->request($method, $endpoint, $finalPayload ?? []);
151143

152144
if (200 === $response->getStatusCode() && '' === $response->getContent(false)) {
153145
return [];
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Store\Bridge\Weaviate;
13+
14+
use Symfony\AI\Store\Exception\InvalidArgumentException;
15+
use Symfony\AI\Store\ManagedStoreInterface;
16+
use Symfony\AI\Store\StoreInterface;
17+
use Symfony\Component\HttpClient\HttpClient;
18+
use Symfony\Component\HttpClient\ScopingHttpClient;
19+
use Symfony\Contracts\HttpClient\HttpClientInterface;
20+
21+
/**
22+
* @author Guillaume Loulier <personal@guillaumeloulier.fr>
23+
*/
24+
final class StoreFactory
25+
{
26+
public static function create(
27+
string $collection,
28+
?string $endpoint = null,
29+
#[\SensitiveParameter] ?string $apiKey = null,
30+
?HttpClientInterface $httpClient = null,
31+
): StoreInterface&ManagedStoreInterface {
32+
$httpClient = $httpClient instanceof ScopingHttpClient ? $httpClient : HttpClient::create();
33+
34+
if (!$httpClient instanceof ScopingHttpClient && (null === $endpoint || null === $apiKey)) {
35+
throw new InvalidArgumentException(\sprintf('The HttpClient must be an instance of "%s" or both "endpoint" and "apiKey" must be provided.', ScopingHttpClient::class));
36+
}
37+
38+
if (null !== $endpoint) {
39+
$defaultOptions = [];
40+
if (null !== $apiKey) {
41+
$defaultOptions['auth_bearer'] = $apiKey;
42+
}
43+
44+
$httpClient = ScopingHttpClient::forBaseUri($httpClient, $endpoint, $defaultOptions);
45+
}
46+
47+
return new Store($httpClient, $collection);
48+
}
49+
}

src/store/src/Bridge/Weaviate/Tests/IntegrationTest.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
namespace Symfony\AI\Store\Bridge\Weaviate\Tests;
1313

1414
use PHPUnit\Framework\Attributes\Group;
15-
use Symfony\AI\Store\Bridge\Weaviate\Store;
15+
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory;
1616
use Symfony\AI\Store\StoreInterface;
1717
use Symfony\AI\Store\Test\AbstractStoreIntegrationTestCase;
18-
use Symfony\Component\HttpClient\HttpClient;
1918

2019
/**
2120
* @author Christopher Hertel <mail@christopher-hertel.de>
@@ -25,11 +24,6 @@ final class IntegrationTest extends AbstractStoreIntegrationTestCase
2524
{
2625
protected static function createStore(): StoreInterface
2726
{
28-
return new Store(
29-
HttpClient::create(),
30-
'http://127.0.0.1:8080',
31-
'symfony',
32-
'TestCollection',
33-
);
27+
return StoreFactory::create('TestCollection', 'http://127.0.0.1:8080', 'symfony');
3428
}
3529
}

0 commit comments

Comments
 (0)