-
-
Notifications
You must be signed in to change notification settings - Fork 103
[Store][Supabase] Add store #551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
chr-hertel
merged 1 commit into
symfony:main
from
junaidbinfarooq:feat/issue-320-support-for-supabase-store
Oct 11, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
Supabase Bridge | ||
=============== | ||
|
||
The Supabase bridge provides vector storage capabilities using `pgvector`_ extension through the REST API. | ||
|
||
.. note:: | ||
|
||
Unlike the Postgres Store, the Supabase Store requires manual setup of the database schema because Supabase doesn't | ||
allow arbitrary SQL execution via REST API. | ||
|
||
Requirements | ||
~~~~~~~~~~~~ | ||
|
||
* Enable `pgvector extension`_ in the relevant schema of your Supabase project for using `vector`_ column types. | ||
* Add columns for embedding (type `vector`) and metadata (type `jsonb`) to your table | ||
* Pre-configured RPC `function`_ for similarity search | ||
|
||
See section below for detailed SQL commands. | ||
|
||
Database Setup | ||
-------------- | ||
|
||
Execute the following SQL commands in your Supabase SQL Editor: | ||
|
||
Enable ``pgvector`` extension | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: sql | ||
|
||
CREATE EXTENSION IF NOT EXISTS vector; | ||
|
||
Create the `documents` table | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: sql | ||
|
||
CREATE TABLE IF NOT EXISTS documents ( | ||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), | ||
embedding vector(768) NOT NULL, | ||
metadata JSONB | ||
); | ||
|
||
Create the similarity search function | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: sql | ||
|
||
CREATE OR REPLACE FUNCTION match_documents( | ||
query_embedding vector(768), | ||
match_count int DEFAULT 10, | ||
match_threshold float DEFAULT 0.0 | ||
) | ||
RETURNS TABLE ( | ||
id UUID, | ||
embedding vector, | ||
metadata JSONB, | ||
score float | ||
) | ||
LANGUAGE sql | ||
AS $$ | ||
SELECT | ||
documents.id, | ||
documents.embedding, | ||
documents.metadata, | ||
1- (documents.embedding <=> query_embedding) AS score | ||
FROM documents | ||
WHERE 1- (documents.embedding <=> query_embedding) >= match_threshold | ||
ORDER BY documents.embedding <=> query_embedding ASC | ||
LIMIT match_count; | ||
$$; | ||
|
||
Create an index for better performance | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: sql | ||
|
||
CREATE INDEX IF NOT EXISTS documents_embedding_idx | ||
ON documents USING ivfflat (embedding vector_cosine_ops); | ||
|
||
Configuration | ||
------------- | ||
|
||
Basic Configuration | ||
~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: php | ||
|
||
use Symfony\AI\Store\Bridge\Supabase\Store; | ||
use Symfony\Component\HttpClient\HttpClient; | ||
|
||
$store = new Store( | ||
HttpClient::create(), | ||
'https://your-project.supabase.co', | ||
'your-anon-key', | ||
'documents', // table name | ||
'embedding', // vector field name | ||
768, // vector dimension (depending on your embedding model) | ||
'match_documents' // function name | ||
); | ||
|
||
Bundle Configuration | ||
~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: yaml | ||
|
||
# config/packages/ai.yaml | ||
ai: | ||
store: | ||
supabase: | ||
my_supabase_store: | ||
url: 'https://your-project.supabase.co' | ||
api_key: '%env(SUPABASE_API_KEY)%' | ||
table: 'documents' | ||
vector_field: 'embedding' | ||
vector_dimension: 768 | ||
function_name: 'match_documents' | ||
|
||
Environment Variables | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: bash | ||
|
||
# .env.local | ||
SUPABASE_URL=https://your-project.supabase.co | ||
SUPABASE_API_KEY=your-supabase-anon-key | ||
|
||
Usage | ||
----- | ||
|
||
Adding Documents | ||
~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: php | ||
|
||
use Symfony\AI\Platform\Vector\Vector; | ||
use Symfony\AI\Store\Document\Metadata; | ||
use Symfony\AI\Store\Document\VectorDocument; | ||
use Symfony\Component\Uid\Uuid; | ||
|
||
$document = new VectorDocument( | ||
Uuid::v4(), | ||
new Vector([0.1, 0.2, 0.3, /* ... 768 dimensions */]), | ||
new Metadata(['title' => 'My Document', 'category' => 'example']) | ||
); | ||
|
||
$store->add($document); | ||
|
||
Querying Documents | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
.. code-block:: php | ||
|
||
$queryVector = new Vector([0.1, 0.2, 0.3, /* ... 768 dimensions */]); | ||
|
||
$results = $store->query($queryVector, [ | ||
'max_items' => 10, | ||
'min_score' => 0.7 | ||
]); | ||
|
||
foreach ($results as $document) { | ||
echo "ID: " . $document->id . "\n"; | ||
echo "Score: " . $document->score . "\n"; | ||
echo "Metadata: " . json_encode($document->metadata->getArrayCopy()) . "\n"; | ||
} | ||
|
||
Customization | ||
------------- | ||
|
||
You can customize the Supabase setup for different requirements: | ||
|
||
Table Name | ||
~~~~~~~~~~ | ||
|
||
Change ``documents`` to your preferred table name in both the SQL setup and configuration. | ||
|
||
Vector Field Name | ||
~~~~~~~~~~~~~~~~~ | ||
|
||
Change ``embedding`` to your preferred field name in both the SQL setup and configuration. | ||
|
||
Vector Dimension | ||
~~~~~~~~~~~~~~~~ | ||
|
||
Change ``768`` to match your embedding model's dimensions in both the SQL setup and configuration. | ||
|
||
Distance Metric | ||
~~~~~~~~~~~~~~~ | ||
|
||
* Cosine: ``<=>`` (default, recommended for most embeddings) | ||
* Euclidean: ``<->`` | ||
* Inner Product: ``<#>`` | ||
|
||
Index Type | ||
~~~~~~~~~~ | ||
|
||
* ``ivfflat``: Good balance of speed and accuracy | ||
* ``hnsw``: Better for high-dimensional vectors (requires PostgreSQL 14+) | ||
|
||
Limitations | ||
----------- | ||
|
||
* Manual schema setup required (no automatic table creation) | ||
* Limited to Supabase's REST API capabilities | ||
* Requires pre-configured RPC functions for complex queries | ||
* Vector dimension must be consistent across all documents | ||
|
||
Performance Considerations | ||
-------------------------- | ||
|
||
* Use appropriate index types based on your vector dimensions | ||
* Consider using ``hnsw`` indexes for high-dimensional vectors | ||
* Batch document insertions when possible (up to 200 documents per request) | ||
* Monitor your Supabase usage limits and quotas | ||
|
||
Security Considerations | ||
----------------------- | ||
|
||
* Use row-level security (RLS) policies if needed | ||
* Consider using service role keys for server-side operations | ||
* Validate vector dimensions in your application code | ||
* Implement proper error handling for API failures | ||
|
||
.. _`pgvector`: https://github.com/pgvector/pgvector | ||
.. _`pgvector extension`: https://supabase.com/docs/guides/database/extensions/pgvector | ||
.. _`vector`: https://supabase.com/docs/guides/ai/vector-columns | ||
.. _`function`: https://supabase.com/docs/guides/database/functions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 <[email protected]> | ||
* | ||
* 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\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'), | ||
table: env('SUPABASE_TABLE'), | ||
vectorFieldName: env('SUPABASE_VECTOR_FIELD'), | ||
vectorDimension: (int) env('SUPABASE_VECTOR_DIMENSION'), | ||
functionName: env('SUPABASE_MATCH_FUNCTION'), | ||
); | ||
|
||
$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, env('OLLAMA_EMBEDDINGS')); | ||
$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, env('OLLAMA_LLM'), [$processor], [$processor]); | ||
|
||
$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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.