Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
UPGRADE FROM 0.5 to 0.6
=======================

Store
-----

* The `endpointUrl` parameter for `QdrantStore` has been removed
* The `apiKey` parameter for `QdrantStore` has been removed
* The `endpointUrl` parameter for `WeaviateStore` has been removed
* The `apiKey` parameter for `WeaviateStore` has been removed

UPGRADE FROM 0.4 to 0.5
=======================

Expand Down
9 changes: 2 additions & 7 deletions examples/rag/weaviate.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Store\Bridge\Weaviate\Store;
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory;
use Symfony\AI\Store\Document\Metadata;
use Symfony\AI\Store\Document\TextDocument;
use Symfony\AI\Store\Document\Vectorizer;
Expand All @@ -28,12 +28,7 @@
require_once dirname(__DIR__).'/bootstrap.php';

// initialize the store
$store = new Store(
httpClient: http_client(),
endpointUrl: env('WEAVIATE_HOST'),
apiKey: env('WEAVIATE_API_KEY'),
collection: 'Movies',
);
$store = StoreFactory::create('Movies', env('WEAVIATE_HOST'), env('WEAVIATE_API_KEY'));

// initialize the index
$store->setup();
Expand Down
1 change: 1 addition & 0 deletions src/ai-bundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ CHANGELOG
* Add `TraceableAgent`
* Add `TraceableStore`
* Add `setup_options` configuration for PostgreSQL store to pass extra fields to `ai:store:setup`
* Add support for custom HttpClient for `Qdrant` and `Weaviate` stores

0.5
---
Expand Down
11 changes: 8 additions & 3 deletions src/ai-bundle/config/store/weaviate.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
->useAttributeAsKey('name')
->arrayPrototype()
->children()
->stringNode('endpoint')->cannotBeEmpty()->end()
->stringNode('api_key')->isRequired()->end()
->stringNode('collection')->end()
->stringNode('endpoint')->end()
->stringNode('api_key')->end()
->stringNode('http_client')
->defaultValue('http_client')
->end()
->stringNode('collection')
->info('The name of the store will be used if the "collection" is not set')
->end()
->end()
->end();
9 changes: 5 additions & 4 deletions src/ai-bundle/src/AiBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
use Symfony\AI\Store\Bridge\Typesense\Store as TypesenseStore;
use Symfony\AI\Store\Bridge\Vektor\Store as VektorStore;
use Symfony\AI\Store\Bridge\Weaviate\Store as WeaviateStore;
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory as WeaviateStoreFactory;
use Symfony\AI\Store\Distance\DistanceCalculator;
use Symfony\AI\Store\Distance\DistanceStrategy;
use Symfony\AI\Store\Document\Vectorizer;
Expand Down Expand Up @@ -2005,14 +2006,14 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde
}

foreach ($stores as $name => $store) {
$definition = new Definition(WeaviateStore::class);
$definition
$definition = (new Definition(WeaviateStore::class))
->setFactory(WeaviateStoreFactory::class.'::create')
->setLazy(true)
->setArguments([
new Reference('http_client'),
$store['collection'] ?? $name,
$store['endpoint'],
$store['api_key'],
$store['collection'] ?? $name,
new Reference($store['http_client']),
])
->addTag('proxy', ['interface' => StoreInterface::class])
->addTag('proxy', ['interface' => ManagedStoreInterface::class])
Expand Down
64 changes: 53 additions & 11 deletions src/ai-bundle/tests/DependencyInjection/AiBundleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
use Symfony\AI\Store\Bridge\Typesense\Store as TypesenseStore;
use Symfony\AI\Store\Bridge\Vektor\Store as VektorStore;
use Symfony\AI\Store\Bridge\Weaviate\Store as WeaviateStore;
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory as WeaviateStoreFactory;
use Symfony\AI\Store\Distance\DistanceCalculator;
use Symfony\AI\Store\Distance\DistanceStrategy;
use Symfony\AI\Store\Document\Filter\TextContainsFilter;
Expand Down Expand Up @@ -3521,7 +3522,7 @@ public function testTypesenseStoreWithCustomCollectionCanBeConfigured()
$this->assertTrue($container->hasAlias(StoreInterface::class));
}

