Skip to content

Commit 4695898

Browse files
committed
refactor(store): WeaviateStoreFactory introduced
1 parent 9e5e8ab commit 4695898

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
@@ -7,6 +7,7 @@ CHANGELOG
77
* Move debug service decorating to compiler pass to cover user-defined services
88
* Add `TraceableAgent`
99
* Add `TraceableStore`
10+
* Add support for custom HttpClient for `Qdrant` and `Weaviate` stores
1011

1112
0.5
1213
---

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;
@@ -2003,14 +2004,14 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde
20032004
}
20042005

20052006
foreach ($stores as $name => $store) {
2006-
$definition = new Definition(WeaviateStore::class);
2007-
$definition
2007+
$definition = (new Definition(WeaviateStore::class))
2008+
->setFactory(WeaviateStoreFactory::class.'::create')
20082009
->setLazy(true)
20092010
->setArguments([
2010-
new Reference('http_client'),
2011+
$store['collection'] ?? $name,
20112012
$store['endpoint'],
20122013
$store['api_key'],
2013-
$store['collection'] ?? $name,
2014+
new Reference($store['http_client']),
20142015
])
20152016
->addTag('proxy', ['interface' => StoreInterface::class])
20162017
->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;
@@ -3512,7 +3513,7 @@ public function testTypesenseStoreWithCustomCollectionCanBeConfigured()
35123513
$this->assertTrue($container->hasAlias(StoreInterface::class));
35133514
}
35143515

3515-
public function testWevaviateStoreCanBeConfigured()
3516+
public function testWeaviateStoreCanBeConfigured()
35163517
{
35173518
$container = $this->buildContainer([
35183519
'ai' => [
@@ -3531,14 +3532,15 @@ public function testWevaviateStoreCanBeConfigured()
35313532

35323533
$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
35333534
$this->assertSame(WeaviateStore::class, $definition->getClass());
3534-
3535+
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
35353536
$this->assertTrue($definition->isLazy());
3537+
35363538
$this->assertCount(4, $definition->getArguments());
3537-
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
3538-
$this->assertSame('http_client', (string) $definition->getArgument(0));
3539+
$this->assertSame('my_weaviate_store', $definition->getArgument(0));
35393540
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
35403541
$this->assertSame('bar', $definition->getArgument(2));
3541-
$this->assertSame('my_weaviate_store', $definition->getArgument(3));
3542+
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
3543+
$this->assertSame('http_client', (string) $definition->getArgument(3));
35423544

35433545
$this->assertTrue($definition->hasTag('proxy'));
35443546
$this->assertSame([
@@ -3552,10 +3554,7 @@ public function testWevaviateStoreCanBeConfigured()
35523554
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $weaviate_my_weaviate_store'));
35533555
$this->assertTrue($container->hasAlias(StoreInterface::class.' $weaviateMyWeaviateStore'));
35543556
$this->assertTrue($container->hasAlias(StoreInterface::class));
3555-
}
35563557

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

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

3614+
$this->assertTrue($container->hasDefinition('ai.store.weaviate.my_weaviate_store'));
3615+
3616+
$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
3617+
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
3618+
$this->assertSame(WeaviateStore::class, $definition->getClass());
35783619
$this->assertTrue($definition->isLazy());
3620+
35793621
$this->assertCount(4, $definition->getArguments());
3580-
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
3581-
$this->assertSame('http_client', (string) $definition->getArgument(0));
3622+
$this->assertSame('my_weaviate_collection', $definition->getArgument(0));
35823623
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
35833624
$this->assertSame('bar', $definition->getArgument(2));
3584-
$this->assertSame('my_weaviate_collection', $definition->getArgument(3));
3625+
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
3626+
$this->assertSame('scoped_http_client', (string) $definition->getArgument(3));
35853627

35863628
$this->assertTrue($definition->hasTag('proxy'));
35873629
$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)