Getting Started with Pipelines
Where to Start
The best place to start is with the Pipelines Overview to get an understanding of what Pipelines is and how it works.
Installation
Pipelines is included with the EDB Postgres AI - AI Accelerator suite of tools. To install Pipelines, follow the instructions in the AI Accelerator Installation Guide.
Using Pipelines
Once you have Pipelines installed, you can start using it to work with your data.
Log in to your Postgres server and ensure the Pipelines extension is installed:
CREATE EXTENSION aidb CASCADE;
We'll be working solely with Postgres table data for this example, so we won't need to install the pgfs extension.
Let's also create an example table to work with:
CREATE TABLE products ( id SERIAL PRIMARY KEY, product_name TEXT NOT NULL, description TEXT, last_updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP );
CREATE TABLE
And let's insert some data:
INSERT INTO products (product_name, description) VALUES ('Hamburger', 'A delicious combination of bread and meat'), ('Cheesburger', 'Improving on a classic, the cheese brings favorite flavors'), ('Fish n Chips', 'The fish is a little greasy and the chips do not help'), ('Fries', 'Never sure about these on their own, needs seasoning'), ('Burrito', 'Always ready for this parcel of edible wonder'), ('Pizza', 'It is very much a staple, but the rolled dough with toppings does not inspire'), ('Sandwich', 'The blandest of offerings, the sandwich is predominantly boring bread'), ('Veggie Burger', 'The ultra-processed vegetable product in this is neither healthy nor delicious'), ('Kebab', 'Maybe one of the great edible treats, sliced lamb, salad and crisp pitta');
INSERT 0 9
So now we have a table with some data in it, food products and some very personal opinions about them.
Creating a Retriever
The first step to using Pipelines with this data is to create a retriever. A retriever is a way to access the data in the table and use it in AI workflows.
select aidb.create_retriever_for_table('products_retriever', 't5', 'products', 'description', 'Text');
create_retriever_for_table ------------------------------ products_retriever (1 row)
Querying the retriever
Now that we have created a retriever, we can query it to get similar results based on the data in the table.
select * from aidb.retrieve_key('products_retriever','I like it',5);
ERROR: Query returned no data. Hint: The "products_retriever_vector" table is likely empty. Make sure the embeddings have been computed.
First, we haven't computed embeddings for our retriever yet.
The products_retriever_vector
table is where aidb keeps the computed embeddings for the retriever.
Let's compute those embeddings now using aidb.bulk_embedding
:
select aidb.bulk_embedding('products_retriever');
INFO: bulk_embedding_text found 9 rows in retriever products_retriever bulk_embedding ---------------- (1 row)
Now we can query the retriever again:
select * from aidb.retrieve_key('products_retriever','I like it',4);
key | distance -----+-------------------- 4 | 1.0369428080621286 3 | 1.03737124138149 2 | 1.0839594107837638 5 | 1.0869412071766262 (4 rows)
Now we have some results. The key
column is the primary key of the row in the products
table, and the distance
column is the distance between the query and the result. The lower the distance, the more similar the result is to the query.
What we really want is the actual matching text, not just the key. We can use aidb.retrieve_text
for that:
select * from aidb.retrieve_text('products_retriever','I like it',4);
key | value | distance -----+------------------------------------------------------------+-------------------- 4 | Never sure about these on their own, needs seasoning | 1.0369428080621286 3 | The fish is a little greasy and the chips do not help | 1.03737124138149 2 | Improving on a classic, the cheese brings favorite flavors | 1.0839594107837638 5 | Always ready for this parcel of edible wonder | 1.0869412071766262 (4 rows)
Now we have the actual data from the table that matches the query.
You may want the row data from the products
table instead of the products_retriever_vector
table. You can do that by joining the two tables:
select * from aidb.retrieve_key('products_retriever','I like it',4) as a left join products as b on a.key=b.id;
key | distance | id | product_name | description | last_updated_at -----+--------------------+----+--------------+------------------------------------------------------------+---------------------------------- 2 | 1.0839594107837638 | 2 | Cheesburger | Improving on a classic, the cheese brings favorite flavors | 04-DEC-24 16:48:52.599806 +00:00 3 | 1.03737124138149 | 3 | Fish n Chips | The fish is a little greasy and the chips do not help | 04-DEC-24 16:48:52.599806 +00:00 4 | 1.0369428080621286 | 4 | Fries | Never sure about these on their own, needs seasoning | 04-DEC-24 16:48:52.599806 +00:00 5 | 1.0869412071766262 | 5 | Burrito | Always ready for this parcel of edible wonder | 04-DEC-24 16:48:52.599806 +00:00 (4 rows)
Now you have the actual data from the products
table that matches the query and as you can see, the full power of Postgres is available to you to work with your AI workflows.
One more thing, auto-embedding
As it stands vectors have been calculated for our data, but if we added data to the table it wouldn't be automatically embedded. The retriever would go out of sync.
To keep the embeddings up to date, we can enable auto-embedding:
select aidb.enable_auto_embedding_for_table('products_retriever');
enable_auto_embedding_for_table --------------------------------- (1 row)
Now, if we add data to the table, the embeddings will be automatically calculated. We can quickly test this:
INSERT INTO products (product_name, description) VALUES ('Pasta', 'A carb-heavy delight that is always welcome, especially with a good sauce'), ('Salad', 'Meh, it is what it is and it is not much. Occasionally saved by a good dressing');
NOTICE: Running auto embedding for retriever products. key: "10" content: "A carb-heavy delight that is always welcome, especially with a good sauce" NOTICE: Running auto embedding for retriever products. key: "11" content: "Meh, it is what it is and it is not much. Occasionally saved by a good dressing" INSERT 0 2
select * from aidb.retrieve_key('products_retriever','I like it',4) as a left join products as b on a.key=b.id;
key | distance | id | product_name | description | last_updated_at -----+--------------------+----+--------------+---------------------------------------------------------------------------------+---------------------------------- 10 | 1.0351907976251493 | 10 | Pasta | A carb-heavy delight that is always welcome, especially with a good sauce | 04-DEC-24 17:09:44.97484 +00:00 11 | 0.979874632270706 | 11 | Salad | Meh, it is what it is and it is not much. Occasionally saved by a good dressing | 04-DEC-24 17:09:44.97484 +00:00 3 | 1.03737124138149 | 3 | Fish n Chips | The fish is a little greasy and the chips do not help | 04-DEC-24 16:48:52.599806 +00:00 4 | 1.0369428080621286 | 4 | Fries | Never sure about these on their own, needs seasoning | 04-DEC-24 16:48:52.599806 +00:00 (4 rows)
Further reading
In the Models section, you can learn how to create more models with Pipelines, including external models from OpenAI API compatible services.
In the Retrievers section, you can learn more about how to use retrievers with external data sources, local files or S3 storage, and how to use the retriever functions to get the data you need.
Could this page be better? Report a problem or suggest an addition!