public function testWevaviateStoreCanBeConfigured()
public function testWeaviateStoreCanBeConfigured()
{
$container = $this->buildContainer([
'ai' => [
Expand All @@ -3540,14 +3541,15 @@ public function testWevaviateStoreCanBeConfigured()

$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
$this->assertSame(WeaviateStore::class, $definition->getClass());

$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
$this->assertTrue($definition->isLazy());

$this->assertCount(4, $definition->getArguments());
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
$this->assertSame('http_client', (string) $definition->getArgument(0));
$this->assertSame('my_weaviate_store', $definition->getArgument(0));
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
$this->assertSame('bar', $definition->getArgument(2));
$this->assertSame('my_weaviate_store', $definition->getArgument(3));
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
$this->assertSame('http_client', (string) $definition->getArgument(3));

$this->assertTrue($definition->hasTag('proxy'));
$this->assertSame([
Expand All @@ -3561,10 +3563,7 @@ public function testWevaviateStoreCanBeConfigured()
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $weaviate_my_weaviate_store'));
$this->assertTrue($container->hasAlias(StoreInterface::class.' $weaviateMyWeaviateStore'));
$this->assertTrue($container->hasAlias(StoreInterface::class));
}

public function testWevaviateStoreWithCustomCollectionCanBeConfigured()
{
$container = $this->buildContainer([
'ai' => [
'store' => [
Expand All @@ -3582,15 +3581,58 @@ public function testWevaviateStoreWithCustomCollectionCanBeConfigured()
$this->assertTrue($container->hasDefinition('ai.store.weaviate.my_weaviate_store'));

$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
$this->assertSame(WeaviateStore::class, $definition->getClass());
$this->assertTrue($definition->isLazy());

$this->assertCount(4, $definition->getArguments());
$this->assertSame('my_weaviate_collection', $definition->getArgument(0));
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
$this->assertSame('bar', $definition->getArgument(2));
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
$this->assertSame('http_client', (string) $definition->getArgument(3));

$this->assertTrue($definition->hasTag('proxy'));
$this->assertSame([
['interface' => StoreInterface::class],
['interface' => ManagedStoreInterface::class],
], $definition->getTag('proxy'));
$this->assertTrue($definition->hasTag('ai.store'));

$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $my_weaviate_store'));
$this->assertTrue($container->hasAlias(StoreInterface::class.' $myWeaviateStore'));
$this->assertTrue($container->hasAlias('.'.StoreInterface::class.' $weaviate_my_weaviate_store'));
$this->assertTrue($container->hasAlias(StoreInterface::class.' $weaviateMyWeaviateStore'));
$this->assertTrue($container->hasAlias(StoreInterface::class));

$container = $this->buildContainer([
'ai' => [
'store' => [
'weaviate' => [
'my_weaviate_store' => [
'endpoint' => 'http://localhost:8080',
'api_key' => 'bar',
'collection' => 'my_weaviate_collection',
'http_client' => 'scoped_http_client',
],
],
],
],
]);

$this->assertTrue($container->hasDefinition('ai.store.weaviate.my_weaviate_store'));

$definition = $container->getDefinition('ai.store.weaviate.my_weaviate_store');
$this->assertSame([WeaviateStoreFactory::class, 'create'], $definition->getFactory());
$this->assertSame(WeaviateStore::class, $definition->getClass());
$this->assertTrue($definition->isLazy());

$this->assertCount(4, $definition->getArguments());
$this->assertInstanceOf(Reference::class, $definition->getArgument(0));
$this->assertSame('http_client', (string) $definition->getArgument(0));
$this->assertSame('my_weaviate_collection', $definition->getArgument(0));
$this->assertSame('http://localhost:8080', $definition->getArgument(1));
$this->assertSame('bar', $definition->getArgument(2));
$this->assertSame('my_weaviate_collection', $definition->getArgument(3));
$this->assertInstanceOf(Reference::class, $definition->getArgument(3));
$this->assertSame('scoped_http_client', (string) $definition->getArgument(3));

$this->assertTrue($definition->hasTag('proxy'));
$this->assertSame([
Expand Down
6 changes: 6 additions & 0 deletions src/store/src/Bridge/Weaviate/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGELOG
=========

0.6
---

* [BC BREAK] The `endpointUrl` parameter for `Store` has been removed
* [BC BREAK] The `apiKey` parameter for `Store` has been removed

0.1
---

Expand Down
10 changes: 1 addition & 9 deletions src/store/src/Bridge/Weaviate/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ final class Store implements ManagedStoreInterface, StoreInterface
{
public function __construct(
private readonly HttpClientInterface $httpClient,
private readonly string $endpointUrl,
#[\SensitiveParameter] private readonly string $apiKey,
private readonly string $collection,
) {
}
Expand Down Expand Up @@ -137,17 +135,11 @@ public function drop(array $options = []): void
*/
private function request(string $method, string $endpoint, array $payload): array
{
$url = \sprintf('%s/%s', $this->endpointUrl, $endpoint);

$finalPayload = [
'auth_bearer' => $this->apiKey,
];

if ([] !== $payload) {
$finalPayload['json'] = $payload;
}

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

if (200 === $response->getStatusCode() && '' === $response->getContent(false)) {
return [];
Expand Down
42 changes: 42 additions & 0 deletions src/store/src/Bridge/Weaviate/StoreFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Store\Bridge\Weaviate;

use Symfony\AI\Store\ManagedStoreInterface;
use Symfony\AI\Store\StoreInterface;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\ScopingHttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
* @author Guillaume Loulier <personal@guillaumeloulier.fr>
*/
final class StoreFactory
{
public static function create(
string $collection,
?string $endpoint = null,
#[\SensitiveParameter] ?string $apiKey = null,
?HttpClientInterface $httpClient = null,
): StoreInterface&ManagedStoreInterface {
if (null !== $endpoint) {
$defaultOptions = [];
if (null !== $apiKey) {
$defaultOptions['auth_bearer'] = $apiKey;
}

$httpClient = ScopingHttpClient::forBaseUri($httpClient ?? HttpClient::create(), $endpoint, $defaultOptions);
}

return new Store($httpClient, $collection);
}
}
10 changes: 2 additions & 8 deletions src/store/src/Bridge/Weaviate/Tests/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
namespace Symfony\AI\Store\Bridge\Weaviate\Tests;

use PHPUnit\Framework\Attributes\Group;
use Symfony\AI\Store\Bridge\Weaviate\Store;
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory;
use Symfony\AI\Store\StoreInterface;
use Symfony\AI\Store\Test\AbstractStoreIntegrationTestCase;
use Symfony\Component\HttpClient\HttpClient;

/**
* @author Christopher Hertel <mail@christopher-hertel.de>
Expand All @@ -25,11 +24,6 @@ final class IntegrationTest extends AbstractStoreIntegrationTestCase
{
protected static function createStore(): StoreInterface
{
return new Store(
HttpClient::create(),
'http://127.0.0.1:8080',
'symfony',
'TestCollection',
);
return StoreFactory::create('TestCollection', 'http://127.0.0.1:8080', 'symfony');
}
}
37 changes: 37 additions & 0 deletions src/store/src/Bridge/Weaviate/Tests/StoreFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\AI\Store\Bridge\Weaviate\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\AI\Store\Bridge\Weaviate\Store;
use Symfony\AI\Store\Bridge\Weaviate\StoreFactory;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\HttpClient\ScopingHttpClient;

final class StoreFactoryTest extends TestCase
{
public function testStoreCanBeCreatedWithHttpClientAndRequiredInfos()
{
$store = StoreFactory::create('foo', 'http://127.0.0.1:6333', 'bar');

$this->assertInstanceOf(Store::class, $store);
}

public function testStoreCanBeCreatedWithScopingHttpClient()
{
$store = StoreFactory::create('foo', httpClient: ScopingHttpClient::forBaseUri(HttpClient::create(), 'http://127.0.0.1:6333', [
'auth_bearer' => 'bar',
]));

$this->assertInstanceOf(Store::class, $store);
}
}
Loading
Loading