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
8 changes: 8 additions & 0 deletions examples/.env
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,11 @@ CLICKHOUSE_TABLE=symfony
# Weaviate (store)
WEAVIATE_HOST=http://127.0.0.1:8080
WEAVIATE_API_KEY=symfony

# Supabase (store)
SUPABASE_URL=
SUPABASE_API_KEY=
SUPABASE_TABLE=
SUPABASE_VECTOR_FIELD=
SUPABASE_VECTOR_DIMENSION=
SUPABASE_MATCH_FUNCTION=
69 changes: 69 additions & 0 deletions examples/rag/supabase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?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.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Fixtures\Movies;
use Symfony\AI\Platform\Bridge\Ollama\Ollama;
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Store\Bridge\Supabase\Store;
use Symfony\AI\Store\Document\Loader\InMemoryLoader;
use Symfony\AI\Store\Document\Metadata;
use Symfony\AI\Store\Document\TextDocument;
use Symfony\AI\Store\Document\Vectorizer;
use Symfony\AI\Store\Indexer;
use Symfony\Component\Uid\Uuid;

require_once dirname(__DIR__).'/bootstrap.php';

$store = new Store(
httpClient: http_client(),
url: env('SUPABASE_URL'),
apiKey: env('SUPABASE_API_KEY'),
);

$documents = [];

foreach (Movies::all() as $movie) {
$documents[] = new TextDocument(
id: Uuid::v4(),
content: 'Title: '.$movie['title'].\PHP_EOL.'Director: '.$movie['director'].\PHP_EOL.'Description: '.$movie['description'],
metadata: new Metadata($movie),
);
}

$platform = PlatformFactory::create(
env('OLLAMA_HOST_URL'),
http_client()
);

$vectorizer = new Vectorizer($platform, new Ollama('mxbai-embed-large'));
$loader = new InMemoryLoader($documents);
$indexer = new Indexer($loader, $vectorizer, $store, logger: logger());
$indexer->index();

$similaritySearch = new SimilaritySearch($vectorizer, $store);
$toolbox = new Toolbox([$similaritySearch], logger: logger());
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, new Ollama('llama3.2:3b'), [$processor], [$processor], logger: logger());

$messages = new MessageBag(
Message::forSystem('Please answer all user questions only using SimilaritySearch function.'),
Message::ofUser('Which movie fits the theme of technology?')
);

$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
18 changes: 18 additions & 0 deletions src/ai-bundle/config/options.php
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,24 @@
->end()
->end()
->end()
->arrayNode('supabase')
->useAttributeAsKey('name')
->arrayPrototype()
->children()
->stringNode('http_client')
->cannotBeEmpty()
->defaultValue('http_client')
->info('Service ID of the HTTP client to use')
->end()
->scalarNode('url')->isRequired()->cannotBeEmpty()->end()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following #604, please make the http client configurable, you can barely copy paste from #604, thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see it done for any other store. Am I missing something here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a rebase you should

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still sclaraNode()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand.
Could you help me here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, sure, please use stringNode() or integerNode()

->scalarNode('api_key')->isRequired()->cannotBeEmpty()->end()
->scalarNode('table')->end()
->scalarNode('vector_field')->end()
->integerNode('vector_dimension')->end()
->scalarNode('function_name')->end()
->end()
->end()
->end()
->arrayNode('typesense')
->useAttributeAsKey('name')
->arrayPrototype()
Expand Down
6 changes: 3 additions & 3 deletions src/ai-bundle/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Configuration
HTTP Client Configuration
-------------------------

Each platform can be configured with a custom HTTP client service to handle API requests.
Each platform can be configured with a custom HTTP client service to handle API requests.
This allows you to customize timeouts, proxy settings, SSL configurations, and other HTTP-specific options.

By default, all platforms use the standard Symfony HTTP client service (``http_client``):
Expand Down Expand Up @@ -237,7 +237,7 @@ The system prompt text will be automatically translated using the configured tra
Memory Provider Configuration
-----------------------------

Memory providers allow agents to access and utilize conversation history and context from previous interactions.
Memory providers allow agents to access and utilize conversation history and context from previous interactions.
This enables agents to maintain context across conversations and provide more personalized responses.

**Static Memory (Simple)**
Expand Down Expand Up @@ -292,7 +292,7 @@ Memory can work independently or alongside the system prompt:
model:
class: 'Symfony\AI\Platform\Bridge\OpenAi\Gpt'
memory: 'You are a helpful assistant with conversation history'

# Agent with both memory and prompt (memory prepended to prompt)
memory_and_prompt_agent:
model:
Expand Down
35 changes: 35 additions & 0 deletions src/ai-bundle/src/AiBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
use Symfony\AI\Store\Bridge\Neo4j\Store as Neo4jStore;
use Symfony\AI\Store\Bridge\Pinecone\Store as PineconeStore;
use Symfony\AI\Store\Bridge\Qdrant\Store as QdrantStore;
use Symfony\AI\Store\Bridge\Supabase\Store as SupabaseStore;
use Symfony\AI\Store\Bridge\SurrealDb\Store as SurrealDbStore;
use Symfony\AI\Store\Bridge\Typesense\Store as TypesenseStore;
use Symfony\AI\Store\Bridge\Weaviate\Store as WeaviateStore;
Expand Down Expand Up @@ -1095,6 +1096,40 @@ private function processStoreConfig(string $type, array $stores, ContainerBuilde
$container->setDefinition('ai.store.'.$type.'.'.$name, $definition);
}
}

if ('supabase' === $type) {
foreach ($stores as $name => $store) {
$arguments = [
isset($store['http_client']) ? new Reference($store['http_client']) : new Definition(HttpClientInterface::class),
$store['url'],
$store['api_key'],
];

if (\array_key_exists('table', $store)) {
$arguments[3] = $store['table'];
}

if (\array_key_exists('vector_field', $store)) {
$arguments[4] = $store['vector_field'];
}

if (\array_key_exists('vector_dimension', $store)) {
$arguments[5] = $store['vector_dimension'];
}

if (\array_key_exists('function_name', $store)) {
$arguments[6] = $store['function_name'];
}

$definition = new Definition(SupabaseStore::class);
$definition
->addTag('ai.store')
->setArguments($arguments);

$container->setDefinition('ai.store.supabase.'.$name, $definition);
$container->registerAliasForArgument('ai.store.'.$name, StoreInterface::class, (new Target($name.'Store'))->getParsedName());
}
}
}

/**
Expand Down
10 changes: 10 additions & 0 deletions src/ai-bundle/tests/DependencyInjection/AiBundleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2181,6 +2181,16 @@ private function getFullConfig(): array
'namespaced_user' => true,
],
],
'supabase' => [
'my_supabase_store' => [
'url' => 'https://test.supabase.co',
'api_key' => 'supabase_test_key',
'table' => 'my_supabase_table',
'vector_field' => 'my_embedding',
'vector_dimension' => 1024,
'function_name' => 'my_match_function',
],
],
'typesense' => [
'my_typesense_store' => [
'endpoint' => 'http://localhost:8108',
Expand Down
1 change: 1 addition & 0 deletions src/store/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ CHANGELOG
- Pinecone
- PostgreSQL with pgvector extension
- Qdrant
- Supabase
- SurrealDB
- Typesense
- Weaviate
Expand Down
1 change: 1 addition & 0 deletions src/store/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"pinecone",
"postgres",
"qdrant",
"supabase",
"surrealdb",
"typesense",
"weaviate"
Expand Down
Loading